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.

440 lines
13 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. device.c
  5. Abstract:
  6. WinDbg Extension Api
  7. Author:
  8. Wesley Witt (wesw) 15-Aug-1993
  9. Environment:
  10. User Mode.
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. #define FLAG_NAME(flag) {flag, #flag}
  16. FLAG_NAME DeviceObjectExtensionFlags[] = {
  17. FLAG_NAME(DOE_UNLOAD_PENDING), // 00000001
  18. FLAG_NAME(DOE_DELETE_PENDING), // 00000002
  19. FLAG_NAME(DOE_REMOVE_PENDING), // 00000004
  20. FLAG_NAME(DOE_REMOVE_PROCESSED), // 00000008
  21. FLAG_NAME(DOE_START_PENDING), // 00000010
  22. FLAG_NAME(DOE_RAW_FDO), // 20000000
  23. FLAG_NAME(DOE_BOTTOM_OF_FDO_STACK), // 40000000
  24. FLAG_NAME(DOE_DESIGNATED_FDO), // 80000000
  25. { 0, 0 }
  26. };
  27. DECLARE_API( devobj )
  28. /*++
  29. Routine Description:
  30. Dump a device object.
  31. Arguments:
  32. args - the location of the device object to dump.
  33. Return Value:
  34. None
  35. --*/
  36. {
  37. ULONG64 deviceToDump ;
  38. char deviceExprBuf[256] ;
  39. char *deviceExpr ;
  40. //
  41. // !devobj DeviceAddress DumpLevel
  42. // where DeviceAddress can be an expression or device name
  43. // and DumpLevel is a hex mask
  44. //
  45. strcpy(deviceExprBuf, "\\Device\\") ;
  46. deviceExpr = deviceExprBuf+strlen(deviceExprBuf) ;
  47. deviceToDump = 0 ;
  48. strcpy(deviceExpr, args) ;
  49. //
  50. // The debugger will treat C0000000 as a symbol first, then a number if
  51. // no match comes up. We sanely reverse this ordering.
  52. //
  53. if (IsHexNumber(deviceExpr)) {
  54. deviceToDump = GetExpression(deviceExpr) ;
  55. } else if (deviceExpr[0] == '\\') {
  56. deviceToDump = FindObjectByName( deviceExpr, 0);
  57. } else if (isalpha(deviceExpr[0])) {
  58. //
  59. // Perhaps it's an object. Try with \\Device\\ prepended...
  60. //
  61. deviceToDump = FindObjectByName((PUCHAR) deviceExprBuf, 0);
  62. }
  63. if (deviceToDump == 0) {
  64. //
  65. // Last try, is it an expression to evaluate?
  66. //
  67. deviceToDump = GetExpression( deviceExpr ) ;
  68. }
  69. if(deviceToDump == 0) {
  70. dprintf("Device object %s not found\n", args);
  71. return E_INVALIDARG;
  72. }
  73. DumpDevice( deviceToDump, 0, TRUE);
  74. return S_OK;
  75. }
  76. VOID
  77. DumpDevice(
  78. ULONG64 DeviceAddress,
  79. ULONG FieldLength,
  80. BOOLEAN FullDetail
  81. )
  82. /*++
  83. Routine Description:
  84. Displays the driver name for the device object if FullDetail == FALSE.
  85. Otherwise displays more information about the device and the device queue.
  86. Arguments:
  87. DeviceAddress - address of device object to dump.
  88. FieldLength - Width of printf field for driver name (eg %11s).
  89. FullDetail - TRUE means the device object name, driver name, and
  90. information about Irps queued to the device.
  91. Return Value:
  92. None
  93. --*/
  94. {
  95. ULONG result;
  96. ULONG i;
  97. ULONG64 nextEntry;
  98. ULONG64 queueAddress;
  99. ULONG64 irp;
  100. BOOLEAN devObjExtRead;
  101. ULONG Type=0, ReferenceCount=0, DeviceType=0, Flags=0, DeviceObjEx_ExtensionFlags=0,
  102. DeviceQueue_Busy=0;
  103. ULONG64 DriverObject=0, CurrentIrp=0, Vpb=0, DeviceObjectExtension=0,
  104. DeviceExtension=0, DeviceObjEx_Dope=0, DeviceObjEx_DeviceNode=0,
  105. DeviceObjEx_AttachedTo=0, AttachedDevice=0, DeviceQueue_Dev_Flink=0,
  106. DeviceQueue_Dev_Blink=0;
  107. #define RECUR DBG_DUMP_FIELD_RECUR_ON_THIS
  108. #define F_ADDR DBG_DUMP_FIELD_RETURN_ADDRESS
  109. #define COPY DBG_DUMP_FIELD_COPY_FIELD_DATA
  110. FIELD_INFO deviceFields[] = {
  111. {"DriverObject", NULL, 0, COPY, 0, (PVOID) &DriverObject},
  112. {"Type", NULL, 0, COPY, 0, (PVOID) &Type},
  113. {"CurrentIrp", NULL, 0, COPY, 0, (PVOID) &CurrentIrp},
  114. {"ReferenceCount", NULL, 0, COPY, 0, (PVOID) &ReferenceCount},
  115. {"DeviceType", NULL, 0, COPY, 0, (PVOID) &DeviceType},
  116. {"Flags", NULL, 0, COPY, 0, (PVOID) &Flags},
  117. {"Vpb", NULL, 0, COPY, 0, (PVOID) &Vpb},
  118. {"DeviceObjectExtension", NULL, 0, COPY | RECUR, 0, (PVOID) &DeviceObjectExtension},
  119. {"DeviceObjectExtension->Dope", NULL, 0, COPY, 0, (PVOID) &DeviceObjEx_Dope},
  120. {"DeviceObjectExtension->DeviceNode", NULL, 0, COPY, 0, (PVOID) &DeviceObjEx_DeviceNode},
  121. {"DeviceObjectExtension->ExtensionFlags", NULL, 0, COPY, 0, (PVOID) &DeviceObjEx_ExtensionFlags},
  122. {"DeviceObjectExtension->AttachedTo", NULL, 0, COPY, 0, (PVOID) &DeviceObjEx_AttachedTo},
  123. {"DeviceExtension",NULL, 0, COPY, 0, (PVOID) &DeviceExtension},
  124. {"AttachedDevice", NULL, 0, COPY, 0, (PVOID) &AttachedDevice},
  125. {"DeviceQueue", NULL, 0, RECUR,0, NULL},
  126. {"DeviceQueue.Busy", NULL, 0, COPY, 0, (PVOID) &DeviceQueue_Busy},
  127. {"DeviceQueue.DeviceListHead", NULL, 0, RECUR | F_ADDR, 0, NULL},
  128. {"DeviceQueue.DeviceListHead.Flink", NULL, 0, COPY | F_ADDR, 0, (PVOID) &DeviceQueue_Dev_Flink},
  129. {"DeviceQueue.DeviceListHead.Blink", NULL, 0, COPY | F_ADDR, 0, (PVOID) &DeviceQueue_Dev_Blink},
  130. };
  131. SYM_DUMP_PARAM DevSym = {
  132. sizeof (SYM_DUMP_PARAM), "nt!_DEVICE_OBJECT", DBG_DUMP_NO_PRINT, DeviceAddress,
  133. NULL, NULL, NULL, sizeof (deviceFields) / sizeof (FIELD_INFO), &deviceFields[0]
  134. };
  135. if ((Ioctl(IG_DUMP_SYMBOL_INFO, &DevSym, DevSym.size))) {
  136. dprintf("%08p: Could not read device object or _DEVICE_OBJECT not found\n", DeviceAddress);
  137. return;
  138. }
  139. if (Type != IO_TYPE_DEVICE) {
  140. dprintf("%08p: is not a device object\n", DeviceAddress);
  141. return;
  142. }
  143. if (FullDetail == TRUE) {
  144. //
  145. // Dump the device name if present.
  146. //
  147. dprintf("Device object (%08p) is for:\n ", DeviceAddress);
  148. DumpObjectName(DeviceAddress) ;
  149. }
  150. DumpDriver( DriverObject, FieldLength, 0);
  151. if (FullDetail == TRUE) {
  152. //
  153. // Dump Irps related to driver.
  154. //
  155. dprintf(" DriverObject %08p\n", DriverObject);
  156. dprintf("Current Irp %08p RefCount %d Type %08lx Flags %08lx\n",
  157. CurrentIrp,
  158. ReferenceCount,
  159. DeviceType,
  160. Flags);
  161. if (Vpb) {
  162. dprintf("Vpb %08p ", Vpb);
  163. }
  164. dprintf("DevExt %08p DevObjExt %08p ",
  165. DeviceExtension,
  166. DeviceObjectExtension);
  167. devObjExtRead = FALSE ;
  168. if (DeviceObjectExtension) {
  169. devObjExtRead = TRUE ;
  170. if (DeviceObjEx_Dope) {
  171. dprintf("Dope %08p ", DeviceObjEx_Dope);
  172. }
  173. if(DeviceObjEx_DeviceNode) {
  174. dprintf("DevNode %08p ",
  175. DeviceObjEx_DeviceNode);
  176. }
  177. dprintf("\n");
  178. DumpFlags(0,
  179. "ExtensionFlags",
  180. DeviceObjEx_ExtensionFlags,
  181. DeviceObjectExtensionFlags);
  182. } else {
  183. dprintf("\n");
  184. }
  185. if (AttachedDevice) {
  186. dprintf("AttachedDevice (Upper) %08p", AttachedDevice);
  187. DumpDevice(AttachedDevice, 0, FALSE) ;
  188. dprintf("\n") ;
  189. }
  190. if (devObjExtRead && DeviceObjEx_AttachedTo) {
  191. dprintf("AttachedTo (Lower) %08p", DeviceObjEx_AttachedTo);
  192. DumpDevice(DeviceObjEx_AttachedTo, 0, FALSE) ;
  193. dprintf("\n") ;
  194. }
  195. if (DeviceQueue_Busy) {
  196. ULONG64 listHead = DeviceAddress, DevFlinkAddress;
  197. for (i=0; i<DevSym.nFields; i++) {
  198. if (!strcmp(deviceFields[i].fName, "DeviceQueue.DeviceListHead")) {
  199. listHead = deviceFields[i].address;
  200. }
  201. if (!strcmp(deviceFields[i].fName, "DeviceQueue.DeviceListHead.Flink")) {
  202. DevFlinkAddress = deviceFields[i].address;
  203. }
  204. }
  205. // listHead += FIELD_OFFSET(DEVICE_OBJECT, DeviceQueue.DeviceListHead);
  206. if (DeviceQueue_Dev_Flink == listHead) {
  207. dprintf("Device queue is busy -- Queue empty.\n");
  208. // } else if (IsListEmpty(& DeviceQueue.DeviceListHead)) {
  209. // dprintf("Device queue is busy -- Queue empty\n");
  210. } else if(DeviceQueue_Dev_Flink == DeviceQueue_Dev_Blink) {
  211. dprintf("Device queue is busy - Queue flink = blink\n");
  212. } else {
  213. ULONG64 DevListOffset=0, DevQEntryOffset=0;
  214. FIELD_INFO getOffset = {0};
  215. //
  216. // Get offsets required for list
  217. //
  218. DevSym.addr = 0; DevSym.nFields =1; DevSym.Fields = &getOffset;
  219. DevSym.sName = "nt!_KDEVICE_QUEUE_ENTRY"; getOffset.fName = "DeviceListEntry";
  220. Ioctl(IG_DUMP_SYMBOL_INFO, &DevSym, DevSym.size);
  221. DevListOffset = getOffset.address;
  222. DevSym.sName = "nt!_IRP"; getOffset.fName = "Tail.Overlay.DeviceQueueEntry";
  223. Ioctl(IG_DUMP_SYMBOL_INFO, &DevSym, DevSym.size);
  224. DevQEntryOffset = getOffset.address;
  225. dprintf("DeviceQueue: ");
  226. nextEntry = DeviceQueue_Dev_Flink;
  227. i = 0;
  228. /*
  229. while ((PCH) nextEntry != (PCH)
  230. ((PCH) DeviceAddress +
  231. ((PCH) &deviceObject.DeviceQueue.DeviceListHead.Flink -
  232. (PCH) &deviceObject))) {
  233. */
  234. while (nextEntry != (DevFlinkAddress)) {
  235. ULONG64 DevList_Flink=0;
  236. queueAddress = nextEntry - DevListOffset;
  237. /*CONTAINING_RECORD(nextEntry,KDEVICE_QUEUE_ENTRY,
  238. DeviceListEntry);*/
  239. GetFieldValue(queueAddress, "_KDEVICE_QUEUE_ENTRY", "DeviceListEntry.Flink", DevList_Flink);
  240. nextEntry = DevList_Flink;
  241. irp = queueAddress - DevQEntryOffset;
  242. /*CONTAINING_RECORD(queueAddress,
  243. IRP,
  244. Tail.Overlay.DeviceQueueEntry);*/
  245. dprintf("%08p%s",
  246. irp,
  247. (i & 0x03) == 0x03 ? "\n\t " : " ");
  248. if (CheckControlC()) {
  249. break;
  250. }
  251. ++i;
  252. }
  253. dprintf("\n");
  254. }
  255. } else {
  256. dprintf("Device queue is not busy.\n");
  257. }
  258. }
  259. }
  260. VOID
  261. DumpObjectName(
  262. ULONG64 ObjectAddress
  263. )
  264. {
  265. ULONG64 pObjectHeader;
  266. ULONG64 pNameInfo;
  267. PUCHAR buffer;
  268. UNICODE_STRING unicodeString;
  269. ULONG result, NameInfoOffset=0;
  270. ULONG off=0;
  271. if (GetFieldOffset("_OBJECT_HEADER", "Body", &off)) {
  272. // Type not found
  273. return;
  274. }
  275. pObjectHeader = ObjectAddress - off;
  276. if (!GetFieldValue(pObjectHeader, "_OBJECT_HEADER", "NameInfoOffset", NameInfoOffset)) {
  277. ULONG64 bufferAddr=0;
  278. ULONG Len=0, MaxLen=0;
  279. //
  280. // Get Name info's address
  281. //
  282. pNameInfo = (NameInfoOffset ? (pObjectHeader - NameInfoOffset) : 0);
  283. if (!InitTypeRead(pNameInfo, _OBJECT_HEADER_NAME_INFO)) {
  284. Len = (ULONG) ReadField(Name.Length);
  285. MaxLen = (ULONG) ReadField(Name.MaximumLength);
  286. bufferAddr = ReadField(Name.Buffer);
  287. buffer = LocalAlloc(LPTR, MaxLen);
  288. if (buffer != NULL) {
  289. unicodeString.MaximumLength = (USHORT) MaxLen;
  290. unicodeString.Length = (USHORT) Len;
  291. unicodeString.Buffer = (PWSTR)buffer;
  292. if (ReadMemory(bufferAddr,
  293. buffer,
  294. unicodeString.Length,
  295. &result) && (result == unicodeString.Length)) {
  296. dprintf("%wZ", &unicodeString);
  297. }
  298. LocalFree(buffer);
  299. }
  300. }
  301. }
  302. }
  303. HRESULT
  304. GetDevObjInfo(
  305. IN ULONG64 DeviceObject,
  306. OUT PDEBUG_DEVICE_OBJECT_INFO pDevObjInfo)
  307. {
  308. ZeroMemory(pDevObjInfo, sizeof(DEBUG_DEVICE_OBJECT_INFO));
  309. pDevObjInfo->SizeOfStruct = sizeof(DEBUG_DEVICE_OBJECT_INFO);
  310. pDevObjInfo->DevObjAddress = DeviceObject;
  311. if (InitTypeRead(DeviceObject, nt!_DEVICE_OBJECT)) {
  312. return E_INVALIDARG;
  313. }
  314. pDevObjInfo->CurrentIrp = ReadField(CurrentIrp);
  315. pDevObjInfo->DevExtension = ReadField(DevExtension);
  316. pDevObjInfo->DevObjExtension = ReadField(DevObjExtension);
  317. pDevObjInfo->DriverObject = ReadField(DriverObject);
  318. pDevObjInfo->QBusy = (BOOL) ReadField(DeviceQueue.Busy);
  319. pDevObjInfo->ReferenceCount = (ULONG) ReadField(ReferenceCount);
  320. return S_OK;
  321. }
  322. EXTENSION_API( GetDevObjInfo )(
  323. IN PDEBUG_CLIENT Client,
  324. IN ULONG64 DeviceObject,
  325. OUT PDEBUG_DEVICE_OBJECT_INFO pDevObjInfo)
  326. {
  327. HRESULT Hr = E_FAIL;
  328. INIT_API();
  329. if (pDevObjInfo && (pDevObjInfo->SizeOfStruct == sizeof(DEBUG_DEVICE_OBJECT_INFO))) {
  330. Hr = GetDevObjInfo(DeviceObject, pDevObjInfo);
  331. }
  332. EXIT_API();
  333. return Hr;
  334. }