You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
584 lines
15 KiB
584 lines
15 KiB
/*++
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
umrx.h
|
|
|
|
Abstract:
|
|
|
|
This module defines the types and functions which make up the reflector
|
|
library. These functions are used by the miniredirs to reflect calls upto
|
|
the user mode.
|
|
|
|
Author:
|
|
|
|
Rohan Kumar [rohank] 14-March-1999
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#ifndef _UMRX_H_
|
|
#define _UMRX_H_
|
|
|
|
#include "align.h"
|
|
#include "status.h"
|
|
|
|
//
|
|
// Unreferenced local variable.
|
|
//
|
|
#pragma warning(error:4101)
|
|
|
|
IMPORTANT_STRUCTURE(UMRX_ASYNCENGINE_CONTEXT);
|
|
IMPORTANT_STRUCTURE(UMRX_DEVICE_OBJECT);
|
|
|
|
//
|
|
// The BUGBUG macro expands to NOTHING. Its basically used to describe problems
|
|
// associated with the current code.
|
|
//
|
|
#define BUGBUG(_x_)
|
|
|
|
//
|
|
// The argument signatures that are used in a lot of the reflector and miniredir
|
|
// functions.
|
|
//
|
|
#define UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE \
|
|
PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext, \
|
|
PRX_CONTEXT RxContext
|
|
|
|
//
|
|
// The arguments that are passed to a lof of the reflector and miniredir
|
|
// functions.
|
|
//
|
|
#define UMRX_ASYNCENGINE_ARGUMENTS AsyncEngineContext,RxContext
|
|
|
|
//
|
|
// The global list of all the currently active AsyncEngineContexts and the
|
|
// resource that is used to synchronize access to it.
|
|
//
|
|
extern LIST_ENTRY UMRxAsyncEngineContextList;
|
|
extern ERESOURCE UMRxAsyncEngineContextListLock;
|
|
|
|
//
|
|
// The ASYNCENG_HISTORY structure which is used to keep track of the history
|
|
// of AsyncEngineContext structure.
|
|
//
|
|
#define UMRX_ASYNCENG_HISTORY_SIZE 32
|
|
typedef struct _ASYNCENG_HISTORY {
|
|
ULONG Next;
|
|
ULONG Submits;
|
|
struct {
|
|
ULONG Longs[2];
|
|
} Markers[UMRX_ASYNCENG_HISTORY_SIZE];
|
|
} ASYNCENG_HISTORY, *PASYNCENG_HISTORY;
|
|
|
|
//
|
|
// This macro defines the flags of the AsyncEngineContext strucutre.
|
|
//
|
|
#define UMRX_ASYNCENG_DEFINE_CTX_FLAG(a, c) \
|
|
RX_DEFINE_FLAG(UMRX_ASYNCENG_CTX_FLAG_##a, c, 0xffff)
|
|
typedef enum {
|
|
UMRX_ASYNCENG_DEFINE_CTX_FLAG(ASYNC_OPERATION, 0)
|
|
} UMRX_ASYNCENG_CONTEXT_FLAGS;
|
|
|
|
//
|
|
// The prototype of the ContextFormatRoutine specified by the Miniredir.
|
|
//
|
|
typedef
|
|
NTSTATUS
|
|
(*PUMRX_ASYNCENG_CONTEXT_FORMAT_ROUTINE) (
|
|
PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
|
|
USHORT FormatContext
|
|
);
|
|
|
|
//
|
|
// The prototype of the continuation routine specified by the Miniredir.
|
|
//
|
|
typedef
|
|
NTSTATUS
|
|
(*PUMRX_ASYNCENG_CONTINUE_ROUTINE) (
|
|
UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE
|
|
);
|
|
|
|
//
|
|
// The prototype of the format routine specified by the Miniredir.
|
|
//
|
|
typedef
|
|
NTSTATUS
|
|
(*PUMRX_ASYNCENG_USERMODE_FORMAT_ROUTINE) (
|
|
UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
|
|
PUMRX_USERMODE_WORKITEM_HEADER WorkItem,
|
|
ULONG WorkItemLength,
|
|
PULONG_PTR ReturnedLength
|
|
);
|
|
|
|
//
|
|
// The prototype of the precompletion routine specified by the Miniredir.
|
|
//
|
|
typedef
|
|
BOOL
|
|
(*PUMRX_ASYNCENG_USERMODE_PRECOMPLETION_ROUTINE) (
|
|
UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
|
|
PUMRX_USERMODE_WORKITEM_HEADER WorkItem,
|
|
ULONG WorkItemLength,
|
|
BOOL OperationCancelled
|
|
);
|
|
|
|
//
|
|
// The various states of an AsyncEngineContext.
|
|
//
|
|
typedef enum _UMRX_ASYNCENGINE_CONTEXT_STATE {
|
|
UMRxAsyncEngineContextAllocated = 0,
|
|
UMRxAsyncEngineContextInUserMode,
|
|
UMRxAsyncEngineContextBackFromUserMode,
|
|
UMRxAsyncEngineContextCancelled
|
|
} UMRX_ASYNCENGINE_CONTEXT_STATE;
|
|
|
|
//
|
|
// The AsyncEngineContext strucutre that is shared across all the miniredirs.
|
|
// It contains information common to all the miniredirs.
|
|
//
|
|
typedef struct _UMRX_ASYNCENGINE_CONTEXT {
|
|
|
|
//
|
|
// The header below is a common header which is present at the start of all
|
|
// the data strucutres manipulated by the RDBSS and the MiniRedirs. It is
|
|
// used for debugging purposes and for keeping track of the number of times
|
|
// a node (data structure) has been referenced.
|
|
//
|
|
MRX_NORMAL_NODE_HEADER;
|
|
|
|
//
|
|
// This listEntry is used to insert the AsyncEngineContext into the global
|
|
// UMRxAsyncEngineContextList list.
|
|
//
|
|
LIST_ENTRY ActiveContextsListEntry;
|
|
|
|
UMRX_ASYNCENGINE_CONTEXT_STATE AsyncEngineContextState;
|
|
|
|
//
|
|
// Is this context handling a synchronous or an asynchronous operation?
|
|
//
|
|
BOOL AsyncOperation;
|
|
|
|
//
|
|
// If this is an AsyncOperation, then RxLowIoCompletion is called only if
|
|
// this is set to TRUE. Some operations like CreateSrvCall are Async but
|
|
// do not need LowIoCompletion to be called.
|
|
//
|
|
BOOL ShouldCallLowIoCompletion;
|
|
|
|
//
|
|
// Was IoMarkIrpPending called on the Irp that is being handled by this
|
|
// AsyncEngineContext?
|
|
//
|
|
BOOL ContextMarkedPending;
|
|
|
|
//
|
|
// The system tick count when this context was created. This value is used
|
|
// in timing out requests that take more than a specified time.
|
|
//
|
|
LARGE_INTEGER CreationTimeInTickCount;
|
|
|
|
//
|
|
// The RxContext data structure that is passed in by the RDBSS. It describes
|
|
// an Irp while it is being processed and contains state information that
|
|
// allows global resources to be released as the Irp is completed.
|
|
//
|
|
PRX_CONTEXT RxContext;
|
|
|
|
//
|
|
// The context ptr that saves the incoming (from RDBSS) state of
|
|
// MRxContext[0] (which is a field of the RxContext data structure).
|
|
//
|
|
PVOID SavedMinirdrContextPtr;
|
|
|
|
//
|
|
// Pointer to IRP used to call down to the underlying file system.
|
|
//
|
|
PIRP CalldownIrp;
|
|
|
|
//
|
|
// The I/O status block is set to indicate the status of a given I/O
|
|
// request.
|
|
//
|
|
union {
|
|
IO_STATUS_BLOCK;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
};
|
|
|
|
//
|
|
// The work item which is queued to be completed.
|
|
//
|
|
RX_WORK_QUEUE_ITEM WorkQueueItem;
|
|
|
|
//
|
|
// Flags that set and indicate the state of the AsyncEngineContext.
|
|
//
|
|
USHORT Flags;
|
|
|
|
BOOLEAN FileInformationCached;
|
|
BOOLEAN FileNotExists;
|
|
|
|
BOOLEAN ParentDirInfomationCached;
|
|
BOOLEAN ParentDirIsEncrypted;
|
|
|
|
//
|
|
// The continuation routine which is to be called for this I/O request.
|
|
//
|
|
PUMRX_ASYNCENG_CONTINUE_ROUTINE Continuation;
|
|
|
|
//
|
|
// List of shared memory allocations for this context. All are freed when
|
|
// this context is freed.
|
|
//
|
|
LIST_ENTRY AllocationList;
|
|
|
|
//
|
|
// The UserMode structure.
|
|
//
|
|
struct {
|
|
//
|
|
// The work entry thats inserted into the Queue of the
|
|
// UMRdrDeviceObject.
|
|
//
|
|
LIST_ENTRY WorkQueueLinks;
|
|
|
|
//
|
|
// The routine that formats the arguments of the I/O request which is
|
|
// reflected to the usermode.
|
|
//
|
|
PUMRX_ASYNCENG_USERMODE_FORMAT_ROUTINE FormatRoutine;
|
|
|
|
//
|
|
// The routine that is called (to do some final cleanup etc.)just before
|
|
// an I/O operation that was sent to the usermode gets completed.
|
|
//
|
|
//
|
|
PUMRX_ASYNCENG_USERMODE_PRECOMPLETION_ROUTINE PrecompletionRoutine;
|
|
|
|
//
|
|
// The event used to signal a thread waiting for a MID to be freed up.
|
|
//
|
|
KEVENT WaitForMidEvent;
|
|
|
|
//
|
|
// The serial number set before sending this conttext to the user mode.
|
|
//
|
|
ULONG CallUpSerialNumber;
|
|
|
|
//
|
|
// The MID value of the context.
|
|
//
|
|
USHORT CallUpMid;
|
|
|
|
union {
|
|
struct {
|
|
//
|
|
//
|
|
//
|
|
PBYTE CapturedOutputBuffer;
|
|
};
|
|
//
|
|
//
|
|
//
|
|
ULONG SetInfoBufferLength;
|
|
};
|
|
} UserMode;
|
|
|
|
//
|
|
// The context passed to the function called in the context of a worker
|
|
// thread.
|
|
//
|
|
PVOID PostedOpContext;
|
|
|
|
//
|
|
// The completion status of a posted operation. Operations get posted to
|
|
// worker threads created by RDBSS.
|
|
//
|
|
NTSTATUS PostedOpStatus;
|
|
|
|
//
|
|
// This is set to the global serialnumber (for this operation) of RxContext.
|
|
//
|
|
ULONG SerialNumber;
|
|
|
|
//
|
|
// Used to keep track of the history of the operations on the AsynEngCtx.
|
|
//
|
|
ASYNCENG_HISTORY History;
|
|
|
|
//
|
|
// This is set to the CurrentIrp in RxContext which points to the
|
|
// origination irp.
|
|
//
|
|
PIRP RxContextCapturedRequestPacket;
|
|
|
|
} UMRX_ASYNCENGINE_CONTEXT, *PUMRX_ASYNCENGINE_CONTEXT;
|
|
|
|
#define SIZEOF_UMRX_ASYNCENGINE_CONTEXT sizeof(UMRX_ASYNCENGINE_CONTEXT)
|
|
|
|
//
|
|
// The API of the reflector library exposed to the miniredirs. These are the
|
|
// only functions of the library that the miniredirs should use to reflect
|
|
// the requests to the user mode.
|
|
//
|
|
|
|
NTSTATUS
|
|
UMRxInitializeDeviceObject(
|
|
OUT PUMRX_DEVICE_OBJECT UMRefDeviceObject,
|
|
IN USHORT MaxNumberMids,
|
|
IN USHORT InitialMids,
|
|
IN SIZE_T HeapSize
|
|
);
|
|
|
|
NTSTATUS
|
|
UMRxCleanUpDeviceObject(
|
|
PUMRX_DEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
NTSTATUS
|
|
UMRxAsyncEngOuterWrapper(
|
|
IN PRX_CONTEXT RxContext,
|
|
IN ULONG AdditionalBytes,
|
|
IN PUMRX_ASYNCENG_CONTEXT_FORMAT_ROUTINE ContextFormatRoutine,
|
|
USHORT FormatContext,
|
|
IN PUMRX_ASYNCENG_CONTINUE_ROUTINE Continuation,
|
|
IN PSZ RoutineName
|
|
);
|
|
|
|
NTSTATUS
|
|
UMRxSubmitAsyncEngUserModeRequest(
|
|
UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
|
|
PUMRX_ASYNCENG_USERMODE_FORMAT_ROUTINE FormatRoutine,
|
|
PUMRX_ASYNCENG_USERMODE_PRECOMPLETION_ROUTINE PrecompletionRoutine
|
|
);
|
|
|
|
BOOLEAN
|
|
UMRxFinalizeAsyncEngineContext(
|
|
IN OUT PUMRX_ASYNCENGINE_CONTEXT *AEContext
|
|
);
|
|
|
|
NTSTATUS
|
|
UMRxAsyncEngineCalldownIrpCompletion (
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP CalldownIrp,
|
|
IN OUT PVOID Context
|
|
);
|
|
|
|
typedef
|
|
NTSTATUS
|
|
(*PUMRX_POSTABLE_OPERATION) (
|
|
IN OUT PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext
|
|
);
|
|
NTSTATUS
|
|
UMRxPostOperation (
|
|
UMRX_ASYNCENGINE_ARGUMENT_SIGNATURE,
|
|
IN OUT PVOID PostedOpContext,
|
|
IN PUMRX_POSTABLE_OPERATION Operation
|
|
);
|
|
|
|
PBYTE
|
|
UMRxAllocateSecondaryBuffer (
|
|
IN OUT PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
|
|
SIZE_T Length
|
|
);
|
|
|
|
NTSTATUS
|
|
UMRxFreeSecondaryBuffer (
|
|
IN OUT PUMRX_ASYNCENGINE_CONTEXT AsyncEngineContext,
|
|
PBYTE Buffer
|
|
);
|
|
|
|
VOID
|
|
UMRxReleaseCapturedThreads (
|
|
IN OUT PUMRX_DEVICE_OBJECT UMRdrDeviceObject
|
|
);
|
|
|
|
VOID
|
|
UMRxAssignWork (
|
|
IN PUMRX_DEVICE_OBJECT UMRdrDeviceObject,
|
|
IN OUT PUMRX_USERMODE_WORKITEM_HEADER InputWorkItem,
|
|
IN ULONG InputWorkItemLength,
|
|
IN OUT PUMRX_USERMODE_WORKITEM_HEADER OutputWorkItem,
|
|
IN ULONG OutputWorkItemLength,
|
|
OUT PIO_STATUS_BLOCK IoStatus
|
|
);
|
|
|
|
NTSTATUS
|
|
UMRxResumeAsyncEngineContext(
|
|
IN OUT PRX_CONTEXT RxContext
|
|
);
|
|
|
|
NTSTATUS
|
|
UMRxImpersonateClient(
|
|
IN PSECURITY_CLIENT_CONTEXT SecurityClientContext,
|
|
IN OUT PUMRX_USERMODE_WORKITEM_HEADER WorkItemHeader
|
|
);
|
|
|
|
NTSTATUS
|
|
UMRxReadDWORDFromTheRegistry(
|
|
IN PWCHAR RegKey,
|
|
IN PWCHAR ValueToRead,
|
|
OUT LPDWORD DataRead
|
|
);
|
|
|
|
|
|
#define UMRxRevertClient() PsRevertToSelf()
|
|
|
|
//
|
|
// Macro definitions used by the reflector and the miniredirs.
|
|
//
|
|
|
|
//
|
|
// Check to see if we have a correct AsyncEngineContext node.
|
|
//
|
|
#define ASSERT_ASYNCENG_CONTEXT(__p) \
|
|
ASSERT(NodeType(__p) == UMRX_NTC_ASYNCENGINE_CONTEXT)
|
|
|
|
//
|
|
// This macro is used to do the async completion for read/write/locks. Note
|
|
// that the call to lowiocompletion will try to complete the irp thereby
|
|
// freeing the user's mdl. We use this macro so that there will be only one
|
|
// version of this code. When we combine the start routines, this will be
|
|
// unmacroed.
|
|
//
|
|
#define UMRxAsyncEngAsyncCompletionIfNecessary(AECTX, RXCONTEXT) { \
|
|
if (ContinueEntryCount > 1) { \
|
|
BOOLEAN FinalizationComplete; \
|
|
if (FALSE) { DbgBreakPoint(); } \
|
|
(RXCONTEXT)->StoredStatus = NtStatus; \
|
|
RxLowIoCompletion((RXCONTEXT)); \
|
|
FinalizationComplete = UMRxFinalizeAsyncEngineContext(&(AECTX)); \
|
|
ASSERT(!FinalizationComplete); \
|
|
} \
|
|
}
|
|
|
|
//
|
|
// This macro allows one to execute conditional debugging code.
|
|
//
|
|
#if DBG
|
|
#define DEBUG_ONLY_CODE(x) x
|
|
#else
|
|
#define DEBUG_ONLY_CODE(x)
|
|
#endif
|
|
|
|
//
|
|
// The heap is shared between kernel and user but only the kernel component
|
|
// allocates and frees into the heap.
|
|
//
|
|
typedef struct _UMRX_SHARED_HEAP {
|
|
LIST_ENTRY HeapListEntry;
|
|
PBYTE VirtualMemoryBuffer;
|
|
SIZE_T VirtualMemoryLength;
|
|
PVOID Heap;
|
|
ULONG HeapAllocationCount;
|
|
BOOLEAN HeapFull;
|
|
} UMRX_SHARED_HEAP, * PUMRX_SHARED_HEAP;
|
|
|
|
//
|
|
// NodeType Codes.
|
|
//
|
|
#define UMRX_NTC_ASYNCENGINE_CONTEXT ((USHORT)0xedd0)
|
|
|
|
//
|
|
// This strucutre defines the fields which the reflector and the miniredir can
|
|
// share and is encapsulated in the miniredirs device object. The miniredirs
|
|
// device object may contain some other fields which are specific to its
|
|
// operation.
|
|
//
|
|
typedef struct _UMRX_DEVICE_OBJECT {
|
|
|
|
//
|
|
// The RDBSS's device object structure.
|
|
//
|
|
union {
|
|
RDBSS_DEVICE_OBJECT;
|
|
RDBSS_DEVICE_OBJECT RxDeviceObject;
|
|
};
|
|
|
|
//
|
|
// The max size of the heap that can be allocated.
|
|
//
|
|
SIZE_T NewHeapSize;
|
|
|
|
//
|
|
// List of shared heaps created by worker threads.
|
|
//
|
|
LIST_ENTRY SharedHeapList;
|
|
|
|
//
|
|
// Used to synchronize the heap allocation/deletion, creation/destruction.
|
|
//
|
|
ERESOURCE HeapLock;
|
|
|
|
//
|
|
// Mid atlas and its management and synchronization.
|
|
//
|
|
struct {
|
|
PRX_MID_ATLAS MidAtlas;
|
|
FAST_MUTEX MidManagementMutex;
|
|
LIST_ENTRY WaitingForMidListhead;
|
|
};
|
|
|
|
struct {
|
|
|
|
//
|
|
// The Queue of the device object where the requests which need reflection
|
|
// wait.
|
|
//
|
|
KQUEUE Queue;
|
|
|
|
//
|
|
// Used to synchronize the KQUEUE insertions.
|
|
//
|
|
ERESOURCE QueueLock;
|
|
|
|
//
|
|
// The timeout value used by the worker threads when waiting on the
|
|
// KQUEUE for requests to be taken to user mode.
|
|
//
|
|
LARGE_INTEGER TimeOut;
|
|
|
|
//
|
|
// Used to release the worker threads which are waiting on the KQUEUE.
|
|
// Once the worker threads are released, no requests can be reflected.
|
|
//
|
|
LIST_ENTRY PoisonEntry;
|
|
|
|
//
|
|
// Used to signal the thread (which comes down with an IOCTL to release
|
|
// the worker threads) waiting for all the worker threads to be
|
|
// released.
|
|
//
|
|
KEVENT RunDownEvent;
|
|
|
|
//
|
|
// Number of worker threads waiting on the KQUEUE.
|
|
//
|
|
ULONG NumberOfWorkerThreads;
|
|
|
|
//
|
|
// Number of workitems (requests to be reflected) in the queue.
|
|
//
|
|
ULONG NumberOfWorkItems;
|
|
|
|
//
|
|
// Are the worker threads still willing to take the requests.
|
|
//
|
|
BOOLEAN WorkersAccepted;
|
|
|
|
} Q;
|
|
|
|
//
|
|
// Always incremented and assigned to the AsyncEngineContext's serial
|
|
// number.
|
|
//
|
|
ULONG NextSerialNumber;
|
|
|
|
} UMRX_DEVICE_OBJECT, *PUMRX_DEVICE_OBJECT;
|
|
|
|
#endif //_UMRX_H_
|
|
|