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.

3568 lines
101 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: hmgr.cxx
  3. *
  4. * Copyright (c) 2000 Microsoft Corporation
  5. *
  6. \**************************************************************************/
  7. #include "precomp.hxx"
  8. // Sometimes GDI _ENTRY structure can't be read.
  9. // We can use another module's version since the structure should be the same.
  10. CHAR szEntryType[MAX_PATH];
  11. CachedType Entry = {FALSE, "_ENTRY", 0, 0, 0};
  12. // Cache virtual table addresses for each session since the lookup is slow.
  13. // Additionally cache one for the current session since it too is now slow.
  14. #define NUM_CACHED_SESSIONS 8
  15. struct {
  16. ULONG UniqueState;
  17. ULONG64 VirtualTableAddr;
  18. } CachedTableAddr[NUM_CACHED_SESSIONS+1] = { { 0, 0 } };
  19. BitFieldInfo *HandleIndex;
  20. BitFieldInfo *HandleType;
  21. BitFieldInfo *HandleAltType;
  22. BitFieldInfo *HandleFullType;
  23. BitFieldInfo *HandleStock;
  24. BitFieldInfo *HandleFullUnique;
  25. /******************************Public*Routine******************************\
  26. *
  27. * Routine Name:
  28. *
  29. * HmgrInit
  30. *
  31. * Routine Description:
  32. *
  33. * Initialize or reinitialize information to be read from symbols files
  34. *
  35. * Arguments:
  36. *
  37. * Client - PDEBUG_CLIENT
  38. *
  39. * Return Value:
  40. *
  41. * none
  42. *
  43. \**************************************************************************/
  44. void HmgrInit(PDEBUG_CLIENT Client)
  45. {
  46. strcpy(szEntryType, GDIType(_ENTRY));
  47. Entry.Valid = FALSE;
  48. Entry.Module = 0;
  49. Entry.TypeId = 0;
  50. Entry.Size = 0;
  51. if (HandleIndex != NULL) HandleIndex->Valid = FALSE;
  52. if (HandleType != NULL) HandleType->Valid = FALSE;
  53. if (HandleAltType != NULL) HandleAltType->Valid = FALSE;
  54. if (HandleFullType != NULL) HandleFullType->Valid = FALSE;
  55. if (HandleStock != NULL) HandleStock->Valid = FALSE;
  56. if (HandleFullUnique != NULL) HandleFullUnique->Valid = FALSE;
  57. for (int s = 0; s < sizeof(CachedTableAddr)/sizeof(CachedTableAddr[0]); s++)
  58. {
  59. CachedTableAddr[s].UniqueState = INVALID_UNIQUE_STATE;
  60. }
  61. return;
  62. }
  63. /******************************Public*Routine******************************\
  64. *
  65. * Routine Name:
  66. *
  67. * HmgrExit
  68. *
  69. * Routine Description:
  70. *
  71. * Clean up any outstanding allocations or references
  72. *
  73. * Arguments:
  74. *
  75. * none
  76. *
  77. * Return Value:
  78. *
  79. * none
  80. *
  81. \**************************************************************************/
  82. void HmgrExit()
  83. {
  84. if (HandleIndex != NULL)
  85. {
  86. delete HandleIndex;
  87. HandleIndex = NULL;
  88. }
  89. if (HandleType != NULL)
  90. {
  91. delete HandleType;
  92. HandleType = NULL;
  93. }
  94. if (HandleAltType != NULL)
  95. {
  96. delete HandleAltType;
  97. HandleAltType = NULL;
  98. }
  99. if (HandleFullType != NULL)
  100. {
  101. delete HandleFullType;
  102. HandleFullType = NULL;
  103. }
  104. if (HandleStock != NULL)
  105. {
  106. delete HandleStock;
  107. HandleStock = NULL;
  108. }
  109. if (HandleFullUnique != NULL)
  110. {
  111. delete HandleFullUnique;
  112. HandleFullUnique = NULL;
  113. }
  114. return;
  115. }
  116. /******************************Public*Routine******************************\
  117. *
  118. * Routine Name:
  119. *
  120. * GetEntryType
  121. *
  122. * Routine Description:
  123. *
  124. * looks up hmgr entry type id and module
  125. *
  126. * Arguments:
  127. *
  128. * Client - PDEBUG_CLIENT
  129. * TypeId - Pointer to receive entry's type id
  130. * Module - Pointer to receive entry's module
  131. *
  132. * Return Value:
  133. *
  134. * S_OK if successful.
  135. *
  136. \**************************************************************************/
  137. HRESULT
  138. GetEntryType(
  139. PDEBUG_CLIENT Client,
  140. PULONG TypeId,
  141. PULONG64 Module
  142. )
  143. {
  144. HRESULT hr = S_OK;
  145. if (!Entry.Valid)
  146. {
  147. OutputControl OutCtl(Client);
  148. PDEBUG_SYMBOLS Symbols;
  149. if (TypeId != NULL) *TypeId = 0;
  150. if (Module != NULL) *Module = 0;
  151. if (Client == NULL) return E_INVALIDARG;
  152. if (Type_Module.Base == 0)
  153. {
  154. OutCtl.OutErr("Symbols not initialized properly.\n"
  155. " Please use !reinit.\n");
  156. return S_FALSE;
  157. }
  158. if ((hr = Client->QueryInterface(__uuidof(IDebugSymbols),
  159. (void **)&Symbols)) != S_OK)
  160. {
  161. return hr;
  162. }
  163. if ((hr = Symbols->GetTypeId(Type_Module.Base, Entry.Type, &Entry.TypeId)) == S_OK)
  164. {
  165. Entry.Module = Type_Module.Base;
  166. Entry.Valid = TRUE;
  167. sprintf(szEntryType, "%s!%s", Type_Module.Name, Entry.Type);
  168. OutCtl.OutVerb("Found %s in module %s @ 0x%p.\n",
  169. Entry.Type, Type_Module.Name, Entry.Module);
  170. }
  171. else
  172. {
  173. ULONG ModuleIndex = 0;
  174. ULONG64 ModuleBase = 0;
  175. while (Symbols->GetModuleByIndex(ModuleIndex, &Entry.Module) == S_OK &&
  176. Entry.Module != 0)
  177. {
  178. if ((hr = Symbols->GetTypeId(Entry.Module,
  179. Entry.Type,
  180. &Entry.TypeId)) == S_OK)
  181. {
  182. OutCtl.OutVerb("Found %s: TypeId 0x%lx in module @ 0x%p.\n",
  183. Entry.Type, Entry.TypeId, Entry.Module);
  184. break;
  185. }
  186. ModuleIndex++;
  187. Entry.Module = 0;
  188. }
  189. if (hr != S_OK)
  190. {
  191. Entry.Module = 0;
  192. Entry.TypeId = 0;
  193. OutCtl.OutErr("Unable to find type '%s'.\n", Entry.Type);
  194. }
  195. else
  196. {
  197. Entry.Valid = TRUE;
  198. if (Symbols->GetModuleNames(ModuleIndex, Entry.Module,
  199. NULL, 0, NULL,
  200. szEntryType, sizeof(szEntryType), NULL,
  201. NULL, 0, NULL) == S_OK)
  202. {
  203. OutCtl.OutVerb("Found %s in module(%lu) %s @ %p.\n",
  204. Entry.Type, ModuleIndex, szEntryType, Entry.Module);
  205. strcat(szEntryType, "!");
  206. strcat(szEntryType, "_ENTRY");
  207. }
  208. else
  209. {
  210. OutCtl.OutVerb("Found %s in unknown module(%lu) @ %p.\n",
  211. Entry.Type, ModuleIndex, Entry.Module);
  212. strcpy(szEntryType, Entry.Type);
  213. }
  214. }
  215. }
  216. }
  217. if (hr == S_OK)
  218. {
  219. if (TypeId != NULL) *TypeId = Entry.TypeId;
  220. if (Module != NULL) *Module = Entry.Module;
  221. }
  222. return hr;
  223. }
  224. /******************************Public*Routine******************************\
  225. *
  226. * Routine Name:
  227. *
  228. * GetEntrySize
  229. *
  230. * Routine Description:
  231. *
  232. * looks up hmgr entry size
  233. *
  234. * Arguments:
  235. *
  236. * Client - PDEBUG_CLIENT
  237. *
  238. * Return Value:
  239. *
  240. * address of handle manager entry
  241. *
  242. \**************************************************************************/
  243. ULONG GetEntrySize(
  244. PDEBUG_CLIENT Client
  245. )
  246. {
  247. if (Entry.Size == 0)
  248. {
  249. PDEBUG_SYMBOLS Symbols;
  250. if (Client != NULL &&
  251. GetEntryType(Client, NULL, NULL) == S_OK &&
  252. Client->QueryInterface(__uuidof(IDebugSymbols),
  253. (void **)&Symbols) == S_OK)
  254. {
  255. if (Symbols->GetTypeSize(Entry.Module,
  256. Entry.TypeId,
  257. &Entry.Size) != S_OK)
  258. {
  259. OutputControl OutCtl(Client);
  260. OutCtl.OutErr("Unable to get size of _ENTRY.\n");
  261. Entry.Size = 0;
  262. }
  263. Symbols->Release();
  264. }
  265. }
  266. return Entry.Size;
  267. }
  268. /******************************Public*Routine******************************\
  269. *
  270. * Routine Name:
  271. *
  272. * GetIndexFromHandle
  273. *
  274. * Routine Description:
  275. *
  276. * Decodes entry index from engine handle
  277. *
  278. * Arguments:
  279. *
  280. * Client - PDEBUG_CLIENT
  281. * Handle64 - engine handle
  282. * Index - Address to receive extracted handle index
  283. *
  284. * Return Value:
  285. *
  286. * S_OK on success
  287. *
  288. \**************************************************************************/
  289. HRESULT
  290. GetIndexFromHandle(
  291. PDEBUG_CLIENT Client,
  292. ULONG64 Handle64,
  293. PULONG64 Index
  294. )
  295. {
  296. HRESULT hr = S_FALSE;
  297. if (HandleIndex == NULL)
  298. {
  299. HandleIndex = new BitFieldInfo;
  300. }
  301. if (HandleIndex == NULL)
  302. {
  303. hr = E_OUTOFMEMORY;
  304. }
  305. else if (HandleIndex->Valid)
  306. {
  307. hr = S_OK;
  308. }
  309. else
  310. {
  311. BitFieldParser BitFieldReader(Client, HandleIndex);
  312. OutputState OutState(Client);
  313. if ((hr = BitFieldReader.Ready()) == S_OK &&
  314. (hr = OutState.Setup(0, &BitFieldReader)) == S_OK)
  315. {
  316. // Read index bit field from symbol file
  317. if (OutState.Execute("dt " GDIType(GDIHandleBitFields) " Index") != S_OK ||
  318. BitFieldReader.ParseOutput() != S_OK ||
  319. BitFieldReader.Complete() != S_OK)
  320. {
  321. // Use position 0 and INDEX_BITS from ntgdistr.h
  322. HandleIndex->Valid = HandleIndex->Compose(0, INDEX_BITS);
  323. hr = HandleIndex->Valid ? S_OK : S_FALSE;
  324. }
  325. }
  326. }
  327. if (Index != NULL)
  328. {
  329. if (hr == S_OK)
  330. {
  331. *Index = (Handle64 & HandleIndex->Mask) >> HandleIndex->BitPos;
  332. }
  333. else
  334. {
  335. *Index = 0;
  336. }
  337. }
  338. return hr;
  339. }
  340. /******************************Public*Routine******************************\
  341. *
  342. * Routine Name:
  343. *
  344. * GetTypeFromHandle
  345. *
  346. * Routine Description:
  347. *
  348. * Decodes base type from engine handle
  349. *
  350. * Arguments:
  351. *
  352. * Client - PDEBUG_CLIENT
  353. * Handle64 - engine handle
  354. * Type - Address to receive extracted handle type
  355. * Flags - Extraction options
  356. * GET_BITS_UNSHIFTED - Field bits not shifted to start at bit 0
  357. *
  358. * Return Value:
  359. *
  360. * S_OK on success
  361. *
  362. \**************************************************************************/
  363. HRESULT
  364. GetTypeFromHandle(
  365. PDEBUG_CLIENT Client,
  366. ULONG64 Handle64,
  367. PULONG64 Type,
  368. FLONG Flags
  369. )
  370. {
  371. HRESULT hr = S_FALSE;
  372. if (HandleType == NULL)
  373. {
  374. HandleType = new BitFieldInfo;
  375. }
  376. if (HandleType == NULL)
  377. {
  378. hr = E_OUTOFMEMORY;
  379. }
  380. else if (HandleType->Valid)
  381. {
  382. hr = S_OK;
  383. }
  384. else
  385. {
  386. BitFieldParser BitFieldReader(Client, HandleType);
  387. OutputState OutState(Client);
  388. if ((hr = BitFieldReader.Ready()) == S_OK &&
  389. (hr = OutState.Setup(0, &BitFieldReader)) == S_OK)
  390. {
  391. // Read index bit field from symbol file
  392. if ((hr = OutState.Execute("dt " GDIType(GDIHandleBitFields) " Type")) != S_OK ||
  393. (hr = BitFieldReader.ParseOutput()) != S_OK ||
  394. (hr = BitFieldReader.Complete()) != S_OK)
  395. {
  396. // Use position TYPE_SHIFT and TYPE_BITS from ntgdistr.h
  397. HandleType->Valid = HandleType->Compose(TYPE_SHIFT, TYPE_BITS);
  398. hr = HandleType->Valid ? S_OK : S_FALSE;
  399. }
  400. }
  401. }
  402. if (Type != NULL)
  403. {
  404. if (hr == S_OK)
  405. {
  406. *Type = Handle64 & HandleType->Mask;
  407. if (!(Flags & GET_BITS_UNSHIFTED))
  408. {
  409. *Type >>= HandleType->BitPos;
  410. }
  411. }
  412. else
  413. {
  414. *Type = 0;
  415. }
  416. }
  417. return hr;
  418. }
  419. /******************************Public*Routine******************************\
  420. *
  421. * Routine Name:
  422. *
  423. * GetAltTypeFromHandle
  424. *
  425. * Routine Description:
  426. *
  427. * Decodes alt type from engine handle
  428. *
  429. * Arguments:
  430. *
  431. * Client - PDEBUG_CLIENT
  432. * Handle64 - engine handle
  433. * AltType - Address to receive extracted alt handle type
  434. * Flags - Extraction options
  435. * GET_BITS_UNSHIFTED - Field bits not shifted to start at bit 0
  436. *
  437. * Return Value:
  438. *
  439. * S_OK on success
  440. *
  441. \**************************************************************************/
  442. HRESULT
  443. GetAltTypeFromHandle(
  444. PDEBUG_CLIENT Client,
  445. ULONG64 Handle64,
  446. PULONG64 AltType,
  447. FLONG Flags
  448. )
  449. {
  450. HRESULT hr = S_FALSE;
  451. if (HandleAltType == NULL)
  452. {
  453. HandleAltType = new BitFieldInfo;
  454. }
  455. if (HandleAltType == NULL)
  456. {
  457. hr = E_OUTOFMEMORY;
  458. }
  459. else if (HandleAltType->Valid)
  460. {
  461. hr = S_OK;
  462. }
  463. else
  464. {
  465. BitFieldParser BitFieldReader(Client, HandleAltType);
  466. OutputState OutState(Client);
  467. if ((hr = BitFieldReader.Ready()) == S_OK &&
  468. (hr = OutState.Setup(0, &BitFieldReader)) == S_OK)
  469. {
  470. // Read index bit field from symbol file
  471. if ((hr = OutState.Execute("dt " GDIType(GDIHandleBitFields) " AltType")) != S_OK ||
  472. (hr = BitFieldReader.ParseOutput()) != S_OK ||
  473. (hr = BitFieldReader.Complete()) != S_OK)
  474. {
  475. // Use position ALTTYPE_SHIFT and ALTTYPE_BITS from ntgdistr.h
  476. HandleAltType->Valid = HandleAltType->Compose(ALTTYPE_SHIFT, ALTTYPE_BITS);
  477. hr = HandleAltType->Valid ? S_OK : S_FALSE;
  478. }
  479. }
  480. }
  481. if (AltType != NULL)
  482. {
  483. if (hr == S_OK)
  484. {
  485. *AltType = Handle64 & HandleAltType->Mask;
  486. if (!(Flags & GET_BITS_UNSHIFTED))
  487. {
  488. *AltType >>= HandleAltType->BitPos;
  489. }
  490. }
  491. else
  492. {
  493. *AltType = 0;
  494. }
  495. }
  496. return hr;
  497. }
  498. /******************************Public*Routine******************************\
  499. *
  500. * Routine Name:
  501. *
  502. * GetFullTypeFromHandle
  503. *
  504. * Routine Description:
  505. *
  506. * Decodes full type from engine handle
  507. *
  508. * Arguments:
  509. *
  510. * Client - PDEBUG_CLIENT
  511. * Handle64 - engine handle
  512. * FullType - Address to receive extracted full handle type
  513. * Flags - Extraction options
  514. * GET_BITS_UNSHIFTED - Field bits not shifted to start at bit 0
  515. *
  516. * Return Value:
  517. *
  518. * S_OK on success
  519. *
  520. \**************************************************************************/
  521. HRESULT
  522. GetFullTypeFromHandle(
  523. PDEBUG_CLIENT Client,
  524. ULONG64 Handle64,
  525. PULONG64 FullType,
  526. FLONG Flags
  527. )
  528. {
  529. HRESULT hr = S_FALSE;
  530. if (HandleFullType == NULL)
  531. {
  532. HandleFullType = new BitFieldInfo;
  533. }
  534. if (HandleFullType == NULL)
  535. {
  536. hr = E_OUTOFMEMORY;
  537. }
  538. else if (HandleFullType->Valid)
  539. {
  540. hr = S_OK;
  541. }
  542. else
  543. {
  544. if ((hr = GetTypeFromHandle(Client, 0, NULL)) == S_OK &&
  545. (hr = GetAltTypeFromHandle(Client, 0, NULL)) == S_OK)
  546. {
  547. if (!HandleType->Valid || HandleType->Bits == 0)
  548. {
  549. *HandleFullType = *HandleAltType;
  550. }
  551. else if (!HandleAltType->Valid || HandleAltType->Bits == 0)
  552. {
  553. *HandleFullType = *HandleType;
  554. }
  555. else
  556. {
  557. ULONG64 Mask;
  558. HandleFullType->BitPos = min(HandleType->BitPos, HandleAltType->BitPos);
  559. HandleFullType->Bits = max(HandleAltType->Bits+HandleAltType->BitPos,
  560. HandleType->Bits+HandleType->BitPos) -
  561. HandleFullType->BitPos;
  562. HandleFullType->Mask = HandleAltType->Mask | HandleType->Mask;
  563. // Make sure we have the BitPos and Bits count correct
  564. for (Mask = HandleFullType->Mask >> HandleFullType->BitPos;
  565. HandleFullType->Bits > 0 && ((Mask & 1) == 0);
  566. HandleFullType->Bits--, Mask >> 1)
  567. {
  568. HandleFullType->BitPos++;
  569. }
  570. HandleFullType->Valid = (HandleFullType->Bits > 0);
  571. }
  572. if (!HandleFullType->Valid)
  573. {
  574. hr = S_FALSE;
  575. }
  576. }
  577. }
  578. if (FullType != NULL)
  579. {
  580. if (hr == S_OK)
  581. {
  582. *FullType = Handle64 & HandleFullType->Mask;
  583. if (!(Flags & GET_BITS_UNSHIFTED))
  584. {
  585. *FullType >>= HandleFullType->BitPos;
  586. }
  587. }
  588. else
  589. {
  590. *FullType = 0;
  591. }
  592. }
  593. return hr;
  594. }
  595. /******************************Public*Routine******************************\
  596. *
  597. * Routine Name:
  598. *
  599. * GetStockFromHandle
  600. *
  601. * Routine Description:
  602. *
  603. * Decodes stock value from engine handle
  604. *
  605. * Arguments:
  606. *
  607. * Client - PDEBUG_CLIENT
  608. * Handle64 - engine handle
  609. * Stock - Address to receive extracted handle stock setting
  610. * Flags - Extraction options
  611. * GET_BITS_UNSHIFTED - Field bits not shifted to start at bit 0
  612. *
  613. * Return Value:
  614. *
  615. * S_OK on success
  616. *
  617. \**************************************************************************/
  618. HRESULT
  619. GetStockFromHandle(
  620. PDEBUG_CLIENT Client,
  621. ULONG64 Handle64,
  622. PULONG64 Stock,
  623. FLONG Flags
  624. )
  625. {
  626. HRESULT hr = S_FALSE;
  627. if (HandleStock == NULL)
  628. {
  629. HandleStock = new BitFieldInfo;
  630. }
  631. if (HandleStock == NULL)
  632. {
  633. hr = E_OUTOFMEMORY;
  634. }
  635. else if (HandleStock->Valid)
  636. {
  637. hr = S_OK;
  638. }
  639. else
  640. {
  641. BitFieldParser BitFieldReader(Client, HandleStock);
  642. OutputState OutState(Client);
  643. if ((hr = BitFieldReader.Ready()) == S_OK &&
  644. (hr = OutState.Setup(0, &BitFieldReader)) == S_OK)
  645. {
  646. // Read index bit field from symbol file
  647. if ((hr = OutState.Execute("dt " GDIType(GDIHandleBitFields) " Stock")) != S_OK ||
  648. (hr = BitFieldReader.ParseOutput()) != S_OK ||
  649. (hr = BitFieldReader.Complete()) != S_OK)
  650. {
  651. // Use position STOCK_SHIFT and STOCK_BITS from ntgdistr.h
  652. HandleStock->Valid = HandleStock->Compose(STOCK_SHIFT, STOCK_BITS);
  653. hr = HandleStock->Valid ? S_OK : S_FALSE;
  654. }
  655. }
  656. }
  657. if (Stock != NULL)
  658. {
  659. if (hr == S_OK)
  660. {
  661. *Stock = Handle64 & HandleStock->Mask;
  662. if (!(Flags & GET_BITS_UNSHIFTED))
  663. {
  664. *Stock >>= HandleStock->BitPos;
  665. }
  666. }
  667. else
  668. {
  669. *Stock = 0;
  670. }
  671. }
  672. return hr;
  673. }
  674. /******************************Public*Routine******************************\
  675. *
  676. * Routine Name:
  677. *
  678. * GetFullUniqueFromHandle
  679. *
  680. * Routine Description:
  681. *
  682. * Decodes full unique value from engine handle
  683. *
  684. * Arguments:
  685. *
  686. * Client - PDEBUG_CLIENT
  687. * Handle64 - engine handle
  688. * FullUnique - Address to receive extracted handle FullUnique value
  689. * Flags - Extraction options
  690. * GET_BITS_UNSHIFTED - Field bits not shifted to start at bit 0
  691. *
  692. * Return Value:
  693. *
  694. * S_OK on success
  695. *
  696. \**************************************************************************/
  697. HRESULT
  698. GetFullUniqueFromHandle(
  699. PDEBUG_CLIENT Client,
  700. ULONG64 Handle64,
  701. PULONG64 FullUnique,
  702. ULONG Flags
  703. )
  704. {
  705. HRESULT hr = S_FALSE;
  706. if (HandleFullUnique == NULL)
  707. {
  708. HandleFullUnique = new BitFieldInfo;
  709. }
  710. if (HandleFullUnique == NULL)
  711. {
  712. hr = E_OUTOFMEMORY;
  713. }
  714. else if (HandleFullUnique->Valid)
  715. {
  716. hr = S_OK;
  717. }
  718. else
  719. {
  720. if (HandleIndex == NULL || !HandleIndex->Valid)
  721. {
  722. // Try to read Index bitfield
  723. hr = GetIndexFromHandle(Client, 0, NULL);
  724. }
  725. if (HandleIndex != NULL && HandleIndex->Valid)
  726. {
  727. BitFieldInfo GDIHandle;
  728. BitFieldParser BitFieldReader(Client, &GDIHandle);
  729. OutputState OutState(Client);
  730. if ((hr = BitFieldReader.Ready()) == S_OK &&
  731. (hr = OutState.Setup(0, &BitFieldReader)) == S_OK)
  732. {
  733. // Read FullUnique from symbol file
  734. if (OutState.Execute("dt " GDIType(GDIHandleBitFields)) == S_OK &&
  735. BitFieldReader.ParseOutput() == S_OK &&
  736. BitFieldReader.Complete() == S_OK)
  737. {
  738. ULONG64 Mask;
  739. HandleFullUnique->BitPos = HandleIndex->BitPos + HandleIndex->Bits;
  740. HandleFullUnique->Bits = GDIHandle.Bits - HandleFullUnique->BitPos;
  741. HandleFullUnique->Mask = GDIHandle.Mask & ~HandleIndex->Mask;
  742. // Make sure we have the BitPos and Bits count correct
  743. for (Mask = HandleFullUnique->Mask >> HandleFullUnique->BitPos;
  744. HandleFullUnique->Bits > 0 && ((Mask & 1) == 0);
  745. HandleFullUnique->Bits--, Mask >> 1)
  746. {
  747. HandleFullUnique->BitPos++;
  748. }
  749. HandleFullUnique->Valid = (HandleFullUnique->Bits > 0);
  750. }
  751. else
  752. {
  753. // Use values from ntgdistr.h
  754. HandleFullUnique->Valid =
  755. HandleFullUnique->Compose(TYPE_SHIFT,
  756. TYPE_BITS +
  757. ALTTYPE_BITS +
  758. STOCK_BITS +
  759. UNIQUE_BITS);
  760. }
  761. hr = HandleFullUnique->Valid ? S_OK : S_FALSE;
  762. }
  763. }
  764. }
  765. if (FullUnique != NULL)
  766. {
  767. if (hr == S_OK)
  768. {
  769. *FullUnique = Handle64 & HandleFullUnique->Mask;
  770. if (!(Flags & GET_BITS_UNSHIFTED))
  771. {
  772. *FullUnique >>= HandleFullUnique->BitPos;
  773. }
  774. }
  775. else
  776. {
  777. *FullUnique = 0;
  778. }
  779. }
  780. return hr;
  781. }
  782. /******************************Public*Routine******************************\
  783. *
  784. * Routine Name:
  785. *
  786. * GetHandleTable
  787. *
  788. * Routine Description:
  789. *
  790. * reads current location of handle table
  791. *
  792. * Arguments:
  793. *
  794. * Client - PDEBUG_CLIENT
  795. * TableAddr - PULONG64 to return start address of handle table
  796. *
  797. * Return Value:
  798. *
  799. * If successful, S_OK.
  800. *
  801. \**************************************************************************/
  802. HRESULT
  803. GetHandleTable(
  804. PDEBUG_CLIENT Client,
  805. PULONG64 TableAddr
  806. )
  807. {
  808. ULONG CurrentUniqueState = UniqueTargetState;
  809. HRESULT hr;
  810. PDEBUG_CONTROL Control;
  811. PDEBUG_SYMBOLS Symbols;
  812. PDEBUG_DATA_SPACES Data;
  813. if (TableAddr == NULL)
  814. {
  815. return E_INVALIDARG;
  816. }
  817. if (CurrentUniqueState != INVALID_UNIQUE_STATE)
  818. {
  819. if (SessionId < NUM_CACHED_SESSIONS)
  820. {
  821. if (CachedTableAddr[SessionId].UniqueState == CurrentUniqueState)
  822. {
  823. *TableAddr = CachedTableAddr[SessionId].VirtualTableAddr;
  824. return S_OK;
  825. }
  826. }
  827. else if (SessionId == CURRENT_SESSION)
  828. {
  829. if (CachedTableAddr[NUM_CACHED_SESSIONS].UniqueState == CurrentUniqueState)
  830. {
  831. *TableAddr = CachedTableAddr[NUM_CACHED_SESSIONS].VirtualTableAddr;
  832. return S_OK;
  833. }
  834. }
  835. }
  836. *TableAddr = 0;
  837. if (Client == NULL) return E_INVALIDARG;
  838. OutputControl OutCtl(Client);
  839. if ((hr = Client->QueryInterface(__uuidof(IDebugSymbols),
  840. (void **)&Symbols)) != S_OK)
  841. {
  842. return hr;
  843. }
  844. if ((hr = Client->QueryInterface(__uuidof(IDebugDataSpaces),
  845. (void **)&Data)) != S_OK)
  846. {
  847. Symbols->Release();
  848. return hr;
  849. }
  850. CHAR PointerName[80];
  851. ULONG64 pent;
  852. hr = S_FALSE;
  853. if (TargetClass != DEBUG_CLASS_USER_WINDOWS)
  854. {
  855. sprintf(PointerName, "%s!gpentHmgr", GDIKM_Module.Name);
  856. hr = Symbols->GetOffsetByName(PointerName, &pent);
  857. if (hr != S_OK)
  858. {
  859. OutCtl.OutErr("Unable to locate %s\n", PointerName);
  860. }
  861. }
  862. if (hr != S_OK && SessionId == CURRENT_SESSION)
  863. {
  864. sprintf(PointerName, "%s!pGdiSharedHandleTable", GDIUM_Module.Name);
  865. hr = Symbols->GetOffsetByName(PointerName, &pent);
  866. if (hr != S_OK)
  867. {
  868. OutCtl.OutErr("Unable to locate %s\n", PointerName);
  869. }
  870. }
  871. if (hr == S_OK)
  872. {
  873. if (SessionId == CURRENT_SESSION)
  874. {
  875. hr = Data->ReadPointersVirtual(1, pent, TableAddr);
  876. if (hr == S_OK)
  877. {
  878. CachedTableAddr[NUM_CACHED_SESSIONS].VirtualTableAddr = *TableAddr;
  879. CachedTableAddr[NUM_CACHED_SESSIONS].UniqueState = CurrentUniqueState;
  880. }
  881. }
  882. else
  883. {
  884. ULONG64 pentPhys;
  885. if ((hr = GetPhysicalAddress(Client,
  886. SessionId,
  887. pent,
  888. &pentPhys)) == S_OK)
  889. {
  890. hr = ReadPointerPhysical(Client, pentPhys, TableAddr);
  891. if (hr == S_OK)
  892. {
  893. if (SessionId < NUM_CACHED_SESSIONS)
  894. {
  895. CachedTableAddr[SessionId].VirtualTableAddr = *TableAddr;
  896. CachedTableAddr[SessionId].UniqueState = CurrentUniqueState;
  897. }
  898. }
  899. }
  900. }
  901. if (hr == S_OK)
  902. {
  903. if (!*TableAddr)
  904. {
  905. OutCtl.OutErr(" GDI handle manager is not initialized or symbols are incorrect.\n"
  906. " %s @ %#p is NULL.\n", PointerName, pent);
  907. hr = S_FALSE;
  908. }
  909. }
  910. else
  911. {
  912. OutCtl.OutErr("Unable to get the contents of %s @ %#p\n",
  913. PointerName, pent);
  914. }
  915. }
  916. Data->Release();
  917. Symbols->Release();
  918. return hr;
  919. }
  920. /******************************Public*Routine******************************\
  921. *
  922. * Routine Name:
  923. *
  924. * GetMaxHandles
  925. *
  926. * Routine Description:
  927. *
  928. * reads current maximum number of handles
  929. *
  930. * Arguments:
  931. *
  932. * Client - PDEBUG_CLIENT
  933. *
  934. * Return Value:
  935. *
  936. * Zero for failure, otherwise maximum valid handle index
  937. *
  938. \**************************************************************************/
  939. HRESULT
  940. GetMaxHandles(
  941. PDEBUG_CLIENT Client,
  942. PULONG64 MaxHandles
  943. )
  944. {
  945. static ULONG CachedUniqueState = INVALID_UNIQUE_STATE;
  946. static ULONG LastSession = INVALID_SESSION;
  947. static ULONG64 LastMaxHandles = 0;
  948. ULONG CurrentUniqueState = UniqueTargetState;
  949. HRESULT hr;
  950. if (MaxHandles == NULL) return E_INVALIDARG;
  951. if (CurrentUniqueState != INVALID_UNIQUE_STATE &&
  952. CachedUniqueState == CurrentUniqueState &&
  953. LastSession == SessionId)
  954. {
  955. *MaxHandles = LastMaxHandles;
  956. return S_OK;
  957. }
  958. if (Client == NULL) return E_INVALIDARG;
  959. OutputControl OutCtl(Client);
  960. hr = S_FALSE;
  961. if (TargetClass != DEBUG_CLASS_USER_WINDOWS)
  962. {
  963. CHAR SymName[80];
  964. sprintf(SymName, "%s!gcMaxHmgr", GDIKM_Module.Name);
  965. hr = ReadSymbolData(Client, SymName, MaxHandles, sizeof(*MaxHandles), NULL);
  966. if (hr != S_OK)
  967. {
  968. OutCtl.OutErr("Unable to get contents of %s\n", SymName);
  969. }
  970. }
  971. if (hr != S_OK)
  972. {
  973. ULONG64 Module;
  974. ULONG TypeId;
  975. if ((hr = GetTypeId(Client, "_GDI_SHARED_MEMORY", &TypeId, &Module)) == S_OK)
  976. {
  977. ULONG NumHandles;
  978. hr = GetFieldSize(Client, Module, TypeId, "aentryHmgr",
  979. NULL, &NumHandles, NULL);
  980. if (hr == S_OK)
  981. {
  982. *MaxHandles = NumHandles;
  983. }
  984. else
  985. {
  986. OutCtl.OutErr("Unable to get length of _GDI_SHARED_MEMORY.aentryHmgr\n");
  987. }
  988. }
  989. }
  990. if (hr == S_OK)
  991. {
  992. CachedUniqueState = CurrentUniqueState;
  993. LastSession = SessionId;
  994. LastMaxHandles = *MaxHandles;
  995. }
  996. return hr;
  997. }
  998. /******************************Public*Routine******************************\
  999. *
  1000. * Routine Name:
  1001. *
  1002. * GetEntryAddress
  1003. *
  1004. * Routine Description:
  1005. *
  1006. * looks up hmgr entry for an engine handle index
  1007. *
  1008. * Arguments:
  1009. *
  1010. * Client - PDEBUG_CLIENT
  1011. * Index64 -- engine handle index
  1012. *
  1013. * Return Value:
  1014. *
  1015. * address of handle manager entry
  1016. *
  1017. \**************************************************************************/
  1018. HRESULT
  1019. GetEntryAddress(
  1020. PDEBUG_CLIENT Client,
  1021. ULONG64 Handle64,
  1022. PULONG64 EntryAddr,
  1023. PBOOL Physical
  1024. )
  1025. {
  1026. HRESULT hr;
  1027. ULONG64 Index;
  1028. ULONG64 MaxIndex;
  1029. ULONG64 TableAddr;
  1030. ULONG EntSize;
  1031. *EntryAddr = 0;
  1032. *Physical = FALSE;
  1033. if ((hr = GetIndexFromHandle(Client, Handle64, &Index)) == S_OK &&
  1034. (hr = GetHandleTable(Client, &TableAddr)) == S_OK &&
  1035. (hr = GetMaxHandles(Client, &MaxIndex)) == S_OK)
  1036. {
  1037. if (Index >= MaxIndex)
  1038. {
  1039. OutputControl OutCtl(Client);
  1040. OutCtl.OutVerb("Bad index: Index (%I64x) >= Max Handles (%I64x)\n",
  1041. Index, MaxIndex);
  1042. hr = S_FALSE;
  1043. }
  1044. else
  1045. {
  1046. if ((EntSize = GetEntrySize(Client)) == 0)
  1047. {
  1048. hr = S_FALSE;
  1049. }
  1050. }
  1051. }
  1052. if (hr == S_OK)
  1053. {
  1054. if (SessionId != CURRENT_SESSION)
  1055. {
  1056. *Physical = TRUE;
  1057. hr = GetPhysicalAddress(Client, SessionId,
  1058. TableAddr + EntSize * Index,
  1059. EntryAddr);
  1060. }
  1061. else
  1062. {
  1063. *EntryAddr = TableAddr + EntSize * Index;
  1064. }
  1065. }
  1066. return hr;
  1067. }
  1068. /******************************Public*Routine******************************\
  1069. *
  1070. * Routine Name:
  1071. *
  1072. * GetObjectAddress
  1073. *
  1074. * Routine Desciption:
  1075. *
  1076. * Converts an engine handle to an address of an object
  1077. *
  1078. * Arguments:
  1079. *
  1080. * Client - PDEBUG_CLIENT
  1081. * Handle64 -- engine handle
  1082. * ValidateBaseObj -- verifies _BASEOBJECT.hHmgr == Handle64
  1083. * ExcpectedType -- Object type expected to find
  1084. *
  1085. * Return Value:
  1086. *
  1087. * Address of object if Handle64 leads to valid object of ExpectedType
  1088. * otherwise 0.
  1089. *
  1090. \**************************************************************************/
  1091. HRESULT
  1092. GetObjectAddress(
  1093. PDEBUG_CLIENT Client,
  1094. ULONG64 Handle64,
  1095. PULONG64 Address,
  1096. UCHAR ExpectedType,
  1097. BOOL ValidateFullUnique,
  1098. BOOL ValidateBaseObj
  1099. )
  1100. {
  1101. HRESULT hr;
  1102. PDEBUG_CONTROL Control;
  1103. PDEBUG_SYMBOLS Symbols;
  1104. ULONG64 EntryAddr;
  1105. BOOL Physical;
  1106. UCHAR Type;
  1107. ULONG64 ObjAddr = 0;
  1108. if (Address != NULL) *Address = 0;
  1109. if (Client == NULL) return E_INVALIDARG;
  1110. if ((hr = Client->QueryInterface(__uuidof(IDebugControl),
  1111. (void **)&Control)) != S_OK)
  1112. {
  1113. return hr;
  1114. }
  1115. if ((hr = Client->QueryInterface(__uuidof(IDebugSymbols),
  1116. (void **)&Symbols)) != S_OK)
  1117. {
  1118. Control->Release();
  1119. return hr;
  1120. }
  1121. OutputControl OutCtl(Client);
  1122. if ((hr = GetEntryAddress(Client, Handle64, &EntryAddr, &Physical)) == S_OK)
  1123. {
  1124. ULONG64 EntryModule = 0;
  1125. ULONG EntryTypeId = 0;
  1126. ULONG64 HandlesFullUnique;
  1127. DEBUG_VALUE FullUnique;
  1128. DEBUG_VALUE Objt;
  1129. DEBUG_VALUE pobj;
  1130. TypeOutputParser EntryReader(Client);
  1131. OutputState OutState(Client);
  1132. ULONG TypeOutFlags = DEBUG_OUTTYPE_RECURSION_LEVEL(((Physical || !ValidateBaseObj) ? 1 : 2));
  1133. if ((hr = OutState.Setup(0, &EntryReader)) == S_OK &&
  1134. (hr = OutState.OutputType(Physical,
  1135. EntryAddr,
  1136. Entry.Module,
  1137. Entry.TypeId,
  1138. TypeOutFlags)) == S_OK)
  1139. {
  1140. if (ExpectedType != ANY_TYPE)
  1141. {
  1142. if ((hr = EntryReader.Get(&Objt, "Objt", DEBUG_VALUE_INT8)) != S_OK)
  1143. {
  1144. OutCtl.OutErr("Unable to get entry's object type, %s.\n",
  1145. pszHRESULT(hr));
  1146. }
  1147. if (hr == S_OK &&
  1148. ExpectedType != Objt.I8)
  1149. {
  1150. OutCtl.OutVerb(" Expected type (0x%lx) doesn't match entry's (0x%lx)\n",
  1151. (ULONG)ExpectedType, (ULONG)Objt.I8);
  1152. hr = S_FALSE;
  1153. }
  1154. }
  1155. if (hr == S_OK && ValidateFullUnique)
  1156. {
  1157. if ((hr = EntryReader.Get(&FullUnique, "FullUnique", DEBUG_VALUE_INT64)) != S_OK)
  1158. {
  1159. OutCtl.OutErr("Unable to get entry's full unique value, %s.\n",
  1160. pszHRESULT(hr));
  1161. }
  1162. if (hr == S_OK &&
  1163. (hr = GetFullUniqueFromHandle(Client, Handle64, &HandlesFullUnique)) != S_OK)
  1164. {
  1165. OutCtl.OutErr("Unable to extract full unique value from handle, %s.\n",
  1166. pszHRESULT(hr));
  1167. }
  1168. if (hr == S_OK &&
  1169. HandlesFullUnique != FullUnique.I64)
  1170. {
  1171. OutCtl.OutVerb(" Handle's full unique value (0x%p) doesn't match entry's (0x%p)\n",
  1172. HandlesFullUnique, FullUnique.I64);
  1173. hr = S_FALSE;
  1174. }
  1175. }
  1176. // If valid so far, get the object address.
  1177. if (hr == S_OK)
  1178. {
  1179. if ((hr = EntryReader.Get(&pobj, "pobj", DEBUG_VALUE_INT64)) != S_OK)
  1180. {
  1181. OutCtl.OutErr("Unable to get entry's object address, %s.\n",
  1182. pszHRESULT(hr));
  1183. }
  1184. else
  1185. {
  1186. ObjAddr = pobj.I64;
  1187. }
  1188. }
  1189. if (hr == S_OK && ValidateBaseObj)
  1190. {
  1191. DEBUG_VALUE ObjHandle;
  1192. if (Physical)
  1193. {
  1194. hr = OutState.OutputTypeVirtual(ObjAddr, "_BASEOBJECT", 0);
  1195. }
  1196. if (hr != S_OK ||
  1197. (hr = EntryReader.Get(&ObjHandle, "hHmgr", DEBUG_VALUE_INT64)) != S_OK)
  1198. {
  1199. OutCtl.OutErr("Unable to read object's base info, %s.\n",
  1200. pszHRESULT(hr));
  1201. }
  1202. if (hr == S_OK &&
  1203. ObjHandle.I64 != Handle64)
  1204. {
  1205. // If Handle64's full unique bits weren't validated and
  1206. // Handle64 doesn't match hHmgr in baseobj,
  1207. // set them to to full unique from entry.
  1208. if (!ValidateFullUnique)
  1209. {
  1210. if ((hr = EntryReader.Get(&FullUnique, "FullUnique", DEBUG_VALUE_INT64)) != S_OK)
  1211. {
  1212. OutCtl.OutErr("Unable to get entry's full unique value, %s.\n",
  1213. pszHRESULT(hr));
  1214. }
  1215. // Make sure HandleFullUnique is valid
  1216. if (hr == S_OK &&
  1217. (hr = GetFullUniqueFromHandle(Client, 0, NULL)) != S_OK)
  1218. {
  1219. OutCtl.OutErr("Unable to compose handle from entry, %s.\n", pszHRESULT(hr));
  1220. }
  1221. else
  1222. {
  1223. Handle64 = (Handle64 & ~(HandleFullUnique->Mask)) |
  1224. (FullUnique.I64 << HandleFullUnique->BitPos);
  1225. if (Control->IsPointer64Bit() != S_OK)
  1226. {
  1227. Handle64 = DEBUG_EXTEND64(Handle64);
  1228. }
  1229. }
  1230. }
  1231. if (hr == S_OK &&
  1232. ObjHandle.I64 != Handle64)
  1233. {
  1234. OutCtl.OutVerb(" Handle (0x%p) doesn't match object's hHmgr (0x%p)\n",
  1235. Handle64, ObjHandle.I64);
  1236. hr = S_FALSE;
  1237. }
  1238. }
  1239. }
  1240. }
  1241. }
  1242. if (hr == S_OK &&
  1243. Address != NULL)
  1244. {
  1245. *Address = ObjAddr;
  1246. }
  1247. Symbols->Release();
  1248. Control->Release();
  1249. return hr;
  1250. }
  1251. /******************************Public*Routine******************************\
  1252. *
  1253. * Routine Name:
  1254. *
  1255. * GetObjectHandle
  1256. *
  1257. * Routine Desciption:
  1258. *
  1259. * Retrieves handle of an object from it address
  1260. *
  1261. * Arguments:
  1262. *
  1263. * Client -- PDEBUG_CLIENT
  1264. * ObjectAddr -- Address of OBJECT
  1265. * Handle64 -- ULONG64 to receive engine handle
  1266. * ValidateHandle -- verifies ENTRY.pobj == ObjectAddr
  1267. * ExcpectedType -- Object type expected to find
  1268. * Currently only value when ValidateHandle is TRUE
  1269. *
  1270. * Return Value:
  1271. *
  1272. * HRESULT of retrieval attempts and validation.
  1273. * S_OK indicates everything succeeded.
  1274. *
  1275. \**************************************************************************/
  1276. HRESULT
  1277. GetObjectHandle(
  1278. PDEBUG_CLIENT Client,
  1279. ULONG64 ObjectAddr,
  1280. PULONG64 Handle64,
  1281. BOOL ValidateHandle,
  1282. UCHAR ExpectedType
  1283. )
  1284. {
  1285. HRESULT hr;
  1286. DEBUG_VALUE ObjHandle;
  1287. TypeOutputParser ObjectReader(Client);
  1288. OutputState OutState(Client);
  1289. if (Handle64 != NULL) *Handle64 = 0;
  1290. if (ObjectAddr == 0) return E_INVALIDARG;
  1291. if ((hr = OutState.Setup(0, &ObjectReader)) == S_OK &&
  1292. (hr = OutState.OutputTypeVirtual(ObjectAddr,
  1293. "_BASEOBJECT",
  1294. 0)) == S_OK)
  1295. {
  1296. hr = ObjectReader.Get(&ObjHandle, "hHmgr", DEBUG_VALUE_INT64);
  1297. }
  1298. if (hr == S_OK && ValidateHandle)
  1299. {
  1300. ULONG64 ObjectAddrFromHmgr;
  1301. hr = GetObjectAddress(Client, ObjHandle.I64, &ObjectAddrFromHmgr,
  1302. ExpectedType, TRUE, FALSE);
  1303. if (hr == S_OK &&
  1304. ObjectAddrFromHmgr != ObjectAddr)
  1305. {
  1306. hr = S_FALSE;
  1307. }
  1308. }
  1309. if (hr == S_OK && Handle64 != NULL)
  1310. {
  1311. *Handle64 = ObjHandle.I64;
  1312. }
  1313. return hr;
  1314. }
  1315. /******************************Public*Routine******************************\
  1316. *
  1317. * Routine Name:
  1318. *
  1319. * OutputHandleInfo
  1320. *
  1321. * Routine Desciption:
  1322. *
  1323. * Retrieves handle of an object from it address
  1324. *
  1325. * Arguments:
  1326. *
  1327. * Client -- PDEBUG_CLIENT
  1328. * Handle64 -- engine handle
  1329. *
  1330. * Return Value:
  1331. *
  1332. * HRESULT of retrieval attempts and validation.
  1333. * S_OK indicates everything succeeded.
  1334. *
  1335. \**************************************************************************/
  1336. HRESULT
  1337. OutputHandleInfo(
  1338. OutputControl *OutCtl,
  1339. PDEBUG_CLIENT Client,
  1340. PDEBUG_VALUE Handle
  1341. )
  1342. {
  1343. if (Client == NULL || OutCtl == NULL || Handle == NULL)
  1344. {
  1345. return E_INVALIDARG;
  1346. }
  1347. HRESULT hrRet;
  1348. HRESULT hr;
  1349. DEBUG_VALUE ConvValue;
  1350. ULONG64 Type;
  1351. ULONG64 FullType;
  1352. ULONG64 Stock;
  1353. ENUMDEF *pEnumDef;
  1354. if (Handle->Type != DEBUG_VALUE_INT64)
  1355. {
  1356. if ((hr = OutCtl->CoerceValue(Handle, DEBUG_VALUE_INT64, &ConvValue)) != S_OK)
  1357. {
  1358. return hr;
  1359. }
  1360. Handle = &ConvValue;
  1361. }
  1362. if (Handle->I64 == 0)
  1363. {
  1364. return S_OK;
  1365. }
  1366. hrRet = GetTypeFromHandle(Client, Handle->I64, &Type);
  1367. if (hrRet == S_OK)
  1368. {
  1369. DbgPrint("Handle 0x%I64x's type is %I64x.\n", Handle->I64, Type);
  1370. pEnumDef = aedENTRY_Objt;
  1371. while (pEnumDef->psz != NULL)
  1372. {
  1373. if (pEnumDef->ul == Type)
  1374. {
  1375. OutCtl->Output(pEnumDef->psz);
  1376. break;
  1377. }
  1378. pEnumDef++;
  1379. }
  1380. if (pEnumDef->psz == NULL)
  1381. {
  1382. OutCtl->Output("Unknown type %I64d", Type);
  1383. }
  1384. }
  1385. else
  1386. {
  1387. OutCtl->Output("Unable to extract type");
  1388. }
  1389. hr = GetFullTypeFromHandle(Client, Handle->I64, &FullType, GET_BITS_UNSHIFTED);
  1390. if (hr == S_OK)
  1391. {
  1392. DbgPrint("Handle 0x%I64x's Full Type is %I64x.\n", Handle->I64, FullType);
  1393. pEnumDef = aedENTRY_FullType;
  1394. while (pEnumDef->psz != NULL)
  1395. {
  1396. if (pEnumDef->ul == FullType)
  1397. {
  1398. OutCtl->Output(" : %s", pEnumDef->psz);
  1399. break;;
  1400. }
  1401. pEnumDef++;
  1402. }
  1403. if (pEnumDef->psz == NULL)
  1404. {
  1405. ULONG64 AltType;
  1406. hr = GetAltTypeFromHandle(Client, Handle->I64, &AltType);
  1407. if (hr == S_OK && AltType != 0)
  1408. {
  1409. OutCtl->Output(" : Unknown alt type %I64d", AltType);
  1410. }
  1411. }
  1412. }
  1413. else if (hrRet == S_OK)
  1414. {
  1415. hrRet = hr;
  1416. }
  1417. hr = GetStockFromHandle(Client, Handle->I64, &Stock);
  1418. if (hr == S_OK)
  1419. {
  1420. if (Stock)
  1421. {
  1422. OutCtl->Output(" (STOCK)");
  1423. }
  1424. }
  1425. else if (hrRet == S_OK)
  1426. {
  1427. hrRet = hr;
  1428. }
  1429. return hrRet;
  1430. }
  1431. HRESULT
  1432. OutputFullUniqueInfo(
  1433. OutputControl *OutCtl,
  1434. PDEBUG_CLIENT Client,
  1435. PDEBUG_VALUE FullUnique
  1436. )
  1437. {
  1438. if (Client == NULL || OutCtl == NULL || FullUnique == NULL)
  1439. {
  1440. return E_INVALIDARG;
  1441. }
  1442. HRESULT hr;
  1443. ULONG64 FullUniqTest;
  1444. DEBUG_VALUE Handle;
  1445. hr = GetFullUniqueFromHandle(Client, -1, &FullUniqTest);
  1446. if (hr == S_OK)
  1447. {
  1448. if (FullUniqTest == 0)
  1449. {
  1450. hr = S_FALSE;
  1451. }
  1452. else
  1453. {
  1454. if (FullUnique->Type == DEBUG_VALUE_INT64)
  1455. {
  1456. Handle = *FullUnique;
  1457. }
  1458. else
  1459. {
  1460. hr = OutCtl->CoerceValue(FullUnique, DEBUG_VALUE_INT64, &Handle);
  1461. if (hr != S_OK) return hr;
  1462. }
  1463. Handle.I64 <<= HandleFullUnique->BitPos;
  1464. hr = OutputHandleInfo(OutCtl, Client, &Handle);
  1465. }
  1466. }
  1467. return hr;
  1468. }
  1469. char *pszTypes[] = {
  1470. "DEF_TYPE ",
  1471. "DC_TYPE ",
  1472. "UNUSED1 ",
  1473. "UNUSED2 ",
  1474. "RGN_TYPE ",
  1475. "SURF_TYPE ",
  1476. "CLIOBJ_TYPE ",
  1477. "PATH_TYPE ",
  1478. "PAL_TYPE ",
  1479. "ICMLCS_TYPE ",
  1480. "LFONT_TYPE ",
  1481. "RFONT_TYPE ",
  1482. "PFE_TYPE ",
  1483. "PFT_TYPE ",
  1484. "ICMCXF_TYPE ",
  1485. "ICMDLL_TYPE ",
  1486. "BRUSH_TYPE ",
  1487. "UNUSED3 ",
  1488. "UNUSED4 ",
  1489. "SPACE_TYPE ",
  1490. "UNUSED5 ",
  1491. "META_TYPE ",
  1492. "EFSTATE_TYPE ",
  1493. "BMFD_TYPE ",
  1494. "VTFD_TYPE ",
  1495. "TTFD_TYPE ",
  1496. "RC_TYPE ",
  1497. "TEMP_TYPE ",
  1498. "DRVOBJ_TYPE ",
  1499. "DCIOBJ_TYPE ",
  1500. "SPOOL_TYPE ",
  1501. "TOTALS ",
  1502. "DEF "
  1503. };
  1504. /******************************Public*Routine******************************\
  1505. * DECLARE_API( dumphmgr )
  1506. *
  1507. * Dumps the count of handles in Hmgr for each object type.
  1508. *
  1509. * History:
  1510. * 21-Feb-1995 -by- Lingyun Wang [lingyunw]
  1511. * Wrote it.
  1512. \**************************************************************************/
  1513. /*
  1514. HmgCurrentNumberOfObjects
  1515. HmgMaximumNumberOfObjects
  1516. HmgCurrentNumberOfLookAsideObjects
  1517. HmgMaximumNumberOfLookAsideObjects
  1518. HmgNumberOfObjectsAllocated
  1519. HmgNumberOfLookAsideHits
  1520. HmgCurrentNumberOfHandles
  1521. HmgMaximumNumberOfHandles
  1522. HmgNumberOfHandlesAllocated
  1523. */
  1524. DECLARE_API( dumphmgr )
  1525. {
  1526. INIT_API();
  1527. ExtWarn("Extension 'dumphmgr' is not fully converted.\n");
  1528. HRESULT hr;
  1529. ULONG64 pent;
  1530. ULONG64 gcMaxHmgr;
  1531. ULONG entSize;
  1532. DEBUG_VALUE ObjType;
  1533. ULONG ulLoop; // loop variable
  1534. ULONG pulCount[MAX_TYPE + 2];
  1535. ULONG cUnknown = 0;
  1536. ULONG cUnknownSize = 0;
  1537. ULONG cUnused = 0;
  1538. DecArrayDumper(HmgCurrentNumberOfHandles, ULONG);
  1539. DecArrayDumper(HmgMaximumNumberOfHandles, ULONG);
  1540. DecArrayDumper(HmgNumberOfHandlesAllocated, ULONG);
  1541. DecArrayDumper(HmgCurrentNumberOfObjects, ULONG);
  1542. DecArrayDumper(HmgMaximumNumberOfObjects, ULONG);
  1543. DecArrayDumper(HmgNumberOfObjectsAllocated, ULONG);
  1544. DecArrayDumper(HmgCurrentNumberOfLookAsideObjects, ULONG);
  1545. DecArrayDumper(HmgMaximumNumberOfLookAsideObjects, ULONG);
  1546. DecArrayDumper(HmgNumberOfLookAsideHits, ULONG);
  1547. char *TableHeader;
  1548. char TableFormat[128];
  1549. while (*args && isspace(*args)) args++;
  1550. if (*args != '\0')
  1551. {
  1552. ExtOut("dumphmgr displays the count of each type of object in the handle manager\n"
  1553. "\n"
  1554. "Usage: dumphmgr [-?]\n"
  1555. " -? shows this help\n"
  1556. "\n"
  1557. " If available statics for Handles, Objects, and objects allocated\n"
  1558. " from LookAside lists are shown. Each class has three statics:\n"
  1559. " Cur - current number of items allocated\n"
  1560. " Max - largest number of items ever allocated at one time\n"
  1561. " Total - total allocations ever made for that item\n"
  1562. );
  1563. EXIT_API(S_OK);
  1564. }
  1565. // Get the pointers and counts
  1566. if ((hr = GetHandleTable(Client, &pent)) != S_OK ||
  1567. (hr = GetMaxHandles(Client, &gcMaxHmgr)) != S_OK)
  1568. {
  1569. EXIT_API(hr);
  1570. }
  1571. ExtOut("Handle Entry Table at 0x%p.\n", pent);
  1572. ExtOut("Max handles out so far %I64u.\n", gcMaxHmgr);
  1573. entSize = GetEntrySize(Client);
  1574. if (!entSize || !gcMaxHmgr)
  1575. {
  1576. EXIT_API(S_FALSE);
  1577. }
  1578. ULONG Reserved;
  1579. ULONG64 Module;
  1580. ULONG TypeId;
  1581. if ((hr = GetTypeId(Client, "_GDI_SHARED_MEMORY", &TypeId, &Module)) == S_OK)
  1582. {
  1583. hr = GetFieldSize(Client, Module, TypeId, "aentryHmgr", &Reserved);
  1584. }
  1585. // Print out the amount reserved and committed
  1586. ExtOut("Page Size: %lu Entry Size: %lu\n", PageSize, entSize);
  1587. ExtOut("Total Hmgr: Reserved memory ");
  1588. if (hr == S_OK)
  1589. {
  1590. ExtOut("%lu", Reserved);
  1591. }
  1592. else
  1593. {
  1594. ExtOut("?");
  1595. }
  1596. ExtOut(" Committed %lu\n", ((( (ULONG)gcMaxHmgr * entSize) + PageSize) & ~(PageSize - 1)));
  1597. ExtOut("\n");
  1598. for (ulLoop = 0; ulLoop <= TOTAL_TYPE; ulLoop++)
  1599. {
  1600. pulCount[ulLoop] = 0;
  1601. }
  1602. TypeOutputParser TypeReader(Client);
  1603. OutputState OutState(Client);
  1604. ULONG64 EntryModule;
  1605. ULONG EntryTypeId;
  1606. if ((hr = TypeReader.LookFor(&ObjType, "Objt", DEBUG_VALUE_INT8)) == S_OK &&
  1607. (hr = OutState.Setup(0, &TypeReader)) == S_OK)
  1608. {
  1609. if ((hr = GetTypeId(Client, szEntryType,
  1610. &EntryTypeId, &EntryModule)) != S_OK)
  1611. {
  1612. ExtErr("GetTypeId(%s) failed.\n", szEntryType);
  1613. }
  1614. }
  1615. if (hr != S_OK)
  1616. {
  1617. ExtErr("Failed to prepare type read: %s\n", pszHRESULT(hr));
  1618. EXIT_API(hr);
  1619. }
  1620. for (ulLoop = 0; ulLoop < gcMaxHmgr; ulLoop++)
  1621. {
  1622. if (g_pExtControl->GetInterrupt() == S_OK)
  1623. {
  1624. ExtErr("User cancled.\n");
  1625. EXIT_API(E_ABORT);
  1626. }
  1627. TypeReader.DiscardOutput();
  1628. TypeReader.Relook();
  1629. if ((hr = OutState.OutputTypeVirtual(pent,
  1630. EntryModule,
  1631. EntryTypeId,
  1632. 0)) != S_OK ||
  1633. (hr = TypeReader.ParseOutput()) != S_OK ||
  1634. (hr = TypeReader.Complete()) != S_OK)
  1635. {
  1636. ExtErr("Error reading table entry @ %p, %s\n", pent, pszHRESULT(hr));
  1637. ExtWarn("Only %lu entries were read.\n", ulLoop);
  1638. break;
  1639. }
  1640. if (ObjType.I8 == DEF_TYPE)
  1641. {
  1642. cUnused++;
  1643. }
  1644. if (ObjType.I8 > MAX_TYPE)
  1645. {
  1646. cUnknown++;
  1647. }
  1648. else
  1649. {
  1650. pulCount[ObjType.I8]++;
  1651. }
  1652. pent += entSize;
  1653. }
  1654. ULONG64 TmpOffset; // Have to pass an valid pointer when checking for a symbol.
  1655. if (g_pExtSymbols->GetOffsetByName(GDISymbol(HmgCurrentNumberOfObjects), &TmpOffset) == S_OK &&
  1656. HmgCurrentNumberOfObjects.ReadArray(GDISymbol(HmgCurrentNumberOfObjects)) &&
  1657. HmgMaximumNumberOfObjects.ReadArray(GDISymbol(HmgMaximumNumberOfObjects)) &&
  1658. HmgCurrentNumberOfLookAsideObjects.ReadArray(GDISymbol(HmgCurrentNumberOfLookAsideObjects)) &&
  1659. HmgMaximumNumberOfLookAsideObjects.ReadArray(GDISymbol(HmgMaximumNumberOfLookAsideObjects)) &&
  1660. HmgNumberOfObjectsAllocated.ReadArray(GDISymbol(HmgNumberOfObjectsAllocated)) &&
  1661. HmgNumberOfLookAsideHits.ReadArray(GDISymbol(HmgNumberOfLookAsideHits)) &&
  1662. HmgCurrentNumberOfHandles.ReadArray(GDISymbol(HmgCurrentNumberOfHandles)) &&
  1663. HmgMaximumNumberOfHandles.ReadArray(GDISymbol(HmgMaximumNumberOfHandles)) &&
  1664. HmgNumberOfHandlesAllocated.ReadArray(GDISymbol(HmgNumberOfHandlesAllocated))
  1665. )
  1666. {
  1667. ExtOut(" Current ---- Handles ----- ---- Objects ----- --- LookAside ----\n"
  1668. " TYPE Handles Cur Max Total Cur Max Total Cur Max Total\n");
  1669. _snprintf(TableFormat, sizeof(TableFormat),
  1670. "%%s%%6lu %%c %s %s %s %s %s %s %s %s %s\n",
  1671. HmgCurrentNumberOfHandles.SetPrintFormat(5),
  1672. HmgMaximumNumberOfHandles.SetPrintFormat(5),
  1673. HmgNumberOfHandlesAllocated.SetPrintFormat(6),
  1674. HmgCurrentNumberOfObjects.SetPrintFormat(5),
  1675. HmgMaximumNumberOfObjects.SetPrintFormat(5),
  1676. HmgNumberOfObjectsAllocated.SetPrintFormat(6),
  1677. HmgCurrentNumberOfLookAsideObjects.SetPrintFormat(5),
  1678. HmgMaximumNumberOfLookAsideObjects.SetPrintFormat(5),
  1679. HmgNumberOfLookAsideHits.SetPrintFormat(6)
  1680. );
  1681. }
  1682. else
  1683. {
  1684. ExtOut(" Current\n"
  1685. " TYPE Handles\n");
  1686. _snprintf(TableFormat, sizeof(TableFormat), "%%s%%6lu\n");
  1687. }
  1688. // init the totals
  1689. pulCount[TOTAL_TYPE] = 0;
  1690. HmgCurrentNumberOfObjects[TOTAL_TYPE] = 0;
  1691. HmgCurrentNumberOfLookAsideObjects[TOTAL_TYPE] = 0;
  1692. HmgMaximumNumberOfHandles[TOTAL_TYPE] = 0;
  1693. HmgMaximumNumberOfObjects[TOTAL_TYPE] = 0;
  1694. HmgMaximumNumberOfLookAsideObjects[TOTAL_TYPE] = 0;
  1695. HmgNumberOfHandlesAllocated[TOTAL_TYPE] = 0;
  1696. HmgNumberOfObjectsAllocated[TOTAL_TYPE] = 0;
  1697. HmgNumberOfLookAsideHits[TOTAL_TYPE] = 0;
  1698. // now go through printing each line and accumulating totals
  1699. for (ulLoop = 0; ulLoop <= MAX_TYPE; ulLoop++)
  1700. {
  1701. ExtOut(TableFormat,
  1702. pszTypes[ulLoop],
  1703. pulCount[ulLoop],
  1704. ((pulCount[ulLoop] == HmgCurrentNumberOfHandles[ulLoop]) ? '=' :
  1705. ((pulCount[ulLoop] < HmgCurrentNumberOfHandles[ulLoop]) ? '<' : '>')),
  1706. HmgCurrentNumberOfHandles[ulLoop],
  1707. HmgMaximumNumberOfHandles[ulLoop],
  1708. HmgNumberOfHandlesAllocated[ulLoop],
  1709. HmgCurrentNumberOfObjects[ulLoop],
  1710. HmgMaximumNumberOfObjects[ulLoop],
  1711. HmgNumberOfObjectsAllocated[ulLoop],
  1712. HmgCurrentNumberOfLookAsideObjects[ulLoop],
  1713. HmgMaximumNumberOfLookAsideObjects[ulLoop],
  1714. HmgNumberOfLookAsideHits[ulLoop]);
  1715. if (ulLoop != DEF_TYPE)
  1716. {
  1717. pulCount[TOTAL_TYPE] += pulCount[ulLoop];
  1718. HmgCurrentNumberOfHandles[TOTAL_TYPE] += HmgCurrentNumberOfHandles[ulLoop];
  1719. HmgMaximumNumberOfHandles[TOTAL_TYPE] += HmgMaximumNumberOfHandles[ulLoop];
  1720. HmgNumberOfHandlesAllocated[TOTAL_TYPE] += HmgNumberOfHandlesAllocated[ulLoop];
  1721. HmgCurrentNumberOfObjects[TOTAL_TYPE] += HmgCurrentNumberOfObjects[ulLoop];
  1722. HmgMaximumNumberOfObjects[TOTAL_TYPE] += HmgMaximumNumberOfObjects[ulLoop];
  1723. HmgNumberOfObjectsAllocated[TOTAL_TYPE] += HmgNumberOfObjectsAllocated[ulLoop];
  1724. HmgCurrentNumberOfLookAsideObjects[TOTAL_TYPE] += HmgCurrentNumberOfLookAsideObjects[ulLoop];
  1725. HmgMaximumNumberOfLookAsideObjects[TOTAL_TYPE] += HmgMaximumNumberOfLookAsideObjects[ulLoop];
  1726. HmgNumberOfLookAsideHits[TOTAL_TYPE] += HmgNumberOfLookAsideHits[ulLoop];
  1727. }
  1728. }
  1729. ExtOut(TableFormat,
  1730. pszTypes[TOTAL_TYPE],
  1731. pulCount[TOTAL_TYPE],
  1732. ((pulCount[TOTAL_TYPE] == HmgCurrentNumberOfHandles[TOTAL_TYPE]) ? '=' :
  1733. ((pulCount[TOTAL_TYPE] < HmgCurrentNumberOfHandles[TOTAL_TYPE]) ? '<' : '>')),
  1734. HmgCurrentNumberOfHandles[TOTAL_TYPE],
  1735. HmgMaximumNumberOfHandles[TOTAL_TYPE],
  1736. HmgNumberOfHandlesAllocated[TOTAL_TYPE],
  1737. HmgCurrentNumberOfObjects[TOTAL_TYPE],
  1738. HmgMaximumNumberOfObjects[TOTAL_TYPE],
  1739. HmgNumberOfObjectsAllocated[TOTAL_TYPE],
  1740. HmgCurrentNumberOfLookAsideObjects[TOTAL_TYPE],
  1741. HmgMaximumNumberOfLookAsideObjects[TOTAL_TYPE],
  1742. HmgNumberOfLookAsideHits[TOTAL_TYPE]);
  1743. ExtOut ("\ncUnused objects %lu\n", cUnused);
  1744. ExtOut("cUnknown objects %lu %lu\n",cUnknown,cUnknownSize);
  1745. EXIT_API(S_OK);
  1746. }
  1747. char *pszTypes2[] = {
  1748. "DEF",
  1749. "DC",
  1750. "UNUSED_2", // "LDB",
  1751. "UNUSED_3", // "PDB",
  1752. "RGN",
  1753. "SURF",
  1754. "CLIOBJ",
  1755. "PATH",
  1756. "PAL",
  1757. "ICMLCS",
  1758. "LFONT",
  1759. "RFONT",
  1760. "PFE",
  1761. "PFT",
  1762. "ICMCXF",
  1763. "ICMDLL",
  1764. "BRUSH",
  1765. "UNUSED_17", // "D3D_HANDLE",
  1766. "UNUSED_18", // "CACHE",
  1767. "SPACE",
  1768. "UNUSED_20", // "DBRUSH"
  1769. "META",
  1770. "EFSTATE",
  1771. "BMFD",
  1772. "VTFD",
  1773. "TTFD",
  1774. "RC",
  1775. "TEMP",
  1776. "DRVOBJ",
  1777. "DCIOBJ",
  1778. "SPOOL"
  1779. };
  1780. /******************************Public*Class********************************\
  1781. * class AccumPidObjects
  1782. *
  1783. \**************************************************************************/
  1784. class PidObjects {
  1785. public:
  1786. ULONG Pid;
  1787. PidObjects *pNextPid;
  1788. PidObjects *pPrevPid;
  1789. Array<ULONG> TypeCount;
  1790. PidObjects(ULONG Pid_, ULONG TotalTypes) : TypeCount(TotalTypes)
  1791. {
  1792. Pid = Pid_;
  1793. pNextPid = NULL;
  1794. pPrevPid = NULL;
  1795. }
  1796. };
  1797. class AccumPidObjects {
  1798. public:
  1799. AccumPidObjects(ULONG ulMaxType_, char **pszTypeDesc_);
  1800. ~AccumPidObjects();
  1801. HRESULT Valid();
  1802. VOID Add(ULONG Type)
  1803. {
  1804. ObjectTotals[Type]++;
  1805. ObjectTotals[ulMaxType]++;
  1806. }
  1807. HRESULT Add(ULONG Pid, ULONG Type);
  1808. HRESULT OutputResults(OutputControl *OutCtl, Array<BOOL> &ShowZeroCountForType);
  1809. void Reset();
  1810. Array<ULONG> ObjectTotals;
  1811. private:
  1812. PidObjects *GetFirstPid();
  1813. PidObjects *GetEntry(ULONG Pid);
  1814. ULONG ulMaxType;
  1815. ULONG ulMaxObjectsPerPid;
  1816. PidObjects *PidList; // Linked list of Pids
  1817. char **pszTypeDesc;
  1818. Array<ULONG> ColWidth;
  1819. };
  1820. AccumPidObjects::AccumPidObjects(
  1821. ULONG ulMaxType_,
  1822. char **pszTypeDesc_
  1823. ) : ObjectTotals(ulMaxType_+1), ColWidth(ulMaxType_+1)
  1824. {
  1825. ulMaxType = ulMaxType_;
  1826. PidList = NULL;
  1827. pszTypeDesc = pszTypeDesc_;
  1828. Reset();
  1829. }
  1830. AccumPidObjects::~AccumPidObjects()
  1831. {
  1832. PidObjects *pPO, *pPONext;
  1833. pPO = GetFirstPid();
  1834. while (pPO != NULL)
  1835. {
  1836. pPONext = pPO->pNextPid;
  1837. delete pPO;
  1838. pPO = pPONext;
  1839. }
  1840. }
  1841. HRESULT
  1842. AccumPidObjects::Valid()
  1843. {
  1844. return ((ulMaxType > 0) ? S_OK : S_FALSE);
  1845. }
  1846. HRESULT
  1847. AccumPidObjects::Add(
  1848. ULONG Pid,
  1849. ULONG Type
  1850. )
  1851. {
  1852. PidObjects *pEntry;
  1853. pEntry = GetEntry(Pid);
  1854. if (pEntry == NULL) return E_FAIL;
  1855. Add(Type);
  1856. pEntry->TypeCount[Type]++;
  1857. pEntry->TypeCount[ulMaxType]++;
  1858. if (pEntry->TypeCount[ulMaxType] > ulMaxObjectsPerPid)
  1859. {
  1860. ulMaxObjectsPerPid = pEntry->TypeCount[ulMaxType];
  1861. PidList = pEntry;
  1862. }
  1863. return S_OK;
  1864. }
  1865. HRESULT
  1866. AccumPidObjects::OutputResults(
  1867. OutputControl *OutCtl,
  1868. Array<BOOL> &ShowZeroCountForType
  1869. )
  1870. {
  1871. HRESULT hr = S_OK;
  1872. PidObjects *pPO;
  1873. ULONG Type;
  1874. // Output headers
  1875. hr = OutCtl->Output("Pid\\Type %*s", ColWidth[ulMaxType], "Total");
  1876. for (Type = 0; hr == S_OK && Type < ulMaxType; Type++)
  1877. {
  1878. if (ObjectTotals[Type] > 0 || ShowZeroCountForType[Type])
  1879. {
  1880. hr = OutCtl->Output(" %*s", ColWidth[Type], pszTypeDesc[Type]);
  1881. }
  1882. }
  1883. if (hr == S_OK) hr = OutCtl->Output("\n");
  1884. // Output per PID results
  1885. for (pPO = GetFirstPid(); hr == S_OK && pPO != NULL; pPO = pPO->pNextPid)
  1886. {
  1887. hr = OutCtl->Output("%8lx: %*lu", pPO->Pid,
  1888. ColWidth[ulMaxType], pPO->TypeCount[ulMaxType]);
  1889. for (Type = 0; hr == S_OK && Type < ulMaxType; Type++)
  1890. {
  1891. if (ObjectTotals[Type] > 0 || ShowZeroCountForType[Type])
  1892. {
  1893. hr = OutCtl->Output(" %*lu", ColWidth[Type], pPO->TypeCount[Type]);
  1894. }
  1895. }
  1896. if (hr == S_OK) hr = OutCtl->Output("\n");
  1897. }
  1898. // Output totals
  1899. hr = OutCtl->Output(" Totals: %*lu",
  1900. ColWidth[ulMaxType], ObjectTotals[ulMaxType]);
  1901. for (Type = 0; hr == S_OK && Type < ulMaxType; Type++)
  1902. {
  1903. if (ObjectTotals[Type] > 0 || ShowZeroCountForType[Type])
  1904. {
  1905. hr = OutCtl->Output(" %*lu", ColWidth[Type], ObjectTotals[Type]);
  1906. }
  1907. }
  1908. OutCtl->Output("\n");
  1909. return hr;
  1910. }
  1911. void
  1912. AccumPidObjects::Reset()
  1913. {
  1914. PidObjects *pPO, *pPONext;
  1915. ULONG i;
  1916. pPO = GetFirstPid();
  1917. while (pPO != NULL)
  1918. {
  1919. pPONext = pPO->pNextPid;
  1920. delete pPO;
  1921. pPO = pPONext;
  1922. }
  1923. PidList = NULL;
  1924. ulMaxObjectsPerPid = 0;
  1925. for (i = 0; i < ulMaxType; i++)
  1926. {
  1927. ObjectTotals[i] = 0;
  1928. ColWidth[i] = max(6, strlen(pszTypeDesc[i]));
  1929. }
  1930. ObjectTotals[ulMaxType] = 0;
  1931. ColWidth[ulMaxType] = 8;
  1932. }
  1933. PidObjects*
  1934. AccumPidObjects::GetFirstPid()
  1935. {
  1936. PidObjects *pPO = PidList;
  1937. if (pPO != NULL)
  1938. {
  1939. while (pPO->pPrevPid != NULL)
  1940. pPO = pPO->pPrevPid;
  1941. }
  1942. return pPO;
  1943. }
  1944. PidObjects*
  1945. AccumPidObjects::GetEntry(
  1946. ULONG Pid
  1947. )
  1948. {
  1949. PidObjects *pPO = PidList;
  1950. if (pPO != NULL && pPO->Pid != Pid)
  1951. {
  1952. if (pPO->Pid < Pid)
  1953. {
  1954. while (pPO->pNextPid != NULL)
  1955. {
  1956. pPO = pPO->pNextPid;
  1957. if (pPO->Pid >= Pid)
  1958. {
  1959. break;
  1960. }
  1961. }
  1962. }
  1963. else
  1964. {
  1965. while (pPO->pPrevPid != NULL)
  1966. {
  1967. pPO = pPO->pPrevPid;
  1968. if (pPO->Pid <= Pid)
  1969. {
  1970. break;
  1971. }
  1972. }
  1973. }
  1974. }
  1975. if (pPO == NULL || pPO->Pid != Pid)
  1976. {
  1977. PidObjects *pPONew = new PidObjects(Pid, ulMaxType+1);
  1978. if (pPONew != NULL)
  1979. {
  1980. if (pPO == NULL)
  1981. {
  1982. PidList = pPONew;
  1983. }
  1984. else if (pPO->Pid < Pid)
  1985. {
  1986. pPONew->pNextPid = pPO->pNextPid;
  1987. pPONew->pPrevPid = pPO;
  1988. pPO->pNextPid = pPONew;
  1989. if (pPONew->pNextPid != NULL)
  1990. {
  1991. pPONew->pNextPid->pPrevPid = pPONew;
  1992. }
  1993. }
  1994. else
  1995. {
  1996. pPONew->pNextPid = pPO;
  1997. pPONew->pPrevPid = pPO->pPrevPid;
  1998. pPO->pPrevPid = pPONew;
  1999. if (pPONew->pPrevPid != NULL)
  2000. {
  2001. pPONew->pPrevPid->pNextPid = pPONew;
  2002. }
  2003. }
  2004. }
  2005. pPO = pPONew;
  2006. }
  2007. return pPO;
  2008. }
  2009. /******************************Public*Routine******************************\
  2010. * DECLARE_API( dumpobj )
  2011. *
  2012. * History:
  2013. * 21-Feb-1995 -by- Lingyun Wang [lingyunw]
  2014. * Wrote it.
  2015. * 29-Dec-2000 -by- Jason Hartman [jasonha]
  2016. * Ported to Type debugging API.
  2017. \**************************************************************************/
  2018. #define USE_READ 0
  2019. #define ENTRY_RECURSE_LEVELS 1
  2020. DECLARE_API( dumpobjr )
  2021. {
  2022. HRESULT hr;
  2023. BEGIN_API( dumpobjr );
  2024. BOOL CheckType = TRUE;
  2025. Array<BOOL> MatchType(TOTAL_TYPE);
  2026. Array<CHAR> TypeList;
  2027. BOOL CheckPid = FALSE;
  2028. BOOL ThisPid;
  2029. DEBUG_VALUE MatchPid = {0, DEBUG_VALUE_INVALID};
  2030. BOOL TrackPerPid;
  2031. BOOL CheckLock = FALSE;
  2032. BOOL Summary = FALSE;
  2033. BOOL BadArg = FALSE;
  2034. BOOL UseIndex = FALSE;
  2035. DEBUG_VALUE StartIndex = {0, DEBUG_VALUE_INVALID};
  2036. OutputControl OutCtl(Client);
  2037. ULONG64 EntryAddr;
  2038. ULONG64 gcMaxHmgr;
  2039. ULONG EntrySize;
  2040. ULONG Index = 0;
  2041. ULONG LongestType = 0;
  2042. int i;
  2043. for (i = 0; i <= MAX_TYPE; i++)
  2044. {
  2045. ULONG Len = strlen(pszTypes2[i]);
  2046. if (Len > LongestType)
  2047. {
  2048. LongestType = Len;
  2049. }
  2050. }
  2051. while (!BadArg)
  2052. {
  2053. while (isspace(*args)) args++;
  2054. if (*args == '-')
  2055. {
  2056. // Process switches
  2057. args++;
  2058. BadArg = (*args == '\0' || isspace(*args));
  2059. while (*args != '\0' && !isspace(*args))
  2060. {
  2061. switch (tolower(*args))
  2062. {
  2063. case 'a':
  2064. if (CheckType && !TypeList.IsEmpty())
  2065. {
  2066. BadArg = TRUE;
  2067. OutCtl.OutErr("Error: -a may not be specified with a Type list.\n");
  2068. }
  2069. else
  2070. {
  2071. CheckType = FALSE;
  2072. }
  2073. break;
  2074. case 'i':
  2075. if (CheckPid && MatchPid.Type == DEBUG_VALUE_INVALID)
  2076. {
  2077. BadArg = TRUE;
  2078. OutCtl.OutErr("Error: PID value not found after -%c.\n",
  2079. (ThisPid ? 'p' : 'n'));
  2080. }
  2081. else
  2082. {
  2083. UseIndex = TRUE;
  2084. }
  2085. break;
  2086. case 'l': CheckLock = TRUE; break;
  2087. case 'n':
  2088. if (UseIndex && StartIndex.Type == DEBUG_VALUE_INVALID)
  2089. {
  2090. BadArg = TRUE;
  2091. OutCtl.OutErr("Error: Index value not found after -i.\n");
  2092. }
  2093. else if (CheckPid && ThisPid)
  2094. {
  2095. BadArg = TRUE;
  2096. OutCtl.OutErr("Error: -n may not be used with -p.\n");
  2097. }
  2098. else
  2099. {
  2100. CheckPid = TRUE;
  2101. ThisPid = FALSE;
  2102. }
  2103. break;
  2104. case 'p':
  2105. if (UseIndex && StartIndex.Type == DEBUG_VALUE_INVALID)
  2106. {
  2107. BadArg = TRUE;
  2108. OutCtl.OutErr("Error: Index value not found after -i.\n");
  2109. }
  2110. if (CheckPid && !ThisPid)
  2111. {
  2112. BadArg = TRUE;
  2113. OutCtl.OutErr("Error: -p may not be used with -n.\n");
  2114. }
  2115. else
  2116. {
  2117. CheckPid = TRUE;
  2118. ThisPid = TRUE;
  2119. }
  2120. break;
  2121. case 's': Summary = TRUE; break;
  2122. default:
  2123. BadArg = TRUE;
  2124. break;
  2125. }
  2126. if (BadArg) break;
  2127. args++;
  2128. }
  2129. }
  2130. else
  2131. {
  2132. if (*args == '\0') break;
  2133. if (CheckPid && MatchPid.Type == DEBUG_VALUE_INVALID)
  2134. {
  2135. // This argument must be a PID.
  2136. CHAR EOPChar;
  2137. PSTR EOP = (PSTR)args;
  2138. ULONG Rem;
  2139. // Find end of string to evaulate as a pid
  2140. while (*EOP != '\0' && !isspace(*EOP)) EOP++;
  2141. EOPChar = *EOP;
  2142. *EOP = '\0';
  2143. if (isxdigit(*args) &&
  2144. Evaluate(Client, args, DEBUG_VALUE_INT32,
  2145. EVALUATE_DEFAULT_RADIX, &MatchPid,
  2146. &Rem) == S_OK &&
  2147. args + Rem == EOP)
  2148. {
  2149. args = EOP;
  2150. }
  2151. else
  2152. {
  2153. OutCtl.OutErr("Error: Couldn't evaluate '%s' as a PID.\n",
  2154. args);
  2155. BadArg = TRUE;
  2156. }
  2157. *EOP = EOPChar;
  2158. }
  2159. else if (UseIndex && StartIndex.Type == DEBUG_VALUE_INVALID)
  2160. {
  2161. // This argument must be the start Index.
  2162. CHAR EOIChar;
  2163. PSTR EOI = (PSTR)args;
  2164. ULONG Rem;
  2165. // Find end of string to evaulate as an index
  2166. while (*EOI != '\0' && !isspace(*EOI)) EOI++;
  2167. EOIChar = *EOI;
  2168. *EOI = '\0';
  2169. if (isxdigit(*args) &&
  2170. Evaluate(Client, args, DEBUG_VALUE_INT32,
  2171. EVALUATE_DEFAULT_RADIX, &StartIndex,
  2172. &Rem) == S_OK &&
  2173. args + Rem == EOI)
  2174. {
  2175. args = EOI;
  2176. }
  2177. else
  2178. {
  2179. OutCtl.OutErr("Error: Couldn't evaluate '%s' as an Index.\n",
  2180. args);
  2181. BadArg = TRUE;
  2182. }
  2183. *EOI = EOIChar;
  2184. }
  2185. else
  2186. {
  2187. // This argument must be a Type specification.
  2188. if (!CheckType)
  2189. {
  2190. OutCtl.OutErr("Error: a Type list may not be specified with -a.\n");
  2191. BadArg = TRUE;
  2192. break;
  2193. }
  2194. for (i = 0; i <= MAX_TYPE; i++)
  2195. {
  2196. SIZE_T CheckLen = strlen(pszTypes2[i]);
  2197. if (_strnicmp(args, pszTypes2[i], CheckLen) == 0 &&
  2198. (!iscsym(args[CheckLen]) ||
  2199. (_strnicmp(&args[CheckLen], "_TYPE", 5) == 0 &&
  2200. !iscsym(args[CheckLen+5])
  2201. )))
  2202. {
  2203. if (!MatchType[i])
  2204. {
  2205. // Add Type to list
  2206. SIZE_T CatLoc = TypeList.GetLength();
  2207. if (CatLoc > 0)
  2208. {
  2209. TypeList[CatLoc] = ' ';
  2210. }
  2211. TypeList.Set(pszTypes2[i], CheckLen+1, CatLoc);
  2212. }
  2213. MatchType[i] = TRUE;
  2214. args += CheckLen;
  2215. if (iscsym(*args)) args += 5;
  2216. break;
  2217. }
  2218. }
  2219. if (i > MAX_TYPE)
  2220. {
  2221. OutCtl.OutErr("Error: Unknown Type in '%s'.\n", args);
  2222. BadArg = TRUE;
  2223. break;
  2224. }
  2225. }
  2226. }
  2227. }
  2228. if (!BadArg)
  2229. {
  2230. if (CheckType && TypeList.IsEmpty())
  2231. {
  2232. OutCtl.OutErr("Error: Missing -a or Type list.\n");
  2233. BadArg = TRUE;
  2234. }
  2235. else if (CheckPid && MatchPid.Type == DEBUG_VALUE_INVALID)
  2236. {
  2237. OutCtl.OutErr("Error: Missing PID.\n");
  2238. BadArg = TRUE;
  2239. }
  2240. else if (UseIndex && StartIndex.Type == DEBUG_VALUE_INVALID)
  2241. {
  2242. OutCtl.OutErr("Error: Missing Index.\n");
  2243. BadArg = TRUE;
  2244. }
  2245. }
  2246. if (BadArg)
  2247. {
  2248. OutCtl.Output("Usage: dumpobj [-?ls] [-np PID] [-i Index] <-a | Type(s)>\n"
  2249. "\n"
  2250. " a - All object types\n"
  2251. " i - Hmgr Entry Index to begin dump\n"
  2252. " l - Check Lock\n"
  2253. " n - Entries NOT owned by pid\n"
  2254. " p - Entries owned by pid\n"
  2255. " s - Summary counts only\n"
  2256. "\n"
  2257. " The -s option combined with the -a option will produce\n"
  2258. " a list of the totals for each object type.\n");
  2259. OutCtl.Output("\n Valid Type values are:\n");
  2260. i = 0;
  2261. while (i <= MAX_TYPE)
  2262. {
  2263. do
  2264. {
  2265. OutCtl.Output(" %-*s", LongestType, pszTypes2[i++]);
  2266. } while (i <= MAX_TYPE && i%4);
  2267. OutCtl.Output("\n");
  2268. }
  2269. return S_OK;
  2270. }
  2271. //
  2272. // Get the pointers and counts from win32k
  2273. //
  2274. if ((hr = GetHandleTable(Client, &EntryAddr)) != S_OK ||
  2275. (hr = GetMaxHandles(Client, &gcMaxHmgr)) != S_OK)
  2276. {
  2277. return hr;
  2278. }
  2279. EntrySize = GetEntrySize(Client);
  2280. if (!gcMaxHmgr || !EntrySize || !EntryAddr)
  2281. {
  2282. OutCtl.OutErr("Error: gpentHmgr = %p, gcMaxHmgr = %I64u\n", EntryAddr, gcMaxHmgr);
  2283. return S_OK;
  2284. }
  2285. if (UseIndex) Index = StartIndex.I32;
  2286. OutCtl.Output("Searching %s %I64u entries starting at 0x%p",
  2287. (Index ? "remaining" : "all"), gcMaxHmgr - Index, EntryAddr);
  2288. if (SessionId != CURRENT_SESSION)
  2289. {
  2290. OutCtl.Output(" in session %s", SessionStr);
  2291. }
  2292. OutCtl.Output(".\n");
  2293. PDEBUG_CONTROL Control;
  2294. PDEBUG_SYMBOLS Symbols;
  2295. BOOL IsPointer64Bit;
  2296. BOOL ComposeHandles;
  2297. ULONG PointerSize;
  2298. if ((hr = Client->QueryInterface(__uuidof(IDebugControl),
  2299. (void **)&Control)) != S_OK)
  2300. {
  2301. return hr;
  2302. }
  2303. if ((hr = Client->QueryInterface(__uuidof(IDebugSymbols),
  2304. (void **)&Symbols)) != S_OK)
  2305. {
  2306. Control->Release();
  2307. return hr;
  2308. }
  2309. if (!Summary)
  2310. {
  2311. // Setup some things neded for listing entries.
  2312. IsPointer64Bit = (Control->IsPointer64Bit() == S_OK);
  2313. // Make sure HandleFullUnique is valid
  2314. hr = GetFullUniqueFromHandle(Client, 0, NULL);
  2315. if (hr != S_OK)
  2316. {
  2317. OutCtl.OutWarn("Unable to compose handles from entries, %s.\n",
  2318. pszHRESULT(hr));
  2319. }
  2320. ComposeHandles = (hr == S_OK);
  2321. }
  2322. OutCtl.Output("Object %s for %s objects",
  2323. Summary ? "count" : "list",
  2324. CheckType ? TypeList.GetBuffer() : "all");
  2325. if (CheckPid)
  2326. {
  2327. if (!ThisPid) OutCtl.Output(" NOT");
  2328. OutCtl.Output(" owned by PID 0x%lx\n", MatchPid.I32);
  2329. }
  2330. else
  2331. {
  2332. OutCtl.Output(" with any owner\n");
  2333. }
  2334. if (!Summary)
  2335. {
  2336. PointerSize = IsPointer64Bit ? 21 : 10;
  2337. // "0x1234 0x12345678 0xXX 0x12345678 1 4294967295 Tttt 0x1234 0xXX 0x...\n"
  2338. OutCtl.Output("Index Handle %-*s PID Lock ShareCount %-*s Unique %-*s Flags\n",
  2339. PointerSize, "ObjectAddr", LongestType, "Type", PointerSize, "UserAddr");
  2340. }
  2341. TrackPerPid = (!CheckPid || !ThisPid);
  2342. AccumPidObjects ObjectCount(MAX_TYPE, pszTypes2);
  2343. TypeOutputParser TypeReader(Client);
  2344. OutputState OutState(Client, FALSE);
  2345. DEBUG_VALUE Type;
  2346. #if ENTRY_RECURSE_LEVELS >= 2
  2347. DEBUG_VALUE Lock;
  2348. #else
  2349. DEBUG_VALUE ulObj;
  2350. #endif
  2351. DEBUG_VALUE PID;
  2352. DEBUG_VALUE Unique;
  2353. DEBUG_VALUE Flags;
  2354. ULONG ObjsNotAssignedToPID = 0;
  2355. ULONG FailedReads = 0;
  2356. BOOL FailedRead = FALSE;
  2357. BOOL NeedNewLine = FALSE;
  2358. HANDLE hHeap = GetProcessHeap();
  2359. PBYTE EntryBuffer = NULL;
  2360. ULONG ObjtOffset;
  2361. if (hHeap != NULL &&
  2362. (EntryBuffer = (PBYTE)HeapAlloc(hHeap, 0, EntrySize)) != NULL &&
  2363. Symbols->GetFieldOffset(Entry.Module, Entry.TypeId, "Objt", &ObjtOffset) == S_OK &&
  2364. (hr = OutState.Setup(0, &TypeReader)) == S_OK)
  2365. {
  2366. for (Index = 0; Index < gcMaxHmgr; Index++, EntryAddr += EntrySize/*, DbgPrint(" }\n")*/)
  2367. {
  2368. // DbgPrint("{");
  2369. if (FailedRead) FailedReads++;
  2370. if (Index % 40 == 0)
  2371. {
  2372. OutCtl.Output((Summary ? DEBUG_OUTPUT_NORMAL : DEBUG_OUTPUT_VERBOSE), ".");
  2373. NeedNewLine = TRUE;
  2374. }
  2375. if (Control->GetInterrupt() == S_OK)
  2376. {
  2377. NeedNewLine = FALSE;
  2378. OutCtl.OutErr("User aborted at index %lu\n", Index);
  2379. hr = E_ABORT;
  2380. break;
  2381. }
  2382. TypeReader.DiscardOutput();
  2383. /* DbgPrint(" Read");
  2384. Symbols->ReadTypedDataVirtual(EntryAddr,
  2385. Entry.Module,
  2386. Entry.TypeId,
  2387. EntryBuffer,
  2388. EntrySize,
  2389. NULL);
  2390. DbgPrint("Type");*/
  2391. // DbgPrint(" Out");
  2392. if (SessionId != CURRENT_SESSION)
  2393. {
  2394. ULONG64 PhysEntryAddr;
  2395. if ((hr = GetPhysicalAddress(Client,
  2396. SessionId,
  2397. EntryAddr,
  2398. &PhysEntryAddr)) == S_OK)
  2399. {
  2400. hr = OutState.OutputType(TRUE,
  2401. PhysEntryAddr,
  2402. Entry.Module,
  2403. Entry.TypeId,
  2404. DEBUG_OUTTYPE_NO_INDENT |
  2405. DEBUG_OUTTYPE_NO_OFFSET |
  2406. DEBUG_OUTTYPE_COMPACT_OUTPUT |
  2407. DEBUG_OUTTYPE_RECURSION_LEVEL(ENTRY_RECURSE_LEVELS));
  2408. }
  2409. }
  2410. else
  2411. {
  2412. hr = OutState.OutputTypeVirtual(EntryAddr,
  2413. Entry.Module,
  2414. Entry.TypeId,
  2415. DEBUG_OUTTYPE_NO_INDENT |
  2416. DEBUG_OUTTYPE_NO_OFFSET |
  2417. DEBUG_OUTTYPE_COMPACT_OUTPUT |
  2418. DEBUG_OUTTYPE_RECURSION_LEVEL(ENTRY_RECURSE_LEVELS));
  2419. }
  2420. // DbgPrint("Type");
  2421. if (hr == S_OK)
  2422. {
  2423. // DbgPrint(" Objt");
  2424. #if USE_READ
  2425. #else
  2426. hr = TypeReader.Get(&Type, "Objt", DEBUG_VALUE_INT32);
  2427. #endif
  2428. if (hr != S_OK) Type.Type = DEBUG_VALUE_INVALID;
  2429. if (CheckType &&
  2430. ((FailedRead = (Type.Type != DEBUG_VALUE_INT32)) ||
  2431. !MatchType[Type.I32]))
  2432. {
  2433. // OutCtl.OutWarn("Type %lu doesn't match.\n", Type.I32);
  2434. continue;
  2435. }
  2436. #if ENTRY_RECURSE_LEVELS >= 2
  2437. // DbgPrint(" Lock");
  2438. if (CheckLock &&
  2439. ((FailedRead = (TypeReader.Get(&Lock, "Lock",
  2440. DEBUG_VALUE_INT32) != S_OK)) ||
  2441. Lock.I32 == 0))
  2442. {
  2443. OutCtl.OutWarn("Lock required, but not locked.\n");
  2444. continue;
  2445. }
  2446. // DbgPrint(" PID");
  2447. PID.Type = DEBUG_VALUE_INVALID;
  2448. FailedRead = (TypeReader.Get(&PID, "Pid_Shifted", DEBUG_VALUE_INT32) != S_OK);
  2449. PID.I32 *= 2;
  2450. if (CheckPid)
  2451. {
  2452. if (FailedRead ||
  2453. ((PID.I32 == MatchPid.I32) ? !ThisPid : ThisPid))
  2454. {
  2455. continue;
  2456. }
  2457. }
  2458. #else
  2459. ulObj.Type = DEBUG_VALUE_INVALID;
  2460. FailedRead = (TypeReader.Get(&ulObj, "ulObj", DEBUG_VALUE_INT32) != S_OK);
  2461. PID.Type = ulObj.Type;
  2462. PID.I32 = (ulObj.I32 & ~1);
  2463. if (CheckLock || CheckPid)
  2464. {
  2465. if (FailedRead)
  2466. {
  2467. // OutCtl.OutWarn("ulObj is required, but wasn't read.\n");
  2468. continue;
  2469. }
  2470. // DbgPrint(" Lock");
  2471. if (CheckLock && (ulObj.I32 & 1) == 0)
  2472. {
  2473. // OutCtl.OutWarn("Lock required, but not locked.\n");
  2474. continue;
  2475. }
  2476. // DbgPrint(" PID");
  2477. if (CheckPid &&
  2478. (PID.I32 == MatchPid.I32) ? !ThisPid : ThisPid)
  2479. {
  2480. continue;
  2481. }
  2482. }
  2483. #endif
  2484. FailedRead = (Type.Type != DEBUG_VALUE_INT32);
  2485. if (!FailedRead)
  2486. {
  2487. // DbgPrint(" MATCH");
  2488. if (TrackPerPid)
  2489. {
  2490. if (PID.Type != DEBUG_VALUE_INT32 ||
  2491. ObjectCount.Add(PID.I32, Type.I32) != S_OK)
  2492. {
  2493. ObjsNotAssignedToPID++;
  2494. ObjectCount.Add(Type.I32);
  2495. }
  2496. }
  2497. else
  2498. {
  2499. ObjectCount.Add(Type.I32);
  2500. }
  2501. }
  2502. if (!Summary)
  2503. {
  2504. PCSTR pszValue;
  2505. if (NeedNewLine)
  2506. {
  2507. OutCtl.OutVerb("\n");
  2508. NeedNewLine = FALSE;
  2509. }
  2510. // Index
  2511. OutCtl.Output("0x%.4lx ", Index);
  2512. // Handle
  2513. if (ComposeHandles &&
  2514. TypeReader.Get(&Unique, "FullUnique", DEBUG_VALUE_INT64) == S_OK)
  2515. {
  2516. ULONG64 Handle64;
  2517. Handle64 = (Index & ~(HandleFullUnique->Mask)) |
  2518. (Unique.I64 << HandleFullUnique->BitPos);
  2519. if (IsPointer64Bit)
  2520. {
  2521. Handle64 = DEBUG_EXTEND64(Handle64);
  2522. }
  2523. OutCtl.Output("0x%p ", Handle64);
  2524. }
  2525. else
  2526. {
  2527. OutCtl.Output("%*s ", PointerSize, "?");
  2528. }
  2529. // ObjectAddr
  2530. if (TypeReader.Get(NULL, "pobj") == S_OK &&
  2531. TypeReader.GetValueString(&pszValue) == S_OK)
  2532. {
  2533. OutCtl.Output("%*s ", PointerSize, pszValue);
  2534. }
  2535. else
  2536. {
  2537. OutCtl.Output("%*s ", PointerSize, "?");
  2538. }
  2539. // PID
  2540. if (PID.Type == DEBUG_VALUE_INT32)
  2541. {
  2542. OutCtl.Output("0x%.8lx ", PID.I32);
  2543. }
  2544. else
  2545. {
  2546. OutCtl.Output(" ? ");
  2547. }
  2548. // Lock
  2549. #if ENTRY_RECURSE_LEVELS >= 2
  2550. if (Lock.Type == DEBUG_VALUE_INT32 ||
  2551. TypeReader.Get(&Lock, "Lock", DEBUG_VALUE_INT32) == S_OK)
  2552. {
  2553. OutCtl.Output("%4lu ", Lock.I32);
  2554. }
  2555. else
  2556. {
  2557. OutCtl.Output(" ? ");
  2558. }
  2559. #else
  2560. if (ulObj.Type == DEBUG_VALUE_INT32)
  2561. {
  2562. OutCtl.Output("%4lu ", ulObj.I32 & 1);
  2563. }
  2564. else
  2565. {
  2566. OutCtl.Output(" ? ");
  2567. }
  2568. #endif
  2569. // ShareCount
  2570. OutCtl.Output("<Not Read> ");
  2571. // Type
  2572. if (Type.Type == DEBUG_VALUE_INT32 ||
  2573. TypeReader.Get(&Type, "Objt", DEBUG_VALUE_INT32) == S_OK)
  2574. {
  2575. OutCtl.Output("%-*s ", LongestType, pszTypes2[Type.I32]);
  2576. }
  2577. else
  2578. {
  2579. OutCtl.Output("%-*s ", LongestType, "?");
  2580. }
  2581. // Unique
  2582. if (Unique.Type == DEBUG_VALUE_INT64 ||
  2583. TypeReader.Get(&Unique, "FullUnique", DEBUG_VALUE_INT64) == S_OK)
  2584. {
  2585. OutCtl.Output("0x%.4I64x ", Unique.I64);
  2586. }
  2587. else
  2588. {
  2589. OutCtl.Output(" ? ");
  2590. }
  2591. // UserAddr
  2592. if (TypeReader.Get(NULL, "pUser") == S_OK &&
  2593. TypeReader.GetValueString(&pszValue) == S_OK)
  2594. {
  2595. OutCtl.Output("%*s ", PointerSize, pszValue);
  2596. }
  2597. else
  2598. {
  2599. OutCtl.Output("%*s ", PointerSize, "?");
  2600. }
  2601. // Flags
  2602. if (TypeReader.Get(&Flags, "Flags", DEBUG_VALUE_INT64) == S_OK &&
  2603. TypeReader.GetValueString(&pszValue) == S_OK)
  2604. {
  2605. OutCtl.Output("%s (", pszValue);
  2606. Flags.I64 = OutputFlags(&OutCtl, afdENTRY_Flags, Flags.I64, TRUE);
  2607. OutCtl.Output(")");
  2608. if (Flags.I64)
  2609. {
  2610. OutCtl.Output(" Unknown Flags: 0x%I64x", Flags.I64);
  2611. }
  2612. }
  2613. else
  2614. {
  2615. OutCtl.Output("?");
  2616. }
  2617. OutCtl.Output("\n");
  2618. }
  2619. }
  2620. else
  2621. {
  2622. FailedRead = TRUE;
  2623. }
  2624. }
  2625. if (FailedRead) FailedReads++;
  2626. if (NeedNewLine)
  2627. {
  2628. OutCtl.Output((Summary ? DEBUG_OUTPUT_NORMAL : DEBUG_OUTPUT_VERBOSE), "\n");
  2629. }
  2630. if (FailedReads)
  2631. {
  2632. OutCtl.OutWarn("Warning: %lu entry reads failed -> uncounted.\n", FailedReads);
  2633. }
  2634. if (ObjsNotAssignedToPID)
  2635. {
  2636. OutCtl.OutWarn("Warning: %lu entries weren't assigned to a PID.\n", ObjsNotAssignedToPID);
  2637. }
  2638. if (Index < gcMaxHmgr)
  2639. {
  2640. OutCtl.OutWarn("Warning: Entries at and beyond index 0x%lx weren't processed.\n", Index);
  2641. }
  2642. // Display results
  2643. ObjectCount.OutputResults(&OutCtl, MatchType);
  2644. }
  2645. if (EntryBuffer != NULL)
  2646. {
  2647. HeapFree(hHeap, 0, EntryBuffer);
  2648. }
  2649. Symbols->Release();
  2650. Control->Release();
  2651. return S_OK;
  2652. }
  2653. #if 1
  2654. #define TYPE_ALL 0
  2655. #define PID_ALL 0x8002
  2656. DECLARE_API( dumpobj )
  2657. {
  2658. BEGIN_API( dumpobj );
  2659. INIT_API();
  2660. ExtWarn("Extension 'dumpobj' is not fully converted.\n");
  2661. HRESULT hr;
  2662. ULONG64 pent;
  2663. ULONG64 gcMaxHmgr;
  2664. ULONG entSize;
  2665. ULONG ulLoop;
  2666. ULONG Pid = PID_ALL;
  2667. BOOL AnyPid = TRUE;
  2668. BOOL MatchPid = TRUE;
  2669. ULONG Type = TYPE_ALL;
  2670. BOOL bCheckLock = FALSE;
  2671. BOOL bSummary = FALSE;
  2672. BOOL bShareCount = FALSE;
  2673. int i;
  2674. PARSE_ARGUMENTS(dumpobj_help);
  2675. if(ntok<1) {
  2676. goto dumpobj_help;
  2677. }
  2678. //find valid tokens - ignore the rest
  2679. bShareCount = (parse_iFindSwitch(tokens, ntok, 'c') >= 0);
  2680. bCheckLock = (parse_iFindSwitch(tokens, ntok, 'l') >= 0);
  2681. bSummary = (parse_iFindSwitch(tokens, ntok, 's') >= 0);
  2682. MatchPid = !(parse_iFindSwitch(tokens, ntok, 'n') >= 0);
  2683. tok_pos = parse_iFindSwitch(tokens, ntok, 'p');
  2684. if (tok_pos>=0)
  2685. {
  2686. tok_pos++;
  2687. if ((tok_pos+1)>=ntok)
  2688. {
  2689. goto dumpobj_help; //-p requires a pid and it can't be the last arg
  2690. }
  2691. AnyPid = FALSE;
  2692. Pid = (LONG)GetExpression(tokens[tok_pos]);
  2693. }
  2694. //find first non-switch token not preceeded by a -p
  2695. tok_pos = -1;
  2696. do {
  2697. tok_pos = parse_FindNonSwitch(tokens, ntok, tok_pos+1);
  2698. } while ( (tok_pos!=-1)&&(parse_iIsSwitch(tokens, tok_pos-1, 'p')));
  2699. if(tok_pos==-1) {
  2700. goto dumpobj_help;
  2701. }
  2702. //CHECKLOOP
  2703. for (Type = 0; Type <= MAX_TYPE; ++Type)
  2704. {
  2705. if (parse_iIsToken(tokens, tok_pos, pszTypes2[Type]) ||
  2706. parse_iIsToken(tokens, tok_pos, pszTypes[Type]))
  2707. {
  2708. break;
  2709. }
  2710. }
  2711. if (Type > MAX_TYPE) {
  2712. goto dumpobj_help;
  2713. }
  2714. //
  2715. // Get the pointers and counts from win32k
  2716. //
  2717. if ((hr = GetHandleTable(Client, &pent)) != S_OK ||
  2718. (hr = GetMaxHandles(Client, &gcMaxHmgr)) != S_OK)
  2719. {
  2720. EXIT_API(hr);
  2721. }
  2722. entSize = GetEntrySize(Client);
  2723. ExtVerb("gpentHmgr = %p, gcMaxHmgr = %I64u\n", pent, gcMaxHmgr);
  2724. if (!gcMaxHmgr || !entSize || !pent)
  2725. {
  2726. ExtErr("Error: gpentHmgr = %p, gcMaxHmgr = %I64u\n", pent, gcMaxHmgr);
  2727. EXIT_API(S_OK);
  2728. }
  2729. //
  2730. // dprintf out the amount reserved and committed, note we assume a 4K page size
  2731. //
  2732. dprintf("object list for %s type objects",Type == TYPE_ALL ? "ALL" : pszTypes2[Type]);
  2733. if (AnyPid)
  2734. {
  2735. dprintf(" with any owner\n");
  2736. }
  2737. else
  2738. {
  2739. if (!MatchPid) dprintf(" NOT");
  2740. dprintf(" owned by PID 0x%lx\n",Pid);
  2741. }
  2742. if(!bSummary) {
  2743. dprintf("%4s, %8s, %6s, %6s, %4s, %8s, %8s, %6s, %6s, %8s,%9s\n",
  2744. "I","handle","Lock","sCount","pid","pv","objt","unique","Flags","pUser","Tlock");
  2745. dprintf("--------------------------------------------------------------------------------------------\n");
  2746. }
  2747. {
  2748. LONG ObjCount = 0;
  2749. LONG ObjArray[MAX_TYPE+1];
  2750. for(i=0;i<=MAX_TYPE;i++) {
  2751. ObjArray[i]=0;
  2752. }
  2753. //CHECKLOOP
  2754. for (ulLoop = 0; ulLoop < gcMaxHmgr; ulLoop++)
  2755. {
  2756. if (CheckControlC())
  2757. {
  2758. ExtErr("User aborted at index %lu\n", ulLoop);
  2759. EXIT_API(E_ABORT);
  2760. }
  2761. if (bSummary && ulLoop % 40 == 0) ExtVerb(".");
  2762. ULONG error;
  2763. ULONG objt;
  2764. ULONG ThisPid;
  2765. ULONG64 pobj;
  2766. USHORT fullUnique;
  2767. UCHAR flags;
  2768. ULONG64 pUser;
  2769. ULONG owner;
  2770. ULONG shareCount;
  2771. if (error = GetFieldValue(pent, szEntryType, "Objt", objt))
  2772. {
  2773. ExtErr("Error reading table entry\n");
  2774. ExtErr(" (GetFieldValue returned %s @ %p)\n", pszWinDbgError(error), pent);
  2775. EXIT_API(S_OK);
  2776. }
  2777. if (error = GetFieldValue(pent, szEntryType, "ObjectOwner", owner))
  2778. {
  2779. ExtErr("error reading table entry\n");
  2780. ExtErr(" (GetFieldValue returned %s)\n", pszWinDbgError(error));
  2781. EXIT_API(S_OK);
  2782. }
  2783. ThisPid = owner & PID_MASK;
  2784. if (0 && gbVerbose)
  2785. {
  2786. dprintf("Type: %lu, PID: %lu, Locked: %s\n", objt, ThisPid, (owner & LOCK_MASK) ? "YES" : "NO");
  2787. }
  2788. if (
  2789. ((objt == Type) || (Type == TYPE_ALL)) &&
  2790. (AnyPid ||
  2791. (MatchPid ? (ThisPid == Pid) : (ThisPid != Pid))) &&
  2792. ((!bCheckLock) || (owner & LOCK_MASK))
  2793. )
  2794. {
  2795. ObjCount++;
  2796. if (!bSummary)
  2797. {
  2798. if (GetFieldData(pent, szEntryType, "FullUnique", sizeof(fullUnique), &fullUnique))
  2799. {
  2800. ExtErr("error reading FullUnique\n");
  2801. EXIT_API(S_OK);
  2802. }
  2803. if (GetFieldData(pent, szEntryType, "Flags", sizeof(flags), &flags))
  2804. {
  2805. ExtErr("error reading flags\n");
  2806. EXIT_API(S_OK);
  2807. }
  2808. if (GetFieldData(pent, szEntryType, "pUser", sizeof(pUser), &pUser))
  2809. {
  2810. ExtErr("error reading pUser\n");
  2811. EXIT_API(S_OK);
  2812. }
  2813. if (GetFieldData(pent, szEntryType, "einfo.pobj", sizeof(pobj), &pobj))
  2814. {
  2815. ExtErr("error reading einfo.pobj\n");
  2816. EXIT_API(S_OK);
  2817. }
  2818. dprintf("%4lx, %08lx, %6lx",
  2819. ulLoop,
  2820. MAKE_HMGR_HANDLE(ulLoop,fullUnique),
  2821. owner & LOCK_MASK);
  2822. if (!bShareCount)
  2823. {
  2824. dprintf(", Unread");
  2825. }
  2826. else if (GetFieldData(pobj, GDIType(_BASEOBJECT), "ulShareCount", sizeof(shareCount), &shareCount))
  2827. {
  2828. dprintf(", ??????");
  2829. }
  2830. else
  2831. {
  2832. dprintf(", %6lx", shareCount);
  2833. }
  2834. dprintf(", %4lx, %p", ThisPid, pobj);
  2835. dprintf(", %8s, %6hx, %6lx, %p, %p\n",
  2836. pszTypes2[objt],
  2837. fullUnique,
  2838. flags,
  2839. pUser,
  2840. pUser);
  2841. }
  2842. else
  2843. {
  2844. ObjArray[objt]++;
  2845. }
  2846. }
  2847. pent += entSize;
  2848. }
  2849. if(bSummary && (Type==TYPE_ALL)) {
  2850. for(i=0;i<=MAX_TYPE; i++) {
  2851. if(ObjArray[i]>0) {
  2852. dprintf("%s\t%ld\n", pszTypes2[i], ObjArray[i]);
  2853. }
  2854. }
  2855. }
  2856. ExtOut("Total objects = %li",ObjCount);
  2857. // Subtract any unused objects
  2858. if (bSummary && ObjArray[0])
  2859. {
  2860. ExtOut(" - %li = %li", ObjArray[0], ObjCount - ObjArray[0]);
  2861. }
  2862. ExtOut("\n");
  2863. }
  2864. EXIT_API(S_OK);
  2865. dumpobj_help:
  2866. dprintf("Usage: dumpobj [-?] [-n] [-p pid] [-l] [-s] object_type\n");
  2867. dprintf("\t-l check lock\n");
  2868. dprintf("\t-s summary\n");
  2869. dprintf("\t-n not pid\n\n");
  2870. dprintf(" The -s option combined with the DEF object type will produce\n"
  2871. " a list of the totals for each object type.\n\n");
  2872. dprintf(" Valid object_type values are:\n");
  2873. for (i=0; i<=MAX_TYPE; ) {
  2874. do
  2875. {
  2876. dprintf(" %-12s", pszTypes2[i++]);
  2877. } while (i <= MAX_TYPE && i%4);
  2878. dprintf("\n");
  2879. }
  2880. EXIT_API(S_OK);
  2881. }
  2882. #endif
  2883. /******************************Public*Routine******************************\
  2884. * DECLARE_API( dh )
  2885. *
  2886. * Debugger extension to dump a handle.
  2887. *
  2888. * History:
  2889. * 21-Feb-1995 -by- Lingyun Wang [lingyunw]
  2890. * Wrote it.
  2891. \**************************************************************************/
  2892. DECLARE_API( dh )
  2893. {
  2894. BEGIN_API( dh );
  2895. HRESULT hr;
  2896. DEBUG_VALUE Handle;
  2897. ULONG64 offENTRY;
  2898. BOOL Physical;
  2899. OutputControl OutCtl(Client);
  2900. while (isspace(*args)) args++;
  2901. if (*args == '-' ||
  2902. (hr = Evaluate(Client, args, DEBUG_VALUE_INT64, 0, &Handle, NULL)) != S_OK ||
  2903. Handle.I64 == 0)
  2904. {
  2905. OutCtl.Output("Usage: dh [-?] <Handle>\n");
  2906. }
  2907. else
  2908. {
  2909. OutCtl.Output("--------------------------------------------------\n");
  2910. OutCtl.Output("GDI Entry for handle 0x%p:\n", Handle.I64);
  2911. if ((hr = GetEntryAddress(Client, Handle.I64, &offENTRY, &Physical)) == S_OK)
  2912. {
  2913. OutputFilter OutFilter(Client);
  2914. OutputState OutState(Client, FALSE);
  2915. OutputControl OutCtl;
  2916. if ((hr = OutState.Setup(DEBUG_OUTPUT_NORMAL |
  2917. DEBUG_OUTPUT_ERROR |
  2918. DEBUG_OUTPUT_WARNING,
  2919. &OutFilter)) == S_OK &&
  2920. (hr = OutCtl.SetControl(DEBUG_OUTCTL_THIS_CLIENT |
  2921. DEBUG_OUTCTL_NOT_LOGGED,
  2922. OutState.Client)) == S_OK)
  2923. {
  2924. hr = DumpType(OutState.Client,
  2925. szEntryType,
  2926. offENTRY,
  2927. DEBUG_OUTTYPE_NO_INDENT | DEBUG_OUTTYPE_NO_OFFSET,
  2928. &OutCtl,
  2929. Physical);
  2930. if (hr == S_OK)
  2931. {
  2932. OutFilter.Skip(OUTFILTER_QUERY_EVERY_LINE |
  2933. OUTFILTER_QUERY_WHOLE_WORD,
  2934. "_EINFO");
  2935. OutFilter.Skip(OUTFILTER_SKIP_DEFAULT, "_OBJECTOWNER");
  2936. BOOL DumpObj = FALSE;
  2937. DEBUG_VALUE Value;
  2938. CHAR ReplacementText[80];
  2939. // Check for used vs free entry
  2940. if (OutFilter.Query("Objt", &Value, DEBUG_VALUE_INT8) == S_OK)
  2941. {
  2942. DumpObj = (Value.I8 != DEF_TYPE);
  2943. OutFilter.Skip(OUTFILTER_QUERY_EVERY_LINE |
  2944. OUTFILTER_QUERY_WHOLE_WORD,
  2945. (Value.I8 == DEF_TYPE) ? "pobj" : "hFree");
  2946. }
  2947. // Account for Pid shifting
  2948. if (OutFilter.Query("Pid_Shifted", &Value, DEBUG_VALUE_INT32) == S_OK)
  2949. {
  2950. sprintf(ReplacementText,
  2951. "Pid : 0x%lx (%ld)",
  2952. 2*Value.I32, 2*Value.I32);
  2953. OutFilter.Replace(OUTFILTER_REPLACE_LINE | OUTFILTER_QUERY_ONE_LINE,
  2954. "Pid_Shifted", ReplacementText);
  2955. }
  2956. hr = OutFilter.OutputText();
  2957. if (hr == S_OK && DumpObj)
  2958. {
  2959. if (TargetClass != DEBUG_CLASS_USER_WINDOWS)
  2960. {
  2961. if ((hr = OutFilter.Query("pobj", &Value, DEBUG_VALUE_INT64)) == S_OK)
  2962. {
  2963. // Restore OutCtl settings
  2964. OutCtl.SetControl(DEBUG_OUTCTL_AMBIENT, Client);
  2965. OutCtl.Output("--------------------------------------------------\n");
  2966. if (Physical)
  2967. {
  2968. ULONG64 PhysAddr;
  2969. ASSERTMSG("HMGR Entry was looked up thru a physical address, but the SessionId is CURRENT.\n", SessionId != CURRENT_SESSION);
  2970. hr = GetPhysicalAddress(Client,
  2971. SessionId,
  2972. Value.I64,
  2973. &PhysAddr);
  2974. if (hr == S_OK)
  2975. {
  2976. Value.I64 = PhysAddr;
  2977. }
  2978. else
  2979. {
  2980. OutCtl.OutErr("GDI BaseObject @ 0x%p in session %lu in unavailable.\n",
  2981. Value.I64, SessionId);
  2982. }
  2983. }
  2984. if (hr == S_OK)
  2985. {
  2986. OutCtl.Output("GDI BaseObject @ %s0x%p:\n",
  2987. ((Physical) ? "#" : ""),
  2988. Value.I64);
  2989. hr = DumpType(Client,
  2990. "_BASEOBJECT",
  2991. Value.I64,
  2992. DEBUG_OUTTYPE_NO_INDENT |
  2993. DEBUG_OUTTYPE_NO_OFFSET,
  2994. &OutCtl,
  2995. Physical);
  2996. }
  2997. }
  2998. }
  2999. }
  3000. }
  3001. if (hr != S_OK)
  3002. {
  3003. OutCtl.OutErr("Type Dump returned %s.\n", pszHRESULT(hr));
  3004. }
  3005. }
  3006. else
  3007. {
  3008. OutCtl.OutErr(" Output state/control setup returned %s.\n",
  3009. pszHRESULT(hr));
  3010. }
  3011. }
  3012. else
  3013. {
  3014. OutCtl.Output(" ** Unable to find a valid entry address. **\n");
  3015. }
  3016. OutCtl.Output("--------------------------------------------------\n");
  3017. }
  3018. return S_OK;
  3019. }
  3020. /******************************Public*Routine******************************\
  3021. * DECLARE_API( dht )
  3022. *
  3023. * Debugger extension to extract type data from a handle.
  3024. *
  3025. * History:
  3026. * 21-Feb-1995 -by- Lingyun Wang [lingyunw]
  3027. * Wrote it.
  3028. * 30-Nov-2000 -by- Jason Hartman [jasonha]
  3029. * Ported to 64 bit debugger API.
  3030. \**************************************************************************/
  3031. DECLARE_API( dht )
  3032. {
  3033. BEGIN_API( dht );
  3034. HRESULT hr;
  3035. DEBUG_VALUE Handle;
  3036. ULONG64 Index;
  3037. ULONG64 FullUnique;
  3038. OutputControl OutCtl(Client);
  3039. while (isspace(*args)) args++;
  3040. if (*args == '-' ||
  3041. (hr = Evaluate(Client, args, DEBUG_VALUE_INT64, 0, &Handle, NULL)) != S_OK ||
  3042. Handle.I64 == 0)
  3043. {
  3044. OutCtl.Output("Usage: dht [-?] <Handle>\n");
  3045. }
  3046. else
  3047. {
  3048. OutCtl.Output("Handle: 0x%p\n", Handle.I64);
  3049. if (GetIndexFromHandle(Client, Handle.I64, &Index) == S_OK)
  3050. {
  3051. OutCtl.Output(" Index: 0x%p\n", Index);
  3052. }
  3053. if (GetFullUniqueFromHandle(Client, Handle.I64, &FullUnique) == S_OK)
  3054. {
  3055. OutCtl.Output(" FullUnique: 0x%p\n", FullUnique);
  3056. }
  3057. OutCtl.Output(" Type: ");
  3058. hr = OutputHandleInfo(&OutCtl, Client, &Handle);
  3059. OutCtl.Output("\n");
  3060. }
  3061. return hr;
  3062. }