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.

334 lines
8.3 KiB

  1. //+----------------------------------------------------------------------------//+----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 2001, Microsoft Corporation
  4. //
  5. // File: rxcontx.c
  6. //
  7. // Contents: Contains functions for allocating contexts and Cancel Routines
  8. //
  9. //
  10. // Functions:
  11. //
  12. // Author - Rohan Phillips (Rohanp)
  13. //-----------------------------------------------------------------------------
  14. #include "ntifs.h"
  15. #include <rxcontx.h>
  16. #ifdef ALLOC_PRAGMA
  17. #pragma alloc_text(PAGE, RxInitializeContext)
  18. #pragma alloc_text(PAGE, DfsInitializeContextResources)
  19. #pragma alloc_text(PAGE, DfsDeInitializeContextResources)
  20. #endif
  21. #define RX_IRPC_POOLTAG ('rsfd')
  22. KSPIN_LOCK RxStrucSupSpinLock = {0};
  23. LIST_ENTRY RxActiveContexts;
  24. ULONG NumberOfActiveContexts = 0;
  25. NPAGED_LOOKASIDE_LIST RxContextLookasideList;
  26. //+-------------------------------------------------------------------------
  27. //
  28. // Function: DfsInitializeContextResources
  29. //
  30. // Arguments:
  31. //
  32. // Returns: Status
  33. // ERROR_SUCCESS on success
  34. // ERROR status code otherwise
  35. //
  36. //
  37. // Description: Initializes all resources needed for allocating contexts
  38. //
  39. //--------------------------------------------------------------------------
  40. NTSTATUS DfsInitializeContextResources(void)
  41. {
  42. NTSTATUS Status = STATUS_SUCCESS;
  43. PAGED_CODE();
  44. KeInitializeSpinLock( &RxStrucSupSpinLock );
  45. // Initialize the look aside list for RxContext allocation
  46. ExInitializeNPagedLookasideList(
  47. &RxContextLookasideList,
  48. ExAllocatePoolWithTag,
  49. ExFreePool,
  50. 0,
  51. sizeof(RX_CONTEXT),
  52. RX_IRPC_POOLTAG,
  53. 32);
  54. InitializeListHead(&RxActiveContexts);
  55. return Status;
  56. }
  57. //+-------------------------------------------------------------------------
  58. //
  59. // Function: DfsDeInitializeContextResources
  60. //
  61. // Arguments:
  62. //
  63. // Returns: Status
  64. // ERROR_SUCCESS on success
  65. // ERROR status code otherwise
  66. //
  67. //
  68. // Description: DeInitializes all resources needed for allocating contexts
  69. //
  70. //--------------------------------------------------------------------------
  71. NTSTATUS DfsDeInitializeContextResources(void)
  72. {
  73. NTSTATUS Status = STATUS_SUCCESS;
  74. PAGED_CODE();
  75. ExDeleteNPagedLookasideList(&RxContextLookasideList);
  76. return Status;
  77. }
  78. //+-------------------------------------------------------------------------
  79. //
  80. // Function: RxInitializeContext
  81. //
  82. // Arguments:
  83. //
  84. // Returns:
  85. //
  86. //
  87. // Description: initializes a context
  88. //
  89. //--------------------------------------------------------------------------
  90. VOID
  91. RxInitializeContext(
  92. IN PIRP Irp,
  93. IN OUT PRX_CONTEXT RxContext)
  94. {
  95. PAGED_CODE();
  96. RxContext->ReferenceCount = 1;
  97. // Initialize the Sync Event.
  98. KeInitializeEvent(
  99. &RxContext->SyncEvent,
  100. SynchronizationEvent,
  101. FALSE);
  102. if(Irp)
  103. {
  104. if (!IoIsOperationSynchronous(Irp))
  105. {
  106. SetFlag( RxContext->Flags, DFS_CONTEXT_FLAG_ASYNC_OPERATION );
  107. }
  108. }
  109. // Set the Irp fields.
  110. RxContext->CurrentIrp = Irp;
  111. RxContext->OriginalThread = RxContext->LastExecutionThread = PsGetCurrentThread();
  112. }
  113. //+-------------------------------------------------------------------------
  114. //
  115. // Function: RxCreateRxContext
  116. //
  117. // Arguments:
  118. //
  119. // Returns: Pointer to context information
  120. //
  121. //
  122. // Description: allocates a context
  123. //
  124. //--------------------------------------------------------------------------
  125. PRX_CONTEXT
  126. RxCreateRxContext (
  127. IN PIRP Irp,
  128. IN ULONG InitialContextFlags
  129. )
  130. {
  131. PRX_CONTEXT RxContext = NULL;
  132. ULONG RxContextFlags = 0;
  133. KIRQL SavedIrql;
  134. RxContext = ExAllocateFromNPagedLookasideList(
  135. &RxContextLookasideList);
  136. if(RxContext == NULL)
  137. {
  138. return(NULL);
  139. }
  140. InterlockedIncrement(&NumberOfActiveContexts);
  141. RtlZeroMemory( RxContext, sizeof(RX_CONTEXT) );
  142. RxContext->Flags = RxContextFlags;
  143. RxInitializeContext(Irp,RxContext);
  144. KeAcquireSpinLock( &RxStrucSupSpinLock, &SavedIrql );
  145. InsertTailList(&RxActiveContexts,&RxContext->ContextListEntry);
  146. KeReleaseSpinLock( &RxStrucSupSpinLock, SavedIrql );
  147. return RxContext;
  148. }
  149. //+-------------------------------------------------------------------------
  150. //
  151. // Function: RxDereferenceAndDeleteRxContext_Real
  152. //
  153. // Arguments:
  154. //
  155. // Returns:
  156. //
  157. //
  158. // Description: Deallocates a context
  159. //
  160. //--------------------------------------------------------------------------
  161. VOID
  162. RxDereferenceAndDeleteRxContext_Real (
  163. IN PRX_CONTEXT RxContext
  164. )
  165. {
  166. PRX_CONTEXT pStopContext = NULL;
  167. LONG FinalRefCount = 0;
  168. KIRQL SavedIrql;
  169. KeAcquireSpinLock( &RxStrucSupSpinLock, &SavedIrql );
  170. FinalRefCount = InterlockedDecrement(&RxContext->ReferenceCount);
  171. if (FinalRefCount == 0)
  172. {
  173. RemoveEntryList(&RxContext->ContextListEntry);
  174. InterlockedDecrement(&NumberOfActiveContexts);
  175. RtlZeroMemory( RxContext, sizeof(RX_CONTEXT) );
  176. ExFreeToNPagedLookasideList(
  177. &RxContextLookasideList,
  178. RxContext );
  179. }
  180. KeReleaseSpinLock( &RxStrucSupSpinLock, SavedIrql );
  181. }
  182. //+-------------------------------------------------------------------------
  183. //
  184. // Function: RxSetMinirdrCancelRoutine
  185. //
  186. // Arguments:
  187. //
  188. // Returns:
  189. //
  190. //
  191. // Description: Sets up a cancel routine
  192. //
  193. //--------------------------------------------------------------------------
  194. NTSTATUS
  195. RxSetMinirdrCancelRoutine(
  196. IN OUT PRX_CONTEXT RxContext,
  197. IN DFS_CALLDOWN_ROUTINE DfsCancelRoutine)
  198. {
  199. NTSTATUS Status = STATUS_SUCCESS;
  200. KIRQL SavedIrql;
  201. KeAcquireSpinLock( &RxStrucSupSpinLock, &SavedIrql );
  202. if (!FlagOn(RxContext->Flags, DFS_CONTEXT_FLAG_CANCELLED))
  203. {
  204. RxContext->CancelRoutine = DfsCancelRoutine;
  205. Status = STATUS_SUCCESS;
  206. }
  207. else
  208. {
  209. Status = STATUS_CANCELLED;
  210. }
  211. KeReleaseSpinLock( &RxStrucSupSpinLock, SavedIrql );
  212. return Status;
  213. }
  214. //+-------------------------------------------------------------------------
  215. //
  216. // Function: RxCancelRoutine
  217. //
  218. // Arguments:
  219. //
  220. // Returns:
  221. //
  222. //
  223. // Description: The main cancel routine
  224. //
  225. //--------------------------------------------------------------------------
  226. VOID
  227. RxCancelRoutine(
  228. PDEVICE_OBJECT pDeviceObject,
  229. PIRP pIrp)
  230. {
  231. PRX_CONTEXT pRxContext = NULL;
  232. PLIST_ENTRY pListEntry = NULL;
  233. DFS_CALLDOWN_ROUTINE DfsCancelRoutine = NULL;
  234. KIRQL SavedIrql;
  235. // Locate the context corresponding to the given Irp.
  236. KeAcquireSpinLock( &RxStrucSupSpinLock, &SavedIrql );
  237. pListEntry = RxActiveContexts.Flink;
  238. while (pListEntry != &RxActiveContexts)
  239. {
  240. pRxContext = CONTAINING_RECORD(pListEntry,RX_CONTEXT,ContextListEntry);
  241. if (pRxContext->CurrentIrp == pIrp)
  242. {
  243. break;
  244. }
  245. else
  246. {
  247. pListEntry = pListEntry->Flink;
  248. }
  249. }
  250. if (pListEntry != &RxActiveContexts)
  251. {
  252. SetFlag( pRxContext->Flags, DFS_CONTEXT_FLAG_CANCELLED );
  253. DfsCancelRoutine = pRxContext->CancelRoutine;
  254. pRxContext->CancelRoutine = NULL;
  255. InterlockedIncrement(&pRxContext->ReferenceCount);
  256. }
  257. else
  258. {
  259. pRxContext = NULL;
  260. DfsCancelRoutine = NULL;
  261. }
  262. KeReleaseSpinLock( &RxStrucSupSpinLock, SavedIrql );
  263. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  264. if (pRxContext != NULL)
  265. {
  266. if (DfsCancelRoutine != NULL)
  267. {
  268. (DfsCancelRoutine)(pRxContext);
  269. }
  270. RxDereferenceAndDeleteRxContext(pRxContext);
  271. }
  272. }