/*++ Copyright (c) Microsoft Corporation Module Name: FxRequest.hpp Abstract: This is the request object for the driver frameworks. The request object wraps the IRP, containing persistent information required by the driver frameworks. Author: Environment: Both kernel and user mode Revision History: --*/ #ifndef _FXREQUEST_H_ #define _FXREQUEST_H_ // // Magic number to differentiate between default value and caller provided one // #define USE_DEFAULT_PRIORITY_BOOST ((CHAR) 0x7F) // // This tag is used to set and clear the completion callback state as the // ownership of the request transfers from I/O pkg-to-queue or queue-to-queue. // #define FXREQUEST_STATE_TAG (PVOID) 'tatS' // // This tag is used when the request is added and removed from FxIrpQueue. // #define FXREQUEST_QUEUE_TAG (PVOID) 'ueuQ' // // This tag is used to take a reference in the completion path. // #define FXREQUEST_COMPLETE_TAG (PVOID) 'pmoC' // // Use this tag when you want to temporarily hold the object from // disappearing between unlock and lock operation. // #define FXREQUEST_HOLD_TAG (PVOID) 'dloH' // // This tag is used to take a reference in the completion path. // #define FXREQUEST_FWDPRG_TAG (PVOID) 'PdwF' // // This tag is used to take a reference in the completion path for driver created // requests that support completion operations. // #define FXREQUEST_DCRC_TAG (PVOID) 'CRCD' extern "C" { #if defined(EVENT_TRACING) #include "FxRequest.hpp.tmh" #endif } #if (FX_CORE_MODE == FX_CORE_USER_MODE) #define WDF_REQUEST_SEND_OPTION_IMPERSONATION_FLAGS \ (WDF_REQUEST_SEND_OPTION_IMPERSONATE_CLIENT | \ WDF_REQUEST_SEND_OPTION_IMPERSONATION_IGNORE_FAILURE) #define FxIrpStackFlagsFromSendFlags(sendFlags) \ ((WUDFX_IRP_STACK_FLAGS) \ ((sendFlags) & WDF_REQUEST_SEND_OPTION_IMPERSONATION_FLAGS)) #endif typedef NTSTATUS (*PFN_FX_QUEUE_REQUEST_COMPLETE) ( __in FxRequest* Request, __in FxIoQueue* Queue, __in_opt WDFCONTEXT Context ); struct FxRequestSystemBuffer : public IFxMemory { friend FxRequest; public: FxRequestSystemBuffer( VOID ) { m_Buffer = NULL; } _Must_inspect_result_ virtual PVOID GetBuffer( VOID ); virtual size_t GetBufferSize( VOID ); _Must_inspect_result_ virtual PMDL GetMdl( VOID ); virtual WDFMEMORY GetHandle( VOID ); virtual USHORT GetFlags( VOID ); virtual PFX_DRIVER_GLOBALS GetDriverGlobals( VOID ); virtual ULONG AddRef( __in PVOID Tag, __in LONG Line, __in_opt PSTR File ); virtual ULONG Release( __in PVOID Tag, __in LONG Line, __in_opt PSTR File ); virtual VOID Delete( VOID ); __inline BOOLEAN IsBufferSet( VOID ) { return m_Buffer != NULL ? TRUE : FALSE; } __inline VOID ClearBufferMdl( VOID ) { m_Buffer = NULL; m_Mdl = NULL; } protected: __inline VOID SetBuffer( PVOID Buffer ) { ASSERT(m_Buffer == NULL); m_Buffer = Buffer; } __inline VOID SetMdl( PMDL Mdl ) { ASSERT(m_Mdl == NULL); m_Mdl = Mdl; } FxRequest* GetRequest( VOID ); protected: // // The current irp stack location indicates which type to use // // The buffer / MDL is cached away as a copy instead of using the PIRP values // directly because we want to capture the current state of the irp when // returning the WDFMEMORY. For instance, if used the PIRP value directly // when implementing GetBuffer(), we are subject to the PIRP being formatted // for the next stack location and changing the buffer pointer, or worse, // changing the MDL value and have the resulting MDL not be mapped, and then // a call to MmGetSystemAddressForMdlSafe can return NULL, and thus GetBuffer(), // return NULL, which would violate the contract for GetBuffer(). // // As an example, let's // 1) the WDFREQUEST/PIRP comes in as a read on a direct io device object, // so Irp->MdlAddress = // 2) This WDFMEMORY will return in GetBuffer() // 3) the WDFREQUEST is formatted for an IOCTL which is METHOD_OUT_DIRECT // with a new output buffer. Irp->MdlAddres = now. // 4) This same WDFMEMORY will now return in GetBuffer() // // Essentialy, formatting the WDFREQUEST causes unintended side affects for // the WDFMEMORYs it returns. To eliminate those side affects, we capture // the original buffer. // union { PVOID m_Buffer; PMDL m_Mdl; }; }; struct FxRequestOutputBuffer : public IFxMemory { friend FxRequest; public: FxRequestOutputBuffer( VOID ) { m_Buffer = NULL; } virtual PVOID GetBuffer( VOID ); virtual size_t GetBufferSize( VOID ); _Must_inspect_result_ virtual PMDL GetMdl( VOID ); virtual WDFMEMORY GetHandle( VOID ); virtual USHORT GetFlags( VOID ); virtual PFX_DRIVER_GLOBALS GetDriverGlobals( VOID ); virtual ULONG AddRef( __in PVOID Tag, __in LONG Line, __in_opt PSTR File ); virtual ULONG Release( __in PVOID Tag, __in LONG Line, __in_opt PSTR File ); virtual VOID Delete( VOID ); __inline BOOLEAN IsBufferSet( VOID ) { return m_Buffer != NULL ? TRUE : FALSE; } __inline VOID ClearBufferMdl( VOID ) { m_Buffer = NULL; m_Mdl = NULL; } protected: __inline VOID SetBuffer( __in PVOID Buffer ) { ASSERT(m_Buffer == NULL); m_Buffer = Buffer; } __inline VOID SetMdl( __in PMDL Mdl ) { ASSERT(m_Mdl == NULL); m_Mdl = Mdl; } FxRequest* GetRequest( VOID ); protected: // // The current irp stack location indicates which type to use // // See comments in FxRequestSystemBuffer's union for why we capture the // values vs using them directly from the PIRP. // union { PVOID m_Buffer; PMDL m_Mdl; }; }; // begin_wpp enum enum FxListEntryNames { FxListEntryNameCleanup = 0, // this entry is used when the request is owned by the framework FxListEntryQueueOwned, // this entry is used when the request is presented to the driver FxListEntryDriverOwned, // this entry is used for forward progress FxListEntryForwardProgress }; enum FxRequestPowerStopState { FxRequestPowerStopUnknown = 0, // Initial state // Set when the driver calls WdfRequestStopAcknowledge FxRequestPowerStopAcknowledged = 0x1, // Set when the driver WdfRequestStopAcknowledge with requeue option FxRequestPowerStopAcknowledgedWithRequeue = 0x2, }; // end_wpp class FxRequest : public FxRequestBase { friend FxIoTarget; friend FxIoQueue; friend FxRequestMemory; friend FxRequestOutputBuffer; friend FxRequestSystemBuffer; friend VOID GetTriageInfo(VOID); protected: // // This field points to the queue that the request is currently // associated with. // FxIoQueue* m_IoQueue; FxRequestSystemBuffer m_SystemBuffer; FxRequestOutputBuffer m_OutputBuffer; // // This is for use by the owner of the FxRequest which is FxIoQueue OR FxIoTarget // LIST_ENTRY m_OwnerListEntry; LIST_ENTRY m_OwnerListEntry2; // // This is used by the queue to keep track of all forward progress requests // LIST_ENTRY m_ForwardProgressList; // // Used when the request is a reserved request to track the queue it was // originally allocated for, so that it can be returned to the forward // progress queue for reuse when the request is completed. // FxIoQueue *m_ForwardProgressQueue; // // Generic context exposed to other modules. // PVOID m_InternalContext; // // If TRUE, the client driver has been presented with this WDFREQUEST at // least once. // BOOLEAN m_Presented; // // For tracking whether the driver has acknowledged power stop/purge notifications. // BYTE m_PowerStopState; // // If TRUE, this is a reserved request // BOOLEAN m_Reserved; // // If TRUE, this is used to determine how to free the request - // either to the lookaside list or using ExFreePool // BOOLEAN m_ForwardRequestToParent; public: // // Normally, this is available by the object implementing // IFxListEntry, but currently all callers of this know they // are dealing with an FxRequest*. // // If FxRequests must go on a general typeless list, then // the IFxListEntry interface should be added to FxRequest. // __inline PLIST_ENTRY GetListEntry( __in FxListEntryNames Index ) { switch (Index) { case FxListEntryQueueOwned: return &m_OwnerListEntry; case FxListEntryDriverOwned: return &m_OwnerListEntry2; case FxListEntryForwardProgress: return &m_ForwardProgressList; default: ASSERT(FALSE); return NULL; } } static FxRequest* _FromOwnerListEntry( __in FxListEntryNames Index, __in PLIST_ENTRY OwnerListEntry ) { switch (Index) { case FxListEntryQueueOwned: return CONTAINING_RECORD(OwnerListEntry, FxRequest, m_OwnerListEntry); case FxListEntryDriverOwned: return CONTAINING_RECORD(OwnerListEntry, FxRequest, m_OwnerListEntry2); case FxListEntryForwardProgress: return CONTAINING_RECORD(OwnerListEntry, FxRequest, m_ForwardProgressList); default: ASSERT(FALSE); return NULL; } } __inline VOID CopyCurrentIrpStackLocationToNext( VOID ) { FxIrp* irp = GetSubmitFxIrp(); irp->CopyCurrentIrpStackLocationToNext(); } _Must_inspect_result_ NTSTATUS Reuse( __in PWDF_REQUEST_REUSE_PARAMS ReuseParams ); __inline BOOLEAN IsCancelled( VOID ) { return m_Irp.IsCanceled() || m_Canceled; } __inline VOID CopyCompletionParams( __in PWDF_REQUEST_COMPLETION_PARAMS Params ) { if (m_RequestContext != NULL) { RtlCopyMemory(Params, &m_RequestContext->m_CompletionParams, sizeof(WDF_REQUEST_COMPLETION_PARAMS)); } else { DoTraceLevelMessage( GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGREQUEST, "WdfRequestGetCompletionParams will not return valid information if the" " request is not formatted using WdfIoTargetFormatxxx DDIs" ); FxVerifierDbgBreakPoint(GetDriverGlobals()); WDF_REQUEST_COMPLETION_PARAMS_INIT(Params); } } VOID __inline SetPresented( VOID ) { // // No need to synchronize setting this value with checking it because // we check it in the complete path. We will not be about to present // and completing the request in 2 simultaneous contexts. // m_Presented = TRUE; } VOID AddIrpReference( VOID ); VOID ReleaseIrpReference( VOID ); virtual ULONG AddRefOverride( __in WDFOBJECT_OFFSET Offset, __in PVOID Tag = NULL, __in LONG Line = 0, __in_opt PSTR File = NULL ); virtual ULONG ReleaseOverride( __in WDFOBJECT_OFFSET Offset, __in PVOID Tag = NULL, __in LONG Line = 0, __in_opt PSTR File = NULL ); __inline CfxDevice* GetDevice( VOID ) { return m_Device; } __inline BOOLEAN IsReserved( ) { return m_Reserved; } __inline VOID SetReserved( ) { m_Reserved = TRUE; } __inline VOID SetForwardProgressQueue( __in FxIoQueue *Queue ) { m_ForwardProgressQueue = Queue; } protected: FxRequest( __in PFX_DRIVER_GLOBALS FxDriverGlobals, __in MdIrp Irp, __in FxRequestIrpOwnership Ownership, __in FxRequestConstructorCaller Caller, __in USHORT ObjectSize ); #if DBG ~FxRequest( VOID ); #endif // DBG __inline VOID SetCurrentQueue( __in FxIoQueue *Queue ) { m_IoQueue = Queue; } WDFMEMORY GetMemoryHandle( __in USHORT Offset ) { ULONG_PTR handle; // // The offset into this object must be self relative. // ASSERT(*((PUSHORT) WDF_PTR_ADD_OFFSET(this, Offset)) == Offset); handle = (ULONG_PTR) WDF_PTR_ADD_OFFSET(this, Offset); // // Make sure initial value has the flag bits cleared. // ASSERT((handle & FxHandleFlagMask) == 0); // // We always apply the mask. // handle = handle ^ FxHandleValueMask; // // Make sure final value (before we set the flag) has the flag bits // cleared. // ASSERT((handle & FxHandleFlagMask) == 0); // // This handle is an offset handle |= FxHandleFlagIsOffset; return (WDFMEMORY) handle; } _Must_inspect_result_ virtual NTSTATUS QueryInterface( __in FxQueryInterfaceParams* Params ); public: // Factory functions to create FxRequest* objects _Must_inspect_result_ static NTSTATUS _CreateForPackage( __in CfxDevice* Device, __in PWDF_OBJECT_ATTRIBUTES RequestAttributes, __in MdIrp Irp, __deref_out FxRequest** Request ); _Must_inspect_result_ static NTSTATUS _Create( __in PFX_DRIVER_GLOBALS FxDriverGlobals, __in_opt PWDF_OBJECT_ATTRIBUTES RequestAttributes, __in_opt MdIrp Irp, __in_opt FxIoTarget* Target, __in FxRequestIrpOwnership Ownership, __in FxRequestConstructorCaller Caller, __deref_out FxRequest** Request ); _Must_inspect_result_ FxIoQueue* GetCurrentQueue( VOID ) { if(m_Completed) { return NULL; } return m_IoQueue; } FxRequestCompletionState SetCompletionState( __in FxRequestCompletionState NewState ); VOID __inline SetStatus( __in NTSTATUS Status ) { m_Irp.SetStatus(Status); } NTSTATUS SetInformation( __in ULONG_PTR Information ); ULONG_PTR GetInformation( VOID ); KPROCESSOR_MODE GetRequestorMode( VOID ); __inline NTSTATUS Complete( __in NTSTATUS Status ) { CfxDevice* const fxDevice = GetDevice(); // // Complete the current request object. Can be called directly // by the FxIoQueue to complete a request. // // When an FxRequest is completed, it is marked as completed, // removed from any CSQ it may be a member of, and any registered // callback functions are called. Then the NT IRP is completed, // and the reference count on the object due to the callback routine // is released if a callback routine was specified. // // Completing a request object can cause its reference // count to go to zero, thus deleting it. So the caller // must either reference it explicitly, or not touch it // any more after calling complete. // DoTraceLevelMessage( GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGREQUEST, "Completing WDFREQUEST 0x%p for IRP 0x%p with " "Information 0x%I64x, %!STATUS!", GetHandle(), m_Irp.GetIrp(), m_Irp.GetInformation(), Status); if (fxDevice != NULL) { SetPriorityBoost(fxDevice->GetDefaultPriorityBoost()); } else { SetPriorityBoost(0); } return CompleteInternal(Status); } __inline NTSTATUS CompleteWithInformation( __in NTSTATUS Status, __in ULONG_PTR Information ) { // // Complete the request object. If the status is success, get the // priority boost for the owning device type, and complete the request. // m_Irp.SetInformation(Information); return Complete(Status); } __inline NTSTATUS CompleteWithPriority( __in NTSTATUS Status, __in CCHAR PriorityBoost ) { // // Complete the current request object. Can be called directly // by the FxIoQueue to complete a request. // // When an FxRequest is completed, it is marked as completed, // removed from any CSQ it may be a member of, and any registered // callback functions are called. Then the NT IRP is completed, // and the reference count on the object due to the callback routine // is released if a callback routine was specified. // // Completing a request object can cause its reference // count to go to zero, thus deleting it. So the caller // must either reference it explicitly, or not touch it // any more after calling complete. // DoTraceLevelMessage( GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGREQUEST, "Completing WDFREQUEST 0x%p for IRP 0x%p with " "Information 0x%I64x, %!STATUS!", GetHandle(), m_Irp.GetIrp(), m_Irp.GetInformation(), Status); SetPriorityBoost(PriorityBoost); return CompleteInternal(Status); } // Do not specify argument names FX_DECLARE_VF_FUNCTION( VOID, VerifyPreProcessSendAndForget ); VOID PreProcessSendAndForget( VOID ); VOID PostProcessSendAndForget( VOID ); NTSTATUS GetStatus( VOID ); _Must_inspect_result_ NTSTATUS GetParameters( __out PWDF_REQUEST_PARAMETERS Parameters ); _Must_inspect_result_ NTSTATUS GetMemoryObject( __deref_out IFxMemory** Memory, __out PVOID* Buffer, __out size_t* Length ); _Must_inspect_result_ NTSTATUS GetMdl( __out PMDL *pMdl ); _Must_inspect_result_ NTSTATUS GetDeviceControlOutputMemoryObject( __deref_out IFxMemory** MemoryObject, __out PVOID* Buffer, __out size_t* Length ); _Must_inspect_result_ NTSTATUS GetDeviceControlOutputMdl( __out PMDL *pMdl ); // Do not specify argument names FX_DECLARE_VF_FUNCTION( NTSTATUS, VerifyProbeAndLock ); _Must_inspect_result_ NTSTATUS ProbeAndLockForRead( __in PVOID Buffer, __in ULONG Length, __deref_out FxRequestMemory** pMemoryObject ); _Must_inspect_result_ NTSTATUS ProbeAndLockForWrite( __in PVOID Buffer, __in ULONG Length, __deref_out FxRequestMemory** pMemoryObject ); #if (FX_CORE_MODE == FX_CORE_USER_MODE) _Must_inspect_result_ NTSTATUS Impersonate( _In_ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, _In_ PFN_WDF_REQUEST_IMPERSONATE EvtRequestImpersonate, _In_opt_ PVOID Context ); #endif VOID SetImpersonationFlags( _In_ ULONG Flags ) { #if (FX_CORE_MODE == FX_CORE_USER_MODE) GetSubmitFxIrp()->GetIoIrp()->SetFlagsForNextStackLocation( FxIrpStackFlagsFromSendFlags(Flags)); #else UNREFERENCED_PARAMETER(Flags); #endif } FxIrp* GetFxIrp( VOID ) { return &m_Irp; } __inline FxIoQueue* GetIoQueue( VOID ) { return m_IoQueue; } _Must_inspect_result_ NTSTATUS GetIrp( __deref_out MdIrp* ppIrp ) { if (GetDriverGlobals()->FxVerifierIO) { NTSTATUS status; KIRQL irql; Lock(&irql); status = VerifyRequestIsNotCompleted(GetDriverGlobals()); if (!NT_SUCCESS(status)) { *ppIrp = NULL; status = STATUS_INVALID_DEVICE_REQUEST; } else { *ppIrp = m_Irp.GetIrp(); } Unlock(irql); return status; } else { *ppIrp = m_Irp.GetIrp(); return STATUS_SUCCESS; } } // // Return the FxFileObject if associated with this request // _Must_inspect_result_ NTSTATUS GetFileObject( __deref_out_opt FxFileObject** pFileObject ); // // Get the IoStack location of the request. // // Since this returns the pointer to the underlying IRP // IO_STACK_LOCATION, it can not be called in a situation // which the request is completed out from underneath us. // // Note: Must implemention a version for the drivers use. // Must interact with completion events from the // driver due to cancel as well. // // PIO_STACK_LOCATION GetCurrentIrpStackLocation( VOID ) { if (GetDriverGlobals()->FxVerifierIO) { PIO_STACK_LOCATION ios; KIRQL irql; NTSTATUS status; Lock(&irql); status = VerifyRequestIsNotCompleted(GetDriverGlobals()); if (!NT_SUCCESS(status)) { ios = NULL; } else { ios = m_Irp.GetCurrentIrpStackLocation(); } Unlock(irql); return ios; } else { return m_Irp.GetCurrentIrpStackLocation(); } } // // The following functions are to support use of // the Cancel Safe FxIrpQueue. // // Do not specify argument names FX_DECLARE_VF_FUNCTION_P1( NTSTATUS, VerifyInsertIrpQueue, _In_ FxIrpQueue* ); // // Insert the request in the supplied FxIrpQueue // and associated it with it. // _Must_inspect_result_ NTSTATUS InsertTailIrpQueue( __in FxIrpQueue* IrpQueue, __out_opt ULONG* pRequestCount ); _Must_inspect_result_ NTSTATUS InsertHeadIrpQueue( __in FxIrpQueue* IrpQueue, __out_opt ULONG* pRequestCount ); // // Remove it from the FxIrpQueue it is associated with. // // Returns STATUS_CANCELLED if the cancel routine has // fired and removed it from the queue first. // // _Must_inspect_result_ NTSTATUS RemoveFromIrpQueue( __in FxIrpQueue* IrpQueue ); // // Mark that this request is no longer on the IrpQueue // __inline VOID MarkRemovedFromIrpQueue( VOID ) { m_IrpQueue = NULL; return; } // // Return the FxRequest's CsqContext address // __inline PMdIoCsqIrpContext GetCsqContext( VOID ) { return &m_CsqContext; } // // Function to return an FxRequest from an FxIrpQueue // _Must_inspect_result_ static FxRequest* GetNextRequest( __in FxIrpQueue* IrpQueue ); _Must_inspect_result_ static NTSTATUS GetNextRequest( __in FxIrpQueue* IrpQueue, __in_opt MdFileObject FileObject, __in_opt FxRequest* TagRequest, __deref_out FxRequest** ppOutRequest ); // // Allow peeking at requests in the IrpQueue // _Must_inspect_result_ static NTSTATUS PeekRequest( __in FxIrpQueue* IrpQueue, __in_opt FxRequest* TagRequest, __in_opt MdFileObject FileObject, __out_opt PWDF_REQUEST_PARAMETERS Parameters, __deref_out FxRequest** ppOutRequest ); // // Internal function to retrieve the FxRequest // structure from a pointer to its CsqContext // member. // __inline static FxRequest* RetrieveFromCsqContext( __in PMdIoCsqIrpContext pCsqContext ) { return CONTAINING_RECORD(pCsqContext, FxRequest, m_CsqContext); } __inline BOOLEAN IsInIrpQueue( __in FxIrpQueue* pIrpQueue ) { return pIrpQueue->IsIrpInQueue(GetCsqContext()); } // Do not specify argument names FX_DECLARE_VF_FUNCTION_P1( NTSTATUS, VerifyStopAcknowledge, _In_ BOOLEAN ); VOID StopAcknowledge( __in BOOLEAN Requeue ); __inline BOOLEAN IsPowerStopAcknowledged( VOID ) { return ((m_PowerStopState == FxRequestPowerStopAcknowledged) || (m_PowerStopState == FxRequestPowerStopAcknowledgedWithRequeue))? TRUE : FALSE; } __inline BOOLEAN IsPowerStopAcknowledgedWithRequeue( VOID ) { return (m_PowerStopState == FxRequestPowerStopAcknowledgedWithRequeue) ? TRUE : FALSE; } VOID ClearPowerStopState( VOID ) { m_PowerStopState = FxRequestPowerStopUnknown; } // Do not specify argument names FX_DECLARE_VF_FUNCTION( VOID, VerifierBreakpoint_RequestEarlyDisposeDeferred ); // Do not specify argument names FX_DECLARE_VF_FUNCTION( NTSTATUS, VerifyRequestIsDriverOwned ); // Do not specify argument names FX_DECLARE_VF_FUNCTION( NTSTATUS, VerifyRequestIsCancelable ); // Do not specify argument names FX_DECLARE_VF_FUNCTION( NTSTATUS, VerifyRequestIsNotCancelable ); // Do not specify argument names FX_DECLARE_VF_FUNCTION( NTSTATUS, VerifyRequestIsInCallerContext ); // Do not specify argument names FX_DECLARE_VF_FUNCTION( NTSTATUS, VerifyRequestIsInEvtIoStopContext ); // Do not specify argument names FX_DECLARE_VF_FUNCTION( NTSTATUS, VerifyRequestIsNotCompleted ); // Do not specify argument names FX_DECLARE_VF_FUNCTION( NTSTATUS, VerifyRequestIsTagRequest ); // Do not specify argument names FX_DECLARE_VF_FUNCTION( NTSTATUS, VerifyRequestIsAllocatedFromIo ); // Do not specify argument names FX_DECLARE_VF_FUNCTION( NTSTATUS, VerifyRequestIsCurrentStackValid ); // Do not specify argument names FX_DECLARE_VF_FUNCTION( NTSTATUS, VerifyRequestCanBeCompleted ); VOID FreeRequest( VOID ); __inline VOID ClearFieldsForReuse( VOID ) { m_SystemBuffer.ClearBufferMdl(); m_OutputBuffer.ClearBufferMdl(); ASSERT(m_ForwardRequestToParent == FALSE); FxRequestBase::ClearFieldsForReuse(); // __super call } virtual ULONG Release( __in PVOID Tag, __in LONG Line, __in_opt PSTR File ); __inline BOOLEAN IsRequestForwardedToParent( VOID ) { return m_ForwardRequestToParent; } private: FX_DECLARE_VF_FUNCTION_P1( VOID, VerifyCompleteInternal, _In_ NTSTATUS ); NTSTATUS CompleteInternalReserved( __in NTSTATUS Status, __in CCHAR PriorityBoost ); NTSTATUS CompleteInternal( __in NTSTATUS Status ); VOID PostProcessCompletion( __in FxRequestCompletionState State, __in FxIoQueue* Queue ); VOID PostProcessCompletionForReserved( __in FxRequestCompletionState State, __in FxIoQueue* Queue ); VOID PreProcessCompletionForDriverRequest( __in FxRequestCompletionState State, __in FxIoQueue* Queue ); VOID PostProcessCompletionForDriverRequest( __in FxRequestCompletionState State, __in FxIoQueue* Queue ); static VOID CheckAssumptions( VOID ); VOID AssignMemoryBuffers( __in WDF_DEVICE_IO_TYPE IoType ) { switch (m_Irp.GetMajorFunction()) { case IRP_MJ_DEVICE_CONTROL: case IRP_MJ_INTERNAL_DEVICE_CONTROL: switch (m_Irp.GetParameterIoctlCodeBufferMethod()) { case METHOD_BUFFERED: // // Set the buffer in the memory interface. For kernel mode, // GetOutputBuffer is same as GetSystemBuffer, but for user-mode, // host provides separate buffers, so that input buffer can only be // read, and output buffer can only be written to. // m_SystemBuffer.SetBuffer(m_Irp.GetSystemBuffer()); m_OutputBuffer.SetBuffer(m_Irp.GetOutputBuffer()); break; case METHOD_IN_DIRECT: // // InputBuffer is in SystemBuffer // OutputBuffer is in MdlAddress with read access // KMDF_ONLY_CODE_PATH_ASSERT(); m_SystemBuffer.SetBuffer(m_Irp.GetSystemBuffer()); break; case METHOD_OUT_DIRECT: // // InputBuffer is in SystemBuffer // OutputBuffer is in MdlAddress with write access // KMDF_ONLY_CODE_PATH_ASSERT(); m_SystemBuffer.SetBuffer(m_Irp.GetSystemBuffer()); break; case METHOD_NEITHER: // // Internal device controls are kernel mode to kernel mode, and deal // with direct unmapped pointers. // // In addition, a normal device control with // RequestorMode == KernelMode is also treated as kernel mode // to kernel mode since the I/O Manager will not generate requests // with this setting from a user mode request. // KMDF_ONLY_CODE_PATH_ASSERT(); if (m_Irp.GetMajorFunction() == IRP_MJ_INTERNAL_DEVICE_CONTROL || (m_Irp.GetRequestorMode() == KernelMode)) { m_SystemBuffer.SetBuffer( m_Irp.GetParameterIoctlType3InputBuffer() ); m_OutputBuffer.SetBuffer(m_Irp.GetUserBuffer()); } else { return; } break; } break; case IRP_MJ_READ: case IRP_MJ_WRITE: switch (IoType) { case WdfDeviceIoBuffered: m_SystemBuffer.SetBuffer(m_Irp.GetSystemBuffer()); break; case WdfDeviceIoNeither: KMDF_ONLY_CODE_PATH_ASSERT(); if (m_Irp.GetRequestorMode() == KernelMode) { m_SystemBuffer.SetBuffer(m_Irp.GetUserBuffer()); } else { return; } break; default: return; } break; default: return; } if (m_SystemBuffer.IsBufferSet()) { m_RequestBaseStaticFlags |= FxRequestBaseStaticSystemBufferValid; } if (m_OutputBuffer.IsBufferSet()) { m_RequestBaseStaticFlags |= FxRequestBaseStaticOutputBufferValid; } } public: __inline VOID SetInternalContext( PVOID Context ) { ASSERT(NULL == m_InternalContext); m_InternalContext = Context; } __inline PVOID GetInternalContext( VOID ) { PVOID context; context = m_InternalContext; m_InternalContext = NULL; return context; } }; class FxRequestFromLookaside : public FxRequest { public: FxRequestFromLookaside( __in CfxDevice* Device, __in MdIrp Irp ); PVOID operator new( __in size_t Size, __in CfxDevice* Device, __in_opt PWDF_OBJECT_ATTRIBUTES Attributes ); protected: // // FxObject override // VOID SelfDestruct( VOID ); }; #endif // _FXREQUEST_H_