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.

1246 lines
38 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: process.cxx
  3. *
  4. * Support for dteb and dpeb APIs
  5. *
  6. * Created: 12-Mar-1996
  7. * Author: Mark Enstrom [marke]
  8. *
  9. * Copyright (c) 1996-2000 Microsoft Corporation
  10. \**************************************************************************/
  11. #include "precomp.hxx"
  12. HRESULT
  13. GetProcessField(
  14. IN PDEBUG_CLIENT Client,
  15. IN OUT PULONG64 pProcessAddress,
  16. IN PCSTR FieldPath,
  17. OUT PDEBUG_VALUE FieldValue,
  18. IN ULONG DesiredType
  19. )
  20. {
  21. HRESULT hr;
  22. OutputControl OutCtl(Client);
  23. PDEBUG_SYSTEM_OBJECTS System;
  24. PDEBUG_SYMBOLS Symbols;
  25. ULONG64 ProcessAddress = (pProcessAddress != NULL) ? *pProcessAddress : CURRENT_PROCESS_ADDRESS;
  26. if (Client == NULL || FieldPath == NULL) return E_INVALIDARG;
  27. PCSTR Field = FieldPath;
  28. PCSTR Dot;
  29. // Check FieldPath's basic validity
  30. if (!iscsymf(*Field)) return E_INVALIDARG;
  31. while ((Dot = strchr(Field, '.')) != NULL)
  32. {
  33. Field = Dot + 1;
  34. if (!iscsymf(*Field)) return E_INVALIDARG;
  35. }
  36. // Query interfaces needed
  37. if ((hr = Client->QueryInterface(__uuidof(IDebugSystemObjects),
  38. (void **)&System)) != S_OK)
  39. {
  40. return hr;
  41. }
  42. if ((hr = Client->QueryInterface(__uuidof(IDebugSymbols),
  43. (void **)&Symbols)) != S_OK)
  44. {
  45. System->Release();
  46. return hr;
  47. }
  48. if (ProcessAddress == CURRENT_PROCESS_ADDRESS)
  49. {
  50. hr = System->GetCurrentProcessDataOffset(&ProcessAddress);
  51. if (hr == S_OK)
  52. {
  53. if (ProcessAddress != NULL) *pProcessAddress = ProcessAddress;
  54. }
  55. else
  56. {
  57. OutCtl.OutErr("GetCurrentProcess returned %s.\n", pszHRESULT(hr));
  58. }
  59. }
  60. if (hr == S_OK)
  61. {
  62. TypeOutputParser TypeParser(Client);
  63. OutputState OutState(Client, FALSE);
  64. OutputControl OutCtlToParser;
  65. ULONG ProcessTypeId;
  66. ULONG64 NTModule;
  67. DEBUG_VALUE ProcessObject;
  68. DEBUG_VALUE ObjectType;
  69. if ((hr = OutState.Setup(0, &TypeParser)) == S_OK &&
  70. (hr = OutCtlToParser.SetControl(DEBUG_OUTCTL_THIS_CLIENT |
  71. DEBUG_OUTCTL_NOT_LOGGED |
  72. DEBUG_OUTCTL_OVERRIDE_MASK,
  73. OutState.Client)) == S_OK &&
  74. (hr = Symbols->GetSymbolTypeId("nt!_EPROCESS", &ProcessTypeId, &NTModule)) == S_OK)
  75. {
  76. TypeOutputDumper TypeReader(OutState.Client, &OutCtlToParser);
  77. if ((hr = OutState.OutputTypeVirtual(0, "nt!KOBJECTS", 0)) == S_OK)
  78. {
  79. hr = TypeParser.Get(&ProcessObject, "ProcessObject", DEBUG_VALUE_INT64);
  80. }
  81. if (hr != S_OK)
  82. {
  83. OutCtl.OutWarn("enum nt!KOBJECTS's ProcessObject value wasn't found.\n");
  84. ProcessObject.I64 = 3; // From ke.h
  85. }
  86. TypeParser.DiscardOutput();
  87. TypeReader.IncludeMarked();
  88. TypeReader.MarkField("Pcb.Header.Type");
  89. TypeReader.MarkField(FieldPath);
  90. if ((hr = TypeReader.OutputVirtual(NTModule, ProcessTypeId, ProcessAddress)) == S_OK)
  91. {
  92. // Make sure this object is a process
  93. if ((hr = TypeParser.Get(&ObjectType, "Type", DEBUG_VALUE_INT64)) == S_OK &&
  94. ObjectType.I64 == ProcessObject.I64)
  95. {
  96. OutCtl.OutVerb(" Process Addr = 0x%p\n", ProcessAddress);
  97. hr = TypeParser.Get(FieldValue, Field, DesiredType);
  98. }
  99. else
  100. {
  101. if (hr == S_OK)
  102. {
  103. OutCtl.OutErr("0x%p is not a process object.\n", ProcessAddress);
  104. hr = S_FALSE;
  105. }
  106. else
  107. {
  108. OutCtl.OutErr("Unable to find 'Type' value from nt!_EPROCESS Pcb.Header.\n");
  109. }
  110. }
  111. }
  112. else
  113. {
  114. OutCtl.OutErr("Unable to get process contents at 0x%p.\n", ProcessAddress);
  115. }
  116. }
  117. else
  118. {
  119. OutCtl.OutErr("Unable to prepare nt!_EPROCESS type read.\n");
  120. }
  121. }
  122. Symbols->Release();
  123. System->Release();
  124. return hr;
  125. }
  126. HRESULT
  127. GetThreadField(
  128. IN PDEBUG_CLIENT Client,
  129. IN OUT PULONG64 pThreadAddress,
  130. IN PCSTR FieldPath,
  131. OUT PDEBUG_VALUE FieldValue,
  132. IN ULONG DesiredType
  133. )
  134. {
  135. HRESULT hr;
  136. OutputControl OutCtl(Client);
  137. PDEBUG_SYSTEM_OBJECTS System;
  138. PDEBUG_SYMBOLS Symbols;
  139. ULONG64 ThreadAddress = (pThreadAddress != NULL) ? *pThreadAddress : CURRENT_THREAD_ADDRESS;
  140. if (Client == NULL || FieldPath == NULL) return E_INVALIDARG;
  141. PCSTR Field = FieldPath;
  142. PCSTR Dot;
  143. // Check FieldPath's basic validity
  144. if (!iscsymf(*Field)) return E_INVALIDARG;
  145. while ((Dot = strchr(Field, '.')) != NULL)
  146. {
  147. Field = Dot + 1;
  148. if (!iscsymf(*Field)) return E_INVALIDARG;
  149. }
  150. // Query interfaces needed
  151. if ((hr = Client->QueryInterface(__uuidof(IDebugSystemObjects),
  152. (void **)&System)) != S_OK)
  153. {
  154. return hr;
  155. }
  156. if ((hr = Client->QueryInterface(__uuidof(IDebugSymbols),
  157. (void **)&Symbols)) != S_OK)
  158. {
  159. System->Release();
  160. return hr;
  161. }
  162. if (ThreadAddress == CURRENT_THREAD_ADDRESS)
  163. {
  164. hr = System->GetCurrentThreadDataOffset(&ThreadAddress);
  165. if (hr == S_OK && ThreadAddress != NULL)
  166. *pThreadAddress = ThreadAddress;
  167. }
  168. if (hr == S_OK)
  169. {
  170. TypeOutputParser TypeParser(Client);
  171. OutputState OutState(Client, FALSE);
  172. OutputControl OutCtlToParser;
  173. ULONG ThreadTypeId;
  174. ULONG64 NTModule;
  175. DEBUG_VALUE ThreadObject;
  176. DEBUG_VALUE ObjectType;
  177. if ((hr = OutState.Setup(0, &TypeParser)) == S_OK &&
  178. (hr = OutCtlToParser.SetControl(DEBUG_OUTCTL_THIS_CLIENT |
  179. DEBUG_OUTCTL_NOT_LOGGED |
  180. DEBUG_OUTCTL_OVERRIDE_MASK,
  181. OutState.Client)) == S_OK &&
  182. (hr = Symbols->GetSymbolTypeId("nt!_ETHREAD", &ThreadTypeId, &NTModule)) == S_OK)
  183. {
  184. TypeOutputDumper TypeReader(OutState.Client, &OutCtlToParser);
  185. if ((hr = OutState.OutputTypeVirtual(0, "nt!KOBJECTS", 0)) == S_OK)
  186. {
  187. hr = TypeParser.Get(&ThreadObject, "ThreadObject", DEBUG_VALUE_INT64);
  188. }
  189. if (hr != S_OK)
  190. {
  191. OutCtl.OutWarn("enum nt!KOBJECTS's ThreadObject value wasn't found.\n");
  192. ThreadObject.I64 = 6; // From ke.h
  193. }
  194. TypeParser.DiscardOutput();
  195. TypeReader.IncludeMarked();
  196. TypeReader.MarkField("Tcb.Header.Type");
  197. TypeReader.MarkField(FieldPath);
  198. if ((hr = TypeReader.OutputVirtual(NTModule, ThreadTypeId, ThreadAddress)) == S_OK)
  199. {
  200. // Make sure this object is a thread
  201. if ((hr = TypeParser.Get(&ObjectType, "Type", DEBUG_VALUE_INT64)) == S_OK &&
  202. ObjectType.I64 == ThreadObject.I64)
  203. {
  204. OutCtl.OutVerb(" Thread Addr = 0x%p\n", ThreadAddress);
  205. hr = TypeParser.Get(FieldValue, Field, DesiredType);
  206. }
  207. else
  208. {
  209. if (hr == S_OK)
  210. {
  211. OutCtl.OutErr("0x%p is not a thread object.\n", ThreadAddress);
  212. hr = S_FALSE;
  213. }
  214. else
  215. {
  216. OutCtl.OutErr("Unable to find 'Type' value from nt!_ETHREAD Tcb.Header.\n");
  217. }
  218. }
  219. }
  220. else
  221. {
  222. OutCtl.OutErr("Unable to get thread contents at 0x%p.\n", ThreadAddress);
  223. }
  224. }
  225. else
  226. {
  227. OutCtl.OutErr("Unable to prepare nt!_ETHREAD type read.\n");
  228. }
  229. }
  230. Symbols->Release();
  231. System->Release();
  232. return hr;
  233. }
  234. HRESULT
  235. GetCurrentProcessor(
  236. IN PDEBUG_CLIENT Client,
  237. OPTIONAL OUT PULONG pProcessor,
  238. OPTIONAL OUT PHANDLE phCurrentThread
  239. )
  240. {
  241. HRESULT hr = E_INVALIDARG;
  242. PDEBUG_SYSTEM_OBJECTS DebugSystem;
  243. ULONG64 hCurrentThread;
  244. if (phCurrentThread != NULL) *phCurrentThread = NULL;
  245. if (pProcessor != NULL) *pProcessor = 0;
  246. if (Client == NULL ||
  247. (hr = Client->QueryInterface(__uuidof(IDebugSystemObjects),
  248. (void **)&DebugSystem)) != S_OK)
  249. {
  250. return hr;
  251. }
  252. hr = DebugSystem->GetCurrentThreadHandle(&hCurrentThread);
  253. if (hr == S_OK)
  254. {
  255. if (phCurrentThread != NULL)
  256. {
  257. *phCurrentThread = (HANDLE) hCurrentThread;
  258. }
  259. if (pProcessor != NULL)
  260. {
  261. *pProcessor = (ULONG) hCurrentThread - 1;
  262. }
  263. }
  264. DebugSystem->Release();
  265. return hr;
  266. }
  267. /******************************Public*Routine******************************\
  268. * DumpTebBatch
  269. *
  270. * Dumps GDI TEB batch info
  271. *
  272. * Arguments:
  273. *
  274. * TebAddress - address of Teb
  275. *
  276. * Return Value:
  277. *
  278. * None
  279. *
  280. * History:
  281. *
  282. * 20-Sep-2000 -by- Jason Hartman [jasonha]
  283. *
  284. \**************************************************************************/
  285. // from hmgshare.h
  286. enum _BATCH_TYPE
  287. {
  288. BatchTypePatBlt,
  289. BatchTypePolyPatBlt,
  290. BatchTypeTextOut,
  291. BatchTypeTextOutRect,
  292. BatchTypeSetBrushOrg,
  293. BatchTypeSelectClip,
  294. BatchTypeSelectFont,
  295. BatchTypeDeleteBrush,
  296. BatchTypeDeleteRegion
  297. };
  298. VOID
  299. DumpTebBatch(
  300. PDEBUG_CLIENT Client,
  301. ULONG64 TebAddress
  302. )
  303. {
  304. FIELD_INFO TebBatchFields[] = {
  305. { DbgStr("GdiBatchCount"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
  306. { DbgStr("GdiTebBatch.Offset"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
  307. { DbgStr("GdiTebBatch.HDC"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL},
  308. { DbgStr("GdiTebBatch.Buffer"), NULL, 0, DBG_DUMP_FIELD_FULL_NAME | DBG_DUMP_FIELD_RETURN_ADDRESS, 0, NULL},
  309. };
  310. SYM_DUMP_PARAM TebBatchSym = {
  311. sizeof (SYM_DUMP_PARAM), DbgStr(GDIType(_TEB)),
  312. 0,
  313. TebAddress,
  314. NULL, NULL, NULL,
  315. sizeof(TebBatchFields)/sizeof(TebBatchFields[0]), TebBatchFields
  316. };
  317. ULONG BatchCount;
  318. BOOL OldBatch = FALSE;
  319. ULONG64 BatchEntryAddress;
  320. ULONG64 BatchBufferLength = 0;
  321. ULONG64 BatchBufferEnd;
  322. ULONG SmallestBatchEntrySize = max(1, GetTypeSize(GDIType(BATCHCOMMAND)));
  323. USHORT BatchEntryLength;
  324. USHORT BatchEntryType;
  325. ULONG error;
  326. PrepareCallbacks(FALSE, 0);
  327. ExtOut("GDI Batch Info from Teb %p:\n", TebAddress);
  328. error = Ioctl(IG_DUMP_SYMBOL_INFO, &TebBatchSym, TebBatchSym.size);
  329. if (error)
  330. {
  331. ExtErr("Ioctl returned %s\n", pszWinDbgError(error));
  332. }
  333. else
  334. {
  335. BatchCount = (ULONG)TebBatchFields[0].address;
  336. BatchEntryAddress = TebBatchFields[3].address;
  337. if (BatchCount == 0)
  338. {
  339. ExtOut(" ** Dumping old batch entries **\n");
  340. OldBatch = TRUE;
  341. }
  342. ExtOut("First batch entry @ %p.\n", BatchEntryAddress);
  343. GetArrayDimensions(Client, "_GDI_TEB_BATCH", "Buffer", NULL, (ULONG *)&BatchBufferLength, NULL);
  344. if (TebBatchFields[1].address && TebBatchFields[1].address < BatchBufferLength)
  345. {
  346. BatchBufferLength = TebBatchFields[1].address;
  347. }
  348. BatchBufferEnd = BatchEntryAddress + BatchBufferLength;
  349. while ((OldBatch || BatchCount > 0) && BatchEntryAddress < BatchBufferEnd)
  350. {
  351. error = (ULONG)InitTypeRead(BatchEntryAddress, win32k!BATCHCOMMAND);
  352. if (error)
  353. {
  354. ExtErr("InitTypeRead(%p, %s) returned %s.\n", BatchEntryAddress, GDIType(BATCHCOMMAND), pszWinDbgError(error));
  355. break;
  356. }
  357. BatchEntryLength = (USHORT)ReadField(Length);
  358. if (BatchEntryAddress + BatchEntryLength > BatchBufferEnd)
  359. {
  360. ExtOut("Invalid batch entry - length is too long.\n");
  361. break;
  362. }
  363. if (BatchEntryLength < SmallestBatchEntrySize)
  364. {
  365. ExtOut("Invalid batch entry - length is too small.\n");
  366. break;
  367. }
  368. BatchEntryType = (USHORT)ReadField(Type);
  369. switch (BatchEntryType)
  370. {
  371. case BatchTypePatBlt:
  372. {
  373. ExtOut(" BatchTypePatBlt\n");
  374. }
  375. break;
  376. case BatchTypePolyPatBlt:
  377. {
  378. ExtOut(" BatchTypePolyPatBlt\n");
  379. }
  380. break;
  381. case BatchTypeTextOut:
  382. {
  383. ExtOut(" BatchTypeTextOut\n");
  384. }
  385. break;
  386. case BatchTypeTextOutRect:
  387. {
  388. ExtOut(" BatchTypeTextOutRect\n");
  389. }
  390. break;
  391. case BatchTypeSetBrushOrg:
  392. {
  393. ExtOut(" BatchTypeSetBrushOrg\n");
  394. }
  395. break;
  396. case BatchTypeSelectClip:
  397. {
  398. ExtOut(" BatchTypeSelectClip\n");
  399. }
  400. break;
  401. case BatchTypeSelectFont:
  402. {
  403. ExtOut(" BatchTypeSelectFont\n");
  404. }
  405. break;
  406. case BatchTypeDeleteBrush:
  407. {
  408. ExtOut(" BatchTypeDeleteBrush\n");
  409. }
  410. break;
  411. case BatchTypeDeleteRegion:
  412. {
  413. ExtOut(" BatchTypeDeleteRegion\n");
  414. }
  415. break;
  416. default:
  417. ExtOut(" BatchType %hu is not recognized.\n", BatchEntryType);
  418. }
  419. BatchCount--;
  420. BatchEntryAddress += (ULONG64)BatchEntryLength;
  421. }
  422. if (!OldBatch && BatchCount)
  423. {
  424. ExtOut("Batch may be invalid %lu entries unchecked.\n", BatchCount);
  425. }
  426. }
  427. #if 0
  428. if (istatus)
  429. {
  430. dprintf ("\nGDI Batch count = %li\n",pteb->GdiBatchCount);
  431. if (pteb->GdiBatchCount > 0)
  432. {
  433. ULONG index;
  434. PBATCHCOMMAND pBatch = (PBATCHCOMMAND)&pteb->GdiTebBatch.Buffer[0];
  435. dprintf ("\nGDI Batch HDC = 0x%lx\n",pteb->GdiTebBatch.HDC);
  436. dprintf ("\nGDI Batch offet = 0x%lx\n",pteb->GdiTebBatch.Offset);
  437. for (index=pteb->GdiBatchCount;index>0;index--)
  438. {
  439. dprintf("-----------------------------------------------------\n");
  440. switch (pBatch->Type)
  441. {
  442. case BatchTypePatBlt:
  443. {
  444. PBATCHPATBLT pPatblt = (PBATCHPATBLT)pBatch;
  445. dprintf("Patblt: length = 0x%lx\n",pPatblt->Length);
  446. dprintf("Patblt: x = 0x%lx\n",pPatblt->x);
  447. dprintf("Patblt: y = 0x%lx\n",pPatblt->y);
  448. dprintf("Patblt: cx = 0x%lx\n",pPatblt->cx);
  449. dprintf("Patblt: cy = 0x%lx\n",pPatblt->cy);
  450. dprintf("Patblt: hbr = 0x%lx\n",pPatblt->hbr);
  451. dprintf("Patblt: rop4 = 0x%lx\n",pPatblt->rop4);
  452. dprintf("Patblt: textclr = 0x%lx\n",pPatblt->TextColor);
  453. dprintf("Patblt: backclr = 0x%lx\n",pPatblt->BackColor);
  454. }
  455. break;
  456. case BatchTypePolyPatBlt:
  457. {
  458. PBATCHPOLYPATBLT pPatblt = (PBATCHPOLYPATBLT)pBatch;
  459. PPOLYPATBLT ppoly = (PPOLYPATBLT)(&pPatblt->ulBuffer[0]);
  460. ULONG Count = pPatblt->Count;
  461. dprintf("PolyPatblt: length = 0x%lx\n",pPatblt->Length);
  462. dprintf("Patblt: Count = 0x%lx\n",pPatblt->Count);
  463. dprintf("Patblt: Mode = 0x%lx\n",pPatblt->Mode);
  464. dprintf("Patblt: rop4 = 0x%lx\n",pPatblt->rop4);
  465. dprintf("Patblt: textclr = 0x%lx\n",pPatblt->TextColor);
  466. dprintf("Patblt: backclr = 0x%lx\n",pPatblt->BackColor);
  467. while (Count--)
  468. {
  469. dprintf("\n");
  470. dprintf("\t x = 0x%lx\n",ppoly->x);
  471. dprintf("\t y = 0x%lx\n",ppoly->y);
  472. dprintf("\t cx = 0x%lx\n",ppoly->cx);
  473. dprintf("\t cy = 0x%lx\n",ppoly->cy);
  474. dprintf("\t hbr = 0x%lx\n",ppoly->BrClr.hbr);
  475. ppoly++;
  476. }
  477. }
  478. break;
  479. case BatchTypeTextOut:
  480. {
  481. PBATCHTEXTOUT pText = (PBATCHTEXTOUT)pBatch;
  482. PWCHAR pwchar = (PWCHAR)(&pText->ulBuffer[0]);
  483. PLONG pdx = (PLONG)(&pText->ulBuffer[pText->PdxOffset]);
  484. dprintf("Textout: length = 0x%lx\n",pText->Length);
  485. dprintf("Textout: TextColor = 0x%lx\n",pText->TextColor);
  486. dprintf("Textout: BackColor = 0x%lx\n",pText->BackColor);
  487. dprintf("Textout: BackMode = 0x%lx\n",pText->BackMode);
  488. dprintf("Textout: x = 0x%lx\n",pText->x);
  489. dprintf("Textout: y = 0x%lx\n",pText->y);
  490. dprintf("Textout: fl = 0x%lx\n",pText->fl);
  491. dprintf("Textout: rcl.left = 0x%lx\n",pText->rcl.left);
  492. dprintf("Textout: rcl.top = 0x%lx\n",pText->rcl.top);
  493. dprintf("Textout: rcl.right = 0x%lx\n",pText->rcl.right);
  494. dprintf("Textout: rcl.bottom = 0x%lx\n",pText->rcl.bottom);
  495. dprintf("Textout: dwCodePage = 0x%lx\n",pText->dwCodePage);
  496. dprintf("Textout: cChar = 0x%lx\n",pText->cChar);
  497. dprintf("Textout: PdxOffset = 0x%lx\n",pText->PdxOffset);
  498. if (pText->cChar != 0)
  499. {
  500. dprintf("\t wchar array\n");
  501. dprintf("\t\t");
  502. ULONG ix = pText->cChar;
  503. while (ix--)
  504. {
  505. dprintf("%x ",*pwchar++);
  506. }
  507. dprintf("\n");
  508. if (pText->PdxOffset != 0)
  509. {
  510. dprintf("\t pdx array\n");
  511. dprintf("\t\t");
  512. ULONG ix = pText->cChar;
  513. while (ix--)
  514. {
  515. dprintf("%li ",*pdx++);
  516. }
  517. dprintf("\n");
  518. }
  519. }
  520. }
  521. break;
  522. case BatchTypeTextOutRect:
  523. {
  524. PBATCHTEXTOUTRECT pText = (PBATCHTEXTOUTRECT)pBatch;
  525. dprintf("TextoutRect: length = 0x%lx\n",pText->Length);
  526. dprintf("TextoutRect: BackColor = 0x%lx\n",pText->BackColor);
  527. dprintf("TextoutRect: fl = 0x%lx\n",pText->fl);
  528. dprintf("TextoutRect: rcl.left = 0x%lx\n",pText->rcl.left);
  529. dprintf("TextoutRect: rcl.top = 0x%lx\n",pText->rcl.top);
  530. dprintf("TextoutRect: rcl.right = 0x%lx\n",pText->rcl.right);
  531. dprintf("TextoutRect: rcl.bottom = 0x%lx\n",pText->rcl.bottom);
  532. }
  533. break;
  534. case BatchTypeSetBrushOrg:
  535. {
  536. PBATCHSETBRUSHORG pOrg = (PBATCHSETBRUSHORG)pBatch;
  537. dprintf("SetBrushOrg: length = 0x%lx\n",pOrg->Length);
  538. dprintf("SetBrushOrg: x = 0x%lx\n",pOrg->x);
  539. dprintf("SetBrushOrg: y = 0x%lx\n",pOrg->y);
  540. }
  541. break;
  542. case BatchTypeSelectClip:
  543. {
  544. PBATCHSETBRUSHORG pOrg = (PBATCHSETBRUSHORG)pBatch;
  545. dprintf("SetBrushOrg: length = 0x%lx\n",pOrg->Length);
  546. dprintf("SetBrushOrg: x = 0x%lx\n",pOrg->x);
  547. dprintf("SetBrushOrg: y = 0x%lx\n",pOrg->y);
  548. }
  549. break;
  550. case BatchTypeDeleteBrush:
  551. {
  552. PBATCHDELETEBRUSH pbr = (PBATCHDELETEBRUSH)pBatch;
  553. dprintf("DeleteBrush: length = 0x%lx\n",pbr->Length);
  554. dprintf("DeleteBrush: hbrush = 0x%lx\n",pbr->hbrush);
  555. }
  556. break;
  557. case BatchTypeDeleteRegion:
  558. {
  559. PBATCHDELETEREGION prg = (PBATCHDELETEREGION)pBatch;
  560. dprintf("DeleteRegion: length = 0x%lx\n",prg->Length);
  561. dprintf("DeleteRegion: hregion = 0x%lx\n",prg->hregion);
  562. }
  563. break;
  564. }
  565. pBatch = (PBATCHCOMMAND)((PBYTE)pBatch + pBatch->Length);
  566. }
  567. }
  568. }
  569. else
  570. {
  571. dprintf("Error reading TEB contents\n");
  572. }
  573. #endif // DOES NOT SUPPORT API64
  574. }
  575. /******************************Public*Routine******************************\
  576. * batch
  577. *
  578. * Lists a threads batched GDI commands
  579. \**************************************************************************/
  580. DECLARE_API( batch )
  581. {
  582. dprintf("Extension 'batch' is not fully implemented.\n");
  583. DEBUG_VALUE DebugValue;
  584. ULONG64 TebAddress = -1;
  585. BOOL bShowHelp = FALSE;
  586. INIT_API();
  587. while (*args && isspace(*args)) args++;
  588. if (*args)
  589. {
  590. if (args[0] == '-')
  591. {
  592. if (args[1]=='t' && isspace(args[2]))
  593. {
  594. ULONG64 ThreadAddress;
  595. args += 2;
  596. while (*args && isspace(*args)) args++;
  597. if (*args &&
  598. (g_pExtControl->Evaluate(args,
  599. DEBUG_VALUE_INT64,
  600. &DebugValue,
  601. NULL) != S_OK)
  602. )
  603. {
  604. ExtErr("Invalid arguments: %s\n", args);
  605. bShowHelp = TRUE;
  606. }
  607. else
  608. {
  609. ThreadAddress = DebugValue.I64;
  610. GetThreadField(Client, &ThreadAddress, "Tcb.Teb",
  611. &DebugValue, DEBUG_VALUE_INT64);
  612. TebAddress = DebugValue.I64;
  613. }
  614. }
  615. else
  616. {
  617. if (args[1]!='?')
  618. ExtErr("Invalid arguments: %s\n", args);
  619. bShowHelp = TRUE;
  620. }
  621. }
  622. else
  623. {
  624. if (S_OK != g_pExtControl->Evaluate(args, DEBUG_VALUE_INT64, &DebugValue, NULL))
  625. {
  626. ExtErr("Couldn't evaluate: %s\n", args);
  627. EXIT_API(S_OK);
  628. }
  629. TebAddress = DebugValue.I64;
  630. }
  631. }
  632. if (!bShowHelp)
  633. {
  634. if (TebAddress == (ULONG64)-1)
  635. {
  636. g_pExtSystem->GetCurrentThreadTeb(&TebAddress);
  637. }
  638. ExtVerb(" Teb = %p\n", TebAddress);
  639. if (TebAddress)
  640. {
  641. DumpTebBatch(Client, TebAddress);
  642. }
  643. else
  644. {
  645. ExtErr("NULL Teb.\n");
  646. }
  647. }
  648. if (bShowHelp)
  649. {
  650. ExtOut("Usage: batch [-?] [TEB | -t Thread]\n");
  651. ExtOut(" If TEB and Thread are omitted, defaults to the current thread\n");
  652. }
  653. EXIT_API(S_OK);
  654. }
  655. /******************************Public*Routine******************************\
  656. * dpeb
  657. *
  658. * Dump gdi structure in PEB
  659. *
  660. * Arguments:
  661. *
  662. * pPEB
  663. *
  664. * Return Value:
  665. *
  666. * None
  667. *
  668. * History:
  669. *
  670. * 6-Mar-1996 -by- Mark Enstrom [marke]
  671. *
  672. \**************************************************************************/
  673. #if 0 // DOES NOT SUPPORT API64
  674. VOID
  675. GdiDPEB(
  676. PPEB ppebIn,
  677. PW32PROCESS pw32process,
  678. BOOL bw32
  679. )
  680. {
  681. BYTE lpeb[4096];
  682. BYTE lw32proc[sizeof(W32PROCESS)];
  683. PPEB ppeb = (PPEB)&lpeb[0];
  684. PW32PROCESS pw32 = (PW32PROCESS)&lw32proc[0];
  685. PGDIHANDLECACHE pCache = (PGDIHANDLECACHE)ppeb->GdiHandleBuffer;
  686. int iStatus = move2(lpeb,ppebIn,sizeof(PEB));
  687. if (iStatus)
  688. {
  689. dprintf("\nDump PEB 0x%lx\n",ppebIn);
  690. dprintf("GdiSharedHandleTable = 0x%lx\n",ppeb->GdiSharedHandleTable);
  691. dprintf("GdiDCAttributeList = 0x%lx\n",ppeb->GdiDCAttributeList);
  692. dprintf("\n");
  693. dprintf("GDI Cached brush handles = %li\n",pCache->ulNumHandles[BrushHandle]);
  694. dprintf("GDI Cached pen handles = %li\n",pCache->ulNumHandles[PenHandle]);
  695. dprintf("GDI Cached region handles = %li\n",pCache->ulNumHandles[RegionHandle]);
  696. dprintf("GDI Cached lfont handles = %li\n",pCache->ulNumHandles[LFontHandle]);
  697. PHANDLE pHandle = &pCache->Handle[0];
  698. ULONG ux;
  699. dprintf("\nBRUSH handles\n");
  700. for (ux=0;ux<CACHE_BRUSH_ENTRIES;ux++)
  701. {
  702. dprintf("0x%08lx ",*pHandle++);
  703. if (((ux+1) % 4) == 0)
  704. {
  705. dprintf("\n");
  706. }
  707. }
  708. dprintf("\n\nPEN handles\n");
  709. for (ux=0;ux<CACHE_PEN_ENTRIES;ux++)
  710. {
  711. dprintf("0x%08lx ",*pHandle++);
  712. if (((ux+1) % 4) == 0)
  713. {
  714. dprintf("\n");
  715. }
  716. }
  717. dprintf("\nREGION handles\n");
  718. for (ux=0;ux<CACHE_REGION_ENTRIES;ux++)
  719. {
  720. dprintf("0x%08lx ",*pHandle++);
  721. if (((ux+1) % 4) == 0)
  722. {
  723. dprintf("\n");
  724. }
  725. }
  726. dprintf("\n");
  727. }
  728. else
  729. {
  730. dprintf("Error reading PEB contents\n");
  731. return;
  732. }
  733. if (bw32)
  734. {
  735. iStatus = move2(lw32proc,pw32process,sizeof(W32PROCESS));
  736. if (iStatus)
  737. {
  738. dprintf("W32PROCESS\n");
  739. dprintf("Process Handle Count %li\n",pw32->GDIHandleCount);
  740. PSINGLE_LIST_ENTRY pList = (PSINGLE_LIST_ENTRY)pw32->pDCAttrList;
  741. dprintf("Process DC_ATTRs 0x%lx\n",pw32->pDCAttrList);
  742. //
  743. // dump DCATTRs
  744. //
  745. // while (pList)
  746. // {
  747. // BYTE lList[sizeof(SINGLE_LIST_ENTRY)];
  748. // PSINGLE_LIST_ENTRY puList = (PSINGLE_LIST_ENTRY)&lList[0];
  749. //
  750. // move2(lList,pList,sizeof(SINGLE_LIST_ENTRY));
  751. //
  752. // dprintf("dcattr 0x%lx, next = 0x%lx\n",pList,puList->Next);
  753. //
  754. // pList = puList->Next;
  755. //
  756. // if (CheckControlC())
  757. // {
  758. // return;
  759. // }
  760. // }
  761. //
  762. //
  763. // dump brushattrs
  764. //
  765. pList = (PSINGLE_LIST_ENTRY)pw32->pBrushAttrList;
  766. dprintf("Process BRUSHATTRs 0x%lx:\n",pw32->pBrushAttrList);
  767. // while (pList)
  768. // {
  769. // BYTE lList[sizeof(SINGLE_LIST_ENTRY)];
  770. // PSINGLE_LIST_ENTRY puList = (PSINGLE_LIST_ENTRY)&lList[0];
  771. //
  772. // move2(lList,pList,sizeof(SINGLE_LIST_ENTRY));
  773. //
  774. // dprintf("brushattr 0x%lx, next = 0x%lx\n",pList,puList->Next);
  775. //
  776. // pList = puList->Next;
  777. //
  778. // if (CheckControlC())
  779. // {
  780. // return;
  781. // }
  782. // }
  783. }
  784. }
  785. }
  786. #endif // DOES NOT SUPPORT API64
  787. DECLARE_API( dpeb )
  788. {
  789. dprintf("Extension 'dpeb' is not converted.\n");
  790. #if 0 // DOES NOT SUPPORT API64
  791. PVOID Process;
  792. EPROCESS ProcessContents;
  793. PPEB ppeb;
  794. PW32PROCESS pw32process;
  795. BOOL bW32Thread = FALSE;
  796. //
  797. // dpeb [peb], look for peb input
  798. //
  799. PARSE_ARGUMENTS(peb_help);
  800. if(parse_iFindSwitch(tokens, ntok, 'w')!=-1) {bW32Thread=TRUE;}
  801. //
  802. // use current peb
  803. //
  804. Process = GetCurrentProcessAddress( dwProcessor, hCurrentThread, NULL );
  805. if ( !ReadMemory( (UINT_PTR)Process,
  806. &ProcessContents,
  807. sizeof(EPROCESS),
  808. NULL))
  809. {
  810. dprintf("%08lx: Unable to read _EPROCESS\n", Process );
  811. return;
  812. }
  813. dprintf("Process 0x%p W32Process: 0x%p\n",
  814. (ULONG_PTR)Process,
  815. (ULONG_PTR)ProcessContents.Win32Process);
  816. ppeb = ProcessContents.Peb;
  817. pw32process = (PW32PROCESS)ProcessContents.Win32Process;
  818. GdiDPEB(ppeb,pw32process,bW32Thread);
  819. return;
  820. peb_help:
  821. dprintf("Usage: dpeb [-?] [-w]\n");
  822. dprintf("-w indicates W32PROCESS structure\n");
  823. #endif // DOES NOT SUPPORT API64
  824. EXIT_API(S_OK);
  825. }
  826. DECLARE_API( w32p )
  827. {
  828. HRESULT hr = S_OK;
  829. OutputControl OutCtl(Client);
  830. BOOL BadArg = FALSE;
  831. BOOL ProcessArg = FALSE;
  832. DEBUG_VALUE Address = {0, DEBUG_VALUE_INVALID};
  833. while (!BadArg)
  834. {
  835. while (isspace(*args)) args++;
  836. if (*args == '-')
  837. {
  838. // Process switches
  839. args++;
  840. BadArg = (*args == '\0' || isspace(*args));
  841. while (*args != '\0' && !isspace(*args))
  842. {
  843. switch (tolower(*args))
  844. {
  845. case 'p':
  846. ProcessArg = TRUE;
  847. break;
  848. default:
  849. BadArg = TRUE;
  850. break;
  851. }
  852. if (BadArg) break;
  853. args++;
  854. }
  855. }
  856. else
  857. {
  858. if (*args == '\0') break;
  859. if (Address.Type == DEBUG_VALUE_INVALID)
  860. {
  861. // This argument must be an address or a Process.
  862. CHAR EOPChar;
  863. PSTR EOP = (PSTR)args;
  864. ULONG Rem;
  865. // Find end of string to evaulate as an address or Process
  866. while (*EOP != '\0' && !isspace(*EOP)) EOP++;
  867. EOPChar = *EOP;
  868. *EOP = '\0';
  869. if (isxdigit(*args) &&
  870. Evaluate(Client, args, DEBUG_VALUE_INT64,
  871. EVALUATE_DEFAULT_RADIX, &Address,
  872. &Rem) == S_OK &&
  873. args + Rem == EOP &&
  874. Address.I64 != 0)
  875. {
  876. args = EOP;
  877. }
  878. else
  879. {
  880. OutCtl.OutErr("Error: Couldn't evaluate '%s' as a %s.\n",
  881. args,
  882. (ProcessArg ? "Process" : "W32PROCESS address"));
  883. BadArg = TRUE;
  884. }
  885. *EOP = EOPChar;
  886. }
  887. else
  888. {
  889. // All other arguments are invalid
  890. OutCtl.OutErr("Error: Invalid argument '%s'.\n", args);
  891. BadArg = TRUE;
  892. break;
  893. }
  894. }
  895. }
  896. if (!BadArg)
  897. {
  898. if (ProcessArg && Address.Type == DEBUG_VALUE_INVALID)
  899. {
  900. OutCtl.OutErr("Error: Missing Process.\n");
  901. BadArg = TRUE;
  902. }
  903. }
  904. if (BadArg)
  905. {
  906. if (*args == '?')
  907. {
  908. OutCtl.Output("w32p dumps W32PROCESS stucture for current or specified process.\n\n");
  909. }
  910. OutCtl.Output("Usage: w32p [-?] [W32PROCESS Addr | -p Process]\n");
  911. }
  912. else
  913. {
  914. if (Address.Type == DEBUG_VALUE_INVALID || ProcessArg)
  915. {
  916. ULONG64 ProcessAddr = (Address.Type == DEBUG_VALUE_INVALID) ?
  917. CURRENT_PROCESS_ADDRESS :
  918. Address.I64;
  919. hr = GetProcessField(Client, &ProcessAddr, "Win32Process", &Address, DEBUG_VALUE_INT64);
  920. if (hr == S_OK)
  921. {
  922. if (Address.I64 == 0)
  923. {
  924. OutCtl.Output(" Process 0x%p does not have a Win32Process.\n", ProcessAddr);
  925. hr = S_FALSE;
  926. }
  927. }
  928. else
  929. {
  930. OutCtl.OutErr("Unable to look up Win32Process address.\n");
  931. }
  932. }
  933. if (hr == S_OK)
  934. {
  935. hr = DumpType(Client, "_W32PROCESS", Address.I64);
  936. }
  937. }
  938. return hr;
  939. }
  940. DECLARE_API( w32t )
  941. {
  942. HRESULT hr = S_OK;
  943. OutputControl OutCtl(Client);
  944. BOOL BadArg = FALSE;
  945. BOOL ThreadArg = FALSE;
  946. DEBUG_VALUE Address = {0, DEBUG_VALUE_INVALID};
  947. while (!BadArg)
  948. {
  949. while (isspace(*args)) args++;
  950. if (*args == '-')
  951. {
  952. // Process switches
  953. args++;
  954. BadArg = (*args == '\0' || isspace(*args));
  955. while (*args != '\0' && !isspace(*args))
  956. {
  957. switch (tolower(*args))
  958. {
  959. case 't':
  960. ThreadArg = TRUE;
  961. break;
  962. default:
  963. BadArg = TRUE;
  964. break;
  965. }
  966. if (BadArg) break;
  967. args++;
  968. }
  969. }
  970. else
  971. {
  972. if (*args == '\0') break;
  973. if (Address.Type == DEBUG_VALUE_INVALID)
  974. {
  975. // This argument must be an address or a Thread.
  976. CHAR EOPChar;
  977. PSTR EOP = (PSTR)args;
  978. ULONG Rem;
  979. // Find end of string to evaulate as an address or Thread
  980. while (*EOP != '\0' && !isspace(*EOP)) EOP++;
  981. EOPChar = *EOP;
  982. *EOP = '\0';
  983. if (isxdigit(*args) &&
  984. Evaluate(Client, args, DEBUG_VALUE_INT64,
  985. EVALUATE_DEFAULT_RADIX, &Address,
  986. &Rem) == S_OK &&
  987. args + Rem == EOP &&
  988. Address.I64 != 0)
  989. {
  990. args = EOP;
  991. }
  992. else
  993. {
  994. OutCtl.OutErr("Error: Couldn't evaluate '%s' as a %s.\n",
  995. args,
  996. (ThreadArg ? "Thread" : "W32THREAD address"));
  997. BadArg = TRUE;
  998. }
  999. *EOP = EOPChar;
  1000. }
  1001. else
  1002. {
  1003. // All other arguments are invalid
  1004. OutCtl.OutErr("Error: Invalid argument '%s'.\n", args);
  1005. BadArg = TRUE;
  1006. break;
  1007. }
  1008. }
  1009. }
  1010. if (!BadArg)
  1011. {
  1012. if (ThreadArg && Address.Type == DEBUG_VALUE_INVALID)
  1013. {
  1014. OutCtl.OutErr("Error: Missing Thread.\n");
  1015. BadArg = TRUE;
  1016. }
  1017. }
  1018. if (BadArg)
  1019. {
  1020. if (*args == '?')
  1021. {
  1022. OutCtl.Output("w32t dumps W32TRHEAD stucture for current or specified thread.\n\n");
  1023. }
  1024. OutCtl.Output("Usage: w32t [-?] [W32THREAD Addr | -t Thread]\n");
  1025. }
  1026. else
  1027. {
  1028. if (Address.Type == DEBUG_VALUE_INVALID || ThreadArg)
  1029. {
  1030. ULONG64 ThreadAddr = (Address.Type == DEBUG_VALUE_INVALID) ?
  1031. CURRENT_THREAD_ADDRESS :
  1032. Address.I64;
  1033. hr = GetThreadField(Client, &ThreadAddr, "Tcb.Win32Thread", &Address, DEBUG_VALUE_INT64);
  1034. if (hr == S_OK)
  1035. {
  1036. if (Address.I64 == 0)
  1037. {
  1038. OutCtl.Output(" Thread 0x%p does not have a Win32Thread.\n", ThreadAddr);
  1039. hr = S_FALSE;
  1040. }
  1041. }
  1042. else
  1043. {
  1044. OutCtl.OutErr("Unable to look up Win32Thread address.\n");
  1045. }
  1046. }
  1047. if (hr == S_OK)
  1048. {
  1049. hr = DumpType(Client, "_W32THREAD", Address.I64);
  1050. }
  1051. }
  1052. return hr;
  1053. }