2020-09-24 20:51:15 +00:00
|
|
|
/*++
|
|
|
|
|
|
|
|
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 = <read MDL>
|
|
|
|
// 2) This WDFMEMORY will return <read MDL VA> in GetBuffer()
|
|
|
|
// 3) the WDFREQUEST is formatted for an IOCTL which is METHOD_OUT_DIRECT
|
|
|
|
// with a new output buffer. Irp->MdlAddres = <IOCTL MDL> now.
|
|
|
|
// 4) This same WDFMEMORY will now return <IOCTL MDL VA> 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
|
2020-10-16 03:30:51 +00:00
|
|
|
~FxRequest(
|
2020-09-24 20:51:15 +00:00
|
|
|
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);
|
|
|
|
|
2020-10-16 03:30:51 +00:00
|
|
|
FxRequestBase::ClearFieldsForReuse(); // __super call
|
2020-09-24 20:51:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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_
|