Exemplo n.º 1
0
VOID
FxPkgIo::ResetStateForRestart(
    VOID
)
/*++

Routine Description:
    This is called on a device which has been restarted from the removed
    state.  It will reset purged queues so that they can accept new requests
    when ResumeProcessingForPower is called afterwards.

Arguments:
    None

Return Value:
    None

  --*/
{
    KIRQL irql;
    FxIoQueue* queue;
    SINGLE_LIST_ENTRY queueList, *ple;

    DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGIO,
                        "Restart queues from purged state for WDFDEVICE 0x%p due to "
                        "device restart", m_Device->GetHandle());

    queueList.Next = NULL;

    Lock(&irql);

    GetIoQueueListLocked(&queueList, FxIoQueueIteratorListPowerOn);

    Unlock(irql);

    for (ple = PopEntryList(&queueList);
            ple != NULL;
            ple = PopEntryList(&queueList)) {

        queue = FxIoQueue::_FromPowerSListEntry(ple);

        queue->ResetStateForRestart();

        ple->Next = NULL;

        queue->RELEASE(IO_ITERATOR_POWER_TAG);
    }

    Lock(&irql);

    m_PowerStateOn = TRUE;

    m_QueuesAreShuttingDown = FALSE;

    Unlock(irql);

    return;

}
Exemplo n.º 2
0
VOID
PushUnload( DRIVER_OBJECT* DriverObject )
{
    UNICODE_STRING DeviceLinkU;
    NTSTATUS ntStatus;
    PMAPINFO pMapInfo;
    PSINGLE_LIST_ENTRY pLink;

    DbgPrint("[Push] => (PushUnload)");

    RdUnload(DriverObject);

    //free resources
    pLink=PopEntryList(&lstMapInfo);
    while(pLink)
    {
        pMapInfo=CONTAINING_RECORD(pLink, MAPINFO, link);

        MmUnmapLockedPages(pMapInfo->pvu, pMapInfo->pMdl);
        IoFreeMdl(pMapInfo->pMdl);
        MmUnmapIoSpace(pMapInfo->pvk, pMapInfo->memSize);

        ExFreePool(pMapInfo);

        pLink=PopEntryList(&lstMapInfo);
    }


    //
    //  By default the I/O device is configured incorrectly or the
    // configuration parameters to the driver are incorrect.
    //
    ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;

    //
    // restore the call back routine, thus givinig chance to the
    // user mode application to unload dynamically the driver
    //
    ntStatus = PsSetCreateProcessNotifyRoutine(ProcessCallback, TRUE);

    IoDeleteDevice(DriverObject->DeviceObject);

    RtlInitUnicodeString(&DeviceLinkU, PUSH_SYMLINK_NAME);

    ntStatus=IoDeleteSymbolicLink(&DeviceLinkU);

    if (NT_SUCCESS(ntStatus))
    {
        IoDeleteDevice(DriverObject->DeviceObject);
    }
    else
    {
        DbgPrint("Error: IoDeleteSymbolicLink failed");
    }

    DbgPrint("[Push] <= (PushUnload)");
}
NTSTATUS
VIOSerialPortEvtDeviceD0Exit(
    IN  WDFDEVICE Device,
    IN  WDF_POWER_DEVICE_STATE TargetState
    )
{
    PVIOSERIAL_PORT Port = RawPdoSerialPortGetData(Device)->port;
    PPORT_BUFFER buf;
    PSINGLE_LIST_ENTRY iter;

    UNREFERENCED_PARAMETER(TargetState);

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

    WdfIoQueuePurge(Port->ReadQueue, WDF_NO_EVENT_CALLBACK, WDF_NO_CONTEXT);
    WdfIoQueuePurge(Port->WriteQueue, WDF_NO_EVENT_CALLBACK, WDF_NO_CONTEXT);
    WdfIoQueuePurge(Port->IoctlQueue, WDF_NO_EVENT_CALLBACK, WDF_NO_CONTEXT);

    VIOSerialDisableInterruptQueue(GetInQueue(Port));

    WdfSpinLockAcquire(Port->InBufLock);
    VIOSerialDiscardPortDataLocked(Port);
    Port->InBuf = NULL;
    WdfSpinLockRelease(Port->InBufLock);

    WdfSpinLockAcquire(Port->OutVqLock);
    VIOSerialReclaimConsumedBuffers(Port);
    WdfSpinLockRelease(Port->OutVqLock);

    while (buf = (PPORT_BUFFER)VirtIODeviceDetachUnusedBuf(GetInQueue(Port)))
    {
        VIOSerialFreeBuffer(buf);
    }

    iter = PopEntryList(&Port->WriteBuffersList);
    while (iter != NULL)
    {
        PWRITE_BUFFER_ENTRY entry = CONTAINING_RECORD(iter,
            WRITE_BUFFER_ENTRY, ListEntry);

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

        iter = PopEntryList(&Port->WriteBuffersList);
    };

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "<-- %s\n", __FUNCTION__);

    return STATUS_SUCCESS;
}
Exemplo n.º 4
0
PAPCCONTEXT
DOVERLAPPEDSTRUCTMGR::AllocateApcContext()
/*++

Routine Description:

    Allocates an APC context structure from the pool of available structures.
    
Arguments:

    None

Return Value:

    A pointer the a APC context struct on success else NULL.
    
--*/
{
    PAPCCONTEXT ReturnValue;
    
    EnterCriticalSection(&m_context_free_list_lock);

    ReturnValue = (PAPCCONTEXT)PopEntryList(&m_context_free_list);
    if (ReturnValue){
        ZeroMemory(
            ReturnValue,
            sizeof(APCCONTEXT));
    } //if
    
    LeaveCriticalSection(&m_context_free_list_lock);
    return(ReturnValue);    
}
Exemplo n.º 5
0
PSINGLE_LIST_ENTRY
FASTCALL
ExfInterlockedPopEntryList(
    IN OUT PSINGLE_LIST_ENTRY ListHead,
    IN OUT PKSPIN_LOCK Lock)
{
    BOOLEAN Enable;
    PSINGLE_LIST_ENTRY ListEntry;

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

    /* Pop the first entry from the list */
    ListEntry = PopEntryList(ListHead);
#if DBG
    if (ListEntry)
        ListEntry->Next = (PSINGLE_LIST_ENTRY)0xBADDD0FF;
#endif

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

    /* return the entry */
    return ListEntry;
}
Exemplo n.º 6
0
PVOID
ExAllocateFromPagedLookasideList(
    IN PPAGED_LOOKASIDE_LIST Lookaside
    )

/*++

Routine Description:

    This function removes (pops) the first entry from the specified
    paged lookaside list.

Arguments:

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

Return Value:

    If an entry is removed from the specified lookaside list, then the
    address of the entry is returned as the function value. Otherwise,
    NULL is returned.

--*/

{

    PVOID Entry;

    Lookaside->L.TotalAllocates += 1;

    if (Isx86FeaturePresent(KF_CMPXCHG8B)) {
        if ((Entry = ExInterlockedPopEntrySList(&Lookaside->L.ListHead,
                                                NULL)) == NULL) {

            Lookaside->L.AllocateMisses += 1;
            Entry = (Lookaside->L.Allocate)(Lookaside->L.Type,
                                            Lookaside->L.Size,
                                            Lookaside->L.Tag);
        }

        return Entry;
    }

    ExAcquireFastMutex(&Lookaside->Lock);
    Entry = PopEntryList(&Lookaside->L.ListHead.Next);
    if (Entry == NULL) {
        ExReleaseFastMutex(&Lookaside->Lock);
        Lookaside->L.AllocateMisses += 1;
        Entry = (Lookaside->L.Allocate)(Lookaside->L.Type,
                                        Lookaside->L.Size,
                                        Lookaside->L.Tag);

    } else {
        Lookaside->L.ListHead.Depth -= 1;
        ExReleaseFastMutex(&Lookaside->Lock);
    }

    return Entry;
}
Exemplo n.º 7
0
NTSTATUS
VIOSerialPortEvtDeviceD0Exit(
    IN  WDFDEVICE Device,
    IN  WDF_POWER_DEVICE_STATE TargetState
    )
{
    PVIOSERIAL_PORT Port = RawPdoSerialPortGetData(Device)->port;
    PPORT_BUFFER buf;
    PSINGLE_LIST_ENTRY iter;

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "--> %s TargetState: %d\n",
        __FUNCTION__, TargetState);

    Port->Removed = TRUE;

    VIOSerialDisableInterruptQueue(GetInQueue(Port));

    WdfSpinLockAcquire(Port->InBufLock);
    VIOSerialDiscardPortDataLocked(Port);
    Port->InBuf = NULL;
    WdfSpinLockRelease(Port->InBufLock);

    VIOSerialReclaimConsumedBuffers(Port);

    while (buf = (PPORT_BUFFER)virtqueue_detach_unused_buf(GetInQueue(Port)))
    {
        VIOSerialFreeBuffer(buf);
    }

    iter = PopEntryList(&Port->WriteBuffersList);
    while (iter != NULL)
    {
        PWRITE_BUFFER_ENTRY entry = CONTAINING_RECORD(iter,
            WRITE_BUFFER_ENTRY, ListEntry);

        ExFreePoolWithTag(entry->Buffer, VIOSERIAL_DRIVER_MEMORY_TAG);
        WdfObjectDelete(entry->EntryHandle);

        iter = PopEntryList(&Port->WriteBuffersList);
    };

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "<-- %s\n", __FUNCTION__);

    return STATUS_SUCCESS;
}
Exemplo n.º 8
0
void PCIFreeBars(PVIRTIO_WDF_DRIVER pWdfDriver)
{
    PSINGLE_LIST_ENTRY iter;

    /* unmap IO space and free our BAR descriptors */
    while (iter = PopEntryList(&pWdfDriver->PCIBars)) {
        PVIRTIO_WDF_BAR pBar = CONTAINING_RECORD(iter, VIRTIO_WDF_BAR, ListEntry);
        if (pBar->pBase != NULL && !pBar->bPortSpace) {
            MmUnmapIoSpace(pBar->pBase, pBar->uLength);
        }
        ExFreePoolWithTag(pBar, pWdfDriver->MemoryTag);
    }
}
Exemplo n.º 9
0
VOID
CdUnload(
    __in PDRIVER_OBJECT DriverObject
)
/*++

Routine Description:

    This routine unload routine for CDFS.

Arguments:

    DriverObject - Supplies the driver object for CDFS.

Return Value:

    None.

--*/
{
    PIRP_CONTEXT IrpContext;

    PAGED_CODE();

    UNREFERENCED_PARAMETER( DriverObject );

    //
    // Free any IRP contexts
    //
    while (1) {
        IrpContext = (PIRP_CONTEXT) PopEntryList( &CdData.IrpContextList) ;
        if (IrpContext == NULL) {
            break;
        }
        CdFreePool(&IrpContext);
    }

    IoFreeWorkItem (CdData.CloseItem);
    ExDeleteResourceLite( &CdData.DataResource );
    ObDereferenceObject (CdData.FileSystemDeviceObject);
}
Exemplo n.º 10
0
PSINGLE_LIST_ENTRY
NTAPI
ExInterlockedPopEntryList(
    IN OUT PSINGLE_LIST_ENTRY ListHead,
    IN OUT PKSPIN_LOCK Lock)
{
    BOOLEAN Enable;
    PSINGLE_LIST_ENTRY ListEntry;

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

    /* Pop the first entry from the list */
    ListEntry = PopEntryList(ListHead);

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

    /* Return the entry */
    return ListEntry;
}
Exemplo n.º 11
0
VOID
BalloonLeak(
    IN WDFOBJECT WdfDevice,
    IN size_t num
    )
{
    PPAGE_LIST_ENTRY    pPageListEntry;
    PMDL                pPageMdl;
    PDEVICE_CONTEXT     devCtx = GetDeviceContext(WdfDevice);

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

    num = min(num, PAGE_SIZE/sizeof(PFN_NUMBER));

    for (devCtx->num_pfns = 0; devCtx->num_pfns < num; devCtx->num_pfns++)
    {

        pPageListEntry = (PPAGE_LIST_ENTRY)PopEntryList(&devCtx->PageListHead);

        if (pPageListEntry == NULL)
        {
           TraceEvents(TRACE_LEVEL_WARNING, DBG_HW_ACCESS, "PopEntryList=NULL\n");
           break;
        }

        devCtx->pfns_table[devCtx->num_pfns] = pPageListEntry->PagePfn;
        pPageMdl = pPageListEntry->PageMdl;
        MmFreePagesFromMdl(pPageMdl);
        ExFreePool(pPageMdl);

        ExFreeToNPagedLookasideList(
                                &devCtx->LookAsideList,
                                pPageListEntry
                                );
        devCtx->num_pages--;
    }

    BalloonTellHost(WdfDevice, devCtx->DefVirtQueue);
}
VOID
BalloonLeak(
    IN WDFOBJECT WdfDevice,
    IN size_t num
    )
{
    PDEVICE_CONTEXT ctx = GetDeviceContext(WdfDevice);
    PPAGE_LIST_ENTRY pPageListEntry;
    PMDL pPageMdl;

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

    pPageListEntry = (PPAGE_LIST_ENTRY)PopEntryList(&ctx->PageListHead);
    if (pPageListEntry == NULL)
    {
        TraceEvents(TRACE_LEVEL_WARNING, DBG_HW_ACCESS, "No list entries.\n");
        return;
    }

    pPageMdl = pPageListEntry->PageMdl;

    num = MmGetMdlByteCount(pPageMdl) / PAGE_SIZE;
    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_HW_ACCESS,
        "Deflate balloon with %d pages.\n", num);

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

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

    MmFreePagesFromMdl(pPageMdl);
    ExFreePool(pPageMdl);
    ExFreeToNPagedLookasideList(&ctx->LookAsideList, pPageListEntry);

    BalloonTellHost(WdfDevice, ctx->DefVirtQueue);

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_HW_ACCESS, "<-- %s\n", __FUNCTION__);
}
Exemplo n.º 13
0
PINTERNALOVERLAPPEDSTRUCT
DOVERLAPPEDSTRUCTMGR::PopOverlappedStruct()
/*++

Routine Description:

    Pops a internal overlapped structure off of the free list and initializes
    the structure.

Arguments:

    NONE
Return Value:

    A pointer to a internal overlapped structure on success else NULL

--*/
{
    PINTERNALOVERLAPPEDSTRUCT ReturnValue;

    EnterCriticalSection(&m_overlapped_free_list_lock);

    ReturnValue =
        (PINTERNALOVERLAPPEDSTRUCT)PopEntryList(&m_overlapped_free_list);

    LeaveCriticalSection(&m_overlapped_free_list_lock);

    if (ReturnValue){

        // Init the structure
        ZeroMemory(
            ReturnValue,
            sizeof(INTERNALOVERLAPPEDSTRUCT));
        ReturnValue->iolSignature = STRUCTSIGNATURE;
    } //if

    return(ReturnValue);
}
Exemplo n.º 14
0
NTSTATUS
NTAPI
UserDestroyThreadInfo(struct _ETHREAD *Thread)
{
    PTHREADINFO *ppti;
    PSINGLE_LIST_ENTRY psle;
    PPROCESSINFO ppiCurrent;
    struct _EPROCESS *Process;
    PTHREADINFO ptiCurrent;

    Process = Thread->ThreadsProcess;

    /* Get the Win32 Thread */
    ptiCurrent = PsGetThreadWin32Thread(Thread);

    ASSERT(ptiCurrent);

    TRACE_CH(UserThread,"Destroying pti 0x%p eThread 0x%p\n", ptiCurrent, Thread);

    ptiCurrent->TIF_flags |= TIF_INCLEANUP;
    ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;

    ppiCurrent = ptiCurrent->ppi;
    ASSERT(ppiCurrent);

    IsRemoveAttachThread(ptiCurrent);

    ptiCurrent->TIF_flags |= TIF_DONTATTACHQUEUE;
    ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;

    /* Decrement thread count and check if its 0 */
    ppiCurrent->cThreads--;

    if(ptiCurrent->TIF_flags & TIF_GUITHREADINITIALIZED)
    {
        /* Do now some process cleanup that requires a valid win32 thread */
        if(ptiCurrent->ppi->cThreads == 0)
        {
            /* Check if we have registered the user api hook */
            if(ptiCurrent->ppi == ppiUahServer)
            {
                /* Unregister the api hook */
                UserUnregisterUserApiHook();
            }

            /* Notify logon application to restart shell if needed */
            if(ptiCurrent->pDeskInfo)
            {
                if(ptiCurrent->pDeskInfo->ppiShellProcess == ppiCurrent)
                {
                    DWORD ExitCode = PsGetProcessExitStatus(Process);

                    TRACE_CH(UserProcess, "Shell process is exiting (%lu)\n", ExitCode);

                    UserPostMessage(hwndSAS,
                                    WM_LOGONNOTIFY,
                                    LN_SHELL_EXITED,
                                    ExitCode);

                    ptiCurrent->pDeskInfo->ppiShellProcess = NULL;
                }
            }
        }

        DceFreeThreadDCE(ptiCurrent);
        HOOK_DestroyThreadHooks(Thread);
        EVENT_DestroyThreadEvents(Thread);
        DestroyTimersForThread(ptiCurrent);
        KeSetEvent(ptiCurrent->pEventQueueServer, IO_NO_INCREMENT, FALSE);
        UnregisterThreadHotKeys(ptiCurrent);
        /*
                if (IsListEmpty(&ptiCurrent->WindowListHead))
                {
                   ERR_CH(UserThread,"Thread Window List is Empty!\n");
                }
        */
        co_DestroyThreadWindows(Thread);

        if (ppiCurrent && ppiCurrent->ptiList == ptiCurrent && !ptiCurrent->ptiSibling &&
                ppiCurrent->W32PF_flags & W32PF_CLASSESREGISTERED)
        {
            TRACE_CH(UserThread,"DestroyProcessClasses\n");
            /* no process windows should exist at this point, or the function will assert! */
            DestroyProcessClasses(ppiCurrent);
            ppiCurrent->W32PF_flags &= ~W32PF_CLASSESREGISTERED;
        }

        IntBlockInput(ptiCurrent, FALSE);
        IntCleanupThreadCallbacks(ptiCurrent);

        /* cleanup user object references stack */
        psle = PopEntryList(&ptiCurrent->ReferencesList);
        while (psle)
        {
            PUSER_REFERENCE_ENTRY ref = CONTAINING_RECORD(psle, USER_REFERENCE_ENTRY, Entry);
            TRACE_CH(UserThread,"thread clean: remove reference obj 0x%p\n",ref->obj);
            UserDereferenceObject(ref->obj);

            psle = PopEntryList(&ptiCurrent->ReferencesList);
        }
    }

    /* Find the THREADINFO in the PROCESSINFO's list */
    ppti = &ppiCurrent->ptiList;
    while (*ppti != NULL && *ppti != ptiCurrent)
    {
        ppti = &((*ppti)->ptiSibling);
    }

    /* we must have found it */
    ASSERT(*ppti == ptiCurrent);

    /* Remove it from the list */
    *ppti = ptiCurrent->ptiSibling;

    if (ptiCurrent->KeyboardLayout)
        UserDereferenceObject(ptiCurrent->KeyboardLayout);

    if (gptiForeground == ptiCurrent)
    {
//       IntNotifyWinEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, CHILDID_SELF, 0);
//       IntNotifyWinEvent(EVENT_SYSTEM_FOREGROUND, NULL, OBJID_WINDOW, CHILDID_SELF, 0);

        gptiForeground = NULL;
    }

    // Fixes CORE-6384 & CORE-7030.
    /*    if (ptiLastInput == ptiCurrent)
        {
           if (!ppiCurrent->ptiList)
              ptiLastInput = gptiForeground;
           else
              ptiLastInput = ppiCurrent->ptiList;
           ERR_CH(UserThread,"DTI: ptiLastInput is Cleared!!\n");
        }
    */
    TRACE_CH(UserThread,"Freeing pti 0x%p\n", ptiCurrent);

    /* Free the THREADINFO */
    IntDereferenceThreadInfo(ptiCurrent);

    return STATUS_SUCCESS;
}
Exemplo n.º 15
0
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__);
}
Exemplo n.º 16
0
_Must_inspect_result_
NTSTATUS
FxPkgIo::ResumeProcessingForPower()

/*++

    Routine Description:

    Resumes all PowerManaged queues for automatic I/O processing due to
        a power event that allows I/O to resume.

    Non-PowerManaged queues are left alone.

Arguments:

Return Value:

    NTSTATUS

--*/

{
    KIRQL irql;
    FxIoQueue* queue;
    SINGLE_LIST_ENTRY queueList, *ple;

    DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGIO,
                        "Power resume all queues of WDFDEVICE 0x%p",
                        m_Device->GetHandle());

    queueList.Next = NULL;

    Lock(&irql);

    GetIoQueueListLocked(&queueList, FxIoQueueIteratorListPowerOn);
    //
    // Change the state so that new queues created while we
    // are resuming the existing queues can be in a powered-on state.
    //
    m_PowerStateOn = TRUE;

    //
    // Change the accepting state so that new queues created while we
    // are resuming the existing queues can be accept request.
    //
    m_QueuesAreShuttingDown = FALSE;

    Unlock(irql);

    //
    // We will power-up the queues in two steps. First we will resume
    // the power of all the queues and then we will start dispatching I/Os.
    // This is to avoid a queue being powered up at the begining of the list
    // trying to forward a request to another queue lower in the list that's
    // not powered up yet.
    //
    for(ple = queueList.Next; ple != NULL; ple = ple->Next) {

        queue = FxIoQueue::_FromPowerSListEntry(ple);

        queue->ResumeProcessingForPower();
    }

    for (ple = PopEntryList(&queueList);
            ple != NULL;
            ple = PopEntryList(&queueList)) {

        queue = FxIoQueue::_FromPowerSListEntry(ple);

        queue->StartPowerTransitionOn();

        ple->Next = NULL;

        queue->RELEASE(IO_ITERATOR_POWER_TAG);
    }

    return STATUS_SUCCESS;
}
Exemplo n.º 17
0
_Must_inspect_result_
NTSTATUS
FxPkgIo::StopProcessingForPower(
    __in FxIoStopProcessingForPowerAction Action
)

/*++

    Routine Description:

    Stops all PowerManaged queues automatic I/O processing due to
        a power event that requires I/O to stop.

    This is called on a PASSIVE_LEVEL thread that can block until
    I/O has been stopped, or completed/cancelled.

Arguments:

    Action -

    FxIoStopProcessingForPowerHold:
    the function returns when the driver has acknowledged that it has
    stopped all I/O processing, but may have outstanding "in-flight" requests
    that have not been completed.

    FxIoStopProcessingForPowerPurgeManaged:
    the function returns when all requests from a power managed queue have
    been completed and/or cancelled., and there are no more in-flight requests.

    FxIoStopProcessingForPowerPurgeNonManaged:
    the function returns when all requests from a non-power managed queue have
    been completed and/or cancelled., and there are no more in-flight requests.
    Only called during device-remove.

Return Value:

    NTSTATUS

--*/

{
    KIRQL irql;
    FxIoQueue* queue;
    SINGLE_LIST_ENTRY queueList, *ple;

    DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGIO,
                        "Perform %!FxIoStopProcessingForPowerAction! for all queues of "
                        "WDFDEVICE 0x%p", Action, m_Device->GetHandle());

    queueList.Next = NULL;

    Lock(&irql);
    //
    // Device is moving into low power state. So any new queues
    // created after this point would start off as powered off.
    //
    m_PowerStateOn = FALSE;

    //
    // If queues are shutting down, any new queue created after
    // this point would not accept any requests.
    //
    switch(Action) {
    case FxIoStopProcessingForPowerPurgeManaged:
    case FxIoStopProcessingForPowerPurgeNonManaged:
        m_QueuesAreShuttingDown = TRUE;
        break;
    }

    GetIoQueueListLocked(&queueList, FxIoQueueIteratorListPowerOff);

    Unlock(irql);

    //
    // If the power action is hold then first change the state of all the queues
    // to PowerStartTransition. This will prevent the queues from dispatching
    // new requests before we start asking each queue to stop processing
    // inflight requests.
    //
    if(Action == FxIoStopProcessingForPowerHold) {

        //
        // Walk the list without popping entries because we need to scan
        // the list again.
        //
        for(ple = queueList.Next; ple != NULL; ple = ple->Next) {

            queue = FxIoQueue::_FromPowerSListEntry(ple);

            queue->StartPowerTransitionOff();
        }
    }

    //
    // Ask the queues to stop processing inflight requests.
    //
    for (ple = PopEntryList(&queueList); ple != NULL;
            ple = PopEntryList(&queueList)) {

        queue = FxIoQueue::_FromPowerSListEntry(ple);

        queue->StopProcessingForPower(Action);

        ple->Next = NULL;

        queue->RELEASE(IO_ITERATOR_POWER_TAG);
    }

    return STATUS_SUCCESS;
}
Exemplo n.º 18
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;
}
Exemplo n.º 19
0
/*
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
Exemplo n.º 20
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;
}