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.

307 lines
6.7 KiB

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