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.

533 lines
15 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: path.cxx
  3. *
  4. * PATHOBJ gdikdx extension code.
  5. *
  6. * Copyright (c) 2000 Microsoft Corporation
  7. *
  8. \**************************************************************************/
  9. #include "precomp.hxx"
  10. // PATH
  11. #define GetPATHField(field) \
  12. GetPATHSubField(#field,field)
  13. #define GetPATHSubField(field,local) \
  14. GetFieldData(offPATH, "PATH", field, sizeof(local), &local)
  15. // PATHRECORD
  16. #define GetPATHRECORDField(field) \
  17. GetPATHRECORDSubField(#field,field)
  18. #define GetPATHRECORDSubField(field,local) \
  19. GetFieldData(offPATHRECORD, "PATHRECORD", field, sizeof(local), &local)
  20. /******************************Public*Routine******************************\
  21. *
  22. * Routine Name:
  23. *
  24. * vPrintPOINTFIX
  25. *
  26. * Routine Description:
  27. *
  28. * prints a POINTFIX
  29. *
  30. * Arguments:
  31. *
  32. * pointer to a POINTFIX
  33. *
  34. * Return Value:
  35. *
  36. * none
  37. *
  38. \**************************************************************************/
  39. void
  40. vPrintPOINTFIX(ULONG64 pPOINTFIX)
  41. {
  42. FIX x;
  43. FIX y;
  44. ULONG error;
  45. FIELD_INFO vFields[] =
  46. {
  47. { DbgStr("x"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
  48. { DbgStr("y"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL}
  49. };
  50. SYM_DUMP_PARAM vSym =
  51. {
  52. sizeof (SYM_DUMP_PARAM),
  53. DbgStr(GDIType(POINTFIX)),
  54. DBG_DUMP_NO_PRINT,
  55. 0/*address*/,
  56. NULL, NULL, NULL,
  57. sizeof(vFields)/sizeof(vFields[0]),
  58. vFields
  59. };
  60. vSym.addr = pPOINTFIX;
  61. error = Ioctl(IG_DUMP_SYMBOL_INFO, &vSym, vSym.size);
  62. if(error)
  63. {
  64. dprintf("Unable to get contents of POINTFIX\n");
  65. dprintf(" (Ioctl returned %s)\n", pszWinDbgError(error));
  66. return;
  67. }
  68. x = (FIX) vFields[0].address;
  69. y = (FIX) vFields[1].address;
  70. dprintf(
  71. "(%-#10x, %-#10x) = (%d+(%d/16), %d+(%d/16))"
  72. , x, y, x/16, x&15, y/16, y&15
  73. );
  74. }
  75. ULONG
  76. pointFixCallback(
  77. PFIELD_INFO pField,
  78. PVOID UserContext
  79. )
  80. {
  81. if(pField)
  82. {
  83. vPrintPOINTFIX(pField->address);
  84. dprintf("\n");
  85. }
  86. return STATUS_SUCCESS;
  87. }
  88. /******************************Public*Routine******************************\
  89. * vPrintPATHRECORD
  90. *
  91. * History:
  92. * Mon 20-Jun-1994 15:33:37 by Kirk Olynyk [kirko]
  93. * Wrote it.
  94. \**************************************************************************/
  95. void
  96. vPrintPATHRECORD(ULONG64 offPATHRECORD)
  97. {
  98. FLONG flags, fl;
  99. ULONG count;
  100. ULONG64 pprnext, pprprev;
  101. ULONG offaptfx;
  102. ULONG error;
  103. if(offPATHRECORD)
  104. {
  105. FIELD_INFO vFields[] =
  106. {
  107. { DbgStr("pprnext"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
  108. { DbgStr("pprprev"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
  109. { DbgStr("flags"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
  110. { DbgStr("count"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL}
  111. };
  112. SYM_DUMP_PARAM vSym =
  113. {
  114. sizeof (SYM_DUMP_PARAM),
  115. DbgStr(GDIType(PATHRECORD)),
  116. DBG_DUMP_NO_PRINT,
  117. 0/*address*/,
  118. NULL, NULL, NULL,
  119. sizeof(vFields)/sizeof(vFields[0]),
  120. vFields
  121. };
  122. vSym.addr = offPATHRECORD;
  123. error = Ioctl(IG_DUMP_SYMBOL_INFO, &vSym, vSym.size);
  124. if(error)
  125. {
  126. dprintf("Unable to get contents of PATHRECORD\n");
  127. dprintf(" (Ioctl returned %s)\n", pszWinDbgError(error));
  128. return;
  129. }
  130. pprnext = vFields[0].address;
  131. pprprev = vFields[1].address;
  132. dprintf("\tpprnext = %-#p\n", pprnext);
  133. dprintf("\tpprprev = %-#p\n", pprprev);
  134. flags = (FLONG)vFields[2].address;
  135. fl = flags;
  136. dprintf("\tflags = %-#x\n", fl);
  137. for(FLAGDEF *pfd=afdPD; pfd->psz; pfd++)
  138. {
  139. if(fl & pfd->fl)
  140. dprintf("\t\t\t %s\n", pfd->psz);
  141. }
  142. count = (ULONG)vFields[3].address;
  143. dprintf("\tcount = %u\n", count);
  144. // Get the offset of aptfx in PATHRECORD.
  145. GetFieldOffset("PATHRECORD","aptfx",&offaptfx);
  146. if(count)
  147. {
  148. FIELD_INFO vField = { NULL, NULL, count, 0, 0, pointFixCallback};
  149. SYM_DUMP_PARAM vSym =
  150. {
  151. sizeof(SYM_DUMP_PARAM),
  152. DbgStr(GDIType(POINTFIX)),
  153. DBG_DUMP_ARRAY | DBG_DUMP_NO_PRINT,
  154. offPATHRECORD+offaptfx,
  155. &vField, NULL, NULL, 0, NULL
  156. };
  157. error = Ioctl(IG_DUMP_SYMBOL_INFO, &vSym, vSym.size);
  158. if(error)
  159. {
  160. dprintf("Unable to dump contents of aptfx\n");
  161. dprintf(" (Ioctl returned %s)\n", pszWinDbgError(error));
  162. return;
  163. }
  164. }
  165. dprintf("\n");
  166. }
  167. }
  168. /******************************Public*Routine******************************\
  169. * vPrintPATHList
  170. *
  171. * History:
  172. * Sat 20-May-2000 18:25:21 by Pravin Santiago [pravins]
  173. * Wrote it.
  174. \**************************************************************************/
  175. void vPrintPATHList(ULONG64 offPATH)
  176. {
  177. ULONG64 pprfirst;
  178. ULONG64 pprnext;
  179. ULONG64 ppr_CD;
  180. ULONG64 ppr;
  181. ULONG64 offPATHRECORD;
  182. ULONG count;
  183. GetPATHField(pprfirst);
  184. ppr = ppr_CD = offPATHRECORD = pprfirst;
  185. while(ppr)
  186. {
  187. GetPATHRECORDField(pprnext);
  188. //simple multi-rate cycle detection.
  189. if(ppr_CD)
  190. {
  191. GetFieldData(ppr_CD,
  192. "PATHRECORD",
  193. "pprnext",
  194. sizeof(ppr_CD),
  195. &ppr_CD);
  196. if(ppr_CD)
  197. {
  198. GetFieldData(ppr_CD,
  199. "PATHRECORD",
  200. "pprnext",
  201. sizeof(ppr_CD),
  202. &ppr_CD);
  203. }
  204. }
  205. if(ppr==ppr_CD)
  206. {
  207. dprintf("ERROR: Cycle detected in linked list.\n");
  208. break;
  209. }
  210. if(CheckControlC())
  211. {
  212. break;
  213. }
  214. vPrintPATHRECORD(offPATHRECORD);
  215. ppr = offPATHRECORD = pprnext;
  216. }
  217. }
  218. HRESULT
  219. OutputPATH(
  220. PDEBUG_CLIENT Client,
  221. OutputControl *OutCtl,
  222. ULONG64 Offset,
  223. BOOL DumpRecords
  224. )
  225. {
  226. HRESULT hr = S_OK;
  227. ULONG64 Module;
  228. ULONG TypeId;
  229. OutputControl FilterOutCtl(Client);
  230. if ((hr = GetTypeId(Client, "PATH", &TypeId, &Module)) == S_OK)
  231. {
  232. OutputFilter OutFilter(Client);
  233. OutputState OutState(Client);
  234. if (!DumpRecords ||
  235. ((hr = OutState.Setup(0, &OutFilter)) == S_OK &&
  236. (hr = FilterOutCtl.SetControl(DEBUG_OUTCTL_THIS_CLIENT |
  237. DEBUG_OUTCTL_NOT_LOGGED |
  238. DEBUG_OUTCTL_OVERRIDE_MASK,
  239. OutState.Client)) == S_OK))
  240. {
  241. TypeOutputDumper TypeReader(Client,
  242. (DumpRecords ? &FilterOutCtl : OutCtl));
  243. OutCtl->Output(" PATH @ 0x%p:\n", Offset);
  244. TypeReader.ExcludeMarked();
  245. TypeReader.MarkField("cle.*");
  246. hr = TypeReader.OutputVirtual(Module, TypeId, Offset);
  247. if (hr != S_OK)
  248. {
  249. OutCtl->OutErr("Type Dump for PATH returned %s.\n", pszHRESULT(hr));
  250. }
  251. else if (DumpRecords)
  252. {
  253. DEBUG_VALUE RecOffset;
  254. OutFilter.OutputText(OutCtl, DEBUG_OUTPUT_NORMAL);
  255. if ((hr = OutFilter.Query("pprfirst", &RecOffset, DEBUG_VALUE_INT64)) == S_OK)
  256. {
  257. if (RecOffset.I64 != 0)
  258. {
  259. OutCtl->OutWarn("Path record dumping to be converted.\n");
  260. vPrintPATHList(Offset);
  261. }
  262. else
  263. {
  264. OutCtl->OutErr(" No records to dump.\n");
  265. }
  266. }
  267. else
  268. {
  269. OutCtl->OutErr("Error evaluating 'pprfirst' member.\n");
  270. }
  271. }
  272. }
  273. }
  274. return hr;
  275. }
  276. /******************************Public*Routine******************************\
  277. * EPATHOBJ
  278. *
  279. \**************************************************************************/
  280. DECLARE_API( epathobj )
  281. {
  282. HRESULT hr = S_OK;
  283. BOOL BadSwitch = FALSE;
  284. BOOL DumpPath = FALSE;
  285. BOOL DumpRecords = FALSE;
  286. DEBUG_VALUE Offset;
  287. ULONG64 Module;
  288. ULONG TypeId;
  289. OutputControl OutCtl(Client);
  290. while (!BadSwitch)
  291. {
  292. while (isspace(*args)) args++;
  293. if (*args != '-') break;
  294. args++;
  295. BadSwitch = (*args == '\0' || isspace(*args));
  296. while (*args != '\0' && !isspace(*args))
  297. {
  298. switch (*args)
  299. {
  300. case 'r': DumpRecords = TRUE; // Make sure DumpPath is set too
  301. case 'p': DumpPath = TRUE; break;
  302. default:
  303. BadSwitch = TRUE;
  304. break;
  305. }
  306. if (BadSwitch) break;
  307. args++;
  308. }
  309. }
  310. if (BadSwitch ||
  311. (hr = Evaluate(Client, args, DEBUG_VALUE_INT64, 0, &Offset, NULL)) != S_OK ||
  312. Offset.I64 == 0)
  313. {
  314. OutCtl.Output("Usage: epathobj [-?pr] <EPATHOBJ Addr>\n"
  315. " -p - dump path\n"
  316. " -r - dump path records\n");
  317. }
  318. else
  319. {
  320. if ((hr = GetTypeId(Client, "EPATHOBJ", &TypeId, &Module)) == S_OK)
  321. {
  322. OutputFilter OutFilter(Client);
  323. OutputState OutState(Client);
  324. OutCtl.Output(" EPATHOBJ @ 0x%p:\n", Offset.I64);
  325. if (!DumpPath ||
  326. ((hr = OutState.Setup(0, &OutFilter)) == S_OK &&
  327. (hr = OutCtl.SetControl(DEBUG_OUTCTL_THIS_CLIENT |
  328. DEBUG_OUTCTL_NOT_LOGGED |
  329. DEBUG_OUTCTL_OVERRIDE_MASK,
  330. OutState.Client)) == S_OK))
  331. {
  332. TypeOutputDumper TypeReader(Client, &OutCtl);
  333. hr = TypeReader.OutputVirtual(Module, TypeId, Offset.I64);
  334. if (DumpPath)
  335. {
  336. OutCtl.SetControl(DEBUG_OUTCTL_AMBIENT, Client);
  337. }
  338. if (hr != S_OK)
  339. {
  340. OutCtl.OutErr("Type Dump for EPATHOBJ returned %s.\n", pszHRESULT(hr));
  341. }
  342. else if (DumpPath)
  343. {
  344. OutFilter.OutputText(&OutCtl, DEBUG_OUTPUT_NORMAL);
  345. if ((hr = OutFilter.Query("ppath", &Offset, DEBUG_VALUE_INT64)) == S_OK)
  346. {
  347. if (Offset.I64 != 0)
  348. {
  349. hr = OutputPATH(Client, &OutCtl, Offset.I64, DumpRecords);
  350. }
  351. else
  352. {
  353. OutCtl.OutErr(" No path to dump.\n");
  354. }
  355. }
  356. else
  357. {
  358. OutCtl.OutErr("Error evaluating 'ppath' member.\n");
  359. }
  360. }
  361. }
  362. }
  363. }
  364. return hr;
  365. }
  366. /******************************Public*Routine******************************\
  367. * PATH
  368. *
  369. \**************************************************************************/
  370. DECLARE_API( path )
  371. {
  372. HRESULT hr = S_OK;
  373. BOOL BadSwitch = FALSE;
  374. BOOL DumpRecords = FALSE;
  375. ULONG64 PathAddr;
  376. DEBUG_VALUE Arg;
  377. ULONG64 Module;
  378. ULONG TypeId;
  379. OutputControl OutCtl(Client);
  380. while (!BadSwitch)
  381. {
  382. while (isspace(*args)) args++;
  383. if (*args != '-') break;
  384. args++;
  385. BadSwitch = (*args == '\0' || isspace(*args));
  386. while (*args != '\0' && !isspace(*args))
  387. {
  388. switch (*args)
  389. {
  390. case 'r': DumpRecords = TRUE; break;
  391. default:
  392. BadSwitch = TRUE;
  393. break;
  394. }
  395. if (BadSwitch) break;
  396. args++;
  397. }
  398. }
  399. if (BadSwitch ||
  400. (hr = Evaluate(Client, args, DEBUG_VALUE_INT64, 0, &Arg, NULL)) != S_OK ||
  401. Arg.I64 == 0)
  402. {
  403. OutCtl.Output("Usage: path [-?r] <HPATH | PATH Addr>\n"
  404. " -r - dump records\n");
  405. }
  406. else
  407. {
  408. hr = GetObjectAddress(Client, Arg.I64, &PathAddr, PATH_TYPE, TRUE, TRUE);
  409. if (hr != S_OK || PathAddr == 0)
  410. {
  411. DEBUG_VALUE ObjHandle;
  412. TypeOutputParser TypeParser(Client);
  413. OutputState OutState(Client);
  414. ULONG64 PathAddrFromHmgr;
  415. PathAddr = Arg.I64;
  416. if ((hr = OutState.Setup(0, &TypeParser)) != S_OK ||
  417. (hr = OutState.OutputTypeVirtual(PathAddr, "PATH", 0)) != S_OK ||
  418. (hr = TypeParser.Get(&ObjHandle, "hHmgr", DEBUG_VALUE_INT64)) != S_OK)
  419. {
  420. OutCtl.OutErr("Unable to get contents of PATH::hHmgr\n");
  421. OutCtl.OutErr(" (Type Read returned %s)\n", pszHRESULT(hr));
  422. OutCtl.OutErr(" 0x%p is neither an HPATH nor valid PATH address\n", Arg.I64);
  423. }
  424. else
  425. {
  426. if (GetObjectAddress(Client, ObjHandle.I64, &PathAddrFromHmgr,
  427. PATH_TYPE, TRUE, FALSE) == S_OK &&
  428. PathAddrFromHmgr != PathAddr)
  429. {
  430. OutCtl.OutWarn("\tNote: PATH may not be valid.\n"
  431. "\t It does not have a valid handle manager entry.\n");
  432. }
  433. }
  434. }
  435. if (hr == S_OK)
  436. {
  437. hr = OutputPATH(Client, &OutCtl, PathAddr, DumpRecords);
  438. }
  439. }
  440. return hr;
  441. }
  442. /******************************Public*Routine******************************\
  443. * DECLARE_API( dpo )
  444. *
  445. * dpo -- "dump PATHOBJ"
  446. *
  447. * 21-Feb-1995 -by- Lingyun Wang [lingyunw]
  448. * Wrote it.
  449. \**************************************************************************/
  450. DECLARE_API( dpo )
  451. {
  452. OutputControl OutCtl(Client);
  453. OutCtl.OutWarn("dpo is obsolete. Please use epathobj.\n");
  454. return epathobj(Client, args);
  455. }