コード例 #1
0
_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;
    }
}
コード例 #2
0
ファイル: fxiotargetkm.hpp プロジェクト: AntejaVM/WDF
FORCEINLINE
VOID
FxIoContext::ReleaseAndRestore(
    __in FxRequestBase* Request
    )
{
    FxIrp* irp = NULL;
    
    irp = Request->GetSubmitFxIrp();
    
    if (m_RestoreState) {
        irp->SetSystemBuffer(m_OriginalSystemBuffer);
        irp->SetUserBuffer(m_OriginalUserBuffer);
        irp->SetMdlAddress(m_OriginalMdl);
        irp->SetFlags(m_OriginalFlags);
        m_OriginalSystemBuffer = NULL;
        m_OriginalUserBuffer = NULL;
        m_OriginalMdl = NULL;
        m_OriginalFlags = NULL;

        m_RestoreState = FALSE;
    }

    //
    // If there was a buffer present don't free the buffer here so that
    // it can be reused for any request with the same size.
    // Similarly if there was an MDL to be freed unlock the pages but dont free
    // the Mdl so that it can be reused.
    //
    if (m_MdlToFree != NULL) {
        if (m_UnlockPages) {
            MmUnlockPages(m_MdlToFree);
            m_UnlockPages = FALSE;
        }


        m_DriverGlobals = Request->GetDriverGlobals();
    }

    //
    // Release the 2ndary buffer if we have an outstanding reference
    //
    if (m_OtherMemory != NULL) {
        m_OtherMemory->RELEASE(this);
        m_OtherMemory = NULL;
    }

    //
    // Release the other buffer and all __super related fields
    //
    __super::ReleaseAndRestore(Request);
}
コード例 #3
0
ファイル: fxiotargetkm.hpp プロジェクト: AntejaVM/WDF
FORCEINLINE
VOID
FxIoContext::CopyParameters(
    __in FxRequestBase* Request
    )
{
    switch (m_MajorFunction) {
    case IRP_MJ_WRITE:
        m_CompletionParams.Parameters.Write.Length =
            m_CompletionParams.IoStatus.Information;
        break;

    case IRP_MJ_READ:
        m_CompletionParams.Parameters.Read.Length =
            m_CompletionParams.IoStatus.Information;
        break;

    case IRP_MJ_DEVICE_CONTROL:
    case IRP_MJ_INTERNAL_DEVICE_CONTROL:
        m_CompletionParams.Parameters.Ioctl.Output.Length =
            m_CompletionParams.IoStatus.Information;
        break;

    default:
        ASSERT(FALSE);
    }

    if (m_BufferToFree == NULL) {
        return;
    }

    if (m_CopyBackToBuffer) {
        FxIrp* irp = Request->GetSubmitFxIrp();

        if (irp->GetUserBuffer() != NULL) {
            //
            // UserBuffer contains the caller's original output buffer.
            // Copy the results back into the original buffer.
            //
            if (m_MajorFunction == IRP_MJ_DEVICE_CONTROL ||
                m_MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL) {
                ASSERT(irp->GetInformation() <= m_BufferToFreeLength);
            }

            RtlCopyMemory(irp->GetUserBuffer(),
                          m_BufferToFree,
                          irp->GetInformation());
            m_CopyBackToBuffer = FALSE;
        }
    }
}
コード例 #4
0
_Must_inspect_result_
NTSTATUS
FxIoTarget::FormatIoRequest(
    __inout FxRequestBase* Request,
    __in UCHAR MajorCode,
    __in FxRequestBuffer* IoBuffer,
    __in_opt PLONGLONG DeviceOffset,
    __in_opt FxFileObject* FileObject
    )
{
    FxIoContext* pContext;
    NTSTATUS status;
    ULONG ioLength;
    FxIrp* irp;
    PVOID buffer;

    UNREFERENCED_PARAMETER(FileObject);
    
    ASSERT(MajorCode == IRP_MJ_WRITE || MajorCode == IRP_MJ_READ);

    status = Request->ValidateTarget(this);
    if (!NT_SUCCESS(status)) {
        return status;
    }

    if (Request->HasContextType(FX_RCT_IO)) {
        pContext = (FxIoContext*) Request->GetContext();
    }
    else {
        pContext = new(GetDriverGlobals()) FxIoContext();
        if (pContext == NULL) {
            DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
                                "could not allocate context for request");

            return STATUS_INSUFFICIENT_RESOURCES;
        }

        //
        // Since we can error out and return, remember the allocation before
        // we do anything so we can free it later.
        //
        Request->SetContext(pContext);
    }

    //
    // Save away any references to IFxMemory pointers that are passed
    //
    pContext->StoreAndReferenceMemory(IoBuffer);

    //
    // Setup irp stack
    //
    irp = Request->GetSubmitFxIrp();
    irp->ClearNextStackLocation();

    //
    // copy File object and flags
    //
    CopyFileObjectAndFlags(Request);

    irp->SetMajorFunction(MajorCode);
    pContext->m_MajorFunction = MajorCode;

    ioLength = IoBuffer->GetBufferLength();

    status = IoBuffer->GetBuffer(&buffer);
    if (!NT_SUCCESS(status)) {
        DoTraceLevelMessage(
            GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
            "Could not retrieve i/o buffer, %!STATUS!",
            status);
        goto exit;
    }

    //
    // Since we don't support buffer transformations (buffered->Direct->Neither)
    // we are analogous to "Neither" method in KMDF
    // in which case we just set the Irp buffer to the buffer that is passed in
    //
    if (IRP_MJ_READ == MajorCode) {
        pContext->SwapIrpBuffer(Request,
                                0,
                                NULL,
                                ioLength,
                                buffer);
        
        irp->GetIoIrp()->SetReadParametersForNextStackLocation(
                    ioLength,
                    DeviceOffset,
                    0
                    );
    }
    else if (IRP_MJ_WRITE == MajorCode) {
        pContext->SwapIrpBuffer(Request,
                                ioLength,
                                buffer,
                                0,
                                NULL);
        irp->GetIoIrp()->SetWriteParametersForNextStackLocation(
                    ioLength,
                    DeviceOffset,
                    0
                    );
    }
    /*
    else if (WdfRequestQueryInformation == RequestType)
    {
        pContext->SwapIrpBuffer(pRequest,
                                0,
                                NULL,
                                ioLength,
                                buffer);
    }
    else if (WdfRequestSetInformation == RequestType)
    {
        pContext->SwapIrpBuffer(pRequest,
                                ioLength,
                                buffer,
                                0,
                                NULL);
    }
    */
    else {
        pContext->SwapIrpBuffer(Request, 0, NULL, 0, NULL);
    }

exit:
    
    if (NT_SUCCESS(status)) {
        Request->VerifierSetFormatted();
    }
    else {
        Request->ContextReleaseAndRestore();
    }

    return status;
}
コード例 #5
0
_Must_inspect_result_
NTSTATUS
FxIoTarget::FormatIoctlRequest(
    __in FxRequestBase* Request,
    __in ULONG Ioctl,
    __in BOOLEAN Internal,
    __in FxRequestBuffer* InputBuffer,
    __in FxRequestBuffer* OutputBuffer,
    __in_opt FxFileObject* FileObject
    )
{
    FxIoContext* pContext;
    NTSTATUS status;
    ULONG inLength, outLength;
    FxIrp* irp;
    PVOID inputBuffer;
    PVOID outputBuffer;

    UNREFERENCED_PARAMETER(FileObject);

    irp = Request->GetSubmitFxIrp();

    status = Request->ValidateTarget(this);
    if (!NT_SUCCESS(status)) {
        return status;
    }

    if (Request->HasContextType(FX_RCT_IO)) {
        pContext = (FxIoContext*) Request->GetContext();
    }
    else {
        pContext = new(GetDriverGlobals()) FxIoContext();
        if (pContext == NULL) {
            DoTraceLevelMessage(
                GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
                "Could not allocate context for request");

            return STATUS_INSUFFICIENT_RESOURCES;
        }

        Request->SetContext(pContext);
    }

    inLength = InputBuffer->GetBufferLength();
    outLength = OutputBuffer->GetBufferLength();

    //
    // Capture irp buffers in context and set driver-provided buffers in the irp
    //
    status = InputBuffer->GetBuffer(&inputBuffer);
    if (!NT_SUCCESS(status)) {
        DoTraceLevelMessage(
            GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
            "Could not retrieve input buffer, %!STATUS!",
            status);
        goto exit;
    }

    status = OutputBuffer->GetBuffer(&outputBuffer);
    if (!NT_SUCCESS(status)) {
        DoTraceLevelMessage(
            GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
            "Could not retrieve output buffer, %!STATUS!",
            status);
        goto exit;
    }

    //
    // Save away any references to IFxMemory pointers that are passed
    //
    pContext->StoreAndReferenceMemory(InputBuffer);
    pContext->StoreAndReferenceOtherMemory(OutputBuffer);
    pContext->m_MajorFunction = IRP_MJ_DEVICE_CONTROL;

    //
    // Format next stack location
    //
    irp->ClearNextStackLocation();
    irp->SetMajorFunction(IRP_MJ_DEVICE_CONTROL);

    //
    // copy File object and flags 
    //
    CopyFileObjectAndFlags(Request);

    irp->GetIoIrp()->SetDeviceIoControlParametersForNextStackLocation(
                    Ioctl,
                    inLength,
                    outLength
                    );

    pContext->SwapIrpBuffer(Request,
                            InputBuffer->GetBufferLength(),
                            inputBuffer,
                            OutputBuffer->GetBufferLength(),
                            outputBuffer);
exit:
    
    if (NT_SUCCESS(status)) {
        Request->VerifierSetFormatted();
    }
    else {
        Request->ContextReleaseAndRestore();
    }

    return status;;
}
コード例 #6
0
ファイル: fxpkgio.cpp プロジェクト: AntejaVM/WDF
//
// 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;
}