2020-09-24 20:51:15 +00:00
|
|
|
/*++
|
|
|
|
|
|
|
|
Copyright (c) Microsoft Corporation
|
|
|
|
|
|
|
|
Module Name:
|
|
|
|
|
|
|
|
FxRequestBase.hpp
|
|
|
|
|
|
|
|
Abstract:
|
|
|
|
|
|
|
|
This is the base class which request objects derive from for the driver
|
|
|
|
frameworks.
|
|
|
|
|
|
|
|
The request base object wraps the IRP, containing persistent
|
|
|
|
information required by the driver frameworks.
|
|
|
|
|
|
|
|
Author:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Environment:
|
|
|
|
|
|
|
|
Both kernel and user mode
|
|
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
|
|
--*/
|
|
|
|
|
|
|
|
#ifndef _FXREQUESTBASE_H_
|
|
|
|
#define _FXREQUESTBASE_H_
|
|
|
|
|
2020-10-16 03:30:51 +00:00
|
|
|
#include "fxrequestcallbacks.hpp"
|
|
|
|
|
|
|
|
#define WDF_REQUEST_REUSE_MUST_COMPLETE 2
|
2020-09-24 20:51:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// COMPLETED - set when the request's i/o completion routine has executed
|
|
|
|
//
|
|
|
|
// PENDED - set when the request has been put onto the target's CSQ
|
|
|
|
//
|
|
|
|
// TIMER_SET - set when a timer has been queued along with sending the request
|
|
|
|
// down to the target
|
|
|
|
//
|
|
|
|
// CANCELLED_FROM_TIME - set by the timer to indicate that the request was
|
|
|
|
// cancelled by the timer DPC
|
|
|
|
//
|
|
|
|
// IGNORE_STATE - set when the request is going to be sent ignoring the
|
|
|
|
// state of the target.
|
|
|
|
//
|
|
|
|
enum FxRequestTargetFlags {
|
|
|
|
FX_REQUEST_COMPLETED = 0x01,
|
|
|
|
FX_REQUEST_PENDED = 0x02,
|
|
|
|
FX_REQUEST_TIMER_SET = 0x04,
|
|
|
|
FX_REQUEST_CANCELLED_FROM_TIMER = 0x08,
|
|
|
|
FX_REQUEST_IGNORE_STATE = 0x10,
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// internal private constraints
|
|
|
|
//
|
|
|
|
#define WDF_REQUEST_SEND_INTERNAL_OPTION_FAIL_ON_PEND (0x80000000)
|
|
|
|
|
|
|
|
#define WDF_REQUEST_INTERNAL_CONSTRAINTS_VALID_FLAGS \
|
|
|
|
(WDF_REQUEST_SEND_INTERNAL_OPTION_FAIL_ON_PEND)
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Completion event callback prototype
|
|
|
|
//
|
|
|
|
typedef
|
|
|
|
VOID
|
|
|
|
(*PFN_COMPLETE_COPY_ROUTINE)(
|
|
|
|
__in FxIoTarget* This,
|
|
|
|
__in FxRequest* Request,
|
|
|
|
__in_opt FxRequestContext* Context
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
struct FxRequestTimer : public FxStump {
|
|
|
|
MxTimer Timer;
|
|
|
|
};
|
|
|
|
|
|
|
|
enum FxRequestAllocationSource {
|
|
|
|
REQUEST_ALLOCATED_FROM_IO = 0, // Irp came from the I/O package
|
|
|
|
REQUEST_ALLOCATED_INTERNAL = 1, // Irp was allocated internally and should be freed by the request
|
|
|
|
REQUEST_ALLOCATED_DRIVER = 2, // Irp was given to the request by the driver writer
|
|
|
|
};
|
|
|
|
|
|
|
|
enum FxRequestIrpOwnership {
|
|
|
|
FxRequestOwnsIrp = 1,
|
|
|
|
FxRequestDoesNotOwnIrp,
|
|
|
|
};
|
|
|
|
|
|
|
|
// begin_wpp config
|
|
|
|
// CUSTOM_TYPE(FxRequestIrpOwnership, ItemEnum(FxRequestIrpOwnership));
|
|
|
|
// end_wpp
|
|
|
|
|
|
|
|
enum FxRequestConstructorCaller {
|
|
|
|
FxRequestConstructorCallerIsFx = 1,
|
|
|
|
FxRequestConstructorCallerIsDriver,
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// These defines are for VerifierFlags
|
|
|
|
//
|
|
|
|
enum FxRequestVerifierFlags {
|
|
|
|
// Request has been passed to the Driver
|
|
|
|
FXREQUEST_FLAG_DRIVER_OWNED = 0x0001,
|
|
|
|
|
|
|
|
// Request was returned as a "Tag" request to WdfIoQueuePeekNextRequest.
|
|
|
|
FXREQUEST_FLAG_TAG_REQUEST = 0x0002,
|
|
|
|
|
|
|
|
// Request has been forwarded from one queue to another
|
|
|
|
FXREQUEST_FLAG_FORWARDED = 0x0004,
|
|
|
|
|
|
|
|
// Request is being EvtIoDefault to the driver
|
|
|
|
FXREQUEST_FLAG_DRIVER_DISPATCH = 0x0008,
|
|
|
|
|
|
|
|
// The driver has specified the request as cancelable
|
|
|
|
FXREQUEST_FLAG_DRIVER_CANCELABLE = 0x0010,
|
|
|
|
|
|
|
|
FXREQUEST_FLAG_DRIVER_INPROCESS_CONTEXT = 0x0020,
|
|
|
|
|
|
|
|
// The request has been cancelled
|
|
|
|
FXREQUEST_FLAG_CANCELLED = 0x0040,
|
|
|
|
|
|
|
|
// the next stack location has been formatted
|
|
|
|
FXREQUEST_FLAG_FORMATTED = 0x0080,
|
|
|
|
|
|
|
|
// the request has been sent on an I/O target and is in the target's sent list
|
|
|
|
FXREQUEST_FLAG_SENT_TO_TARGET = 0x0100,
|
|
|
|
|
|
|
|
// used to make sure the driver stop acknowledges in the context of EvtIoStop
|
|
|
|
FXREQUEST_FLAG_DRIVER_IN_EVTIOSTOP_CONTEXT = 0x0200,
|
|
|
|
|
|
|
|
// used to indicate whether the Reserved Request is in use or on Free list
|
|
|
|
FXREQUEST_FLAG_RESERVED_REQUEST_ASSOCIATED_WITH_IRP = 0x0400,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum FxRequestBaseFlags {
|
|
|
|
FxRequestBaseSystemMdlMapped = 0x1,
|
|
|
|
FxRequestBaseOutputMdlMapped = 0x2,
|
|
|
|
FxRequestBaseSyncCleanupContext = 0x10,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum FxRequestBaseStaticFlags {
|
|
|
|
FxRequestBaseStaticSystemBufferValid = 0x1,
|
|
|
|
FxRequestBaseStaticOutputBufferValid = 0x2,
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// Designed to fit into a byte. FxRequestCompletionPkgFlag is a bit value
|
|
|
|
// used to distinguish between calling back into the io package or the current
|
|
|
|
// queue. When calling back into the current queue, we assume m_IoQueue is valid
|
|
|
|
//
|
|
|
|
enum FxRequestCompletionState {
|
|
|
|
FxRequestCompletionStateIoPkgFlag = 0x80,
|
|
|
|
|
|
|
|
FxRequestCompletionStateNone = 0x00,
|
|
|
|
FxRequestCompletionStateQueue = 0x01,
|
|
|
|
FxRequestCompletionStateIoPkg = 0x02 | FxRequestCompletionStateIoPkgFlag,
|
|
|
|
};
|
|
|
|
|
|
|
|
class FxRequestBase : public FxNonPagedObject {
|
|
|
|
|
|
|
|
friend FxIoTarget;
|
|
|
|
friend FxSyncRequest;
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
__inline
|
|
|
|
VOID
|
|
|
|
SetCompletionRoutine(
|
|
|
|
__in_opt PFN_WDF_REQUEST_COMPLETION_ROUTINE CompletionRoutine = NULL,
|
|
|
|
__in_opt WDFCONTEXT CompletionContext = NULL
|
|
|
|
)
|
|
|
|
{
|
|
|
|
m_CompletionRoutine.m_Completion = CompletionRoutine;
|
|
|
|
m_TargetCompletionContext = CompletionContext;
|
|
|
|
}
|
|
|
|
|
|
|
|
PFN_WDF_REQUEST_COMPLETION_ROUTINE
|
|
|
|
ClearCompletionRoutine(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
PFN_WDF_REQUEST_COMPLETION_ROUTINE pRoutine;
|
|
|
|
|
|
|
|
pRoutine = m_CompletionRoutine.m_Completion;
|
|
|
|
m_CompletionRoutine.m_Completion = NULL;
|
|
|
|
|
|
|
|
return pRoutine;
|
|
|
|
}
|
|
|
|
|
|
|
|
WDFCONTEXT
|
|
|
|
ClearCompletionContext(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
WDFCONTEXT pContext;
|
|
|
|
|
|
|
|
pContext = m_TargetCompletionContext;
|
|
|
|
m_TargetCompletionContext = NULL;
|
|
|
|
|
|
|
|
return pContext;
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline
|
|
|
|
BOOLEAN
|
|
|
|
IsCompletionRoutineSet(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return (m_CompletionRoutine.m_Completion != NULL) ?
|
|
|
|
TRUE : FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline
|
|
|
|
BOOLEAN
|
|
|
|
IsCancelRoutineSet(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return (m_CancelRoutine.m_Cancel != NULL) ?
|
|
|
|
TRUE : FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline
|
|
|
|
FxRequestContext*
|
|
|
|
GetContext(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return m_RequestContext;
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline
|
|
|
|
VOID
|
|
|
|
SetContext(
|
|
|
|
__in FxRequestContext* RequestContext = NULL
|
|
|
|
)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// If we are setting to the same value, just return
|
|
|
|
//
|
|
|
|
if (m_RequestContext == RequestContext) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// If we are changing the context to another unique pointer, free the
|
|
|
|
// old context.
|
|
|
|
//
|
|
|
|
if (m_RequestContext != NULL) {
|
|
|
|
delete m_RequestContext;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_RequestContext = RequestContext;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
ContextReleaseAndRestore(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// This does not free the context, rather it tells the context to release
|
|
|
|
// any references it is holding and restore fields back into the PIRP
|
|
|
|
//
|
|
|
|
if (m_RequestContext != NULL && m_Irp.GetIrp() != NULL) {
|
|
|
|
m_RequestContext->ReleaseAndRestore(this);
|
|
|
|
VerifierClearFormatted();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline
|
|
|
|
VOID
|
|
|
|
EnableContextDisposeNotification(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
MarkDisposeOverride();
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline
|
|
|
|
BOOLEAN
|
|
|
|
HasContextType(
|
|
|
|
__in FX_REQUEST_CONTEXT_TYPE Type
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return (m_RequestContext != NULL &&
|
|
|
|
m_RequestContext->m_RequestType == Type) ? TRUE : FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline
|
2020-10-16 03:30:51 +00:00
|
|
|
BOOLEAN
|
2020-09-24 20:51:15 +00:00
|
|
|
HasContext(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return (m_RequestContext != NULL &&
|
|
|
|
m_RequestContext->m_RequestType !=
|
|
|
|
FX_REQUEST_CONTEXT_TYPE_NONE) ? TRUE : FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline
|
|
|
|
MdIrp
|
|
|
|
GetSubmitIrp(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return m_Irp.GetIrp();
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline
|
|
|
|
FxIrp*
|
|
|
|
GetSubmitFxIrp(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return &m_Irp;
|
|
|
|
}
|
|
|
|
|
|
|
|
MdIrp
|
|
|
|
SetSubmitIrp(
|
|
|
|
__in_opt MdIrp NewIrp,
|
|
|
|
__in BOOLEAN FreeIrp = TRUE
|
|
|
|
);
|
|
|
|
|
|
|
|
__inline
|
|
|
|
BOOLEAN
|
|
|
|
CanComplete(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
LONG count;
|
|
|
|
count = InterlockedDecrement(&m_IrpCompletionReferenceCount);
|
|
|
|
ASSERT(count >= 0);
|
|
|
|
return count == 0 ? TRUE : FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
CompleteSubmitted(
|
|
|
|
VOID
|
|
|
|
);
|
|
|
|
|
|
|
|
_Must_inspect_result_
|
|
|
|
NTSTATUS
|
|
|
|
ValidateTarget(
|
|
|
|
__in FxIoTarget* Target
|
|
|
|
);
|
|
|
|
|
|
|
|
__inline
|
|
|
|
FxIoTarget*
|
|
|
|
GetTarget(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return m_Target;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
__inline
|
|
|
|
SetTarget(
|
|
|
|
__in FxIoTarget* Target
|
|
|
|
)
|
|
|
|
{
|
|
|
|
m_Target = Target;
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline
|
|
|
|
UCHAR
|
|
|
|
GetTargetFlags(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
// Assumes caller is holding appropriate lock
|
|
|
|
return m_TargetFlags;
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline
|
|
|
|
VOID
|
|
|
|
SetTargetFlags(
|
|
|
|
__in UCHAR Flags
|
|
|
|
)
|
|
|
|
{
|
|
|
|
// Assumes caller is holding appropriate lock
|
|
|
|
m_TargetFlags |= Flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline
|
|
|
|
ULONG
|
|
|
|
ClearTargetFlags(
|
|
|
|
__in UCHAR Flags
|
|
|
|
)
|
|
|
|
{
|
|
|
|
ULONG oldFlags;
|
|
|
|
|
|
|
|
oldFlags = m_TargetFlags;
|
|
|
|
|
|
|
|
// Assumes caller is holding appropriate lock
|
|
|
|
m_TargetFlags &= ~Flags;
|
|
|
|
|
|
|
|
return oldFlags;
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline
|
|
|
|
VOID
|
|
|
|
SetRequestBaseFlags(
|
|
|
|
__in UCHAR Flags
|
|
|
|
)
|
|
|
|
{
|
|
|
|
// Assumes caller is holding appropriate lock
|
|
|
|
m_RequestBaseFlags|= Flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
SHORT
|
|
|
|
GetVerifierFlagsLocked(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
ASSERT(GetDriverGlobals()->FxVerifierOn);
|
|
|
|
return m_VerifierFlags;
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline
|
|
|
|
SHORT
|
|
|
|
GetVerifierFlags(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
SHORT flags;
|
|
|
|
KIRQL irql;
|
|
|
|
|
|
|
|
Lock(&irql);
|
|
|
|
flags = GetVerifierFlagsLocked();
|
|
|
|
Unlock(irql);
|
|
|
|
|
|
|
|
return flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline
|
|
|
|
VOID
|
|
|
|
SetVerifierFlagsLocked(
|
|
|
|
__in SHORT Flags
|
|
|
|
)
|
|
|
|
{
|
|
|
|
m_VerifierFlags |= Flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline
|
|
|
|
VOID
|
|
|
|
SetVerifierFlags(
|
|
|
|
__in SHORT Flags
|
|
|
|
)
|
|
|
|
{
|
|
|
|
KIRQL irql;
|
|
|
|
|
|
|
|
ASSERT(GetDriverGlobals()->FxVerifierOn);
|
|
|
|
|
|
|
|
Lock(&irql);
|
|
|
|
SetVerifierFlagsLocked(Flags);
|
|
|
|
Unlock(irql);
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline
|
|
|
|
VOID
|
|
|
|
ClearVerifierFlagsLocked(
|
|
|
|
__in SHORT Flags
|
|
|
|
)
|
|
|
|
{
|
|
|
|
m_VerifierFlags &= ~Flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline
|
|
|
|
VOID
|
|
|
|
ClearVerifierFlags(
|
|
|
|
__in SHORT Flags
|
|
|
|
)
|
|
|
|
{
|
|
|
|
KIRQL irql;
|
|
|
|
|
|
|
|
ASSERT(GetDriverGlobals()->FxVerifierOn);
|
|
|
|
|
|
|
|
Lock(&irql);
|
|
|
|
ClearVerifierFlagsLocked(Flags);
|
|
|
|
Unlock(irql);
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline
|
|
|
|
VOID
|
|
|
|
VerifierSetFormatted(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (GetDriverGlobals()->FxVerifierOn &&
|
|
|
|
GetDriverGlobals()->FxVerifierIO) {
|
|
|
|
SetVerifierFlags(FXREQUEST_FLAG_FORMATTED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline
|
|
|
|
VOID
|
|
|
|
VerifierClearFormatted(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (GetDriverGlobals()->FxVerifierOn &&
|
|
|
|
GetDriverGlobals()->FxVerifierIO) {
|
|
|
|
ClearVerifierFlags(FXREQUEST_FLAG_FORMATTED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline
|
|
|
|
BOOLEAN
|
|
|
|
VerifierIsFormatted(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (GetDriverGlobals()->FxVerifierOn &&
|
|
|
|
GetDriverGlobals()->FxVerifierIO) {
|
|
|
|
return (GetVerifierFlags() & FXREQUEST_FLAG_FORMATTED) ? TRUE : FALSE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
//
|
|
|
|
// we are not tracking the state
|
|
|
|
//
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline
|
|
|
|
BOOLEAN
|
|
|
|
ShouldClearContext(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return (m_RequestBaseFlags & FxRequestBaseSyncCleanupContext) ? TRUE
|
|
|
|
: FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
_Must_inspect_result_
|
|
|
|
NTSTATUS
|
|
|
|
CreateTimer(
|
|
|
|
VOID
|
|
|
|
);
|
|
|
|
|
|
|
|
VOID
|
|
|
|
StartTimer(
|
|
|
|
__in LONGLONG Timeout
|
|
|
|
);
|
|
|
|
|
|
|
|
_Must_inspect_result_
|
|
|
|
BOOLEAN
|
|
|
|
CancelTimer(
|
|
|
|
VOID
|
|
|
|
);
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
Cancel(
|
|
|
|
VOID
|
|
|
|
);
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
__inline
|
|
|
|
IsAllocatedFromIo(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return m_IrpAllocation == REQUEST_ALLOCATED_FROM_IO ? TRUE : FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
__inline
|
|
|
|
IsAllocatedDriver(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return m_IrpAllocation == REQUEST_ALLOCATED_DRIVER ? TRUE : FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
__inline
|
|
|
|
IsCanComplete(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return m_CanComplete;
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline
|
|
|
|
VOID
|
|
|
|
SetCompleted(
|
|
|
|
__in BOOLEAN Value
|
|
|
|
)
|
|
|
|
{
|
|
|
|
m_Completed = Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
__inline
|
|
|
|
SetPriorityBoost(
|
|
|
|
CCHAR PriorityBoost
|
|
|
|
)
|
|
|
|
{
|
|
|
|
m_PriorityBoost = PriorityBoost;
|
|
|
|
}
|
|
|
|
|
|
|
|
CCHAR
|
|
|
|
__inline
|
|
|
|
GetPriorityBoost(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return m_PriorityBoost;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
__inline
|
|
|
|
WDFREQUEST
|
|
|
|
GetHandle(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return (WDFREQUEST) GetObjectHandle();
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline
|
|
|
|
static
|
|
|
|
FxRequestBase*
|
|
|
|
_FromListEntry(
|
|
|
|
__in PLIST_ENTRY Entry
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return CONTAINING_RECORD(Entry, FxRequestBase, m_ListEntry);
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline
|
|
|
|
static
|
|
|
|
FxRequestBase*
|
|
|
|
_FromDrainEntry(
|
|
|
|
__in PSINGLE_LIST_ENTRY Entry
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return CONTAINING_RECORD(Entry, FxRequestBase, m_DrainSingleEntry);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
__inline
|
|
|
|
static
|
|
|
|
FxRequestBase*
|
|
|
|
_FromCsqContext(
|
|
|
|
__in PMdIoCsqIrpContext Context
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return CONTAINING_RECORD(Context, FxRequestBase, m_CsqContext);
|
|
|
|
}
|
|
|
|
|
|
|
|
__inline
|
|
|
|
PVOID
|
|
|
|
GetTraceObjectHandle(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
PVOID handle;
|
|
|
|
|
|
|
|
handle = GetObjectHandle();
|
|
|
|
|
|
|
|
if (handle != NULL) {
|
|
|
|
return handle;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return (PVOID) this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
FreeMdls(
|
|
|
|
VOID
|
|
|
|
);
|
|
|
|
|
2020-10-16 03:30:51 +00:00
|
|
|
DECLSPEC_NORETURN
|
2020-09-24 20:51:15 +00:00
|
|
|
VOID
|
|
|
|
FatalError(
|
|
|
|
__in NTSTATUS Status
|
|
|
|
);
|
|
|
|
|
|
|
|
VOID
|
|
|
|
ClearFieldsForReuse(
|
|
|
|
VOID
|
|
|
|
);
|
|
|
|
|
|
|
|
protected:
|
|
|
|
FxRequestBase(
|
|
|
|
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
|
|
|
__in USHORT ObjectSize,
|
|
|
|
__in_opt MdIrp Irp,
|
|
|
|
__in FxRequestIrpOwnership Ownership,
|
|
|
|
__in FxRequestConstructorCaller Caller,
|
|
|
|
__in FxObjectType ObjectType = FxObjectTypeExternal
|
|
|
|
);
|
|
|
|
|
|
|
|
virtual
|
|
|
|
~FxRequestBase(
|
|
|
|
VOID
|
|
|
|
);
|
|
|
|
|
|
|
|
// Do not specify argument names
|
|
|
|
FX_DECLARE_VF_FUNCTION(
|
|
|
|
VOID,
|
|
|
|
VerifyDispose
|
|
|
|
);
|
|
|
|
|
|
|
|
// FxObject overrides
|
|
|
|
virtual
|
|
|
|
BOOLEAN
|
|
|
|
Dispose(
|
|
|
|
VOID
|
|
|
|
);
|
|
|
|
|
|
|
|
static
|
|
|
|
MdDeferredRoutineType _TimerDPC;
|
|
|
|
|
|
|
|
VOID
|
|
|
|
CompleteSubmittedNoContext(
|
|
|
|
VOID
|
|
|
|
);
|
|
|
|
|
|
|
|
VOID
|
|
|
|
ZeroOutDriverContext(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
#if (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
|
|
|
|
RtlZeroMemory(GetSubmitFxIrp()->GetDriverContext(),
|
|
|
|
GetSubmitFxIrp()->GetDriverContextSize());
|
|
|
|
#else
|
|
|
|
//
|
|
|
|
// UMDF host doesn't expose any easier way to zero out the contexts so
|
|
|
|
// set context to NULL one by one.
|
|
|
|
//
|
|
|
|
GetSubmitFxIrp()->SetContext(0, NULL);
|
|
|
|
GetSubmitFxIrp()->SetContext(1, NULL);
|
|
|
|
GetSubmitFxIrp()->SetContext(2, NULL);
|
|
|
|
GetSubmitFxIrp()->SetContext(3, NULL);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
union {
|
|
|
|
//
|
|
|
|
// The cancel safe queues use this context to identify
|
|
|
|
// the request in a race free manner.
|
|
|
|
//
|
|
|
|
MdIoCsqIrpContext m_CsqContext;
|
|
|
|
|
|
|
|
//
|
|
|
|
// IoTargets uses this to track the request when it is sent to the target.
|
|
|
|
// Since the request cannot be on an CSQ and sent to a target at the
|
|
|
|
// same time, we can unionize this with the CSQ context.
|
|
|
|
//
|
|
|
|
LIST_ENTRY m_ListEntry;
|
|
|
|
};
|
|
|
|
|
|
|
|
union {
|
|
|
|
//
|
|
|
|
// IoTargest uses this when it needs to create a list of requests to cancel
|
|
|
|
// when making a state transition
|
|
|
|
//
|
|
|
|
SINGLE_LIST_ENTRY m_DrainSingleEntry;
|
|
|
|
|
|
|
|
//
|
|
|
|
// If TRUE, the driver formatted the request by copying the current stack
|
|
|
|
// location to next or by manually passing in an IO_STACK_LOCATION. This
|
|
|
|
// is union'ed with m_DrainSingleEntry b/c it is only relevant during
|
|
|
|
// send and forget and the request is never enqueued on the target in
|
|
|
|
// this case and m_DrainSingleEntry is used when tracking requests sent
|
|
|
|
// on a target for cancelation due to a target state change.
|
|
|
|
//
|
|
|
|
BOOLEAN m_NextStackLocationFormatted;
|
|
|
|
};
|
|
|
|
|
|
|
|
protected:
|
|
|
|
//
|
|
|
|
// The NT IRP is wrapped by a frameworks FxIrp
|
|
|
|
//
|
|
|
|
// Note: If m_Irp is NULL after initialization, this means
|
|
|
|
// the IRP was cancelled by a FxIrpQueue cancellation
|
|
|
|
// callback, or completed.
|
|
|
|
//
|
|
|
|
FxIrp m_Irp;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Target of the request. Access to this field is unguarded. The following
|
|
|
|
// have access to this field
|
|
|
|
// o The owning target itself
|
|
|
|
// o _TimerDPC()
|
|
|
|
// o Cancel() IFF it has successfully incremented the irp completion ref count
|
|
|
|
//
|
|
|
|
FxIoTarget* m_Target;
|
|
|
|
|
|
|
|
FxRequestContext* m_RequestContext;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FxRequestTimer* m_Timer;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Client driver completion routine to call when the request has come back
|
|
|
|
// from the target device.
|
|
|
|
//
|
|
|
|
FxRequestCancelCallback m_CancelRoutine;
|
|
|
|
|
|
|
|
FxRequestCompletionCallback m_CompletionRoutine;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Context to pass to CompletionRoutine when called
|
|
|
|
//
|
|
|
|
WDFCONTEXT m_TargetCompletionContext;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Synchronization for this field is through Interlocked operations
|
|
|
|
//
|
|
|
|
LONG m_IrpCompletionReferenceCount;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Access to flags guarded by FxIoTarget::Lock
|
|
|
|
//
|
|
|
|
// Values defined in the enum FxRequestTargetFlags
|
|
|
|
//
|
|
|
|
union {
|
|
|
|
UCHAR m_TargetFlags;
|
|
|
|
|
|
|
|
//
|
|
|
|
// These are used purely for debugging, not in live code anywhere!
|
|
|
|
// NOTE: if FxRequestTargetFlagschanges, so this this union
|
|
|
|
//
|
|
|
|
struct {
|
|
|
|
UCHAR Completed : 1;
|
|
|
|
UCHAR FlagsPended : 1;
|
|
|
|
UCHAR TimerSet : 1;
|
|
|
|
UCHAR CancelledFromTimer : 1;
|
|
|
|
UCHAR IgnoreState : 1;
|
|
|
|
} m_TargetFlagsByName;
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// Contains a value from the enum type FxRequestAllocationSource describing
|
|
|
|
// how the irp was allocated
|
|
|
|
//
|
|
|
|
UCHAR m_IrpAllocation;
|
|
|
|
|
|
|
|
BOOLEAN m_Completed;
|
|
|
|
|
|
|
|
BOOLEAN m_Canceled;
|
|
|
|
|
|
|
|
WDFOBJECT_OFFSET_ALIGNED m_SystemBufferOffset;
|
|
|
|
|
|
|
|
union {
|
|
|
|
//
|
|
|
|
// These are flags used by verifier. Set with values from the enum
|
|
|
|
// FxRequestVerifierFlags
|
|
|
|
//
|
|
|
|
SHORT m_VerifierFlags;
|
|
|
|
|
|
|
|
struct {
|
|
|
|
SHORT DriverOwned : 1;
|
|
|
|
SHORT TagRequest : 1;
|
|
|
|
SHORT Forwarded : 1;
|
|
|
|
SHORT DriverDispatch : 1;
|
|
|
|
SHORT DriverCancelable : 1;
|
|
|
|
SHORT DriverInprocessContext : 1;
|
|
|
|
SHORT Cancelled : 1;
|
|
|
|
SHORT Formatted : 1;
|
|
|
|
SHORT SentToTarget : 1;
|
|
|
|
SHORT DriverInEvtIoStopContext : 1;
|
|
|
|
} m_VeriferFlagsByName;
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// If this is !=0, its an indication of outstanding references
|
|
|
|
// on WDM IRP fields such as any system buffers.
|
|
|
|
//
|
|
|
|
LONG m_IrpReferenceCount;
|
|
|
|
|
|
|
|
// This field !=NULL if the request is on an IrpQueue.
|
|
|
|
FxIrpQueue* m_IrpQueue;
|
|
|
|
|
|
|
|
WDFOBJECT_OFFSET_ALIGNED m_OutputBufferOffset;
|
|
|
|
|
|
|
|
union {
|
|
|
|
//
|
|
|
|
// Bit field. Set with values from the enum FxRequestBaseFlags
|
|
|
|
//
|
|
|
|
UCHAR m_RequestBaseFlags;
|
|
|
|
|
|
|
|
struct {
|
|
|
|
UCHAR SystemMdlMapped : 1;
|
|
|
|
UCHAR OutputMdlMapped : 1;
|
|
|
|
UCHAR SyncCleanupContext : 1;
|
|
|
|
} m_RequestBaseFlagsByName;
|
|
|
|
};
|
|
|
|
|
|
|
|
union {
|
|
|
|
//
|
|
|
|
// Bit field. Set with values from the enum FxRequestBaseStaticFlags
|
|
|
|
//
|
|
|
|
|
|
|
|
//
|
|
|
|
UCHAR m_RequestBaseStaticFlags;
|
|
|
|
|
|
|
|
struct {
|
|
|
|
UCHAR SystemBufferValid : 1;
|
|
|
|
UCHAR OutputBufferValid : 1;
|
|
|
|
} m_RequestBaseStaticFlagsByName;
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// Priority boost.
|
|
|
|
//
|
|
|
|
CCHAR m_PriorityBoost;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Contains values from FxRequestCompletionState
|
|
|
|
//
|
|
|
|
BYTE m_CompletionState;
|
|
|
|
|
|
|
|
//
|
|
|
|
// TRUE, request can be completed by the driver.
|
|
|
|
//
|
|
|
|
BOOLEAN m_CanComplete;
|
|
|
|
|
|
|
|
//
|
|
|
|
// If !=NULL, MDL allocated and assocated with the request
|
|
|
|
//
|
|
|
|
PMDL m_AllocatedMdl;
|
|
|
|
};
|
|
|
|
|
|
|
|
#if ((FX_CORE_MODE)==(FX_CORE_KERNEL_MODE))
|
2020-10-16 03:30:51 +00:00
|
|
|
#include "fxrequestbasekm.hpp"
|
|
|
|
#elif ((FX_CORE_MODE)==(FX_CORE_USER_MODE))
|
|
|
|
#include "fxrequestbaseum.hpp"
|
2020-09-24 20:51:15 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#endif // _FXREQUESTBASE_H_
|