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.

300 lines
6.9 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. PpHandle.c
  5. Abstract:
  6. This module implements handle location code for the Plug and Play subsystem.
  7. Author:
  8. Adrian J. Oney - April 4, 2001
  9. Revision History:
  10. --*/
  11. #include "pnpmgrp.h"
  12. #include "pihandle.h"
  13. #pragma hdrstop
  14. #ifdef ALLOC_PRAGMA
  15. //#pragma alloc_text(NONPAGE, PpHandleEnumerateHandlesAgainstPdoStack)
  16. #pragma alloc_text(PAGE, PiHandleEnumerateHandlesAgainstDeviceObject)
  17. #pragma alloc_text(PAGE, PiHandleProcessWalkWorker)
  18. #endif
  19. LOGICAL
  20. PpHandleEnumerateHandlesAgainstPdoStack(
  21. IN PDEVICE_OBJECT PhysicalDeviceObject,
  22. IN PHANDLE_ENUMERATION_CALLBACK HandleEnumCallBack,
  23. IN PVOID Context
  24. )
  25. /*++
  26. Routine Description:
  27. This routine walks every device object in the WDM device stack along with
  28. all filesystem device objects on the other side of a VPB. If any handles
  29. are opened against such device objects, the specified callback is invoked.
  30. Arguments:
  31. PhysicalDeviceObject - Supplies a pointer to the device object at the
  32. bottom of the WDM device stack.
  33. HandleEnumCallBack - Pointer the callback function.
  34. Context - Pointer to information to be passed into the callback function.
  35. Return Value:
  36. TRUE if the enumeration was halted, FALSE otherwise.
  37. --*/
  38. {
  39. PDEVICE_OBJECT currentDevObj, nextDevObj, vpbObj, vpbBottomObj;
  40. LOGICAL stopEnum;
  41. KIRQL oldIrql;
  42. PVPB vpb;
  43. //
  44. // Preinit
  45. //
  46. stopEnum = FALSE;
  47. //
  48. // Start with the device object at the bottom of the stack
  49. //
  50. currentDevObj = PhysicalDeviceObject;
  51. ObReferenceObject(currentDevObj);
  52. do {
  53. //
  54. // Dump any handles opened directly against the specified device object
  55. //
  56. stopEnum = PiHandleEnumerateHandlesAgainstDeviceObject(
  57. currentDevObj,
  58. HandleEnumCallBack,
  59. Context
  60. );
  61. if (stopEnum) {
  62. ObDereferenceObject(currentDevObj);
  63. break;
  64. }
  65. //
  66. // Look for a VPB
  67. //
  68. IoAcquireVpbSpinLock(&oldIrql);
  69. vpb = currentDevObj->Vpb;
  70. vpbObj = NULL;
  71. if (vpb) {
  72. vpbObj = vpb->DeviceObject;
  73. if (vpbObj) {
  74. ObReferenceObject(vpbObj);
  75. }
  76. }
  77. IoReleaseVpbSpinLock(oldIrql);
  78. //
  79. // If we have a vpb object, dump any handles queued against it.
  80. //
  81. if (vpbObj) {
  82. vpbBottomObj = IoGetDeviceAttachmentBaseRef(vpbObj);
  83. stopEnum = PiHandleEnumerateHandlesAgainstDeviceObject(
  84. vpbBottomObj,
  85. HandleEnumCallBack,
  86. Context
  87. );
  88. ObDereferenceObject(vpbBottomObj);
  89. ObDereferenceObject(vpbObj);
  90. if (stopEnum) {
  91. ObDereferenceObject(currentDevObj);
  92. break;
  93. }
  94. }
  95. //
  96. // Advance to the next DO.
  97. //
  98. oldIrql = KeAcquireQueuedSpinLock(LockQueueIoDatabaseLock);
  99. nextDevObj = currentDevObj->AttachedDevice;
  100. if (nextDevObj) {
  101. ObReferenceObject(nextDevObj);
  102. }
  103. KeReleaseQueuedSpinLock(LockQueueIoDatabaseLock, oldIrql);
  104. //
  105. // Drop ref on old DO.
  106. //
  107. ObDereferenceObject(currentDevObj);
  108. //
  109. // Loop.
  110. //
  111. currentDevObj = nextDevObj;
  112. } while (currentDevObj);
  113. return stopEnum;
  114. }
  115. LOGICAL
  116. PiHandleEnumerateHandlesAgainstDeviceObject(
  117. IN PDEVICE_OBJECT DeviceObject,
  118. IN PHANDLE_ENUMERATION_CALLBACK HandleEnumCallBack,
  119. IN PVOID Context
  120. )
  121. /*++
  122. Routine Description:
  123. This routine walks the handle table for each process in the system looking
  124. for handles opened against the passed in device object.
  125. Arguments:
  126. PhysicalDeviceObject - Supplies a pointer to the device object at the
  127. bottom of the WDM device stack.
  128. HandleEnumCallBack - Pointer the callback function.
  129. Context - Pointer to information to be passed into the callback function.
  130. Return Value:
  131. TRUE if the enumeration was halted, FALSE otherwise.
  132. --*/
  133. {
  134. PEPROCESS process;
  135. PHANDLE_TABLE objectTable;
  136. HANDLE_ENUM_CONTEXT handleEnumContext;
  137. LOGICAL stopEnum = FALSE;
  138. for(process = PsGetNextProcess(NULL);
  139. process != NULL;
  140. process = PsGetNextProcess(process)) {
  141. objectTable = ObReferenceProcessHandleTable(process);
  142. if (objectTable) {
  143. handleEnumContext.DeviceObject = DeviceObject;
  144. handleEnumContext.Process = process;
  145. handleEnumContext.CallBack = HandleEnumCallBack;
  146. handleEnumContext.Context = Context;
  147. stopEnum = (LOGICAL) ExEnumHandleTable(
  148. objectTable,
  149. PiHandleProcessWalkWorker,
  150. (PVOID) &handleEnumContext,
  151. NULL
  152. );
  153. ObDereferenceProcessHandleTable(process);
  154. if (stopEnum) {
  155. PsQuitNextProcess(process);
  156. break;
  157. }
  158. }
  159. }
  160. return stopEnum;
  161. }
  162. BOOLEAN
  163. PiHandleProcessWalkWorker(
  164. IN PHANDLE_TABLE_ENTRY ObjectTableEntry,
  165. IN HANDLE HandleId,
  166. IN PHANDLE_ENUM_CONTEXT EnumContext
  167. )
  168. /*++
  169. Routine Description:
  170. This routine gets called back for each handle in a given process. It
  171. examines each handle to see if it is a file object opened against the
  172. device object we are looking for.
  173. Arguments:
  174. ObjectTableEntry - Points to the handle table entry of interest.
  175. HandleId - Supplies the handle.
  176. EnumContext - Context passed in for the enumeration.
  177. Return Value:
  178. TRUE if the enumeration should be stopped, FALSE otherwise.
  179. --*/
  180. {
  181. PDEVICE_OBJECT deviceObject;
  182. POBJECT_HEADER objectHeader;
  183. PFILE_OBJECT fileObject;
  184. objectHeader = OBJECT_FROM_EX_TABLE_ENTRY(ObjectTableEntry);
  185. if (objectHeader->Type != IoFileObjectType) {
  186. //
  187. // Not a file object
  188. //
  189. return FALSE;
  190. }
  191. fileObject = (PFILE_OBJECT) &objectHeader->Body;
  192. deviceObject = IoGetBaseFileSystemDeviceObject( fileObject );
  193. if (deviceObject != EnumContext->DeviceObject) {
  194. //
  195. // Not our device object
  196. //
  197. return FALSE;
  198. }
  199. //
  200. // Found one, invoke the callback!
  201. //
  202. return (BOOLEAN) EnumContext->CallBack(
  203. EnumContext->DeviceObject,
  204. EnumContext->Process,
  205. fileObject,
  206. HandleId,
  207. EnumContext->Context
  208. );
  209. }