_Must_inspect_result_ PVOID FxRequestSystemBuffer::GetBuffer( VOID ) /*++ Routine Description: Returns the system buffer that has been cached away by the call to SetBuffer() Arguments: None Return Value: Valid memory or NULL on error --*/ { FxDevice* pDevice; FxIrp* irp = GetRequest()->GetFxIrp(); WDF_DEVICE_IO_TYPE ioType; switch (irp->GetMajorFunction()) { case IRP_MJ_DEVICE_CONTROL: case IRP_MJ_INTERNAL_DEVICE_CONTROL: return m_Buffer; case IRP_MJ_READ: case IRP_MJ_WRITE: pDevice = FxDevice::GetFxDevice(irp->GetDeviceObject()); ioType = pDevice->GetIoType(); switch (ioType) { case WdfDeviceIoBuffered: return m_Buffer; case WdfDeviceIoDirect: // // FxRequest::GetMemoryObject has already called MmGetSystemAddressForMdlSafe // and returned success, so we know that we can safely call // MmGetSystemAddressForMdlSafe again to get a valid VA pointer. // return Mx::MxGetSystemAddressForMdlSafe(m_Mdl, NormalPagePriority); case WdfDeviceIoNeither: return m_Buffer; default: ASSERT(FALSE); return NULL; } default: ASSERT(FALSE); return NULL; } }
// // This inserts a request into the I/O processing pipeline // _Must_inspect_result_ NTSTATUS FxPkgIo::EnqueueRequest( __in CfxDevice* Device, __inout FxRequest* pRequest ) { NTSTATUS status; FxIoQueue* pQueue; FxIrp* Irp = NULL; FxRequestCompletionState oldState; PFX_DRIVER_GLOBALS FxDriverGlobals = GetDriverGlobals(); SHORT origVerifierFlags = 0; // // Request is owned by the driver, and has a reference count of == 1 // (or > 1 if EvtIoInCallerContext callback took an additional reference), // with a FxPkgIoInProcessRequestComplete callback registered. // ASSERT(pRequest->GetRefCnt() >= 1); Irp = pRequest->GetFxIrp(); DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIO, "WDFREQUEST 0x%p", pRequest->GetObjectHandle()); status = VerifyEnqueueRequestUpdateFlags(FxDriverGlobals, pRequest, &origVerifierFlags); if (!NT_SUCCESS(status)) { return status; } // // Get the associated queue // pQueue = (FxIoQueue*) pRequest->GetInternalContext(); if (NULL == pQueue) { pQueue = m_DispatchTable[Irp->GetMajorFunction()]; if (pQueue == NULL) { // // No queue configured yet, fail request unless the driver is a filter. // if (m_Filter) { goto Forward; } status = STATUS_INVALID_DEVICE_REQUEST; DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIO, "No queue configured for WDFDEVICE 0x%p, " "failing WDFREQUEST 0x%p %!STATUS!", Device->GetHandle(), pRequest->GetObjectHandle(), status); FxVerifierDbgBreakPoint(FxDriverGlobals); // // Return it back to the driver to decide the outcome // goto Error; } } // // If the queue is a default-queue and driver is a filter 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. if (m_Filter && pQueue == m_DefaultQueue && pQueue->IsIoEventHandlerRegistered((WDF_REQUEST_TYPE)Irp->GetMajorFunction()) == FALSE) { // // Default queue doesn't have callback events registered to // handle this request. So forward it down. // goto Forward; } pQueue->AddRef(); // Must add a reference before releasing the callback and its reference pRequest->ADDREF(FXREQUEST_STATE_TAG); // Release the callback oldState = pRequest->SetCompletionState(FxRequestCompletionStateNone); ASSERT(oldState != FxRequestCompletionStateNone); UNREFERENCED_PARAMETER(oldState); status = pQueue->QueueRequestFromForward(pRequest); pQueue->Release(); // // If not successfull, must place the request back // to the state it was in on entry so that the driver // can decide what to do next with it // if (!NT_SUCCESS(status)) { // // If the request comes back to us, it should still // have a reference count of 1 // oldState = pRequest->SetCompletionState(FxRequestCompletionStateIoPkg); ASSERT(oldState == FxRequestCompletionStateNone); UNREFERENCED_PARAMETER(oldState); // // Release the reference count on the request since // the callback will hold the only one that gets // decremented when the request is completed // pRequest->RELEASE(FXREQUEST_STATE_TAG); goto Error; } else { // // On success, can not touch the request since it // may have already been completed // } return status; Forward: // // Cannot send-and-forget a request with a formatted IO context. // if (pRequest->HasContext()) { status = STATUS_INVALID_DEVICE_REQUEST; DoTraceLevelMessage( FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIO, "Cannot send-and-forget WDFREQUEST 0x%p with formatted IO" " context for filter WDFDEVICE 0x%p, %!STATUS!", pRequest->GetObjectHandle(), Device->GetHandle(), status ); FxVerifierDbgBreakPoint(FxDriverGlobals); goto Error; } // // This will skip the current stack location and perform // early dispose on the request. // pRequest->PreProcessSendAndForget(); (VOID)Irp->CallDriver(Device->GetAttachedDevice()); // // This will delete the request and free the memory back // to the device lookaside list. // pRequest->PostProcessSendAndForget(); // // Return a success status in this code path even if the previous call // to send the request to the lower driver failed. The status code returned // by this function should reflect the status of enqueuing the request and // not the status returned by the lower driver. // return STATUS_SUCCESS; Error: // // If not successful, we must set the original verifier flags. // VerifyEnqueueRequestRestoreFlags(FxDriverGlobals, pRequest, origVerifierFlags); return status; }