Source code of Windows XP (NT5)
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.

396 lines
7.6 KiB

  1. /*++
  2. Copyright (c) 1998-2000 Microsoft Corporation
  3. Module Name:
  4. control.c
  5. Abstract:
  6. this has code for the sr control object. this is the object that is
  7. created that matches the HANDLE usermode uses to perform operations
  8. with the sr driver
  9. Author:
  10. Paul McDaniel (paulmcd) 23-Jan-2000
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. //
  15. // Private constants.
  16. //
  17. //
  18. // Private types.
  19. //
  20. //
  21. // Private prototypes.
  22. //
  23. //
  24. // linker commands
  25. //
  26. #ifdef ALLOC_PRAGMA
  27. #pragma alloc_text( PAGE, SrCreateControlObject )
  28. #pragma alloc_text( PAGE, SrDeleteControlObject )
  29. #pragma alloc_text( PAGE, SrCancelControlIo )
  30. #pragma alloc_text( PAGE, SrReferenceControlObject)
  31. #pragma alloc_text( PAGE, SrDereferenceControlObject )
  32. #endif // ALLOC_PRAGMA
  33. //
  34. // Private globals.
  35. //
  36. //
  37. // Public globals.
  38. //
  39. //
  40. // Public functions.
  41. //
  42. //
  43. // you must have the lock EXCLUSIVE prior to calling this !
  44. //
  45. NTSTATUS
  46. SrCreateControlObject(
  47. OUT PSR_CONTROL_OBJECT * ppControlObject,
  48. IN ULONG Options
  49. )
  50. {
  51. NTSTATUS Status = STATUS_SUCCESS;
  52. PSR_CONTROL_OBJECT pControlObject = NULL;
  53. PAGED_CODE();
  54. SrTrace(FUNC_ENTRY, ("SR!SrCreateControlObject()\n"));
  55. //
  56. // allocate the control object
  57. //
  58. pControlObject = SR_ALLOCATE_STRUCT(
  59. NonPagedPool,
  60. SR_CONTROL_OBJECT,
  61. SR_CONTROL_OBJECT_TAG
  62. );
  63. if (pControlObject == NULL)
  64. {
  65. Status = STATUS_INSUFFICIENT_RESOURCES;
  66. goto end;
  67. }
  68. //
  69. // wipe it clean
  70. //
  71. RtlZeroMemory(pControlObject, sizeof(SR_CONTROL_OBJECT));
  72. pControlObject->Signature = SR_CONTROL_OBJECT_TAG;
  73. //
  74. // Start the refcount at 1 (the caller's ref)
  75. //
  76. pControlObject->RefCount = 1;
  77. //
  78. // Copy over the info from create
  79. //
  80. pControlObject->Options = Options;
  81. //
  82. // Init our lists
  83. //
  84. InitializeListHead(&pControlObject->IrpListHead);
  85. InitializeListHead(&pControlObject->NotifyRecordListHead);
  86. //
  87. // Fill in the EPROCESS
  88. //
  89. pControlObject->pProcess = IoGetCurrentProcess();
  90. //
  91. // return the object
  92. //
  93. *ppControlObject = pControlObject;
  94. //
  95. // all done
  96. //
  97. SrTrace(NOTIFY, ("SR!SrCreateControlObject(%p)\n", pControlObject));
  98. end:
  99. if (NT_SUCCESS(Status) == FALSE)
  100. {
  101. if (pControlObject != NULL)
  102. {
  103. SR_FREE_POOL_WITH_SIG(pControlObject, SR_CONTROL_OBJECT_TAG);
  104. }
  105. }
  106. RETURN(Status);
  107. } // SrCreateControlObject
  108. NTSTATUS
  109. SrDeleteControlObject(
  110. IN PSR_CONTROL_OBJECT pControlObject
  111. )
  112. {
  113. NTSTATUS Status;
  114. PLIST_ENTRY pEntry;
  115. ASSERT(IS_GLOBAL_LOCK_ACQUIRED());
  116. PAGED_CODE();
  117. SrTrace(NOTIFY, ("SR!SrDeleteControlObject(%p)\n", pControlObject));
  118. if (IS_VALID_CONTROL_OBJECT(pControlObject) == FALSE)
  119. {
  120. RETURN(STATUS_INVALID_DEVICE_REQUEST);
  121. }
  122. //
  123. // cancel all pending io (just in case)
  124. //
  125. Status = SrCancelControlIo(pControlObject);
  126. CHECK_STATUS(Status);
  127. //
  128. // dump all of our pending notif records...
  129. //
  130. while (IsListEmpty(&pControlObject->NotifyRecordListHead) == FALSE)
  131. {
  132. PSR_NOTIFICATION_RECORD pRecord;
  133. //
  134. // Pop it off the list.
  135. //
  136. pEntry = RemoveHeadList(&pControlObject->NotifyRecordListHead);
  137. pEntry->Blink = pEntry->Flink = NULL;
  138. pRecord = CONTAINING_RECORD( pEntry,
  139. SR_NOTIFICATION_RECORD,
  140. ListEntry );
  141. ASSERT(IS_VALID_NOTIFICATION_RECORD(pRecord));
  142. //
  143. // free the record
  144. //
  145. SR_FREE_POOL_WITH_SIG(pRecord, SR_NOTIFICATION_RECORD_TAG);
  146. //
  147. // move on to the next one
  148. //
  149. } // while (IsListEmpty(&pControlObject->NotifyRecordListHead) == FALSE)
  150. //
  151. // we no longer have a process lying around
  152. //
  153. pControlObject->pProcess = NULL;
  154. //
  155. // and release the final reference ... this should delete it
  156. // (pending async cancels)
  157. //
  158. SrDereferenceControlObject(pControlObject);
  159. pControlObject = NULL;
  160. //
  161. // all done
  162. //
  163. RETURN(STATUS_SUCCESS);
  164. } // SrDeleteControlObject
  165. NTSTATUS
  166. SrCancelControlIo(
  167. IN PSR_CONTROL_OBJECT pControlObject
  168. )
  169. {
  170. PLIST_ENTRY pEntry;
  171. ASSERT(IS_GLOBAL_LOCK_ACQUIRED());
  172. PAGED_CODE();
  173. SrTrace(NOTIFY, ("SR!SrCancelControlIo(%p)\n", pControlObject));
  174. if (IS_VALID_CONTROL_OBJECT(pControlObject) == FALSE)
  175. {
  176. RETURN(STATUS_INVALID_DEVICE_REQUEST);
  177. }
  178. //
  179. // loop over the list and cancel any pending io.
  180. //
  181. while (!IsListEmpty(&pControlObject->IrpListHead))
  182. {
  183. PIRP pIrp;
  184. //
  185. // Pop it off the list.
  186. //
  187. pEntry = RemoveHeadList(&pControlObject->IrpListHead);
  188. pEntry->Blink = pEntry->Flink = NULL;
  189. pIrp = CONTAINING_RECORD(pEntry, IRP, Tail.Overlay.ListEntry);
  190. ASSERT(IS_VALID_IRP(pIrp));
  191. //
  192. // pop the cancel routine
  193. //
  194. if (IoSetCancelRoutine(pIrp, NULL) == NULL)
  195. {
  196. //
  197. // IoCancelIrp pop'd it first
  198. //
  199. // ok to just ignore this irp, it's been pop'd off the queue
  200. // and will be completed in the cancel routine.
  201. //
  202. // keep looping
  203. //
  204. pIrp = NULL;
  205. }
  206. else
  207. {
  208. PSR_CONTROL_OBJECT pIrpControlObject;
  209. //
  210. // cancel it. even if pIrp->Cancel == TRUE we are supposed to
  211. // complete it, our cancel routine will never run.
  212. //
  213. pIrpControlObject = (PSR_CONTROL_OBJECT)(
  214. IoGetCurrentIrpStackLocation(pIrp)->
  215. Parameters.DeviceIoControl.Type3InputBuffer
  216. );
  217. ASSERT(pIrpControlObject == pControlObject);
  218. ASSERT(IS_VALID_CONTROL_OBJECT(pIrpControlObject));
  219. SrDereferenceControlObject(pIrpControlObject);
  220. IoGetCurrentIrpStackLocation(pIrp)->
  221. Parameters.DeviceIoControl.Type3InputBuffer = NULL;
  222. pIrp->IoStatus.Status = STATUS_CANCELLED;
  223. pIrp->IoStatus.Information = 0;
  224. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  225. pIrp = NULL;
  226. }
  227. //
  228. // move on to the next one
  229. //
  230. }
  231. //
  232. // our irp list should now empty.
  233. //
  234. ASSERT(IsListEmpty(&pControlObject->IrpListHead));
  235. RETURN(STATUS_SUCCESS);
  236. } // SrCancelControlIo
  237. VOID
  238. SrReferenceControlObject(
  239. IN PSR_CONTROL_OBJECT pControlObject
  240. )
  241. {
  242. LONG RefCount;
  243. //
  244. // Sanity check.
  245. //
  246. PAGED_CODE();
  247. ASSERT(IS_VALID_CONTROL_OBJECT(pControlObject));
  248. RefCount = InterlockedIncrement( &pControlObject->RefCount );
  249. } // SrReferenceControlObject
  250. VOID
  251. SrDereferenceControlObject(
  252. IN PSR_CONTROL_OBJECT pControlObject
  253. )
  254. {
  255. LONG RefCount;
  256. //
  257. // Sanity check.
  258. //
  259. PAGED_CODE();
  260. ASSERT(IS_VALID_CONTROL_OBJECT(pControlObject));
  261. RefCount = InterlockedDecrement( &pControlObject->RefCount );
  262. if (RefCount == 0)
  263. {
  264. //
  265. // there better not be any items on any lists
  266. //
  267. ASSERT(IsListEmpty(&pControlObject->NotifyRecordListHead));
  268. ASSERT(IsListEmpty(&pControlObject->IrpListHead));
  269. //
  270. // and the memory
  271. //
  272. SR_FREE_POOL_WITH_SIG(pControlObject, SR_CONTROL_OBJECT_TAG);
  273. }
  274. } // SrDereferenceControlObject