732 lines
24 KiB
C
732 lines
24 KiB
C
/*++
|
|
|
|
Copyright (c) 1994 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
RxContx.h
|
|
|
|
Abstract:
|
|
|
|
This module defines RxContext data structure. This structure is used to
|
|
describe an Irp whil it is being processed and contains state information
|
|
that allows global resources to be released as the irp is completed.
|
|
|
|
Author:
|
|
|
|
Joe Linn [JoeLinn] 19-aug-1994
|
|
|
|
Revision History:
|
|
|
|
Balan Sethu Raman [SethuR] 11-4-95
|
|
|
|
Notes:
|
|
|
|
The RX_CONTEXT is a data structure to which additional information provided
|
|
by the various mini redirectors need to be attached. This can be done in one
|
|
of the following three ways
|
|
|
|
1) Allow for context pointers to be defined as part of the RX_CONTEXT which
|
|
the mini redirectors can use to squirrel away their information. This
|
|
implies that every time an RX_CONTEXT is allocated/destroyed the mini
|
|
redirector has to perform an associated allocation/destruction.
|
|
|
|
Since RX_CONTEXT's are created/destroyed in great numbers, this is not an
|
|
acceptable solution.
|
|
|
|
2) The second approach consists of over allocating RX_CONTEXT's by a
|
|
prespecified amount for each mini redirector which is then reserved for
|
|
use by the mini redirector. Such an approach avoids the additional
|
|
allocation/destruction but complicates the RX_CONTEXT management code in
|
|
the wrapper.
|
|
|
|
3) The third approach ( the one that is implemented ) consists of allocating
|
|
a prespecfied area which is the same for all mini redirectors as part of
|
|
each RX_CONTEXT. This is an unformatted area on top of which any desired
|
|
structure can be imposed by the various mini redirectors. Such an approach
|
|
overcomes the disadvantages associated with (1) and (2).
|
|
|
|
All mini redirector writers must try and define the associated mini redirector
|
|
contexts to fit into this area. Those mini redirectors who violate this
|
|
rule will incur a significant performance penalty.
|
|
|
|
--*/
|
|
|
|
#ifndef _RX_CONTEXT_STRUCT_DEFINED_
|
|
#define _RX_CONTEXT_STRUCT_DEFINED_
|
|
#ifndef RDBSS_TRACKER
|
|
#error tracker must be defined right now
|
|
#endif
|
|
|
|
#define RX_TOPLEVELIRP_CONTEXT_SIGNATURE ('LTxR')
|
|
typedef struct _RX_TOPLEVELIRP_CONTEXT {
|
|
union {
|
|
#ifndef __cplusplus
|
|
LIST_ENTRY;
|
|
#endif // __cplusplus
|
|
LIST_ENTRY ListEntry;
|
|
};
|
|
ULONG Signature;
|
|
PRDBSS_DEVICE_OBJECT RxDeviceObject;
|
|
PRX_CONTEXT RxContext;
|
|
PIRP Irp;
|
|
ULONG Flags;
|
|
PVOID Previous;
|
|
PETHREAD Thread;
|
|
} RX_TOPLEVELIRP_CONTEXT, *PRX_TOPLEVELIRP_CONTEXT;
|
|
|
|
BOOLEAN
|
|
RxTryToBecomeTheTopLevelIrp (
|
|
IN OUT PRX_TOPLEVELIRP_CONTEXT TopLevelContext,
|
|
IN PIRP Irp,
|
|
IN PRDBSS_DEVICE_OBJECT RxDeviceObject,
|
|
IN BOOLEAN ForceTopLevel
|
|
);
|
|
|
|
VOID
|
|
__RxInitializeTopLevelIrpContext (
|
|
IN OUT PRX_TOPLEVELIRP_CONTEXT TopLevelContext,
|
|
IN PIRP Irp,
|
|
IN PRDBSS_DEVICE_OBJECT RxDeviceObject,
|
|
IN ULONG Flags
|
|
);
|
|
#define RxInitializeTopLevelIrpContext(a,b,c) {__RxInitializeTopLevelIrpContext(a,b,c,0);}
|
|
|
|
PIRP
|
|
RxGetTopIrpIfRdbssIrp (
|
|
void
|
|
);
|
|
|
|
PRDBSS_DEVICE_OBJECT
|
|
RxGetTopDeviceObjectIfRdbssIrp (
|
|
void
|
|
);
|
|
|
|
VOID
|
|
RxUnwindTopLevelIrp (
|
|
IN OUT PRX_TOPLEVELIRP_CONTEXT TopLevelContext
|
|
);
|
|
|
|
BOOLEAN
|
|
RxIsThisTheTopLevelIrp (
|
|
IN PIRP Irp
|
|
);
|
|
|
|
|
|
#ifdef RDBSS_TRACKER
|
|
typedef struct _RX_FCBTRACKER_CALLINFO {
|
|
ULONG AcquireRelease;
|
|
USHORT SavedTrackerValue;
|
|
USHORT LineNumber;
|
|
PSZ FileName;
|
|
ULONG Flags;
|
|
} RX_FCBTRACKER_CALLINFO, *PRX_FCBTRACKER_CALLINFO;
|
|
#define RDBSS_TRACKER_HISTORY_SIZE 32
|
|
#endif
|
|
|
|
#define MRX_CONTEXT_FIELD_COUNT 4
|
|
#define MRX_CONTEXT_SIZE (sizeof(PVOID) * MRX_CONTEXT_FIELD_COUNT)
|
|
|
|
// Define rxdriver dispatch routine type....almost all of the important routine
|
|
// will have this type.
|
|
|
|
typedef
|
|
NTSTATUS
|
|
(NTAPI *PRX_DISPATCH) ( RXCOMMON_SIGNATURE );
|
|
|
|
typedef struct _NT_CREATE_PARAMETERS {
|
|
ACCESS_MASK DesiredAccess;
|
|
LARGE_INTEGER AllocationSize;
|
|
ULONG FileAttributes;
|
|
ULONG ShareAccess;
|
|
ULONG Disposition;
|
|
ULONG CreateOptions;
|
|
PIO_SECURITY_CONTEXT SecurityContext;
|
|
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
|
|
PVOID DfsContext;
|
|
PVOID DfsNameContext;
|
|
} NT_CREATE_PARAMETERS, *PNT_CREATE_PARAMETERS;
|
|
|
|
typedef struct _RX_CONTEXT {
|
|
// the node type, size and reference count, aka standard header
|
|
|
|
NODE_TYPE_CODE NodeTypeCode;
|
|
NODE_BYTE_SIZE NodeByteSize;
|
|
ULONG ReferenceCount;
|
|
|
|
// the list entry to wire the context to the list of active contexts
|
|
|
|
LIST_ENTRY ContextListEntry;
|
|
|
|
// Major and minor function of the IRP associated with the context
|
|
|
|
UCHAR MajorFunction;
|
|
UCHAR MinorFunction;
|
|
|
|
// this is similar to the same field in Irps; it
|
|
// allows callback routines for async operations
|
|
// to know whether to do asynchronous work or not
|
|
|
|
BOOLEAN PendingReturned;
|
|
|
|
// indicates if the associated request is to be posted to a RDBSS worker thread.
|
|
|
|
BOOLEAN PostRequest;
|
|
|
|
// Originating Device (required for workque algorithms)
|
|
// not currently used but could be used for local minis
|
|
|
|
PDEVICE_OBJECT RealDevice;
|
|
|
|
// ptr to the originating Irp
|
|
PIRP CurrentIrp;
|
|
|
|
// ptr to the IRP stack location
|
|
PIO_STACK_LOCATION CurrentIrpSp;
|
|
|
|
// ptr to the FCB and FOBX, derived from the context pointers in the
|
|
// file object associated with the IRP
|
|
|
|
PMRX_FCB pFcb;
|
|
PMRX_FOBX pFobx;
|
|
PMRX_SRV_OPEN pRelevantSrvOpen;
|
|
PNON_PAGED_FCB NonPagedFcb;
|
|
|
|
// device object calldown (not irpsp.....)
|
|
|
|
PRDBSS_DEVICE_OBJECT RxDeviceObject;
|
|
|
|
// The original thread in which the request was initiated and the last
|
|
// thread in which some processing associated with the context was done
|
|
|
|
PETHREAD OriginalThread;
|
|
PETHREAD LastExecutionThread;
|
|
|
|
PVOID LockManagerContext;
|
|
|
|
// One word of the context is given to rdbss for dbg information
|
|
|
|
PVOID RdbssDbgExtension;
|
|
|
|
RX_SCAVENGER_ENTRY ScavengerEntry;
|
|
|
|
// global serial number for this operation
|
|
|
|
ULONG SerialNumber;
|
|
|
|
// used by minirdrs to see if multiple calls are part
|
|
// of the same larger operation and (therefore) more cacheable
|
|
|
|
ULONG FobxSerialNumber;
|
|
|
|
ULONG Flags;
|
|
|
|
BOOLEAN FcbResourceAcquired;
|
|
BOOLEAN FcbPagingIoResourceAcquired;
|
|
UCHAR MustSucceedDescriptorNumber;
|
|
|
|
// mostly you want the individual components...sometimes it's nice as a pair
|
|
// used to record the status when you can't just return it; e.g., when
|
|
// RXSTATUS is not an appropriate return type or if the consumer of the
|
|
// status didn't call directly (lowiocompletions). minirdrs will not need
|
|
// to set the information directly
|
|
|
|
union {
|
|
struct {
|
|
union {
|
|
NTSTATUS StoredStatus;
|
|
PVOID StoredStatusAlignment;
|
|
};
|
|
ULONG_PTR InformationToReturn;
|
|
};
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
};
|
|
|
|
// the context fields provided for use by the mini redirectors
|
|
// this is defined as a union to force longlong alignment
|
|
|
|
union {
|
|
ULONGLONG ForceLonglongAligmentDummyField;
|
|
PVOID MRxContext[MRX_CONTEXT_FIELD_COUNT];
|
|
};
|
|
|
|
// The following field is included to fix the problem related to write only
|
|
// opens. This introduces a new field for the mini redirector to squirrel
|
|
// some state. This is redundant and should be removed after Windows 2000.
|
|
// Having a unique field reduces the impact of the change that we are making
|
|
// to the specific code path. It will be ideal to use one of the MRXContext
|
|
// fields defined above
|
|
|
|
PVOID WriteOnlyOpenRetryContext;
|
|
|
|
// the cancellation routine to be invoked, set by the mini redirector
|
|
|
|
PMRX_CALLDOWN MRxCancelRoutine;
|
|
|
|
// private dispatch, if any. used in fspdisp
|
|
|
|
PRX_DISPATCH ResumeRoutine;
|
|
|
|
// for posting to worker threads
|
|
// the minirdr can use this for posting within the minirdr
|
|
// a potential problem can arise if the minirdr relies on this both
|
|
// for queueing async stuff and for queueing cancel stuff
|
|
|
|
// The OverflowListEntry is used for queueing items to the overflow queue.
|
|
// This is seperate now to allow us to distinguish between an item in the overflow
|
|
// queue and one in the active work queue (for cancellation logic)
|
|
|
|
RX_WORK_QUEUE_ITEM WorkQueueItem;
|
|
LIST_ENTRY OverflowListEntry;
|
|
|
|
// this event is used for synchronous operations
|
|
// that have to i/f with an underlying async service. it can be used
|
|
// by the minirdr with the following provisions:
|
|
// 1) on entering the minirdr through lowio, it is set to the
|
|
// nonsignaled state (but a wise user will reset it before using
|
|
// it....particularly if it's used multiple times.
|
|
// 2) if you are returning STATUS_PENDING on a sync operation, you must
|
|
// return with it set to the nonsignaled state; that is, either
|
|
// you don't use it or you reset it in this case
|
|
|
|
KEVENT SyncEvent;
|
|
|
|
//this is a list head of operations that are to be released on completion
|
|
|
|
LIST_ENTRY BlockedOperations;
|
|
|
|
//this is the mutex that controls serialization of the blocked operations
|
|
|
|
PFAST_MUTEX BlockedOpsMutex;
|
|
|
|
// these links are used to serialize pipe operations on a
|
|
//per-file-object basis AND FOR LOTS OF OTHER STUFF
|
|
|
|
LIST_ENTRY RxContextSerializationQLinks;
|
|
|
|
union {
|
|
struct {
|
|
union {
|
|
FS_INFORMATION_CLASS FsInformationClass;
|
|
FILE_INFORMATION_CLASS FileInformationClass;
|
|
};
|
|
PVOID Buffer;
|
|
union {
|
|
LONG Length;
|
|
LONG LengthRemaining;
|
|
};
|
|
BOOLEAN ReplaceIfExists;
|
|
BOOLEAN AdvanceOnly;
|
|
} Info;
|
|
|
|
struct {
|
|
UNICODE_STRING SuppliedPathName;
|
|
NET_ROOT_TYPE NetRootType;
|
|
PIO_SECURITY_CONTEXT pSecurityContext;
|
|
} PrefixClaim;
|
|
};
|
|
|
|
// THIS UNION MUST BE LAST....AT SOME POINT, WE MAY START ALLOCATING
|
|
// SMALLER PER OPERATION!
|
|
|
|
union{
|
|
struct {
|
|
NT_CREATE_PARAMETERS NtCreateParameters; // a copy of the createparameters
|
|
ULONG ReturnedCreateInformation;
|
|
PWCH CanonicalNameBuffer; // if the canonical name is larger than available buffer
|
|
PRX_PREFIX_ENTRY NetNamePrefixEntry; // the entry returned by the lookup....for dereferencing
|
|
|
|
PMRX_SRV_CALL pSrvCall; // Server Call being used
|
|
PMRX_NET_ROOT pNetRoot; // Net Root being used
|
|
PMRX_V_NET_ROOT pVNetRoot; // Virtual Net Root
|
|
//PMRX_SRV_OPEN pSrvOpen; // Server Open
|
|
|
|
PVOID EaBuffer;
|
|
ULONG EaLength;
|
|
|
|
ULONG SdLength;
|
|
|
|
ULONG PipeType;
|
|
ULONG PipeReadMode;
|
|
ULONG PipeCompletionMode;
|
|
|
|
USHORT Flags;
|
|
NET_ROOT_TYPE Type; // Type of Net Root(Pipe/File/Mailslot..)
|
|
|
|
BOOLEAN FcbAcquired;
|
|
BOOLEAN TryForScavengingOnSharingViolation;
|
|
BOOLEAN ScavengingAlreadyTried;
|
|
|
|
BOOLEAN ThisIsATreeConnectOpen;
|
|
BOOLEAN TreeConnectOpenDeferred;
|
|
UNICODE_STRING TransportName;
|
|
UNICODE_STRING UserName;
|
|
UNICODE_STRING Password;
|
|
UNICODE_STRING UserDomainName;
|
|
} Create;
|
|
struct {
|
|
ULONG FileIndex;
|
|
BOOLEAN RestartScan;
|
|
BOOLEAN ReturnSingleEntry;
|
|
BOOLEAN IndexSpecified;
|
|
BOOLEAN InitialQuery;
|
|
} QueryDirectory;
|
|
struct {
|
|
PMRX_V_NET_ROOT pVNetRoot;
|
|
} NotifyChangeDirectory;
|
|
struct {
|
|
PUCHAR UserEaList;
|
|
ULONG UserEaListLength;
|
|
ULONG UserEaIndex;
|
|
BOOLEAN RestartScan;
|
|
BOOLEAN ReturnSingleEntry;
|
|
BOOLEAN IndexSpecified;
|
|
} QueryEa;
|
|
struct {
|
|
SECURITY_INFORMATION SecurityInformation;
|
|
ULONG Length;
|
|
} QuerySecurity;
|
|
struct {
|
|
SECURITY_INFORMATION SecurityInformation;
|
|
PSECURITY_DESCRIPTOR SecurityDescriptor;
|
|
} SetSecurity;
|
|
struct {
|
|
ULONG Length;
|
|
PSID StartSid;
|
|
PFILE_GET_QUOTA_INFORMATION SidList;
|
|
ULONG SidListLength;
|
|
BOOLEAN RestartScan;
|
|
BOOLEAN ReturnSingleEntry;
|
|
BOOLEAN IndexSpecified;
|
|
} QueryQuota;
|
|
struct {
|
|
ULONG Length;
|
|
|
|
} SetQuota;
|
|
struct {
|
|
PV_NET_ROOT VNetRoot;
|
|
PSRV_CALL SrvCall;
|
|
PNET_ROOT NetRoot;
|
|
} DosVolumeFunction;
|
|
struct {
|
|
ULONG FlagsForLowIo;
|
|
LOWIO_CONTEXT LowIoContext; // the LOWIO parameters
|
|
}; //no name here....
|
|
LUID FsdUid;
|
|
} ;
|
|
//CODE.IMPROVEMENT remove this to wrapperdbgprivates
|
|
PWCH AlsoCanonicalNameBuffer; // if the canonical name is larger than available buffer
|
|
PUNICODE_STRING LoudCompletionString;
|
|
#ifdef RDBSS_TRACKER
|
|
LONG AcquireReleaseFcbTrackerX;
|
|
ULONG TrackerHistoryPointer;
|
|
#endif
|
|
#ifdef RDBSS_TRACKER
|
|
RX_FCBTRACKER_CALLINFO TrackerHistory[RDBSS_TRACKER_HISTORY_SIZE];
|
|
#endif
|
|
|
|
ULONG dwShadowCritOwner;
|
|
|
|
} RX_CONTEXT;
|
|
|
|
#define RX_DEFINE_RXC_FLAG(a,c) RX_DEFINE_FLAG(RX_CONTEXT_FLAG_##a,c,0xffffffff)
|
|
|
|
typedef enum {
|
|
RX_DEFINE_RXC_FLAG(FROM_POOL, 0)
|
|
RX_DEFINE_RXC_FLAG(WAIT, 1)
|
|
RX_DEFINE_RXC_FLAG(WRITE_THROUGH, 2)
|
|
RX_DEFINE_RXC_FLAG(FLOPPY, 3)
|
|
RX_DEFINE_RXC_FLAG(RECURSIVE_CALL, 4)
|
|
RX_DEFINE_RXC_FLAG(THIS_DEVICE_TOP_LEVEL, 5)
|
|
RX_DEFINE_RXC_FLAG(DEFERRED_WRITE, 6)
|
|
RX_DEFINE_RXC_FLAG(VERIFY_READ, 7)
|
|
RX_DEFINE_RXC_FLAG(STACK_IO_CONTEZT, 8)
|
|
RX_DEFINE_RXC_FLAG(IN_FSP, 9)
|
|
RX_DEFINE_RXC_FLAG(CREATE_MAILSLOT, 10)
|
|
RX_DEFINE_RXC_FLAG(MAILSLOT_REPARSE, 11)
|
|
RX_DEFINE_RXC_FLAG(ASYNC_OPERATION, 12)
|
|
RX_DEFINE_RXC_FLAG(NO_COMPLETE_FROM_FSP, 13)
|
|
RX_DEFINE_RXC_FLAG(POST_ON_STABLE_CONDITION, 14)
|
|
RX_DEFINE_RXC_FLAG(FSP_DELAYED_OVERFLOW_QUEUE, 15)
|
|
RX_DEFINE_RXC_FLAG(FSP_CRITICAL_OVERFLOW_QUEUE, 16)
|
|
RX_DEFINE_RXC_FLAG(MINIRDR_INVOKED, 17)
|
|
RX_DEFINE_RXC_FLAG(WAITING_FOR_RESOURCE, 18)
|
|
RX_DEFINE_RXC_FLAG(CANCELLED, 19)
|
|
RX_DEFINE_RXC_FLAG(SYNC_EVENT_WAITERS, 20)
|
|
RX_DEFINE_RXC_FLAG(NO_PREPOSTING_NEEDED, 21)
|
|
RX_DEFINE_RXC_FLAG(BYPASS_VALIDOP_CHECK, 22)
|
|
RX_DEFINE_RXC_FLAG(BLOCKED_PIPE_RESUME, 23)
|
|
RX_DEFINE_RXC_FLAG(IN_SERIALIZATION_QUEUE, 24)
|
|
RX_DEFINE_RXC_FLAG(NO_EXCEPTION_BREAKPOINT, 25)
|
|
RX_DEFINE_RXC_FLAG(NEEDRECONNECT, 26)
|
|
RX_DEFINE_RXC_FLAG(MUST_SUCCEED, 27)
|
|
RX_DEFINE_RXC_FLAG(MUST_SUCCEED_NONBLOCKING, 28)
|
|
RX_DEFINE_RXC_FLAG(MUST_SUCCEED_ALLOCATED, 29)
|
|
RX_DEFINE_RXC_FLAG(MINIRDR_INITIATED, 31)
|
|
} RX_CONTEXT_FLAGS;
|
|
|
|
#define RX_CONTEXT_PRESERVED_FLAGS (RX_CONTEXT_FLAG_FROM_POOL | \
|
|
RX_CONTEXT_FLAG_MUST_SUCCEED_ALLOCATED | \
|
|
RX_CONTEXT_FLAG_IN_FSP)
|
|
|
|
#define RX_CONTEXT_INITIALIZATION_FLAGS (RX_CONTEXT_FLAG_WAIT | \
|
|
RX_CONTEXT_FLAG_MUST_SUCCEED | \
|
|
RX_CONTEXT_FLAG_MUST_SUCCEED_NONBLOCKING)
|
|
|
|
#define RX_DEFINE_RXC_CREATE_FLAG(a,c) RX_DEFINE_FLAG(RX_CONTEXT_CREATE_FLAG_##a,c,0xffff)
|
|
|
|
typedef enum {
|
|
RX_DEFINE_RXC_CREATE_FLAG(UNC_NAME, 0)
|
|
RX_DEFINE_RXC_CREATE_FLAG(STRIPPED_TRAILING_BACKSLASH, 1)
|
|
RX_DEFINE_RXC_CREATE_FLAG(ADDEDBACKSLASH, 2)
|
|
RX_DEFINE_RXC_CREATE_FLAG(REPARSE,3)
|
|
RX_DEFINE_RXC_CREATE_FLAG(SPECIAL_PATH, 4)
|
|
} RX_CONTEXT_CREATE_FLAGS;
|
|
|
|
#define RX_DEFINE_RXC_LOWIO_FLAG(a,c) RX_DEFINE_FLAG(RXCONTEXT_FLAG4LOWIO_##a,c,0xffffffff)
|
|
|
|
typedef enum {
|
|
RX_DEFINE_RXC_LOWIO_FLAG(PIPE_OPERATION, 0)
|
|
RX_DEFINE_RXC_LOWIO_FLAG(PIPE_SYNC_OPERATION, 1)
|
|
RX_DEFINE_RXC_LOWIO_FLAG(READAHEAD, 2)
|
|
RX_DEFINE_RXC_LOWIO_FLAG(THIS_READ_ENLARGED, 3)
|
|
RX_DEFINE_RXC_LOWIO_FLAG(THIS_IO_BUFFERED, 4)
|
|
RX_DEFINE_RXC_LOWIO_FLAG(LOCK_FCB_RESOURCE_HELD, 5)
|
|
RX_DEFINE_RXC_LOWIO_FLAG(LOCK_WAS_QUEUED_IN_LOCKMANAGER, 6)
|
|
#ifdef __cplusplus
|
|
} RX_CONTEXT_LOWIO_FLAGS;
|
|
#else // !__cplusplus
|
|
} RX_CONTEXT_CREATE_FLAGS;
|
|
#endif // __cplusplus
|
|
|
|
// Macros used to control whether the wrapper breakpoints on an exception
|
|
#if DBG
|
|
#define RxSaveAndSetExceptionNoBreakpointFlag(RXCONTEXT,_yyy){ \
|
|
_yyy = RxContext->Flags & RX_CONTEXT_FLAG_NO_EXCEPTION_BREAKPOINT; \
|
|
RxContext->Flags |= RX_CONTEXT_FLAG_NO_EXCEPTION_BREAKPOINT; \
|
|
}
|
|
#define RxRestoreExceptionNoBreakpointFlag(RXCONTEXT,_yyy){ \
|
|
RxContext->Flags &= ~RX_CONTEXT_FLAG_NO_EXCEPTION_BREAKPOINT; \
|
|
RxContext->Flags |= _yyy; \
|
|
}
|
|
#else
|
|
#define RxSaveAndSetExceptionNoBreakpointFlag(_xxx,_yyy)
|
|
#define RxRestoreExceptionNoBreakpointFlag(_xxx,_yyy)
|
|
#endif
|
|
|
|
// a macro used to ensure that a context hasn't been freed during a wait
|
|
#if DBG
|
|
VOID
|
|
__RxItsTheSameContext(
|
|
PRX_CONTEXT RxContext,
|
|
ULONG CapturedRxContextSerialNumber,
|
|
ULONG Line,
|
|
PSZ File
|
|
);
|
|
#define RxItsTheSameContext() {__RxItsTheSameContext(RxContext,CapturedRxContextSerialNumber,__LINE__,__FILE__);}
|
|
#else
|
|
#define RxItsTheSameContext() {NOTHING;}
|
|
#endif
|
|
|
|
extern NPAGED_LOOKASIDE_LIST RxContextLookasideList;
|
|
|
|
// Macros used in the RDBSS to wrap mini rdr calldowns
|
|
|
|
#define MINIRDR_CALL_THROUGH(STATUS,DISPATCH,FUNC,ARGLIST) \
|
|
{ \
|
|
ASSERT(DISPATCH); \
|
|
ASSERT( NodeType(DISPATCH) == RDBSS_NTC_MINIRDR_DISPATCH ); \
|
|
if (DISPATCH->FUNC == NULL) { \
|
|
STATUS = STATUS_NOT_IMPLEMENTED; \
|
|
} else { \
|
|
RxDbgTrace(0, Dbg, ("MiniRdr Calldown - %s\n",#FUNC)); \
|
|
STATUS = DISPATCH->FUNC ARGLIST; \
|
|
} \
|
|
}
|
|
|
|
#define MINIRDR_CALL(STATUS,CONTEXT,DISPATCH,FUNC,ARGLIST) \
|
|
{ \
|
|
ASSERT(DISPATCH); \
|
|
ASSERT( NodeType(DISPATCH) == RDBSS_NTC_MINIRDR_DISPATCH ); \
|
|
if ( DISPATCH->FUNC == NULL) { \
|
|
STATUS = STATUS_NOT_IMPLEMENTED; \
|
|
} else { \
|
|
if (!BooleanFlagOn((CONTEXT)->Flags,RX_CONTEXT_FLAG_CANCELLED)) { \
|
|
RxDbgTrace(0, Dbg, ("MiniRdr Calldown - %s\n",#FUNC)); \
|
|
RtlZeroMemory(&((CONTEXT)->MRxContext[0]), \
|
|
sizeof((CONTEXT)->MRxContext)); \
|
|
STATUS = DISPATCH->FUNC ARGLIST; \
|
|
} else { \
|
|
STATUS = STATUS_CANCELLED; \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
|
|
//VOID
|
|
//RxWaitSync (
|
|
// IN PRX_CONTEXT RxContext
|
|
// )
|
|
|
|
#define RxWaitSync(RxContext) \
|
|
RxDbgTrace(+1, Dbg, ("RxWaitSync, RxContext = %08lx\n", (RxContext))); \
|
|
(RxContext)->Flags |= RX_CONTEXT_FLAG_SYNC_EVENT_WAITERS; \
|
|
KeWaitForSingleObject( &(RxContext)->SyncEvent, \
|
|
Executive, KernelMode, FALSE, NULL ); \
|
|
RxDbgTrace(-1, Dbg, ("RxWaitSync -> VOID\n", 0 ))
|
|
|
|
//VOID
|
|
//RxSignalSynchronousWaiter (
|
|
// IN PRX_CONTEXT RxContext
|
|
// )
|
|
|
|
#define RxSignalSynchronousWaiter(RxContext) \
|
|
(RxContext)->Flags &= ~RX_CONTEXT_FLAG_SYNC_EVENT_WAITERS; \
|
|
KeSetEvent( &(RxContext)->SyncEvent, 0, FALSE )
|
|
|
|
|
|
#define RxInsertContextInSerializationQueue(pSerializationQueue,RxContext) \
|
|
(RxContext)->Flags |= RX_CONTEXT_FLAG_IN_SERIALIZATION_QUEUE; \
|
|
InsertTailList(pSerializationQueue,&((RxContext)->RxContextSerializationQLinks))
|
|
|
|
INLINE PRX_CONTEXT
|
|
RxRemoveFirstContextFromSerializationQueue(PLIST_ENTRY pSerializationQueue)
|
|
{
|
|
if (IsListEmpty(pSerializationQueue)) {
|
|
return NULL;
|
|
} else {
|
|
PRX_CONTEXT pContext = (PRX_CONTEXT)(CONTAINING_RECORD(pSerializationQueue->Flink,
|
|
RX_CONTEXT,
|
|
RxContextSerializationQLinks));
|
|
|
|
RemoveEntryList(pSerializationQueue->Flink);
|
|
|
|
pContext->RxContextSerializationQLinks.Flink = NULL;
|
|
pContext->RxContextSerializationQLinks.Blink = NULL;
|
|
return pContext;
|
|
}
|
|
}
|
|
|
|
// The following macros provide a mechanism for doing an en masse transfer
|
|
// from one list onto another. This provides a powerful paradigm for dealing
|
|
// with DPC level processing of lists.
|
|
|
|
#define RxTransferList(pDestination,pSource) \
|
|
if (IsListEmpty((pSource))) { \
|
|
InitializeListHead((pDestination)); \
|
|
} else { \
|
|
*(pDestination) = *(pSource); \
|
|
(pDestination)->Flink->Blink = (pDestination); \
|
|
(pDestination)->Blink->Flink = (pDestination); \
|
|
InitializeListHead((pSource)); \
|
|
}
|
|
|
|
#define RxTransferListWithMutex(pDestination,pSource,pMutex) \
|
|
{ \
|
|
ExAcquireFastMutex(pMutex); \
|
|
RxTransferList(pDestination,pSource); \
|
|
ExReleaseFastMutex(pMutex); \
|
|
}
|
|
|
|
|
|
VOID RxInitializeRxContexter(void);
|
|
VOID RxUninitializeRxContexter(void);
|
|
|
|
NTSTATUS
|
|
RxCancelNotifyChangeDirectoryRequestsForVNetRoot(
|
|
PV_NET_ROOT pVNetRoot,
|
|
BOOLEAN ForceFilesClosed
|
|
);
|
|
|
|
VOID
|
|
RxCancelNotifyChangeDirectoryRequestsForFobx(
|
|
PFOBX pFobx);
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
RxSetMinirdrCancelRoutine(
|
|
IN OUT PRX_CONTEXT RxContext,
|
|
IN PMRX_CALLDOWN MRxCancelRoutine);
|
|
|
|
VOID
|
|
NTAPI
|
|
RxInitializeContext(
|
|
IN PIRP Irp,
|
|
IN PRDBSS_DEVICE_OBJECT RxDeviceObject,
|
|
IN ULONG InitialContextFlags,
|
|
IN OUT PRX_CONTEXT RxContext);
|
|
|
|
PRX_CONTEXT
|
|
NTAPI
|
|
RxCreateRxContext (
|
|
IN PIRP Irp,
|
|
IN PRDBSS_DEVICE_OBJECT RxDeviceObject,
|
|
IN ULONG InitialContextFlags
|
|
);
|
|
|
|
VOID
|
|
NTAPI
|
|
RxPrepareContextForReuse(
|
|
IN OUT PRX_CONTEXT RxContext);
|
|
|
|
VOID
|
|
NTAPI
|
|
RxDereferenceAndDeleteRxContext_Real (
|
|
IN PRX_CONTEXT RxContext
|
|
);
|
|
|
|
VOID
|
|
NTAPI
|
|
RxReinitializeContext(
|
|
IN OUT PRX_CONTEXT RxContext);
|
|
|
|
#if DBG
|
|
#define RxDereferenceAndDeleteRxContext(RXCONTEXT) { \
|
|
RxDereferenceAndDeleteRxContext_Real((RXCONTEXT)); \
|
|
(RXCONTEXT) = NULL; \
|
|
}
|
|
#else
|
|
#define RxDereferenceAndDeleteRxContext(RXCONTEXT) { \
|
|
RxDereferenceAndDeleteRxContext_Real((RXCONTEXT)); \
|
|
}
|
|
#endif //
|
|
|
|
extern FAST_MUTEX RxContextPerFileSerializationMutex;
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
__RxSynchronizeBlockingOperationsMaybeDroppingFcbLock(
|
|
IN OUT PRX_CONTEXT RxContext,
|
|
IN OUT PLIST_ENTRY BlockingIoQ,
|
|
IN BOOLEAN DropFcbLock
|
|
);
|
|
#define RxSynchronizeBlockingOperationsAndDropFcbLock(__x,__y) \
|
|
__RxSynchronizeBlockingOperationsMaybeDroppingFcbLock(__x,__y,TRUE)
|
|
#define RxSynchronizeBlockingOperations(__x,__y) \
|
|
__RxSynchronizeBlockingOperationsMaybeDroppingFcbLock(__x,__y,FALSE)
|
|
|
|
VOID
|
|
NTAPI
|
|
RxResumeBlockedOperations_Serially(
|
|
IN OUT PRX_CONTEXT RxContext,
|
|
IN OUT PLIST_ENTRY BlockingIoQ
|
|
);
|
|
|
|
VOID
|
|
RxResumeBlockedOperations_ALL(
|
|
IN OUT PRX_CONTEXT RxContext
|
|
);
|
|
|
|
|
|
VOID
|
|
RxCancelBlockingOperation(
|
|
IN OUT PRX_CONTEXT RxContext);
|
|
|
|
VOID
|
|
RxRemoveOperationFromBlockingQueue(
|
|
IN OUT PRX_CONTEXT RxContext);
|
|
|
|
|
|
#endif // _RX_CONTEXT_STRUCT_DEFINED_
|
|
|