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.

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