Ejemplo n.º 1
0
VOID
FxPkgIo::AddIoQueue(
    __inout FxIoQueue* IoQueue
)
{
    PLIST_ENTRY         listHead, le;
    FxIoQueue*          queue;
    KIRQL               irql;
    FxIoQueueNode*      listNode;
    CCHAR               queueIndex, curIndex;

    listHead = &m_IoQueueListHead;
    queueIndex = FxDevice::GetCxDriverIndex(IoQueue->GetCxDeviceInfo());
    Lock(&irql);

    ASSERT(IoQueue->m_IoPkgListNode.IsNodeType(FxIoQueueNodeTypeQueue));

    //
    // Insert new queue in sorted list; search from last to first.
    //
    for (le = listHead->Blink; le != listHead; le = le->Blink) {
        //
        // Skip any nodes that are not queues. They can be bookmarks for
        // in-progress flush operations.
        //
        listNode = FxIoQueueNode::_FromListEntry(le);
        if (listNode->IsNodeType(FxIoQueueNodeTypeQueue) == FALSE) {
            continue;
        }

        //
        // Get current queue's driver index.
        //
        queue = FxIoQueue::_FromIoPkgListEntry(le);
        curIndex = FxDevice::GetCxDriverIndex(queue->GetCxDeviceInfo());
        //
        // Queues are inserted in order at the end of its allowed range.
        //
        if (curIndex < queueIndex || curIndex == queueIndex) {
            break;
        }
    }

    InsertHeadList(le, &IoQueue->m_IoPkgListNode.m_ListEntry);

    if (m_PowerStateOn) {
        IoQueue->SetPowerState(FxIoQueuePowerOn);
    } else {
        IoQueue->SetPowerState(FxIoQueuePowerOff);
        if (m_QueuesAreShuttingDown) {
            // Clear accept requests
            IoQueue->SetStateForShutdown();
        }
    }

    Unlock(irql);

    return;
}
Ejemplo n.º 2
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
FxIoTargetSelf::Send(
    _In_ MdIrp Irp
    )
/*++    
Routine Description:
    send an MdIrp to the Self IO Target.

Arguments:

    MdIrp for IRP_MJ_READ, IRP_MJ_WRITE, or IRP_MJ_DEVICE_CONTROL

Returns:

    VOID
 
Implementation Note: 

    Function body inspired by WdfDeviceWdmDispatchIrpToIoQueue API.
 
--*/
{
    FxIrp irp(Irp);
    FxIoQueue* queue;
    NTSTATUS status;
    UCHAR majorFunction;
    FxIoInCallerContext* ioInCallerCtx;

#if (FX_CORE_MODE == FX_CORE_USER_MODE)

    //
    // Prepare the request to forward to the inteternal target. 
    //
    (static_cast<IWudfIoIrp2*>(Irp))->PrepareToForwardToSelf();

#else
    //
    // Set Next Stack Location
    //
    irp.SetNextIrpStackLocation();
    
    //
    // Set Device Object.
    //
    irp.SetCurrentDeviceObject(m_Device->GetDeviceObject());
#endif

    majorFunction = irp.GetMajorFunction();

    //
    // Retrieve Queue
    //
    queue = GetDispatchQueue(majorFunction);

    if (queue == NULL) {
        DoTraceLevelMessage(
            GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
            "Send WDFIOTARGET %p, No Dispatch Queue Found for Major Function %d",
            GetObjectHandle(), majorFunction);
        status = STATUS_INVALID_DEVICE_STATE;
        goto Fail;
    }
  
    //
    // Only read/writes/ctrls/internal_ctrls IRPs are allowed to be sent to 
    // Self IO Target
    //
    if (m_Device->GetDispatchPackage(majorFunction) != m_Device->m_PkgIo) {
        status = STATUS_INVALID_PARAMETER;
        DoTraceLevelMessage(
                GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
                "Only Read/Write/Control/Internal-Control IRPs can be "
                "forwarded to Self IO Target 0x%p, %!IRPMJ!, "
                "IRP_MN %x, Device 0x%p, %!STATUS!",
                 GetHandle(), majorFunction, irp.GetMinorFunction(), 
                 m_Device->GetObjectHandle(), status);
        FxVerifierDbgBreakPoint(GetDriverGlobals());
        goto Fail;
    }

    //
    // Retrieve the InContextCallback function
    //
    ioInCallerCtx = m_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.
    // If a failure occurs, DispatchStep2 completes teh Irp 
    //
    (VOID) m_Device->m_PkgIo->DispatchStep2(Irp, ioInCallerCtx, queue);    
    return;

Fail:

    irp.SetStatus(status);
    irp.SetInformation(0);
    irp.CompleteRequest(IO_NO_INCREMENT);

    return;
}
Ejemplo n.º 4
0
FORCEINLINE
_Must_inspect_result_
NTSTATUS
__fastcall
FxPkgIo::DispatchStep1(
    __inout MdIrp       Irp,
    __in    WDFCONTEXT  DispatchContext
)
/*++

    Routine Description:

    Checks for any registered dynamic dispatch callbacks that handles this type of request, else
    selects the default queue based on the IRP's major code.

Arguments:

    Irp - WDM request.

    DispatchContext -  Is the next FxIrpDynamicDispatchInfo element.

Return Value:

    Irp's status.

--*/

{
    NTSTATUS                status;
    FxIrp                   fxIrp(Irp);

    ASSERT(((UCHAR)DispatchContext & FX_IN_DISPATCH_CALLBACK) == 0);

    ASSERT(fxIrp.GetMajorFunction() <= IRP_MJ_MAXIMUM_FUNCTION);

    //
    // Look for I/O dynamic dispatch callbacks.
    //
    if ((PLIST_ENTRY)DispatchContext != &m_DynamicDispatchInfoListHead) {
        int     index;
        index = FxIrpDynamicDispatchInfo::Mj2Index(fxIrp.GetMajorFunction());

        //
        // Only read/writes/ctrls/internal_ctrls IRPs are allowed, i.e., request cannot
        // IRP type in its callback.
        //
        if (index >= (int)FxIrpDynamicDispatchInfo::DynamicDispatchMax) {
            status = STATUS_INVALID_PARAMETER;
            DoTraceLevelMessage(
                GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIO,
                "Driver cannot change the IRP type in its dispatch "
                "callback Irp 0x%p, %!IRPMJ!, IRP_MN %x, Device 0x%p, "
                "%!STATUS!",
                Irp, fxIrp.GetMajorFunction(), fxIrp.GetMinorFunction(),
                m_Device->GetHandle(), status);
            FxVerifierDbgBreakPoint(GetDriverGlobals());
            goto CompleteIrp;
        }

        //
        // Verifier checks.
        //
        status = VerifyDispatchContext(GetDriverGlobals(), DispatchContext);
        if( !NT_SUCCESS(status)) {
            goto CompleteIrp;
        }

        do {
            FxIrpDynamicDispatchInfo* info;

            info = CONTAINING_RECORD(DispatchContext,
                                     FxIrpDynamicDispatchInfo,
                                     ListEntry);
            //
            // Advance to next node.
            //
            DispatchContext = (WDFCONTEXT)(((PLIST_ENTRY)DispatchContext)->Flink);
            ASSERT(((UCHAR)DispatchContext & FX_IN_DISPATCH_CALLBACK) == 0);

            ASSERT(fxIrp.GetMajorFunction() == IRP_MJ_READ ||
                   fxIrp.GetMajorFunction() == IRP_MJ_WRITE ||
                   fxIrp.GetMajorFunction() == IRP_MJ_DEVICE_CONTROL ||
                   fxIrp.GetMajorFunction() == IRP_MJ_INTERNAL_DEVICE_CONTROL);

            //
            // If registered, invoke dispatch callback for this major function.
            //
            ASSERT(index < (int)FxIrpDynamicDispatchInfo::DynamicDispatchMax);
            if (NULL != info->Dispatch[index].EvtDeviceDynamicDispatch) {
                return info->Dispatch[index].EvtDeviceDynamicDispatch(
                           m_Device->GetHandle(),
                           fxIrp.GetMajorFunction(),
                           fxIrp.GetMinorFunction(),
                           fxIrp.GetParameterIoctlCode(),
                           info->Dispatch[index].DriverContext,
                           reinterpret_cast<PIRP> (fxIrp.GetIrp()),
                           (WDFCONTEXT)((ULONG_PTR)DispatchContext |
                                        FX_IN_DISPATCH_CALLBACK)
                       );
            }
        } while ((PLIST_ENTRY)DispatchContext !=
                 &m_DynamicDispatchInfoListHead);
    }

    //
    // Only now push these local variables on the stack, this is to keep the
    // stack from growing unnecessarily in the dynamic dispatch path above.
    //
    FxIoQueue*              queue;
    FxIoInCallerContext*    ioInCallerCtx;

    //
    // Get the queue from the dispatch-table
    //
    queue = m_DispatchTable[fxIrp.GetMajorFunction()];
    if (queue == NULL) {
        ioInCallerCtx = GetIoInCallerContextCallback(NULL);
        if (ioInCallerCtx->m_Method == NULL) {
            //
            // No queue configured yet, fail request unless the driver is a filter.
            //
            if (m_Filter) {
                goto Forward;
            }

            status = STATUS_INVALID_DEVICE_REQUEST;
            DoTraceLevelMessage(
                GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIO,
                "No queue configured for WDFDEVICE 0x%p, failing IRP 0x%p,"
                " %!STATUS!",
                m_Device->GetHandle(), Irp, status);

            goto CompleteIrp;
        }
    }
    else {
        ioInCallerCtx = GetIoInCallerContextCallback(queue->GetCxDeviceInfo());
    }

    //
    // If the driver is filter and queue is a default-queue then before
    // calling the queue, we should make sure the queue can dispatch
    // requests to the driver. If the queue cannot dispatch request,
    // we should forward it down to the lower driver ourself.
    // This is to cover the scenario where the driver has registered only
    // type specific handler and expect the framework to auto-forward other
    // requests.
    //
    if (m_Filter &&
            ioInCallerCtx->m_Method == NULL &&
            queue == m_DefaultQueue &&
            queue->IsIoEventHandlerRegistered((WDF_REQUEST_TYPE)fxIrp.GetMajorFunction()) == FALSE) {
        //
        // Default queue doesn't have callback events registered to
        // handle this request. So forward it down.
        //
        goto Forward;
    }

    //
    // Finally queue request.
    //
    return DispatchStep2(Irp, ioInCallerCtx, queue);

Forward:

    fxIrp.SkipCurrentIrpStackLocation();
    return fxIrp.CallDriver(m_Device->GetAttachedDevice());

CompleteIrp:

    fxIrp.SetStatus(status);
    fxIrp.SetInformation(0);
    fxIrp.CompleteRequest(IO_NO_INCREMENT);

    return status;
}