Example #1
0
File: zone.c Project: GYGit/reactos
/*
 * FUNCTION: Initializes a zone header
 * ARGUMENTS:
 *          Zone = zone header to be initialized
 *          BlockSize = Size (in bytes) of the allocation size of the zone
 *          InitialSegment = Initial segment of storage allocated by the
 *                           caller
 *          InitialSegmentSize = Initial size of the segment
 *
 * @implemented
 */
NTSTATUS
NTAPI
ExInitializeZone(PZONE_HEADER Zone,
                 ULONG BlockSize,
                 PVOID InitialSegment,
                 ULONG InitialSegmentSize)
{
    ULONG i;
    ULONG_PTR Entry;

    /*
     * BlockSize and Segment must be 8-byte aligned.
     * Blocksize cannot exceed Segment Size.
     */
    if (((ULONG_PTR)InitialSegment & 7) ||
        (InitialSegmentSize & 7) ||
        (BlockSize > InitialSegmentSize))
    {
        DPRINT1("Invalid ExInitializeZone Alignment and/or Size\n");
        return STATUS_INVALID_PARAMETER;
    }

    /* Set the Zone Header */
    Zone->BlockSize = BlockSize;

    /* Link empty list */
    Zone->FreeList.Next = NULL;
    Zone->SegmentList.Next = NULL;
    PushEntryList(&Zone->SegmentList,
                  &((PZONE_SEGMENT_HEADER)InitialSegment)->SegmentList);
    ((PZONE_SEGMENT_HEADER)InitialSegment)->Reserved = NULL;

    /* Get first entry */
    Entry = (ULONG_PTR)InitialSegment + sizeof(ZONE_SEGMENT_HEADER);

    /* Loop through the segments */
    for (i = sizeof(ZONE_SEGMENT_HEADER);
         i <= InitialSegmentSize - BlockSize;
         i+= BlockSize)
    {
        /* Link the Free and Segment Lists */
        PushEntryList(&Zone->FreeList, (PSINGLE_LIST_ENTRY)Entry);

        /* Go to the next entry */
        Entry += Zone->BlockSize;
    }

    /* Set Segment Size */
    Zone->TotalSegmentSize = i;

    /* Return success */
    return STATUS_SUCCESS;
}
Example #2
0
PSINGLE_LIST_ENTRY
FASTCALL
ExfInterlockedPushEntryList(
    IN OUT PSINGLE_LIST_ENTRY ListHead,
    IN PSINGLE_LIST_ENTRY ListEntry,
    IN OUT PKSPIN_LOCK Lock)
{
    BOOLEAN Enable;
    PSINGLE_LIST_ENTRY OldListEntry;

    /* Disable interrupts and acquire the spinlock */
    Enable = _ExiDisableInteruptsAndAcquireSpinlock(Lock);

    /* Save the old top entry */
    OldListEntry = ListHead->Next;

    /* Push a new entry on the list */
    PushEntryList(ListHead, ListEntry);

    /* Release the spinlock and restore interrupts */
    _ExiReleaseSpinLockAndRestoreInterupts(Lock, Enable);

    /* return the entry */
    return OldListEntry;
}
Example #3
0
static
VOID
GetIoQueueList_ProcessQueueListEntry(
    PLIST_ENTRY         QueueLE,
    PSINGLE_LIST_ENTRY  SListHead,
    PVOID               Tag
)
{
    FxIoQueueNode*      listNode;
    FxIoQueue*          queue;

    //
    // Skip any nodes that are not queues. They can be bookmarks for
    // in-progress flush operations.
    //
    listNode = FxIoQueueNode::_FromListEntry(QueueLE);
    if (listNode->IsNodeType(FxIoQueueNodeTypeQueue) == FALSE) {
        return;
    }

    queue = FxIoQueue::_FromIoPkgListEntry(QueueLE);
    PushEntryList(SListHead, &queue->m_PowerSListEntry);

    //
    // Add a reference since the request will be touched outside of the
    // lock being held. We will use the enumerant value as the tag.
    //
    queue->ADDREF(Tag);
}
Example #4
0
VOID
DOVERLAPPEDSTRUCTMGR::FreeApcContext(
    PAPCCONTEXT Context
    )
/*++

Routine Description:

    Frees an APC context structure to the pool of available structures.
    
Arguments:

    Context - A pointer to an APC context structure.

Return Value:

    NONE
    
--*/
{
    EnterCriticalSection(&m_overlapped_free_list_lock);

    PushEntryList(&m_overlapped_free_list,
                  (PSINGLE_LIST_ENTRY)Context);
    
    LeaveCriticalSection(&m_overlapped_free_list_lock);
    
}
Example #5
0
VOID
DOVERLAPPEDSTRUCTMGR::PushOverlappedStruct(
    LPWSAOVERLAPPED OverlappedStruct
    )
/*++
  
Routine Description:

    Pushes an internal overlapped structure onto the free list.
    
Arguments:

    A pointer to the InteranlOverlappedStruct member of an internal overlapped
    struct. 
Return Value:

    NONE    
--*/
{
    PINTERNALOVERLAPPEDSTRUCT InternalOverlappedStruct;
    
    
    EnterCriticalSection(&m_overlapped_free_list_lock);

    InternalOverlappedStruct = GetInternalStuctPointer(
        OverlappedStruct);

    assert(STRUCTSIGNATURE == InternalOverlappedStruct->Signature);
    
    PushEntryList(&m_overlapped_free_list,
                  (PSINGLE_LIST_ENTRY)InternalOverlappedStruct);

    LeaveCriticalSection(&m_overlapped_free_list_lock);
    
}
Example #6
0
File: zone.c Project: GYGit/reactos
/*
 * @implemented
 */
NTSTATUS
NTAPI
ExExtendZone(PZONE_HEADER Zone,
             PVOID Segment,
             ULONG SegmentSize)
{
    ULONG_PTR Entry;
    ULONG i;

    /*
     * BlockSize and Segment must be 8-byte aligned.
     * Blocksize cannot exceed Segment Size.
     */
    if (((ULONG_PTR)Segment & 7) ||
        (SegmentSize & 7) ||
        (Zone->BlockSize > SegmentSize))
    {
        DPRINT1("Invalid ExExtendZone Alignment and/or Size\n");
        return STATUS_INVALID_PARAMETER;
    }

    /* Link the Zone and Segment */
    PushEntryList(&Zone->SegmentList,
                  &((PZONE_SEGMENT_HEADER)Segment)->SegmentList);

    /* Get to the first entry */
    Entry = (ULONG_PTR)Segment + sizeof(ZONE_SEGMENT_HEADER);

    /* Loop through the segments */
    for (i = sizeof(ZONE_SEGMENT_HEADER);
         i <= SegmentSize - Zone->BlockSize;
         i+= Zone->BlockSize)
    {
        /* Link the Free and Segment Lists */
        PushEntryList(&Zone->FreeList, (PSINGLE_LIST_ENTRY)Entry);

        /* Go to the next entry */
        Entry += Zone->BlockSize;
    }

    /* Update Segment Size */
    Zone->TotalSegmentSize += i;

    /* Return Success */
    return STATUS_SUCCESS;
}
Example #7
0
VOID
ExFreeToPagedLookasideList(
    IN PPAGED_LOOKASIDE_LIST Lookaside,
    IN PVOID Entry
    )

/*++

Routine Description:

    This function inserts (pushes) the specified entry into the specified
    paged lookaside list.

Arguments:

    Lookaside - Supplies a pointer to a paged lookaside list structure.

    Entry - Supples a pointer to the entry that is inserted in the
        lookaside list.

Return Value:

    None.

--*/

{

    Lookaside->L.TotalFrees += 1;

    if (Isx86FeaturePresent(KF_CMPXCHG8B)) {
        if (ExQueryDepthSList(&Lookaside->L.ListHead) >= Lookaside->L.Depth) {
            Lookaside->L.FreeMisses += 1;
            (Lookaside->L.Free)(Entry);

        } else {
            ExInterlockedPushEntrySList(&Lookaside->L.ListHead,
                                        (PSINGLE_LIST_ENTRY)Entry,
                                        NULL);
        }

        return;
    }

    ExAcquireFastMutex(&Lookaside->Lock);
    if (ExQueryDepthSList(&Lookaside->L.ListHead) >= Lookaside->L.Depth) {
        ExReleaseFastMutex(&Lookaside->Lock);
        Lookaside->L.FreeMisses += 1;
        (Lookaside->L.Free)(Entry);

    } else {
        PushEntryList(&Lookaside->L.ListHead.Next, (PSINGLE_LIST_ENTRY)Entry);
        Lookaside->L.ListHead.Depth += 1;
        ExReleaseFastMutex(&Lookaside->Lock);
    }

    return;
}
Example #8
0
static NTSTATUS EtpSymbolLookupFunction(
    _In_ PVOID Parameter
    )
{
    PSYMBOL_LOOKUP_RESULT result;

    result = Parameter;

    // Don't bother looking up the symbol if the window has already closed.
    if (result->Context->Destroying)
    {
        EtpDereferenceWsWatchContext(result->Context);
        PhFree(result);
        return STATUS_SUCCESS;
    }

    result->Symbol = PhGetSymbolFromAddress(
        result->Context->SymbolProvider,
        (ULONG64)result->Address,
        NULL,
        NULL,
        NULL,
        NULL
        );

    // Fail if we don't have a symbol.
    if (!result->Symbol)
    {
        EtpDereferenceWsWatchContext(result->Context);
        PhFree(result);
        return STATUS_SUCCESS;
    }

    PhAcquireQueuedLockExclusive(&result->Context->ResultListLock);
    PushEntryList(&result->Context->ResultListHead, &result->ListEntry);
    PhReleaseQueuedLockExclusive(&result->Context->ResultListLock);
    EtpDereferenceWsWatchContext(result->Context);

    return STATUS_SUCCESS;
}
Example #9
0
static NTSTATUS VirtQueueAddBuffer(IN PDEVICE_CONTEXT Context,
                                   IN WDFREQUEST Request,
                                   IN size_t Length)
{
    PREAD_BUFFER_ENTRY entry;
    size_t length;
    struct virtqueue *vq = Context->VirtQueue;
    struct VirtIOBufferDescriptor sg;
    int ret;

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "--> %!FUNC!");

    entry = (PREAD_BUFFER_ENTRY)ExAllocatePoolWithTag(NonPagedPool,
        sizeof(READ_BUFFER_ENTRY), VIRT_RNG_MEMORY_TAG);

    if (entry == NULL)
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_READ,
            "Failed to allocate a read entry.");
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    length = min(Length, PAGE_SIZE);
    entry->Buffer = ExAllocatePoolWithTag(NonPagedPool, length,
        VIRT_RNG_MEMORY_TAG);

    if (entry->Buffer == NULL)
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_READ,
            "Failed to allocate a read buffer.");
        ExFreePoolWithTag(entry, VIRT_RNG_MEMORY_TAG);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    entry->Request = Request;

    sg.physAddr = MmGetPhysicalAddress(entry->Buffer);
    sg.length = (unsigned)length;

    WdfSpinLockAcquire(Context->VirtQueueLock);

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ,
        "Push %p Request: %p Buffer: %p",
        entry, entry->Request, entry->Buffer);

    PushEntryList(&Context->ReadBuffersList, &entry->ListEntry);

    ret = virtqueue_add_buf(vq, &sg, 0, 1, entry, NULL, 0);
    if (ret < 0)
    {
        PSINGLE_LIST_ENTRY removed;

        TraceEvents(TRACE_LEVEL_ERROR, DBG_READ,
            "Failed to add buffer to virt queue.");

        TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ,
            "Pop %p Request: %p Buffer: %p",
            entry, entry->Request, entry->Buffer);

        removed = PopEntryList(&Context->ReadBuffersList);
        NT_ASSERT(entry == CONTAINING_RECORD(
            removed, READ_BUFFER_ENTRY, ListEntry));

        ExFreePoolWithTag(entry->Buffer, VIRT_RNG_MEMORY_TAG);
        ExFreePoolWithTag(entry, VIRT_RNG_MEMORY_TAG);

        WdfSpinLockRelease(Context->VirtQueueLock);

        return STATUS_UNSUCCESSFUL;
    }

    WdfSpinLockRelease(Context->VirtQueueLock);

    virtqueue_kick(vq);

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "<-- %!FUNC!");

    return STATUS_SUCCESS;
}
VOID
BalloonFill(
    IN WDFOBJECT WdfDevice,
    IN size_t num)
{
    PMDL                pPageMdl;
    PHYSICAL_ADDRESS    LowAddress;
    PHYSICAL_ADDRESS    HighAddress;
    PPAGE_LIST_ENTRY    pNewPageListEntry;
    PDEVICE_CONTEXT     devCtx = GetDeviceContext(WdfDevice);
    ULONG               pages_per_request = PAGE_SIZE/sizeof(PFN_NUMBER);

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_HW_ACCESS, "--> %s\n", __FUNCTION__);

    LowAddress.QuadPart = 0;
    HighAddress.QuadPart = (ULONGLONG)-1;

    num = min(num, pages_per_request);
    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_HW_ACCESS, "--> BalloonFill num = %d\n", num);

    for (devCtx->num_pfns = 0; devCtx->num_pfns < num; devCtx->num_pfns++)
    {
        if(IsLowMemory(WdfDevice))
        {
           TraceEvents(TRACE_LEVEL_WARNING, DBG_HW_ACCESS,
                "LowMemoryCondition event was set to signaled,allocations stops, BalPageCount=%d\n", devCtx->num_pages);
           break;
        }
        pPageMdl = MmAllocatePagesForMdl(
                                        LowAddress,
                                        HighAddress,
                                        LowAddress,
                                        PAGE_SIZE
                                        );
        if (pPageMdl == NULL)
        {
            TraceEvents(TRACE_LEVEL_WARNING, DBG_HW_ACCESS,
                 "Balloon MDL Page Allocation Failed!!!, BalPageCount=%d\n", devCtx->num_pages);
            break;
        }

        if (MmGetMdlByteCount(pPageMdl) != PAGE_SIZE)
        {
            TraceEvents(TRACE_LEVEL_WARNING, DBG_HW_ACCESS,
                 "Balloon MDL Page Allocation < PAGE_SIZE =%d, Failed!!!, BalPageCount=%d\n",MmGetMdlByteCount(pPageMdl), devCtx->num_pages);
            MmFreePagesFromMdl(pPageMdl);
            ExFreePool(pPageMdl);
            break;
        }

        pNewPageListEntry = (PPAGE_LIST_ENTRY)ExAllocateFromNPagedLookasideList(&devCtx->LookAsideList);
        if (pNewPageListEntry == NULL)
        {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_HW_ACCESS, "List Entry Allocation Failed!!!\n");
            MmFreePagesFromMdl(pPageMdl);
            ExFreePool(pPageMdl);
            break;
        }

        pNewPageListEntry->PageMdl = pPageMdl;
        pNewPageListEntry->PagePfn = devCtx->pfns_table[devCtx->num_pfns] = *MmGetMdlPfnArray(pPageMdl);

        PushEntryList(&devCtx->PageListHead, &(pNewPageListEntry->SingleListEntry));
        devCtx->num_pages++;
    }

    if (devCtx->num_pfns > 0)
    {
        BalloonTellHost(WdfDevice, devCtx->InfVirtQueue);
    }
}
VOID
BalloonFill(
    IN WDFOBJECT WdfDevice,
    IN size_t num)
{
    PDEVICE_CONTEXT ctx = GetDeviceContext(WdfDevice);
    PHYSICAL_ADDRESS LowAddress;
    PHYSICAL_ADDRESS HighAddress;
    PHYSICAL_ADDRESS SkipBytes;
    PPAGE_LIST_ENTRY pNewPageListEntry;
    PMDL pPageMdl;

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_HW_ACCESS, "--> %s\n", __FUNCTION__);

    ctx->num_pfns = 0;

    if (IsLowMemory(WdfDevice))
    {
        TraceEvents(TRACE_LEVEL_WARNING, DBG_HW_ACCESS,
            "Low memory. Allocated pages: %d\n", ctx->num_pages);
        return;
    }

    num = min(num, PAGE_SIZE / sizeof(PFN_NUMBER));
    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_HW_ACCESS,
        "Inflate balloon with %d pages.\n", num);

    LowAddress.QuadPart = 0;
    HighAddress.QuadPart = (ULONGLONG)-1;
    SkipBytes.QuadPart = 0;

#if (NTDDI_VERSION < NTDDI_WS03SP1)
    pPageMdl = MmAllocatePagesForMdl(LowAddress, HighAddress, SkipBytes,
        num * PAGE_SIZE);
#else
    pPageMdl = MmAllocatePagesForMdlEx(LowAddress, HighAddress, SkipBytes,
        num * PAGE_SIZE, MmNonCached, MM_DONT_ZERO_ALLOCATION);
#endif

    if (pPageMdl == NULL)
    {
        TraceEvents(TRACE_LEVEL_WARNING, DBG_HW_ACCESS,
            "Failed to allocate pages.\n");
        return;
    }

    if (MmGetMdlByteCount(pPageMdl) != (num * PAGE_SIZE))
    {
        TraceEvents(TRACE_LEVEL_WARNING, DBG_HW_ACCESS,
            "Not all requested memory was allocated (%d/%d).\n",
            MmGetMdlByteCount(pPageMdl), num * PAGE_SIZE);
        MmFreePagesFromMdl(pPageMdl);
        ExFreePool(pPageMdl);
        return;
    }

    pNewPageListEntry = (PPAGE_LIST_ENTRY)ExAllocateFromNPagedLookasideList(
        &ctx->LookAsideList);

    if (pNewPageListEntry == NULL)
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_HW_ACCESS,
            "Failed to allocate list entry.\n");
        MmFreePagesFromMdl(pPageMdl);
        ExFreePool(pPageMdl);
        return;
    }

    pNewPageListEntry->PageMdl = pPageMdl;
    PushEntryList(&ctx->PageListHead, &(pNewPageListEntry->SingleListEntry));

    ctx->num_pfns = num;
    ctx->num_pages += ctx->num_pfns;

    RtlCopyMemory(ctx->pfns_table, MmGetMdlPfnArray(pPageMdl),
        ctx->num_pfns * sizeof(PFN_NUMBER));

    BalloonTellHost(WdfDevice, ctx->InfVirtQueue);

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_HW_ACCESS, "<-- %s\n", __FUNCTION__);
}
VOID VIOSerialPortWrite(IN WDFQUEUE Queue,
                        IN WDFREQUEST Request,
                        IN size_t Length)
{
    NTSTATUS status;
    PVOID InBuf;
    PVOID buffer;
    PVIOSERIAL_PORT Port;
    PWRITE_BUFFER_ENTRY entry;

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE,
        "--> %s Request: %p Length: %d\n", __FUNCTION__, Request, Length);

    PAGED_CODE();

    status = WdfRequestRetrieveInputBuffer(Request, Length, &InBuf, NULL);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
            "Failed to retrieve input buffer: %x\n", status);
        WdfRequestComplete(Request, status);
        return;
    }

    Port = RawPdoSerialPortGetData(WdfIoQueueGetDevice(Queue))->port;

    if (VIOSerialWillWriteBlock(Port))
    {
        WdfRequestComplete(Request, STATUS_CANT_WAIT);
        return;
    }

    status = WdfRequestMarkCancelableEx(Request,
        VIOSerialPortWriteRequestCancel);

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
            "Failed to mark request as cancelable: %x\n", status);
        WdfRequestComplete(Request, status);
        return;
    }

    buffer = ExAllocatePoolWithTag(NonPagedPool, Length,
        VIOSERIAL_DRIVER_MEMORY_TAG);

    if (buffer == NULL)
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE, "Failed to allocate.\n");
        WdfRequestComplete(Request, STATUS_INSUFFICIENT_RESOURCES);
        return;
    }

    entry = (PWRITE_BUFFER_ENTRY)ExAllocatePoolWithTag(NonPagedPool,
        sizeof(WRITE_BUFFER_ENTRY), VIOSERIAL_DRIVER_MEMORY_TAG);

    if (entry == NULL)
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
            "Failed to allocate write buffer entry.\n");
        ExFreePoolWithTag(buffer, VIOSERIAL_DRIVER_MEMORY_TAG);
        WdfRequestComplete(Request, STATUS_INSUFFICIENT_RESOURCES);
        return;
    }

    RtlCopyMemory(buffer, InBuf, Length);
    WdfRequestSetInformation(Request, (ULONG_PTR)Length);

    entry->Buffer = buffer;
    PushEntryList(&Port->WriteBuffersList, &entry->ListEntry);

    Port->PendingWriteRequest = Request;

    if (VIOSerialSendBuffers(Port, buffer, Length) <= 0)
    {
        PSINGLE_LIST_ENTRY removed;

        TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
            "Failed to send user's buffer.\n");

        ExFreePoolWithTag(buffer, VIOSERIAL_DRIVER_MEMORY_TAG);
        
        removed = PopEntryList(&Port->WriteBuffersList);
        NT_ASSERT(entry == CONTAINING_RECORD(removed, WRITE_BUFFER_ENTRY, ListEntry));
        ExFreePoolWithTag(entry, VIOSERIAL_DRIVER_MEMORY_TAG);        
        
        Port->PendingWriteRequest = NULL;
        WdfRequestComplete(Request, STATUS_INSUFFICIENT_RESOURCES);
    }

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE,"<-- %s\n", __FUNCTION__);
}
Example #13
0
INT
DOVERLAPPEDSTRUCTMGR::Initialize(
        )
/*++

Routine Description:

    The initialization routine for a DOVERLAPPEDSTRUCTMGR  object.  This
    procedure completes the initialzation of the object.  This procedure
    preforms initialization operations that may fail and must be reported since
    there is no way to fail the constructor. 
    
Arguments:

    None
Return Value:

    The  function returns NO_ERROR if successful.  Otherwise it
    returns an appropriate WinSock error code if the initialization
    cannot be completed.
--*/
{
    INT   ReturnCode;
    ULONG BlockSize;
    PBYTE CurrentBlock;
    ULONG BytesAvailable;
    ULONG StructSize;
    
    
    ReturnCode = WSAENOBUFS;

    //
    // Initialize the pool of internal overlapped structs.
    //
    
    // Get memory for our overlapped structs
    BlockSize = sizeof(INTERNALOVERLAPPEDSTRUCT) *
        OUTSTANDINGOVERLAPPEDSTRUCTS;
    m_overlapped_struct_block = (PBYTE) new BYTE[BlockSize];
    
    if (m_overlapped_struct_block){

        // Dice up the memory block into internal overlapped structs and add
        // them to the free list.
        EnterCriticalSection(&m_overlapped_free_list_lock);

        StructSize = sizeof(INTERNALOVERLAPPEDSTRUCT);
        
        BytesAvailable = BlockSize;
        CurrentBlock   = m_overlapped_struct_block;

        while (BytesAvailable > StructSize){
            PushEntryList(&m_overlapped_free_list,
                          (PSINGLE_LIST_ENTRY) CurrentBlock);

            BytesAvailable -= StructSize;
            CurrentBlock += StructSize;
        } //while
        ReturnCode = NO_ERROR;
        LeaveCriticalSection(&m_overlapped_free_list_lock);
    } //if

    //
    // Initialize the pool of APC context structs.
    //
    
    if (NO_ERROR == ReturnCode){

        ReturnCode = WSAENOBUFS;

        BlockSize =  sizeof(APCCONTEXT)* OUTSTANDINGOVERLAPPEDSTRUCTS;
        
        m_context_struct_block = (PBYTE) new BYTE[BlockSize];
        if (m_context_struct_block){

            // Dice up the memory block into APC context structs and add
            // them to the free list.
        
            EnterCriticalSection(&m_context_free_list_lock);

            StructSize = sizeof(APCCONTEXT);
        
            BytesAvailable = BlockSize;
            CurrentBlock   = m_context_struct_block;

            while (BytesAvailable > StructSize){
                PushEntryList(&m_context_free_list,
                              (PSINGLE_LIST_ENTRY) CurrentBlock);

                BytesAvailable -= StructSize;
                CurrentBlock += StructSize;
            } //while
            ReturnCode = NO_ERROR;
            LeaveCriticalSection(&m_context_free_list_lock);
        } //if
    } //if

    if (NO_ERROR != ReturnCode){
        delete(m_overlapped_struct_block);
    } //if
    return(ReturnCode);
}
Example #14
0
NTSTATUS PCIAllocBars(WDFCMRESLIST ResourcesTranslated,
                      PVIRTIO_WDF_DRIVER pWdfDriver)
{
    PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDescriptor;
    ULONG nInterrupts = 0, nMSIInterrupts = 0;
    int nListSize = WdfCmResourceListGetCount(ResourcesTranslated);
    int i;
    PVIRTIO_WDF_BAR pBar;
    PCI_COMMON_HEADER PCIHeader;

    /* read the PCI config header */
    if (pWdfDriver->PCIBus.GetBusData(
        pWdfDriver->PCIBus.Context,
        PCI_WHICHSPACE_CONFIG,
        &PCIHeader,
        0,
        sizeof(PCIHeader)) != sizeof(PCIHeader)) {
        return STATUS_DEVICE_CONFIGURATION_ERROR;
    }
    
    for (i = 0; i < nListSize; i++) {
        pResDescriptor = WdfCmResourceListGetDescriptor(ResourcesTranslated, i);
        if (pResDescriptor) {
            switch (pResDescriptor->Type) {
                case CmResourceTypePort:
                case CmResourceTypeMemory:
                    pBar = (PVIRTIO_WDF_BAR)ExAllocatePoolWithTag(
                        NonPagedPool,
                        sizeof(VIRTIO_WDF_BAR),
                        pWdfDriver->MemoryTag);
                    if (pBar == NULL) {
                        /* undo what we've done so far */
                        PCIFreeBars(pWdfDriver);
                        return STATUS_INSUFFICIENT_RESOURCES;
                    }

                    /* unfortunately WDF doesn't tell us BAR indices */
                    pBar->iBar = virtio_get_bar_index(&PCIHeader, pResDescriptor->u.Memory.Start);
                    if (pBar->iBar < 0) {
                        /* undo what we've done so far */
                        PCIFreeBars(pWdfDriver);
                        return STATUS_NOT_FOUND;
                    }

                    pBar->bPortSpace = !!(pResDescriptor->Flags & CM_RESOURCE_PORT_IO);
                    pBar->BasePA = pResDescriptor->u.Memory.Start;
                    pBar->uLength = pResDescriptor->u.Memory.Length;

                    if (pBar->bPortSpace) {
                        pBar->pBase = (PVOID)(ULONG_PTR)pBar->BasePA.QuadPart;
                    } else {
                        /* memory regions are mapped into the virtual memory space on demand */
                        pBar->pBase = NULL;
                    }
                    PushEntryList(&pWdfDriver->PCIBars, &pBar->ListEntry);
                    break;

                case CmResourceTypeInterrupt:
                    nInterrupts++;
                    if (pResDescriptor->Flags &
                        (CM_RESOURCE_INTERRUPT_LATCHED | CM_RESOURCE_INTERRUPT_MESSAGE)) {
                        nMSIInterrupts++;
                    }
                    break;
            }
        }
    }

    pWdfDriver->nInterrupts = nInterrupts;
    pWdfDriver->nMSIInterrupts = nMSIInterrupts;

    return STATUS_SUCCESS;
}
Example #15
0
NTSTATUS
MapPhysicalMemory(
    VOID* InputBuffer,
    ULONG InputBufferLength,
    ULONG OutputBufferLength,
    ULONG* BytesReturned
    )
{
    PHYSICAL_ADDRESS phyAddr;
    //PPHYMEM_MEM pMem;
    PHYSICAL_MEMORY *physicalMemory;
    PVOID pvk, pvu;

    //DbgPrint("[PUSH] MapPhysicalMemory");

    if (InputBufferLength != sizeof(PHYSICAL_MEMORY) || OutputBufferLength != sizeof(PVOID))
        return STATUS_INVALID_PARAMETER;

    physicalMemory=(PHYSICAL_MEMORY*)InputBuffer;
    phyAddr.QuadPart=(ULONGLONG)physicalMemory->pvAddr;

    //get mapped kernel address
    pvk=MmMapIoSpace(phyAddr, physicalMemory->dwSize, MmNonCached);

    if (pvk)
    {
        //allocate mdl for the mapped kernel address
        PMDL pMdl=IoAllocateMdl(pvk, physicalMemory->dwSize, FALSE, FALSE, NULL);
        if (pMdl)
        {
            PMAPINFO pMapInfo;

            //build mdl and map to user space
            MmBuildMdlForNonPagedPool(pMdl);
            pvu=MmMapLockedPages(pMdl, UserMode);

            //insert mapped infomation to list
            pMapInfo=(PMAPINFO)ExAllocatePool(\
                NonPagedPool, sizeof(MAPINFO));
            pMapInfo->pMdl=pMdl;
            pMapInfo->pvk=pvk;
            pMapInfo->pvu=pvu;
            pMapInfo->memSize=physicalMemory->dwSize;
            PushEntryList(&lstMapInfo, &pMapInfo->link);

            DbgPrint("Map physical 0x%x to virtual 0x%x, size %u", \
                physicalMemory->pvAddr, pvu, physicalMemory->dwSize);

            RtlCopyMemory(InputBuffer, &pvu, sizeof(PVOID));

            *BytesReturned = sizeof(PVOID);

            return STATUS_SUCCESS;
        }
        else
        {
            //allocate mdl error, unmap the mapped physical memory
            MmUnmapIoSpace(pvk, physicalMemory->dwSize);

            return STATUS_INSUFFICIENT_RESOURCES;
        }
    }
    else
        return STATUS_INSUFFICIENT_RESOURCES;
}
/*
715, 	"%wsWindows %ws"
716, 	"%ws Build %ws"
717, 	"Evaluation copy."
718, 	"For testing purposes only."
723, 	"%wsMicrosoft (R) Windows (R) (Build %ws: %ws)"
737, 	"This copy of Windows is not genuine"
738, 	"Test Mode"
*/
BOOL GetWatermarkFromMuiFile(LPTSTR pszFile)
{
	_tcprintf(_T("File name:\t%s\n"), pszFile);

	if (!PathFileExists(pszFile))
	{
		_tcprintf(_T("File not found!\n"));
		return FALSE;
	}


	//
	// Check file version, we need to get the language ID of the mui file.
	//

	MYVERSIONINFO	vi;

	ZeroMemory(&vi, sizeof(MYVERSIONINFO));
	vi.dwSize = sizeof(MYVERSIONINFO);
	if (!GetDllFileVersion(pszFile, &vi))
	{
		_tcprintf(_T("Fail to get file version info!\n")); 
		return FALSE;
	}

	_tcprintf(_T("File version:\t%s\n"), vi.szShortVersion);


	//
	// Load mui file to memory
	//

	HINSTANCE		hInstLib  = NULL;

	hInstLib = LoadLibraryEx(pszFile, NULL, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
	if( NULL == hInstLib )
	{
		_tcprintf(_T("Fail to open file user32.dll.mui!\n")); 
		return FALSE;
	}


	//
	// Get file type
	//

	PIMAGE_DOS_HEADER	pDOSHeader	= (PIMAGE_DOS_HEADER)((DWORD_PTR)hInstLib - 1);
	PIMAGE_NT_HEADERS	pNTHeader	= (PIMAGE_NT_HEADERS) (pDOSHeader->e_lfanew + (DWORD_PTR)pDOSHeader);
	
	_tcprintf(_T("File type:\t"));
	switch (pNTHeader->FileHeader.Machine)
	{
	case IMAGE_FILE_MACHINE_I386:
		_tcprintf(_T("x86"));
		break;
	case IMAGE_FILE_MACHINE_AMD64:
		_tcprintf(_T("x64"));
		break;
	case IMAGE_FILE_MACHINE_IA64:
		_tcprintf(_T("ia64"));
		break;

	default:
		_tcprintf(_T("Unknown\nThis is not a valid file.\n"));

		FreeLibrary(hInstLib);
		return FALSE;
	}

	UINT		uStringID;
	UINT		uStringIDS[]	= {715, 716, 717, 718, 738, 723, 737};
	BOOL		bHasPatched		= FALSE;
	UINT		i				= 0;
	UINT		uMatchingString	= 0;

	// Create string info lists
	SINGLE_LIST_ENTRY	StringsHead;
	PSINGLE_LIST_ENTRY	psLink;
	PRES_STRING_INFO	pStrInfo;

	StringsHead.Next = NULL;

	_tcprintf(_T("\n\n   ID  String                                                Offset  Len Mod"));
	_tcprintf(  _T("\n-----  ----------------------------------------------------  ------  --- ---"));

	for (i=0; i < sizeof(uStringIDS)/sizeof(UINT); i++)
	{
		// Add a entry
		pStrInfo	= (PRES_STRING_INFO)MALLOC(sizeof(RES_STRING_INFO));
		ZeroMemory(pStrInfo, sizeof(RES_STRING_INFO));
		
		pStrInfo->uStringID	= uStringIDS[i];

		LoadStringExx(hInstLib, (WORD)vi.wLangID, pStrInfo);

		if (lstrlen(pStrInfo->pszText) > 0)
		{
			uMatchingString++;
		}

		_tcprintf(_T("\n%5d  %s"), pStrInfo->uStringID, pStrInfo->pszText);
		gotoX(61);
		_tcprintf(_T("0x%4X  %3d"), pStrInfo->dwFileOffset, pStrInfo->dwBytes);

		PushEntryList(&StringsHead, &(pStrInfo->link));

	} // for(i)


	// importance
	FreeLibrary(hInstLib);

	_tcprintf(_T("\n\n"));


	if ( (uMatchingString > 0) && (StringsHead.Next != NULL) )
	{
		_tcprintf(_T("Do you want to patch this file?\n"));
		_tcprintf(_T(" (Y=Yes  /  N=No)\n:"));

		int	iChoice	= getchar();

		if ( (iChoice == _T('y')) || (iChoice == _T('Y')) )
		{
			TCHAR	szFileBackup[MAX_PATH];

			StringCbCopy(szFileBackup, sizeof(szFileBackup), pszFile);
			StringCbCat(szFileBackup, sizeof(szFileBackup), _T(".backup"));

			// make a backup
			CopyFile(pszFile, szFileBackup, FALSE);

			// In real life, if you want to patch \windows\system32\en-us\user32.dll.mui,
			// because the file is in using, you must copy a temp file to do ZeroWatermarkFromMuiFile().
			// Last, using MoveFileEx() to replace the file.

			if (ZeroWatermarkFromMuiFile(pszFile, &StringsHead))
			{
				_tcprintf(_T("\nPatch OK!\n"));
			}
			else
			{
				_tcprintf(_T("\nFail to patch.\n"));
			}


		} // choice y
	}
	else
	{
		_tcprintf(_T("Watermark string is not found, no need to patch.\n"));
	}


	//
	// Removes all string infos, free memory
	//
	psLink	= PopEntryList(&StringsHead);
	while(psLink)
	{
		pStrInfo	= CONTAINING_RECORD(psLink, RES_STRING_INFO, link);

		// free memory
		if (pStrInfo->pszText)
			FREE((LPVOID)(pStrInfo->pszText));

		FREE((LPVOID)pStrInfo);

		// Removes the first entry
		psLink	= PopEntryList(&StringsHead);

	} // while(psLink)


	return TRUE;

} // GetWatermarkFromMuiFile
Example #17
0
/************************************************************************
*************************************** PgDumpTimerTable
*************************************************************************

Description:

	All PatchGuard 2 related timers will wear the "suspect" sttribute.

	ATTENTION: The code uses undocumented kernel APIs. Please keep in mind
	that you shouldn't change the code logic and remember that during
	enumeration your code will run at DISPATCH_LEVEL! 

*/
NTSTATUS PgDumpTimerTable()
{
	KIRQL					OldIrql;
	ULONG					Index;
	PKSPIN_LOCK_QUEUE		LockQueue;
	PKTIMER_TABLE_ENTRY		TimerListHead;
	PLIST_ENTRY				TimerList;
	PKTIMER					Timer;
	PKDPC					TimerDpc;
	CHAR					LogEntryText[2048];
	NTSTATUS				Result = STATUS_SUCCESS;
	HANDLE					hLogFile;
	UNICODE_STRING			LogFileName;
	OBJECT_ATTRIBUTES		ObjAttr;
	IO_STATUS_BLOCK			IOStatus;
	ULONG					LogEntryTextLen;
	SINGLE_LIST_ENTRY		LogListHead = {NULL};
	PSINGLE_LIST_ENTRY		LogList;
	LOGENTRY*				LogEntry;

	ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

	/*
		Open log file...
	*/
	RtlInitUnicodeString(&LogFileName, L"\\??\\C:\\patchguard.log");

	InitializeObjectAttributes(
		&ObjAttr, 
		&LogFileName, 
		OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
		NULL, NULL)

	if(!NT_SUCCESS(Result = ZwCreateFile(
			&hLogFile,
			GENERIC_WRITE,
			&ObjAttr,
			&IOStatus,
			NULL,
			FILE_ATTRIBUTE_NORMAL,
			FILE_SHARE_READ,
			FILE_OVERWRITE_IF,
			FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE,
			NULL, 0)))
	{
		KdPrint(("\r\n" "ERROR: Unable to open file \"\\??\\C:\\patchguard.log\". (NTSTATUS: 0x%p)\r\n", (void*)Result));

		return Result;
	}
	
	/*
		Lock the dispatcher database and loop through the timer list...
	*/
	Result = STATUS_SUCCESS;

	OldIrql = KiAcquireDispatcherLockRaiseToSynch();

	for(Index = 0; Index < TIMER_TABLE_SIZE; Index++)
	{
		// we have to emulate the windows timer bug "Index & 0xFF" for this to work...
		LockQueue = KeTimerIndexToLockQueue((UCHAR)(Index & 0xFF));

		KeAcquireQueuedSpinLockAtDpcLevel(LockQueue);
		
		// now we can work with the timer list...
		TimerListHead = &KiTimerTableListHead[Index];
		TimerList = TimerListHead->Entry.Flink;

		while(TimerList != (PLIST_ENTRY)TimerListHead)
		{
			Timer = CONTAINING_RECORD(TimerList, KTIMER, TimerListEntry);
			TimerDpc = PgDeobfuscateTimerDpc(Timer);
			TimerList = TimerList->Flink;

			if(TimerDpc != NULL)
			{
				memset(LogEntryText, 0, sizeof(LogEntryText));

				LogEntryTextLen = _snprintf(LogEntryText, sizeof(LogEntryText) - 1, 
					"<timer address=\"%p\" index=\"%d\" period=\"0x%p\" hand=\"%d\" duetime=\"0x%p\">\r\n"
					"%s"
					"    <dpc>\r\n"
					"        <DeferredContext value=\"0x%p\">%s</DeferredContext>\r\n"
					"        <DeferredRoutine>0x%p</DeferredRoutine>\r\n"
					"        <DpcListBlink value=\"0x%p\">%s</DpcListBlink>\r\n"
					"        <DpcListFlink value=\"0x%p\">%s</DpcListFlink>\r\n"
					"        <DpcData value=\"0x%p\">%s</DpcData>\r\n"
					"        <Importance>%d</Importance>\r\n"
					"        <Number>%d</Number>\r\n"
					"        <SystemArgument1 value=\"0x%p\">%s</SystemArgument1>\r\n"
					"        <SystemArgument2 value=\"0x%p\">%s</SystemArgument2>\r\n"
					"        <Type>%d</Type>\r\n"
					"    </dpc>\r\n"
					"</timer>\r\n\r\n",
					Timer,
					Index,
					(ULONGLONG)Timer->Period,
					(ULONG)Timer->Header.Hand,
					Timer->DueTime.QuadPart,
					PgIsPatchGuardContext(TimerDpc->DeferredContext)?"    <SUSPECT>true</SUSPECT>\t\n":"",
					TimerDpc->DeferredContext, PointerToString(TimerDpc->DeferredContext),
					TimerDpc->DeferredRoutine, 
					TimerDpc->DpcListEntry.Blink, PointerToString(TimerDpc->DpcListEntry.Blink),
					TimerDpc->DpcListEntry.Flink, PointerToString(TimerDpc->DpcListEntry.Flink),
					TimerDpc->DpcData, PointerToString(TimerDpc->DpcData),
					(ULONG)TimerDpc->Importance,
					(ULONG)TimerDpc->Number,
					TimerDpc->SystemArgument1, PointerToString(TimerDpc->SystemArgument1),
					TimerDpc->SystemArgument2, PointerToString(TimerDpc->SystemArgument2),
					(ULONG)TimerDpc->Type
				);

				// allocate memory and add log entry to list...
				if((LogEntry = (LOGENTRY*)ExAllocatePool(NonPagedPool, sizeof(LOGENTRY) + LogEntryTextLen + 1)) == NULL)
				{
					KeReleaseQueuedSpinLockFromDpcLevel(LockQueue);

					Result = STATUS_NO_MEMORY;

					DbgPrint("\r\n" "WARNING: Not enough non-paged memory to write suspect timer to file. Aborting enumeration...\r\n");

					break;
				}

				LogEntry->Text = (CHAR*)(LogEntry + 1);
				LogEntry->Length = LogEntryTextLen;

				memcpy(LogEntry->Text, LogEntryText, LogEntryTextLen);

				PushEntryList(&LogListHead, &LogEntry->List);
			}
		}

		KeReleaseQueuedSpinLockFromDpcLevel(LockQueue);
	}

	KiReleaseDispatcherLockFromSynchLevel();

	KiExitDispatcher(OldIrql);
		
	KdPrint(("\r\n" "INFORMATION: Completed PatchGuard scan...\r\n"));

	/*
		Loop through the log entries and flush them to disk...
		In case of an error during enumeration this actually won't write any
		files, but just free allocated memory...
	*/
	LogList = PopEntryList(&LogListHead);

	while(LogList != NULL)
	{
		LogEntry = CONTAINING_RECORD(LogList, LOGENTRY, List);

		if(NT_SUCCESS(Result))
		{
			Result = ZwWriteFile(
					hLogFile,
					NULL, NULL, NULL,
					&IOStatus,
					LogEntry->Text,
					LogEntry->Length,
					NULL, NULL);
		}

		ExFreePool(LogEntry);

		LogList = PopEntryList(&LogListHead);
	}

	ZwClose(hLogFile);

	return Result;
}