Leaked source code of windows server 2003
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.

383 lines
10 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. umrx.h
  5. Abstract:
  6. This header defines the UMRxEngine object and associated functions.
  7. The UMRxEngine provides a set of services for dispatch function
  8. writers so they can reflect requests to user-mode components.
  9. Notes:
  10. Code / Ideas have been adopted from Joe Linn's user-mode reflector
  11. Author:
  12. Rohan Phillips [Rohanp] 18-Jan-2001
  13. --*/
  14. #ifndef _UMRX_H_
  15. #define _UMRX_H_
  16. //
  17. // defines and tags
  18. //
  19. #define UMRX_ENGINE_TAG (ULONG) 'xrmU'
  20. #define UMRX_CONTEXT_TAG (ULONG) 'xtcU'
  21. #define REASSIGN_MID 1
  22. #define DONT_REASSIGN_MID 0
  23. #define TICKS_PER_SECOND (10 * 1000 * 1000)
  24. typedef USHORT NODE_TYPE_CODE;
  25. typedef CSHORT NODE_BYTE_SIZE;
  26. typedef struct _MRX_NORMAL_NODE_HEADER {
  27. NODE_TYPE_CODE NodeTypeCode;
  28. NODE_BYTE_SIZE NodeByteSize;
  29. ULONG NodeReferenceCount;
  30. } MRX_NORMAL_NODE_HEADER;
  31. enum {
  32. UMRX_ENGINE_STATE_STOPPED = 0,
  33. UMRX_ENGINE_STATE_STARTING,
  34. UMRX_ENGINE_STATE_STARTED,
  35. UMRX_ENGINE_STATE_STOPPING
  36. };
  37. //
  38. // Define the UMRxEngine object. There is one such object for
  39. // every NET_ROOT. This object contains all the data str needed
  40. // for routing kernel-mode requests to user-mode.
  41. //
  42. typedef struct _UMRX_ENGINE {
  43. // MID to UMRxContext mapping table
  44. struct {
  45. PRX_MID_ATLAS MidAtlas;
  46. FAST_MUTEX MidManagementMutex;
  47. LIST_ENTRY WaitingForMidListhead;
  48. };
  49. struct {
  50. KQUEUE Queue;
  51. LARGE_INTEGER TimeOut;
  52. LIST_ENTRY PoisonEntry;
  53. ULONG NumberOfWorkerThreads;
  54. ULONG NumberOfWorkItems;
  55. ERESOURCE Lock;
  56. ULONG State;
  57. ULONG ThreadAborted;
  58. } Q;
  59. ULONG NextSerialNumber;
  60. ULONG cUserModeReflectionsInProgress;
  61. LIST_ENTRY ActiveLinkHead;
  62. } UMRX_ENGINE, *PUMRX_ENGINE;
  63. void
  64. UMRxAbortPendingRequests(IN PUMRX_ENGINE pUMRxEngine);
  65. //
  66. // Forwards
  67. //
  68. struct _UMRX_CONTEXT;
  69. typedef struct _UMRX_CONTEXT *PUMRX_CONTEXT;
  70. //
  71. // Signatures for function pointers
  72. //
  73. //
  74. // Continue routine is called by InitiateRequest -
  75. // This turns around and submits the request to the
  76. // UMR engine with callbacks for FORMAT and COMPLETION.
  77. //
  78. typedef
  79. NTSTATUS
  80. (*PUMRX_CONTINUE_ROUTINE) (
  81. PUMRX_CONTEXT pUMRxContext,
  82. PRX_CONTEXT pRxContext
  83. );
  84. //
  85. // Format routine - called before user-mode worker thread completes.
  86. // Each dispatch routine will interpret the WORK_ITEM union based on opcode.
  87. // eg: for Create, WorkItem is a CREATE_REQUEST.
  88. //
  89. typedef
  90. NTSTATUS
  91. (*PUMRX_USERMODE_FORMAT_ROUTINE) (
  92. PUMRX_CONTEXT pUMRxContext,
  93. PRX_CONTEXT pRxContext,
  94. PUMRX_USERMODE_WORKITEM WorkItem,
  95. ULONG WorkItemLength,
  96. PULONG ReturnedLength
  97. );
  98. //
  99. // Completion routine - called when user-mode response is received.
  100. // Each dispatch routine will interpret the WORK_ITEM union based on opcode.
  101. // eg: for Create, WorkItem is a CREATE_RESPONSE.
  102. //
  103. typedef
  104. VOID
  105. (*PUMRX_USERMODE_COMPLETION_ROUTINE) (
  106. PUMRX_CONTEXT pUMRxContext,
  107. PRX_CONTEXT pRxContext,
  108. PUMRX_USERMODE_WORKITEM WorkItem,
  109. ULONG WorkItemLength
  110. );
  111. //
  112. // Type of operation reflected to user-mode
  113. //
  114. typedef enum _UMRX_CONTEXT_TYPE {
  115. UMRX_CTXTYPE_IFSDFSLINK = 0,
  116. UMRX_CTXTYPE_GETDFSREPLICAS,
  117. UMRX_CTXTYPE_MAXIMUM
  118. } UMRX_CONTEXT_TYPE;
  119. //
  120. // Define the UMRxContext. This context is sent as part of
  121. // the REQUEST to user-mode. The user-mode handler will
  122. // send the context back in a RESPONSE. The context will be
  123. // used to do the rendezvous with blocked requests.
  124. //
  125. #define UMRX_NTC_CONTEXT ((USHORT)0xedd0)
  126. typedef struct _UMRX_CONTEXT{
  127. MRX_NORMAL_NODE_HEADER;
  128. PUMRX_ENGINE pUMRxEngine; // owning engine object
  129. PRX_CONTEXT RxContext;
  130. PVOID SavedMinirdrContextPtr;
  131. union {
  132. IO_STATUS_BLOCK;
  133. IO_STATUS_BLOCK IoStatusBlock;
  134. };
  135. UMRX_CONTEXT_TYPE CTXType;
  136. PUMRX_CONTINUE_ROUTINE Continuation;
  137. struct {
  138. LIST_ENTRY WorkQueueLinks;
  139. PUMRX_USERMODE_FORMAT_ROUTINE FormatRoutine;
  140. PUMRX_USERMODE_COMPLETION_ROUTINE CompletionRoutine;
  141. KEVENT WaitForMidEvent;
  142. ULONG CallUpSerialNumber;
  143. USHORT CallUpMid;
  144. } UserMode;
  145. LIST_ENTRY ActiveLink;
  146. } UMRX_CONTEXT, *PUMRX_CONTEXT;
  147. #define UMRxReferenceContext(pUMRxContext) {\
  148. ULONG result = InterlockedIncrement(&(pUMRxContext)->NodeReferenceCount); \
  149. RxDbgTrace(0, (DEBUG_TRACE_UMRX), \
  150. ("ReferenceContext result=%08lx\n", result )); \
  151. }
  152. typedef struct _UMRX_WORKITEM_HEADER_PRIVATE {
  153. PUMRX_CONTEXT pUMRxContext;
  154. ULONG SerialNumber;
  155. USHORT Mid;
  156. } UMRX_WORKITEM_HEADER_PRIVATE, *PUMRX_WORKITEM_HEADER_PRIVATE;
  157. //
  158. // Create a UMRX_ENGINE object
  159. //
  160. PUMRX_ENGINE
  161. CreateUMRxEngine();
  162. //
  163. // Close a UMRX_ENGINE object -
  164. // Owner of object ensures that all usage of this object
  165. // is within the Create/Finalize span.
  166. //
  167. VOID
  168. FinalizeUMRxEngine(
  169. IN PUMRX_ENGINE pUMRxEngine
  170. );
  171. //
  172. // Complete queued requests and optional cleanup when the store has exited
  173. //
  174. NTSTATUS
  175. UMRxEngineCompleteQueuedRequests(
  176. IN PUMRX_ENGINE pUMRxEngine,
  177. IN NTSTATUS CompletionStatus,
  178. IN BOOLEAN fCleanup
  179. );
  180. //
  181. // Used to allow an engine to be used again after it's been shutdown.
  182. //
  183. //
  184. NTSTATUS
  185. UMRxEngineRestart(
  186. IN PUMRX_ENGINE pUMRxEngine
  187. );
  188. //
  189. // Initiate a request to the UMR engine -
  190. // This creates a UMRxContext that is used for response rendezvous.
  191. // All IFS dispatch routines will start a user-mode reflection by
  192. // calling this routine. Steps in routine:
  193. //
  194. // 1. Allocate a UMRxContext and set RxContext
  195. // (NOTE: need to have ASSERTs that validate this linkage)
  196. // 2. Set Continue routine ptr and call Continue routine
  197. // 3. If Continue routine is done ie not PENDING, Finalize UMRxContext
  198. //
  199. NTSTATUS
  200. UMRxEngineInitiateRequest (
  201. IN PUMRX_ENGINE pUMRxEngine,
  202. IN PRX_CONTEXT RxContext,
  203. IN UMRX_CONTEXT_TYPE RequestType,
  204. IN PUMRX_CONTINUE_ROUTINE Continuation
  205. );
  206. //
  207. // Create/Finalize UMRX_CONTEXTs
  208. // These are pool allocs/frees
  209. //
  210. PUMRX_CONTEXT
  211. UMRxCreateAndReferenceContext (
  212. IN PRX_CONTEXT RxContext,
  213. IN UMRX_CONTEXT_TYPE RequestType
  214. );
  215. BOOLEAN
  216. UMRxDereferenceAndFinalizeContext (
  217. IN OUT PUMRX_CONTEXT pUMRxContext
  218. );
  219. //
  220. // Submit a request to the UMR engine -
  221. // This adds the request to the engine KQUEUE for processing by
  222. // a user-mode thread. Steps:
  223. //
  224. // 1. set the FORMAT and COMPLETION callbacks in the UMRxContext
  225. // 2. initialize the RxContext sync event
  226. // 3. insert the UMRxContext into the engine KQUEUE
  227. // 4. block on RxContext sync event (for SYNC operations)
  228. // 5. after unblock (ie umode response is back), call Resume routine
  229. //
  230. NTSTATUS
  231. UMRxEngineSubmitRequest(
  232. IN PUMRX_CONTEXT pUMRxContext,
  233. IN PRX_CONTEXT pRxContext,
  234. IN UMRX_CONTEXT_TYPE RequestType,
  235. IN PUMRX_USERMODE_FORMAT_ROUTINE FormatRoutine,
  236. IN PUMRX_USERMODE_COMPLETION_ROUTINE CompletionRoutine
  237. );
  238. //
  239. // Resume is called after I/O thread is unblocked by umode RESPONSE.
  240. // This routine calls any Finish callbacks and then Finalizes the
  241. // UMRxContext.
  242. //
  243. NTSTATUS
  244. UMRxResumeEngineContext(
  245. IN OUT PRX_CONTEXT RxContext
  246. );
  247. //
  248. // The following functions run in the context of user-mode
  249. // worker threads that issue WORK IOCTLs. The IOCTL calls the
  250. // following functions in order:
  251. // 1. UMRxCompleteUserModeRequest() - process a response if needed
  252. // 2. UMRxEngineProcessRequest() - process a request if one is
  253. // available on the UMRxEngine KQUEUE. Since these IOCTLs are
  254. // made on a NET_ROOT, the corresponding UMRxEngine is readily
  255. // available in the NET_ROOT extension.
  256. //
  257. //
  258. // Every IOCTL pended is potentially a Response. If so, process it.
  259. // The first IOCTL pended is usually a NULL Response or 'listen'.
  260. // Steps:
  261. // 1. Get MID from response buffer. Map MID to UMRxContext.
  262. // 2. Call UMRxContext COMPLETION routine.
  263. // 3. Unblock the I/O thread waiting in UMRxEngineSubmitRequest()
  264. //
  265. NTSTATUS
  266. UMRxCompleteUserModeRequest(
  267. IN PUMRX_ENGINE pUMRxEngine,
  268. IN OUT PUMRX_USERMODE_WORKITEM WorkItem,
  269. IN ULONG WorkItemLength,
  270. IN BOOLEAN fReleaseUmrRef,
  271. OUT PIO_STATUS_BLOCK IoStatus,
  272. OUT BOOLEAN * pfReturnImmediately
  273. );
  274. //
  275. // NOTE: if no requests are available, the user-mode thread will
  276. // block till a request is available (It is trivial to make this
  277. // a more async model).
  278. //
  279. // If a request is available, get the corresponding UMRxContext and
  280. // call ProcessRequest.
  281. // Steps:
  282. // 1. Call KeRemoveQueue() to remove a request from the UMRxEngine KQUEUE.
  283. // 2. Get a MID for this UMRxContext and fill it in the WORK_ITEM header.
  284. // 3. Call the UMRxContext FORMAT routine - this fills in the Request params.
  285. // 4. return STATUS_SUCCESS - this causes the IOCTL to complete which
  286. // triggers the user-mode completion and processing of the REQUEST.
  287. //
  288. NTSTATUS
  289. UMRxEngineProcessRequest(
  290. IN PUMRX_ENGINE pUMRxEngine,
  291. OUT PUMRX_USERMODE_WORKITEM WorkItem,
  292. IN ULONG WorkItemLength,
  293. OUT PULONG FormattedWorkItemLength
  294. );
  295. //
  296. // This is called in response to a WORK_CLEANUP IOCTL.
  297. // This routine will insert a dummy item in the engine KQUEUE.
  298. // Each such dummy item inserted will release one thread.
  299. //
  300. NTSTATUS
  301. UMRxEngineReleaseThreads(
  302. IN PUMRX_ENGINE pUMRxEngine
  303. );
  304. //
  305. // Cancel I/O infrastructure
  306. //
  307. typedef
  308. NTSTATUS
  309. (NTAPI *PUMRX_CANCEL_ROUTINE) (
  310. PRX_CONTEXT pRxContext);
  311. // The RX_CONTEXT instance has four fields ( ULONG's ) provided by the wrapper
  312. // which can be used by the mini rdr to store its context. This is used by
  313. // the reflector to identify the parameters for request cancellation
  314. typedef struct _UMRX_RX_CONTEXT {
  315. PUMRX_CANCEL_ROUTINE pCancelRoutine;
  316. PVOID pCancelContext;
  317. union {
  318. struct {
  319. PUMRX_CONTEXT pUMRxContext;
  320. ULONG RxSyncTimeout;
  321. };
  322. IO_STATUS_BLOCK SyncCallDownIoStatus;
  323. };
  324. } UMRX_RX_CONTEXT, *PUMRX_RX_CONTEXT;
  325. #define UMRxGetMinirdrContext(pRxContext) \
  326. ((PUMRX_RX_CONTEXT)(&(pRxContext)->UMRScratchSpace[0]))
  327. #endif // _UMRX_H_