VOID
FxInterrupt::WorkItemHandler(
    VOID
    )
{
    ASSERT(m_EvtInterruptWorkItem != NULL );
    
    FX_TRACK_DRIVER(GetDriverGlobals());

    //
    // Call the drivers registered WorkItemForIsr event callback
    //
    if (m_CallbackLock != NULL) {
        KIRQL irql = 0;

        m_CallbackLock->Lock(&irql);
        
        FxPerfTraceWorkItem(&m_EvtInterruptWorkItem);
        m_EvtInterruptWorkItem(GetHandle(), m_Device->GetHandle());
        m_CallbackLock->Unlock(irql);
    }
    else {
        FxPerfTraceWorkItem(&m_EvtInterruptWorkItem);
        m_EvtInterruptWorkItem(GetHandle(), m_Device->GetHandle());
    }

    return;
}
VOID
FxInterrupt::DpcHandler(
    __in_opt PVOID SystemArgument1,
    __in_opt PVOID SystemArgument2
    )
{
    UNREFERENCED_PARAMETER(SystemArgument1);
    UNREFERENCED_PARAMETER(SystemArgument2);

    ASSERT(m_EvtInterruptDpc != NULL);
    
    FX_TRACK_DRIVER(GetDriverGlobals());

    //
    // Call the drivers registered DpcForIsr event callback
    //
    if (m_CallbackLock != NULL) {
        KIRQL irql = 0;

        m_CallbackLock->Lock(&irql);
        m_EvtInterruptDpc(GetHandle(), m_Device->GetHandle());
        m_CallbackLock->Unlock(irql);
    }
    else {
        m_EvtInterruptDpc(GetHandle(), m_Device->GetHandle());
    }

    return;
}
VOID
FxDpc::DpcHandler(
    __in PKDPC Dpc,
    __in PVOID SystemArgument1,
    __in PVOID SystemArgument2
    )
{
    UNREFERENCED_PARAMETER(Dpc);
    UNREFERENCED_PARAMETER(SystemArgument1);
    UNREFERENCED_PARAMETER(SystemArgument2);

    FX_TRACK_DRIVER(GetDriverGlobals());
    
    if (m_Callback != NULL) {

        FxPerfTraceDpc(&m_Callback);

        if (m_CallbackLock != NULL) {
            KIRQL irql = 0;

            m_CallbackLock->Lock(&irql);
            m_Callback((WDFDPC)(this->GetObjectHandle()));
            m_CallbackLock->Unlock(irql);
        }
        else {
           m_Callback((WDFDPC)(this->GetObjectHandle()));
        }
    }
}
VOID
FxWorkItem::WorkItemHandler(
    VOID
    )
{
    KIRQL irql;
    
    FX_TRACK_DRIVER(GetDriverGlobals());

    Lock(&irql);

    //
    // Mark the workitem as no longer enqueued and completed
    //
    // The handler is allowed to re-enqueue, so mark it before the callback
    //
    m_Enqueued = FALSE;

    m_WorkItemRunningCount++;
    
    Unlock(irql);

    if (m_CallbackLock != NULL) {
        m_CallbackLock->Lock(&irql);
#if FX_IS_KERNEL_MODE
        FxPerfTraceWorkItem(&m_Callback);
#endif
        m_Callback(GetHandle());
        m_CallbackLock->Unlock(irql);
    }
    else {
#if FX_IS_KERNEL_MODE
        FxPerfTraceWorkItem(&m_Callback);
#endif
        m_Callback(GetHandle());
    }

    Lock(&irql);

    m_WorkItemRunningCount--;

    //
    // The workitem can be re-enqueued by the drivers
    // work item handler routine. We can't set the work
    // item completed event until we are sure there are
    // no outstanding work items.
    //

    if (m_WorkItemRunningCount == 0L && m_Enqueued == FALSE) {
        m_WorkItemCompleted.Set();
    }

    Unlock(irql);
}
예제 #5
0
파일: fxpkgio.cpp 프로젝트: AntejaVM/WDF
_Must_inspect_result_
NTSTATUS
FxPkgIo::Dispatch(
    __inout MdIrp Irp
)
{
    FxIrp fxIrp(Irp);
    FX_TRACK_DRIVER(GetDriverGlobals());

    DoTraceLevelMessage(
        GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGIO,
        "WDFDEVICE 0x%p !devobj 0x%p %!IRPMJ!, IRP_MN %x, IRP 0x%p",
        m_Device->GetHandle(), m_Device->GetDeviceObject(),
        fxIrp.GetMajorFunction(),
        fxIrp.GetMinorFunction(), Irp);

    return DispatchStep1(Irp, m_DynamicDispatchInfoListHead.Flink);
}
예제 #6
0
NTSTATUS
WDFEXPORT(WdfDeviceWdmDispatchIrpToIoQueue)(
    __in
    PWDF_DRIVER_GLOBALS DriverGlobals,
    __in
    WDFDEVICE Device,
    __in
    MdIrp Irp,
    __in
    WDFQUEUE Queue,
    __in
    ULONG Flags
    )
{
    FxIoQueue           *queue;
    FxDevice            *device;
    PFX_DRIVER_GLOBALS  fxDriverGlobals;
    PIO_STACK_LOCATION  stack;
    NTSTATUS            status;
    FxIoInCallerContext* ioInCallerCtx;
    
    queue = NULL;
    ioInCallerCtx = NULL;
    
    FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
                         Device,
                         FX_TYPE_DEVICE,
                         (PVOID*) &device);

    fxDriverGlobals = device->GetDriverGlobals();    
    FX_TRACK_DRIVER(fxDriverGlobals);
    
    FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
                         Queue,
                         FX_TYPE_QUEUE,
                         (PVOID*)&queue);
    
    FxPointerNotNull(fxDriverGlobals, Irp);

    //
    // If the caller is a preprocess routine, the contract for this DDI is just like IoCallDriver.  
    // The caller sets up their stack location and then the DDI advances to the next stack
    // location. This means that the caller either has to call IoSkipCurrentIrpStackLocation
    // or IoCopyCurrentIrpStackLocationToNext before calling this DDI.
    //
    if (Flags & WDF_DISPATCH_IRP_TO_IO_QUEUE_PREPROCESSED_IRP) {
        IoSetNextIrpStackLocation(Irp);
    }

    //
    // Verifier checks.
    //
    status = VerifyWdfDeviceWdmDispatchIrpToIoQueue(fxDriverGlobals, 
                                                    device, 
                                                    Irp, 
                                                    queue, 
                                                    Flags);
    if(!NT_SUCCESS(status)) {
        Irp->IoStatus.Status = status;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);

        return status;
    }
    
    //
    // Adjust stack if IRP needs to be forwarded to parent device.
    //
    if (device->m_ParentDevice == queue->GetDevice()) {
        IoCopyCurrentIrpStackLocationToNext(Irp);   
        IoSetNextIrpStackLocation(Irp);    

        //
        // From now on use new device. 
        //
        device = device->m_ParentDevice;
        
        //
        // Save a pointer to the device object for this request so that it can
        // be used later in completion.
        //
        stack = IoGetCurrentIrpStackLocation(Irp);
        stack->DeviceObject = device->GetDeviceObject();
    }
    
    //
    // Get in-context caller callback if required.
    //
    if (Flags & WDF_DISPATCH_IRP_TO_IO_QUEUE_INVOKE_INCALLERCTX_CALLBACK) {
        ioInCallerCtx = device->m_PkgIo->GetIoInCallerContextCallback(
                                                queue->GetCxDeviceInfo());
    }
    
    //
    // DispatchStep2 will convert the IRP into a WDFREQUEST, queue it and if 
    // possible dispatch the request to the driver.
    //
    return device->m_PkgIo->DispatchStep2(Irp, ioInCallerCtx, queue);    
}
VOID
FxEventQueue::EventQueueWorker(
    VOID
    )
/*++

Routine Description:
    This is the work item that attempts to run the queue state machine on
    the special power thread. 


--*/
{
    FxPostProcessInfo info;
    KIRQL irql;
    FxPkgPnp* pPkgPnp;
    
#if (FX_CORE_MODE==FX_CORE_KERNEL_MODE)
    FX_TRACK_DRIVER(m_PkgPnp->GetDriverGlobals());
#endif

    //
    // Cache away m_PkgPnp while we know we still have a valid object.  Once
    // we Unlock() after the worker routine, the object could be gone until
    // the worker routine set a flag postponing deletion.
    //
    pPkgPnp = m_PkgPnp;

    Lock(&irql);

    ASSERT(m_QueueFlags & FxEventQueueFlagWorkItemQueued);

    //
    // Clear the queued flag, so that it's clear that the work item can
    // be safely re-enqueued.
    //
    m_QueueFlags &= ~FxEventQueueFlagWorkItemQueued;

    //
    // We should only see this count rise to a small number (like 10 or so).
    //
    ASSERT(m_WorkItemRunningCount < 0xFF);
    m_WorkItemRunningCount++;

    Unlock(irql);

    //
    // Call the function that will actually run the state machine.
    //
    m_EventWorker(m_PkgPnp, &info, m_EventWorkerContext);

    Lock(&irql);
    m_WorkItemRunningCount--;
    GetFinishedState(&info);
    Unlock(irql);

    //
    // NOTE:  There is no need to use a reference count to keep this event queue
    //        (and the containing state machine) alive.  Instead, the thread
    //        which wants to delete the state machine must wait for this work
    //        item to exit.  If there was a reference to release, we would have
    //        a race between Unlock()ing and releasing the reference if the state
    //        machine moved into the finished state and deletes the device after
    //        we dropped the lock, but before we released the reference.
    //
    //        This is important in that the device deletion can trigger
    //        DriverUnload to run before the release executes.  DriverUnload
    //        frees the IFR buffer.  If this potential release logs something to
    //        the IFR, you would bugcheck.  Since it is impossible to defensively
    //        prevent all destructors from logging to the IFR, we can't use a
    //        ref count here to keep the queue alive.
    //

    //
    // If Evaluate needs to use pPkgPnp, then the call to the worker routine
    // above made sure that pPkgPnp has not yet been freed.
    //
    info.Evaluate(pPkgPnp);
}