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.

1509 lines
40 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. extapi.cxx
  5. Abstract:
  6. This file contains the generic routines and initialization code
  7. used by the debugger extensions routines.
  8. Author:
  9. Jason Hartman (JasonHa) 2000-08-18
  10. Environment:
  11. User Mode
  12. --*/
  13. #include "precomp.hxx"
  14. const BOOL ClientInitialized = FALSE;
  15. PDEBUG_ADVANCED g_pExtAdvanced;
  16. PDEBUG_CLIENT g_pExtClient;
  17. PDEBUG_CONTROL g_pExtControl;
  18. PDEBUG_DATA_SPACES g_pExtData;
  19. PDEBUG_REGISTERS g_pExtRegisters;
  20. PDEBUG_SYMBOLS g_pExtSymbols;
  21. PDEBUG_SYMBOL_GROUP g_pExtSymbolGroup;
  22. PDEBUG_SYSTEM_OBJECTS g_pExtSystem;
  23. #define REF_LIMIT 100
  24. LONG ExtRefCount = 0;
  25. BOOL ExtReady = FALSE;
  26. #define MAX_NAME 2048
  27. DefOutputCallbacks *g_pDefOutputCallbacks = NULL;
  28. // Queries for all debugger interfaces.
  29. extern "C" HRESULT
  30. ExtQuery(PDEBUG_CLIENT Client)
  31. {
  32. HRESULT Hr;
  33. LONG RefCheck;
  34. // Have to have a client to start with;)
  35. if (Client == NULL)
  36. {
  37. return S_FALSE;
  38. }
  39. RefCheck = InterlockedIncrement(&ExtRefCount);
  40. if (RefCheck > REF_LIMIT)
  41. {
  42. DbgPrint("ExtQuery has calls exceeding limit.\n");
  43. InterlockedDecrement(&ExtRefCount);
  44. return S_FALSE;
  45. }
  46. if (RefCheck > 1)
  47. {
  48. // Wait until original refencer completes setup.
  49. //
  50. // If ExtRefCount drops below RefCheck then the
  51. // original referencer failed as well as any
  52. // waiters who started after us.
  53. while (!ExtReady && ExtRefCount >= RefCheck)
  54. Sleep(10);
  55. if (ExtReady)
  56. {
  57. // Make sure the clients match
  58. if (g_pExtClient != Client)
  59. {
  60. InterlockedDecrement(&ExtRefCount);
  61. return S_FALSE;
  62. }
  63. return S_OK;
  64. }
  65. }
  66. // Prepare to query interfaces.
  67. // Make sure no one is currently cleaning up.
  68. while (ExtReady)
  69. {
  70. Sleep(10);
  71. }
  72. if ((Hr = Client->QueryInterface(__uuidof(IDebugAdvanced),
  73. (void **)&g_pExtAdvanced)) != S_OK)
  74. {
  75. goto Fail;
  76. }
  77. if ((Hr = Client->QueryInterface(__uuidof(IDebugControl),
  78. (void **)&g_pExtControl)) != S_OK)
  79. {
  80. goto Fail;
  81. }
  82. if ((Hr = Client->QueryInterface(__uuidof(IDebugDataSpaces),
  83. (void **)&g_pExtData)) != S_OK)
  84. {
  85. goto Fail;
  86. }
  87. if ((Hr = Client->QueryInterface(__uuidof(IDebugRegisters),
  88. (void **)&g_pExtRegisters)) != S_OK)
  89. {
  90. goto Fail;
  91. }
  92. if ((Hr = Client->QueryInterface(__uuidof(IDebugSymbols),
  93. (void **)&g_pExtSymbols)) != S_OK)
  94. {
  95. goto Fail;
  96. }
  97. if ((Hr = g_pExtSymbols->CreateSymbolGroup(&g_pExtSymbolGroup)) != S_OK)
  98. {
  99. goto Fail;
  100. }
  101. if ((Hr = Client->QueryInterface(__uuidof(IDebugSystemObjects),
  102. (void **)&g_pExtSystem)) != S_OK)
  103. {
  104. goto Fail;
  105. }
  106. // If symbols state has changed, make sure GDI symbols are loaded.
  107. if (gbSymbolsNotLoaded)
  108. {
  109. SymbolLoad(Client);
  110. }
  111. g_pExtClient = Client;
  112. ExtReady = TRUE;
  113. return S_OK;
  114. Fail:
  115. ExtRelease(TRUE);
  116. InterlockedDecrement(&ExtRefCount);
  117. return Hr;
  118. }
  119. // Cleans up all debugger interfaces when there are no more references.
  120. // A cleanup will be forced if Cleanup is TRUE.
  121. void
  122. ExtRelease(BOOL Cleanup)
  123. {
  124. // Don't decrement the count when forcing cleanup.
  125. if (Cleanup || InterlockedDecrement(&ExtRefCount) < 1)
  126. {
  127. DbgPrint("Cleaning up interfaces.\n");
  128. EXT_RELEASE(g_pExtAdvanced);
  129. EXT_RELEASE(g_pExtControl);
  130. EXT_RELEASE(g_pExtData);
  131. EXT_RELEASE(g_pExtRegisters);
  132. EXT_RELEASE(g_pExtSymbols);
  133. EXT_RELEASE(g_pExtSystem);
  134. g_pExtClient = NULL;
  135. ExtReady = FALSE;
  136. }
  137. return;
  138. }
  139. // Normal output.
  140. void __cdecl
  141. ExtOut(PCSTR Format, ...)
  142. {
  143. va_list Args;
  144. if (g_pExtControl == NULL)
  145. {
  146. DbgPrint("g_pExtControl is NULL.\n");
  147. return;
  148. }
  149. va_start(Args, Format);
  150. g_pExtControl->OutputVaList(DEBUG_OUTPUT_NORMAL, Format, Args);
  151. va_end(Args);
  152. }
  153. // Error output.
  154. void __cdecl
  155. ExtErr(PCSTR Format, ...)
  156. {
  157. va_list Args;
  158. if (g_pExtControl == NULL)
  159. {
  160. DbgPrint("g_pExtControl is NULL.\n");
  161. return;
  162. }
  163. va_start(Args, Format);
  164. g_pExtControl->OutputVaList(DEBUG_OUTPUT_ERROR, Format, Args);
  165. va_end(Args);
  166. }
  167. // Warning output.
  168. void __cdecl
  169. ExtWarn(PCSTR Format, ...)
  170. {
  171. va_list Args;
  172. if (g_pExtControl == NULL)
  173. {
  174. DbgPrint("g_pExtControl is NULL.\n");
  175. return;
  176. }
  177. va_start(Args, Format);
  178. g_pExtControl->OutputVaList(DEBUG_OUTPUT_WARNING, Format, Args);
  179. va_end(Args);
  180. }
  181. // Verbose output.
  182. void __cdecl
  183. ExtVerb(PCSTR Format, ...)
  184. {
  185. va_list Args;
  186. if (g_pExtControl == NULL)
  187. {
  188. DbgPrint("g_pExtControl is NULL.\n");
  189. return;
  190. }
  191. va_start(Args, Format);
  192. g_pExtControl->OutputVaList(DEBUG_OUTPUT_VERBOSE, Format, Args);
  193. va_end(Args);
  194. }
  195. ExtApiClass::ExtApiClass(
  196. PDEBUG_CLIENT DbgClient
  197. )
  198. {
  199. Client = DbgClient ? DbgClient : g_pExtClient;
  200. if (Client != NULL)
  201. {
  202. Client->AddRef();
  203. }
  204. else
  205. {
  206. if (GetDebugClient(&Client) != S_OK)
  207. {
  208. DbgPrint("Error: Client creation failed.\n");
  209. return;
  210. }
  211. }
  212. if (ExtQuery(Client) != S_OK)
  213. {
  214. DbgPrint("Error: Interface queries failed.\n");
  215. EXT_RELEASE(Client);
  216. }
  217. }
  218. ExtApiClass::~ExtApiClass()
  219. {
  220. if (Client)
  221. {
  222. ExtRelease();
  223. EXT_RELEASE(Client);
  224. }
  225. }
  226. HRESULT
  227. ReadSymbolData(
  228. IN PDEBUG_CLIENT Client,
  229. IN PCSTR Symbol,
  230. OUT PVOID Buffer,
  231. IN ULONG BufferSize,
  232. OUT OPTIONAL PULONG SizeRead
  233. )
  234. {
  235. HRESULT hr;
  236. ULONG64 Module;
  237. ULONG64 Offset;
  238. ULONG TypeId;
  239. ULONG TypeSize;
  240. if (Buffer != NULL)
  241. {
  242. RtlZeroMemory(Buffer, BufferSize);
  243. }
  244. if (SizeRead != NULL)
  245. {
  246. *SizeRead = 0;
  247. }
  248. if (Client == NULL)
  249. {
  250. return E_POINTER;
  251. }
  252. OutputControl OutCtl(Client);
  253. PDEBUG_SYMBOLS Symbols;
  254. if ((hr = Client->QueryInterface(__uuidof(IDebugSymbols),
  255. (void **)&Symbols)) != S_OK)
  256. {
  257. return hr;
  258. }
  259. if ((hr = Symbols->GetOffsetByName(Symbol, &Offset)) == S_OK)
  260. {
  261. if ((hr = Symbols->GetSymbolTypeId(Symbol, &TypeId, &Module)) == S_OK &&
  262. (hr = Symbols->GetTypeSize(Module, TypeId, &TypeSize)) == S_OK)
  263. {
  264. BufferSize = min(BufferSize, TypeSize);
  265. if (SessionId == CURRENT_SESSION)
  266. {
  267. hr = Symbols->ReadTypedDataVirtual(Offset, Module, TypeId, Buffer, BufferSize, SizeRead);
  268. }
  269. else
  270. {
  271. ULONG64 OffsetPhys;
  272. if ((hr = GetPhysicalAddress(Client,
  273. SessionId,
  274. Offset,
  275. &OffsetPhys)) == S_OK)
  276. {
  277. hr = Symbols->ReadTypedDataPhysical(OffsetPhys, Module, TypeId, Buffer, BufferSize, SizeRead);
  278. }
  279. }
  280. }
  281. else
  282. {
  283. OutCtl.OutErr("Couldn't get type info for %s; result 0x%lx.\n", Symbol, hr);
  284. }
  285. }
  286. else
  287. {
  288. OutCtl.OutErr("Couldn't get offset of %s; result 0x%lx.\n", Symbol, hr);
  289. }
  290. Symbols->Release();
  291. return hr;
  292. }
  293. const CHAR szNULL[] = "(null)";
  294. DEBUG_VALUE DbgValNULL = { 0, DEBUG_VALUE_INT64 };
  295. HRESULT
  296. Evaluate(
  297. IN PDEBUG_CLIENT Client,
  298. IN PCSTR Expression,
  299. IN ULONG DesiredType,
  300. IN ULONG Radix,
  301. OUT PDEBUG_VALUE Value,
  302. OUT OPTIONAL PULONG RemainderIndex,
  303. OUT OPTIONAL PULONG StartIndex,
  304. OUT OPTIONAL FLONG Flags
  305. )
  306. {
  307. HRESULT hr = S_FALSE;
  308. PDEBUG_CONTROL Control;
  309. PSTR pStr;
  310. BOOL FoundNULL = FALSE;
  311. ULONG OrgRadix;
  312. CHAR EvalBuffer[128];
  313. ULONG EvalLen;
  314. if (RemainderIndex != NULL) *RemainderIndex = 0;
  315. if (StartIndex != NULL) *StartIndex = 0;
  316. if (Expression == NULL ||
  317. Client == NULL ||
  318. (hr = Client->QueryInterface(__uuidof(IDebugControl),
  319. (void **)&Control)) != S_OK)
  320. {
  321. return hr;
  322. }
  323. pStr = (PSTR)Expression;
  324. while (*pStr != '\n' && (isspace(*pStr) || (*pStr != '-' && ispunct(*pStr))))
  325. {
  326. if (_strnicmp(pStr, szNULL, sizeof(szNULL)-1) == 0)
  327. {
  328. FoundNULL = TRUE;
  329. break;
  330. }
  331. pStr++;
  332. }
  333. if (FoundNULL)
  334. {
  335. hr = Control->CoerceValue(&DbgValNULL,
  336. (DesiredType == DEBUG_VALUE_INVALID) ?
  337. DEBUG_VALUE_INT64 : DesiredType,
  338. Value);
  339. EvalLen = sizeof(szNULL)-1;
  340. }
  341. else
  342. {
  343. // Find expression string and only text revalent
  344. // to evalutating that expression.
  345. //
  346. // Otherwise IDebugControl::Evaluate will spend
  347. // too much time looking up values that are not
  348. // really part of the expression.
  349. //
  350. // IDebugControl::Evaluate also doesn't handle
  351. // binary strings well. We expect binary strings
  352. // to be followed by a non-binary value enclosed
  353. // in parenthesis. Just use that value.
  354. char *psz;
  355. int i = 0;
  356. while (pStr[i] != '\0' &&
  357. (pStr[i] == '0' || pStr[i] == '1'))
  358. {
  359. i++;
  360. }
  361. if (i &&
  362. pStr[i] == ' ' &&
  363. pStr[i+1] == '(' &&
  364. isdigit(pStr[i+2]))
  365. {
  366. pStr += i + 1;
  367. }
  368. psz = pStr;
  369. i = 0;
  370. if (Flags & EVALUATE_COMPACT_EXPR)
  371. {
  372. while ((i < sizeof(EvalBuffer)-1) &&
  373. *psz != '\0' && !isspace(*psz))
  374. {
  375. EvalBuffer[i++] = *psz++;
  376. }
  377. }
  378. else
  379. {
  380. do
  381. {
  382. while ((i < sizeof(EvalBuffer)-1) &&
  383. *psz != '\0' && !isspace(*psz))
  384. {
  385. EvalBuffer[i++] = *psz++;
  386. }
  387. while ((i < sizeof(EvalBuffer)-1) &&
  388. (*psz == ' ' || *psz == '\t'))
  389. {
  390. EvalBuffer[i++] = *psz++;
  391. }
  392. } while ((i < sizeof(EvalBuffer)-1) &&
  393. (ispunct(*psz) && *psz != '-' && *psz != '_' &&
  394. !(psz[0] == '-' && psz[1] == '>')));
  395. // Remove any trailing whitespace
  396. while (i > 0 && isspace(EvalBuffer[i-1])) i--;
  397. }
  398. EvalBuffer[i] = '\0';
  399. if (Radix == 0 ||
  400. ((hr = Control->GetRadix(&OrgRadix)) == S_OK &&
  401. (hr = Control->SetRadix(Radix)) == S_OK)
  402. )
  403. {
  404. // DbgPrint("Calling Eval(%s) --\n", EvalBuffer);
  405. hr = Control->Evaluate(EvalBuffer,
  406. DesiredType,
  407. Value,
  408. &EvalLen);
  409. // DbgPrint("-- Eval returned\n");
  410. if (Radix != 0)
  411. {
  412. Control->SetRadix(OrgRadix);
  413. }
  414. if (hr == S_OK &&
  415. Flags & EVALUATE_COMPACT_EXPR &&
  416. EvalLen != i)
  417. {
  418. hr = S_FALSE;
  419. }
  420. }
  421. else
  422. {
  423. DbgPrint("Can't setup new radix, %lu, for Evaluate.\n", Radix);
  424. }
  425. }
  426. Control->Release();
  427. if (hr == S_OK)
  428. {
  429. if (RemainderIndex != NULL)
  430. {
  431. *RemainderIndex = (ULONG)(pStr - Expression) + EvalLen;
  432. }
  433. if (StartIndex != NULL)
  434. {
  435. *StartIndex = (ULONG)(pStr - Expression);
  436. }
  437. }
  438. return hr;
  439. }
  440. HRESULT
  441. ReadPointerPhysical(
  442. PDEBUG_CLIENT Client,
  443. ULONG64 Offset,
  444. PULONG64 Ptr
  445. )
  446. {
  447. HRESULT hr;
  448. PDEBUG_CONTROL Control;
  449. PDEBUG_DATA_SPACES Data;
  450. DEBUG_VALUE PtrVal;
  451. ULONG BytesRead;
  452. if (Ptr != NULL) *Ptr = 0;
  453. if (Client == NULL) return E_INVALIDARG;
  454. if ((hr = Client->QueryInterface(__uuidof(IDebugControl),
  455. (void **)&Control)) != S_OK)
  456. {
  457. return hr;
  458. }
  459. if ((hr = Client->QueryInterface(__uuidof(IDebugDataSpaces),
  460. (void **)&Data)) != S_OK)
  461. {
  462. Client->Release();
  463. return hr;
  464. }
  465. if (Control->IsPointer64Bit() == S_OK)
  466. {
  467. Control->Output(DEBUG_OUTPUT_VERBOSE, "Read64PointerPhysical(0x%p)\n", Offset);
  468. hr = Data->ReadPhysical(Offset,
  469. &PtrVal.I64,
  470. sizeof(PtrVal.I64),
  471. &BytesRead);
  472. if (hr == S_OK &&
  473. BytesRead != sizeof(PtrVal.I64))
  474. {
  475. Control->Output(DEBUG_OUTPUT_VERBOSE,
  476. "ReadPhysicalPointer only read %lu bytes not %lu.\n",
  477. BytesRead, sizeof(PtrVal.I64));
  478. hr = S_FALSE;
  479. }
  480. if (hr == S_OK) Control->Output(DEBUG_OUTPUT_VERBOSE, " read 0x%p\n", PtrVal.I64);
  481. }
  482. else
  483. {
  484. Control->Output(DEBUG_OUTPUT_VERBOSE, "Read32PointerPhysical(0x%p)\n", Offset);
  485. hr = Data->ReadPhysical(Offset,
  486. &PtrVal.I32,
  487. sizeof(PtrVal.I32),
  488. &BytesRead);
  489. if (hr == S_OK)
  490. {
  491. if (BytesRead != sizeof(PtrVal.I32))
  492. {
  493. Control->Output(DEBUG_OUTPUT_VERBOSE,
  494. "ReadPhysicalPointer only read %lu bytes not %lu.\n",
  495. BytesRead, sizeof(PtrVal.I32));
  496. hr = S_FALSE;
  497. }
  498. else
  499. {
  500. Control->Output(DEBUG_OUTPUT_VERBOSE, " read 0x%p", PtrVal.I64);
  501. PtrVal.I64 = DEBUG_EXTEND64(PtrVal.I32);
  502. Control->Output(DEBUG_OUTPUT_VERBOSE, " -> 0x%I64x\n", PtrVal.I64);
  503. }
  504. }
  505. }
  506. if (hr == S_OK && Ptr != NULL)
  507. {
  508. *Ptr = PtrVal.I64;
  509. }
  510. Data->Release();
  511. Control->Release();
  512. return hr;
  513. }
  514. HRESULT
  515. GetTypeId(
  516. IN PDEBUG_CLIENT Client,
  517. IN PCSTR Type,
  518. OUT PULONG TypeId,
  519. OUT OPTIONAL PULONG64 Module
  520. )
  521. {
  522. HRESULT hr;
  523. PDEBUG_SYMBOLS Symbols;
  524. if (Client == NULL || Type == NULL || TypeId == NULL)
  525. {
  526. return E_INVALIDARG;
  527. }
  528. if ((hr = Client->QueryInterface(__uuidof(IDebugSymbols),
  529. (void **)&Symbols)) != S_OK)
  530. {
  531. return hr;
  532. }
  533. if (strchr(Type, '!') == NULL &&
  534. Type_Module.Base != 0 &&
  535. (hr = Symbols->GetTypeId(Type_Module.Base, Type, TypeId)) == S_OK)
  536. {
  537. if (Module != NULL)
  538. {
  539. *Module = Type_Module.Base;
  540. }
  541. }
  542. else
  543. {
  544. hr = Symbols->GetSymbolTypeId(Type, TypeId, Module);
  545. }
  546. Symbols->Release();
  547. return hr;
  548. }
  549. HRESULT
  550. GetBasicTypeSize(
  551. IN PCSTR Type,
  552. OUT PULONG Size
  553. )
  554. {
  555. HRESULT hr;
  556. ULONG Bytes = 0;
  557. static CHAR PointerBase[] = "Ptr";
  558. static CHAR Char[] = "Char";
  559. static CHAR IntBase[] = "Int";
  560. if (_strnicmp(Type, PointerBase, sizeof(PointerBase)) == 0)
  561. {
  562. Bytes = strtoul(Type+sizeof(PointerBase), NULL, 10) / 8;
  563. }
  564. else
  565. {
  566. // Remove U indicating unsigned
  567. if (*Type == 'U')
  568. {
  569. Type++;
  570. }
  571. if (_strnicmp(Type, Char, sizeof(Char)) == 0)
  572. {
  573. Bytes = 1;
  574. }
  575. else if (_strnicmp(Type, IntBase, sizeof(IntBase)) == 0)
  576. {
  577. PCHAR NextChar;
  578. Bytes = strtoul(Type+sizeof(IntBase), &NextChar, 10);
  579. if (NextChar == NULL ||
  580. toupper(*NextChar) != 'B')
  581. {
  582. Bytes = 0;
  583. }
  584. }
  585. }
  586. if (Bytes != 0)
  587. {
  588. hr = S_OK;
  589. if (Size != NULL)
  590. {
  591. *Size = Bytes;
  592. }
  593. }
  594. else
  595. {
  596. hr = S_FALSE;
  597. }
  598. return hr;
  599. }
  600. HRESULT
  601. GetFieldSize(
  602. IN PDEBUG_CLIENT Client,
  603. IN ULONG64 Module,
  604. IN ULONG TypeId,
  605. IN PCSTR FieldPath,
  606. OUT PULONG pSize,
  607. OUT OPTIONAL PULONG pLength,
  608. OUT OPTIONAL PULONG pEntrySize
  609. )
  610. {
  611. HRESULT hr;
  612. PDEBUG_CONTROL Control;
  613. PDEBUG_SYMBOLS Symbols;
  614. if (pSize != NULL) *pSize = 0;
  615. if (pLength != NULL) *pLength = 0;
  616. if (pEntrySize != NULL) *pEntrySize = 0;
  617. if (Client == NULL ||
  618. FieldPath == NULL ||
  619. !iscsymf(*FieldPath))
  620. {
  621. return E_INVALIDARG;
  622. }
  623. if ((hr = Client->QueryInterface(__uuidof(IDebugControl),
  624. (void **)&Control)) != S_OK)
  625. {
  626. return hr;
  627. }
  628. if ((hr = Client->QueryInterface(__uuidof(IDebugSymbols),
  629. (void **)&Symbols)) != S_OK)
  630. {
  631. Client->Release();
  632. return hr;
  633. }
  634. OutputReader OutReader;
  635. OutputState OutState(Client, FALSE);
  636. PSTR TypeLayout;
  637. PSTR Field;
  638. SIZE_T FieldLen;
  639. CHAR FieldCopy[80];
  640. PCSTR SubFieldPath;
  641. ULONG Size, ArrayLen = 0;
  642. if ((hr = OutState.Setup(0, &OutReader)) == S_OK &&
  643. (hr = OutState.OutputTypeVirtual(0,
  644. Module,
  645. TypeId,
  646. DEBUG_OUTTYPE_NO_INDENT |
  647. DEBUG_OUTTYPE_NO_OFFSET |
  648. DEBUG_OUTTYPE_COMPACT_OUTPUT)) == S_OK &&
  649. (hr = OutReader.GetOutputCopy(&TypeLayout)) == S_OK)
  650. {
  651. SubFieldPath = strchr(FieldPath, '.');
  652. if (SubFieldPath != NULL)
  653. {
  654. FieldLen = SubFieldPath - FieldPath - 1;
  655. SubFieldPath++;
  656. if (FieldLen + 1 > sizeof(FieldCopy))
  657. {
  658. Field = (PSTR)HeapAlloc(GetProcessHeap(), 0, FieldLen + 1);
  659. if (Field == NULL)
  660. {
  661. hr = E_OUTOFMEMORY;
  662. }
  663. }
  664. else
  665. {
  666. Field = FieldCopy;
  667. }
  668. if (hr == S_OK)
  669. {
  670. RtlCopyMemory(Field, FieldPath, FieldLen);
  671. Field[FieldLen] = '\0';
  672. }
  673. }
  674. else
  675. {
  676. Field = (PSTR)FieldPath;
  677. }
  678. if (hr == S_OK)
  679. {
  680. PSTR pStr = TypeLayout;
  681. BOOL FieldFound = FALSE;
  682. while (!FieldFound && pStr != NULL)
  683. {
  684. pStr = strstr(pStr, Field);
  685. if (pStr != NULL)
  686. {
  687. // Check Field is bounded by non-symbol characters
  688. BOOL FieldStart = (pStr-1 < TypeLayout) || (!__iscsym(*(pStr-1)));
  689. // Advance search location
  690. pStr += strlen(Field);
  691. if (FieldStart && !__iscsym(*pStr))
  692. {
  693. FieldFound = TRUE;
  694. }
  695. }
  696. }
  697. if (FieldFound)
  698. {
  699. while (isspace(*pStr)) pStr++;
  700. // Check for an array
  701. if (*pStr == '[')
  702. {
  703. PCHAR EvalEnd;
  704. ArrayLen = strtoul(pStr+1, &EvalEnd, 10);
  705. if (ArrayLen != 0 && *EvalEnd == ']')
  706. {
  707. pStr = EvalEnd + 1;
  708. while (isspace(*pStr)) pStr++;
  709. }
  710. // else following csym check will fail returning error.
  711. }
  712. if (iscsymf(*pStr))
  713. {
  714. PSTR FieldType = pStr;
  715. ULONG SubTypeId;
  716. while (iscsym(*pStr)) pStr++;
  717. *pStr = '\0';
  718. hr = Symbols->GetTypeId(Module, FieldType, &SubTypeId);
  719. if (SubFieldPath != NULL)
  720. {
  721. if (hr == S_OK)
  722. {
  723. hr = GetFieldSize(Client,
  724. Module,
  725. SubTypeId,
  726. SubFieldPath,
  727. pSize,
  728. pLength,
  729. pEntrySize);
  730. }
  731. }
  732. else
  733. {
  734. if (hr == S_OK)
  735. {
  736. hr = Symbols->GetTypeSize(Module, SubTypeId, &Size);
  737. }
  738. else
  739. {
  740. if (GetBasicTypeSize(FieldType, &Size) == S_OK)
  741. {
  742. hr = S_OK;
  743. }
  744. }
  745. if (hr == S_OK)
  746. {
  747. if (pEntrySize != NULL) *pEntrySize = Size;
  748. if (pLength != NULL) *pLength = ArrayLen;
  749. if (pSize != NULL)
  750. {
  751. if (ArrayLen != 0) Size *= ArrayLen;
  752. *pSize = Size;
  753. }
  754. }
  755. }
  756. }
  757. else
  758. {
  759. hr = S_FALSE;
  760. }
  761. }
  762. }
  763. if (Field != NULL && Field != FieldCopy && Field != FieldPath)
  764. {
  765. HeapFree(GetProcessHeap(), 0, Field);
  766. }
  767. OutReader.FreeOutputCopy(TypeLayout);
  768. }
  769. Symbols->Release();
  770. Control->Release();
  771. return hr;
  772. }
  773. ULONG
  774. DbgIntValTypeFromSize(
  775. ULONG Size
  776. )
  777. {
  778. ULONG Type;
  779. switch (Size)
  780. {
  781. case 1: Type = DEBUG_VALUE_INT8; break;
  782. case 2: Type = DEBUG_VALUE_INT16; break;
  783. case 4: Type = DEBUG_VALUE_INT32; break;
  784. case 8: Type = DEBUG_VALUE_INT64; break;
  785. default: Type = DEBUG_VALUE_INVALID; break;
  786. }
  787. return Type;
  788. }
  789. BOOL
  790. GetArrayDimensions(
  791. IN PDEBUG_CLIENT Client,
  792. IN PCSTR Type,
  793. OPTIONAL IN PCSTR Field,
  794. OPTIONAL OUT PULONG ArraySize,
  795. OPTIONAL OUT PULONG ArrayLength,
  796. OPTIONAL OUT PULONG EntrySize
  797. )
  798. {
  799. HRESULT hr;
  800. ULONG64 Module;
  801. ULONG TypeId;
  802. BOOL GotDimensions = FALSE;
  803. ULONG Size, ESize;
  804. if (ArraySize) *ArraySize = 0;
  805. if (ArrayLength) *ArrayLength = 0;
  806. if (EntrySize) *EntrySize = 0;
  807. if (Type == NULL)
  808. {
  809. return FALSE;
  810. }
  811. if (Field != NULL)
  812. {
  813. hr = GetTypeId(Client, Type, &TypeId, &Module);
  814. if (hr == S_OK)
  815. {
  816. hr = GetFieldSize(Client, Module, TypeId, Field,
  817. ArraySize, ArrayLength, EntrySize);
  818. if (hr == S_OK) GotDimensions = TRUE;
  819. }
  820. }
  821. if (!GotDimensions && ExtQuery(Client) == S_OK)
  822. {
  823. ULONG GrpIndex;
  824. CHAR SymbolName[MAX_PATH];
  825. DEBUG_SYMBOL_PARAMETERS Array;
  826. _snprintf(SymbolName, sizeof(SymbolName),
  827. (Field) ? "%s.%s" : Type,
  828. Type, Field);
  829. if (g_pExtSymbolGroup->AddSymbol(SymbolName, &GrpIndex) == S_OK)
  830. {
  831. if (g_pExtSymbolGroup->GetSymbolParameters(GrpIndex, 1, &Array) == S_OK)
  832. {
  833. if (Array.SubElements)
  834. {
  835. if (g_pExtSymbols->GetTypeSize(Array.Module, Array.TypeId, &Size) == S_OK)
  836. {
  837. ExtVerb(" Array %s - Size: %u bytes Length: %u\n", SymbolName, Size, Array.SubElements);
  838. if (ArraySize) *ArraySize = Size;
  839. if (ArrayLength) *ArrayLength = Array.SubElements;
  840. if (EntrySize) *EntrySize = Size / Array.SubElements;
  841. GotDimensions = TRUE;
  842. }
  843. else
  844. {
  845. ExtErr("Couldn't get size of %s.\n", Type);
  846. }
  847. }
  848. else
  849. {
  850. ExtErr("%s has 0 subelements.\n", SymbolName);
  851. }
  852. }
  853. else
  854. {
  855. ExtErr("Couldn't get parameter info for %s.\n", SymbolName);
  856. }
  857. g_pExtSymbolGroup->RemoveSymbolByIndex(GrpIndex);
  858. }
  859. else
  860. {
  861. ExtErr("Couldn't lookup symbol %s.\n", SymbolName);
  862. }
  863. ExtRelease();
  864. }
  865. if (!GotDimensions)
  866. {
  867. ULONG Index = -1;
  868. PCSTR ArrayName = Field ? Field : Type;
  869. char FirstEntryName[128];
  870. ULONG error;
  871. FIELD_INFO EntrySizeField = { DbgStr(Field), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL};
  872. SYM_DUMP_PARAM ArraySym = {
  873. sizeof (SYM_DUMP_PARAM), DbgStr(Type),
  874. DBG_DUMP_NO_PRINT, 0,
  875. NULL, NULL, NULL,
  876. (Field ? 1 : 0), &EntrySizeField
  877. };
  878. ExtVerb("Using WinDbg extension interface.\n");
  879. if (Field)
  880. {
  881. error = Ioctl(IG_DUMP_SYMBOL_INFO, &ArraySym, ArraySym.size);
  882. Size = (error) ? 0 : EntrySizeField.size;
  883. EntrySizeField.fName = DbgStr(FirstEntryName);
  884. }
  885. else
  886. {
  887. Size = Ioctl(IG_GET_TYPE_SIZE, &ArraySym, ArraySym.size);
  888. ArraySym.sName = DbgStr(FirstEntryName);
  889. }
  890. if (Size == 0)
  891. {
  892. dprintf("Array size is zero.\n");
  893. return FALSE;
  894. }
  895. if (ArraySize) *ArraySize = Size;
  896. _snprintf(FirstEntryName, sizeof(FirstEntryName), "%s[0]", ArrayName);
  897. if (Field)
  898. {
  899. error = Ioctl(IG_DUMP_SYMBOL_INFO, &ArraySym, ArraySym.size);
  900. ESize = (error) ? 0 : EntrySizeField.size;
  901. vPrintNativeSymDumpParam(&ArraySym);
  902. }
  903. else
  904. {
  905. ESize = Ioctl(IG_GET_TYPE_SIZE, &ArraySym, ArraySym.size);
  906. }
  907. if (ESize)
  908. {
  909. DbgPrint("%s dimensions: %u bytes [%u] = %u bytes.\n",
  910. ArrayName, ESize, Size/ESize, Size);
  911. if (ArrayLength) *ArrayLength = Size/ESize;
  912. if (EntrySize) *EntrySize = ESize;
  913. GotDimensions = TRUE;
  914. }
  915. }
  916. return GotDimensions;
  917. }
  918. HRESULT
  919. DumpType(
  920. PDEBUG_CLIENT Client,
  921. PCSTR Type,
  922. ULONG64 Offset,
  923. ULONG Flags,
  924. OutputControl *OutCtl,
  925. BOOL Physical
  926. )
  927. {
  928. HRESULT hr;
  929. PDEBUG_SYMBOLS Symbols;
  930. ULONG64 Module;
  931. ULONG TypeId;
  932. OutputControl DefaultOutput;
  933. if (Client == NULL) return E_INVALIDARG;
  934. if (OutCtl == NULL)
  935. {
  936. DefaultOutput.SetControl(DEBUG_OUTCTL_AMBIENT, Client);
  937. OutCtl = &DefaultOutput;
  938. }
  939. if ((hr = GetTypeId(Client, Type, &TypeId, &Module)) != S_OK)
  940. {
  941. OutCtl->OutErr(" Not a type nor symbol - HRESULT %s.\n", pszHRESULT(hr));
  942. }
  943. else
  944. {
  945. TypeOutputDumper TypeReader(Client, OutCtl);
  946. if (!(Flags & DEBUG_OUTTYPE_NO_OFFSET))
  947. {
  948. OutCtl->Output(" %s", Type);
  949. if (Offset != 0) OutCtl->Output(" @ %s0x%p", ((Physical) ? "#" : ""), Offset);
  950. OutCtl->Output((Flags & DEBUG_OUTTYPE_COMPACT_OUTPUT) ? " " : ":\n");
  951. }
  952. hr = TypeReader.OutputType(Physical, Module, TypeId, Offset, Flags, NULL);
  953. }
  954. return hr;
  955. }
  956. HRESULT
  957. ExtDumpType(
  958. IN PDEBUG_CLIENT Client,
  959. IN PCSTR ExtName,
  960. IN PCSTR Type,
  961. IN PCSTR Args
  962. )
  963. {
  964. INIT_API();
  965. HRESULT hr = S_OK;
  966. DEBUG_VALUE Offset;
  967. Offset.I64 = 0;
  968. while (isspace(*Args)) Args++;
  969. if (*Args == '-' ||
  970. (hr = Evaluate(Client, Args, DEBUG_VALUE_INT64, 0, &Offset, NULL)) != S_OK)
  971. {
  972. if (hr != S_OK)
  973. {
  974. ExtErr("Evaluate '%s' returned %s.\n", Args, pszHRESULT(hr));
  975. }
  976. ExtOut("Usage: %s [-?] [%s Addr]\n", ExtName, Type);
  977. }
  978. else
  979. {
  980. hr = DumpType(Client, Type, Offset.I64);
  981. if (hr != S_OK)
  982. {
  983. ExtErr("Type Dump for %s returned %s.\n", Type, pszHRESULT(hr));
  984. }
  985. }
  986. EXIT_API(hr);
  987. }
  988. void
  989. DumpDSP(PDEBUG_CLIENT Client, PDEBUG_SYMBOL_PARAMETERS pDSP)
  990. {
  991. ExtOut(" Module Base : %p\n", pDSP->Module);
  992. ExtOut(" TypeId : %lx\n", pDSP->TypeId);
  993. ExtOut(" ParentSymbol : %lx\n", pDSP->ParentSymbol);
  994. ExtOut(" SubElements : %lu\n", pDSP->SubElements);
  995. ExtOut(" Flags : %lx\n", pDSP->Flags);
  996. ExtOut(" Reserved : %I64u\n", pDSP->Reserved);
  997. }
  998. DECLARE_API(dt)
  999. {
  1000. HRESULT Hr = E_INVALIDARG;
  1001. BOOL VerboseInfo = FALSE;
  1002. BOOL NotGDIType = FALSE;
  1003. BOOL AllClients = FALSE;
  1004. BOOL SessionAddr = FALSE;
  1005. BOOL Physical = FALSE;
  1006. char TypeSym[MAX_NAME];
  1007. char *pcTypeSym = TypeSym;
  1008. DEBUG_VALUE Offset;
  1009. ULONG Index;
  1010. DEBUG_SYMBOL_PARAMETERS DSP;
  1011. DEBUG_VALUE RepeatCount = { {1}, DEBUG_VALUE_INVALID};
  1012. ULONG Size = 0;
  1013. INIT_API();
  1014. while (isspace(*args)) args++;
  1015. while (*args == '-')
  1016. {
  1017. args++;
  1018. do
  1019. {
  1020. switch (tolower(*args))
  1021. {
  1022. case 'v': VerboseInfo = TRUE; break;
  1023. case 's': SessionAddr = TRUE; break;
  1024. case 'n': NotGDIType = TRUE; break;
  1025. case 'c': AllClients = TRUE; break;
  1026. case 'l':
  1027. {
  1028. ULONG RemIndex;
  1029. Hr = Evaluate(Client, args+1, DEBUG_VALUE_INT32, 0, &RepeatCount, &RemIndex);
  1030. if (Hr == S_OK)
  1031. {
  1032. if (RepeatCount.Type == DEBUG_VALUE_INT32 &&
  1033. RepeatCount.I32 > 0)
  1034. {
  1035. if (RepeatCount.I32 < 512)
  1036. {
  1037. args += RemIndex;
  1038. break;
  1039. }
  1040. else
  1041. {
  1042. ExtErr("Array count %lu is higher than 512 limit.\n\n", RepeatCount.I32);
  1043. }
  1044. }
  1045. else
  1046. {
  1047. ExtErr("Invalid array count at \"%s\"\n\n", args+1);
  1048. }
  1049. Hr = E_INVALIDARG;
  1050. }
  1051. else
  1052. {
  1053. ExtErr("Missing array count.\n\n");
  1054. }
  1055. }
  1056. default:
  1057. {
  1058. ExtOut("dt dumps GDI types expanding enum and flag values.\n"
  1059. "\n"
  1060. "Usage: dt [-?vsn] [-l<Count>] <Type|Symbol> [[#]Offset]\n"
  1061. "\n"
  1062. " -v Verbose type/symbol information\n"
  1063. " -s Lookup according to !session setting\n"
  1064. " -n Directly through debug engine\n"
  1065. " -l Dump an array of Type/Symbol Count times\n");
  1066. EXIT_API(*args == '?' ? S_OK : Hr);
  1067. }
  1068. }
  1069. args++;
  1070. } while (!isspace(*args) && *args != '\0');
  1071. while (isspace(*args)) args++;
  1072. }
  1073. // Get Type/Symbol name from argument string
  1074. while (*args != '\0' && !isspace(*args) &&
  1075. (pcTypeSym < (TypeSym + sizeof(TypeSym) - 2)))
  1076. {
  1077. *pcTypeSym++ = *args++;
  1078. }
  1079. // Type/Symbols should be followed by a space or nothing
  1080. if (*args != '\0' && !isspace(*args))
  1081. {
  1082. ExtErr("Invalid arguments\n");
  1083. EXIT_API(E_INVALIDARG);
  1084. }
  1085. *pcTypeSym = '\0';
  1086. while (isspace(*args))
  1087. {
  1088. args++;
  1089. }
  1090. if (*args == '#')
  1091. {
  1092. if (SessionAddr)
  1093. {
  1094. ExtErr("-s may not be combined with physical addresses.\n");
  1095. EXIT_API(E_INVALIDARG);
  1096. }
  1097. Physical = TRUE;
  1098. args++;
  1099. }
  1100. Offset.Type = DEBUG_VALUE_INVALID;
  1101. Hr = Evaluate(Client, args, DEBUG_VALUE_INT64, 0, &Offset, NULL);
  1102. if (Physical && Offset.Type == DEBUG_VALUE_INVALID)
  1103. {
  1104. ExtErr("Invalid offset\n");
  1105. EXIT_API(((Hr != S_OK) ? Hr : E_INVALIDARG));
  1106. }
  1107. if ((Hr = g_pExtSymbolGroup->AddSymbol(TypeSym, &Index)) == S_OK)
  1108. {
  1109. if ((Hr = g_pExtSymbolGroup->GetSymbolParameters(Index, 1, &DSP)) == S_OK)
  1110. {
  1111. if (VerboseInfo) DumpDSP(Client, &DSP);
  1112. }
  1113. else
  1114. {
  1115. ExtErr(" GetSymbolParameters returned error %lX.\n", Hr);
  1116. }
  1117. g_pExtSymbolGroup->RemoveSymbolByIndex(Index);
  1118. }
  1119. else
  1120. {
  1121. ExtVerb(" Not a symbol - Symbol lookup returned error %lX.\n", Hr);
  1122. Hr = GetTypeId(Client, TypeSym, &DSP.TypeId, &DSP.Module);
  1123. if (Hr == S_OK)
  1124. {
  1125. if (VerboseInfo)
  1126. {
  1127. ExtOut(" Module Base : %p\n", DSP.Module);
  1128. ExtOut(" TypeId : %lx\n", DSP.TypeId);
  1129. }
  1130. }
  1131. else
  1132. {
  1133. ExtErr(" Not a type/symbol - %s.\n", pszHRESULT(Hr));
  1134. }
  1135. }
  1136. if (Hr == S_OK && VerboseInfo)
  1137. {
  1138. HRESULT HrCur;
  1139. char ModuleName[40];
  1140. Hr = g_pExtSymbols->GetModuleNames(DEBUG_ANY_ID, DSP.Module,
  1141. NULL, 0, NULL,
  1142. ModuleName, sizeof(ModuleName), NULL,
  1143. NULL, 0, NULL);
  1144. if (Hr == S_OK)
  1145. {
  1146. ExtOut(" Module Name : %s\n", ModuleName);
  1147. }
  1148. else
  1149. {
  1150. ExtErr(" GetModuleNames returned error %lx.\n", Hr);
  1151. }
  1152. ExtVerb("GetTypeName(%p, %lx)\n", DSP.Module, DSP.TypeId);
  1153. char TypeName[MAX_NAME];
  1154. HrCur = g_pExtSymbols->GetTypeName(DSP.Module, DSP.TypeId,
  1155. TypeName, sizeof(TypeName),
  1156. NULL);
  1157. if (HrCur == S_OK)
  1158. {
  1159. ExtOut(" Type Name : %s\n", TypeName);
  1160. }
  1161. else
  1162. {
  1163. ExtErr(" GetTypeName returned error %lx.\n", HrCur);
  1164. if (Hr == S_OK) Hr = HrCur;
  1165. }
  1166. }
  1167. if (Hr == S_OK && ((RepeatCount.I32 != 1) || VerboseInfo))
  1168. {
  1169. Hr = g_pExtSymbols->GetTypeSize(DSP.Module, DSP.TypeId, &Size);
  1170. if (Hr == S_OK)
  1171. {
  1172. if (VerboseInfo)
  1173. {
  1174. ExtOut(" Type Size : %lu\n", Size);
  1175. }
  1176. if (RepeatCount.I32 != 1 && Size == 0)
  1177. {
  1178. ExtErr("Error: GetTypeSize returned size of 0.\n");
  1179. Hr = E_FAIL;
  1180. }
  1181. }
  1182. else
  1183. {
  1184. ExtErr(" GetTypeSize returned error %lx.\n", Hr);
  1185. }
  1186. }
  1187. if (Hr == S_OK)
  1188. {
  1189. // Try to evaluate TypeSym for an offset if none was specified.
  1190. if (*args == '\0' &&
  1191. (Offset.Type == DEBUG_VALUE_INVALID ||
  1192. (Offset.I64 == 0 && !Physical)))
  1193. {
  1194. Offset.Type = DEBUG_VALUE_INVALID;
  1195. Evaluate(Client, TypeSym, DEBUG_VALUE_INT64, 0, &Offset, NULL);
  1196. }
  1197. if (Offset.Type == DEBUG_VALUE_INVALID)
  1198. {
  1199. Offset.I64 = 0;
  1200. }
  1201. else if (SessionAddr && SessionId != CURRENT_SESSION)
  1202. {
  1203. ULONG64 PhysAddr;
  1204. Hr = GetPhysicalAddress(Client, SessionId, Offset.I64, &PhysAddr);
  1205. if (Hr == S_OK)
  1206. {
  1207. Physical = TRUE;
  1208. Offset.I64 = PhysAddr;
  1209. if (RepeatCount.I32 != 1)
  1210. {
  1211. ExtWarn("Array dumping is not supported for session dumps.\n");
  1212. RepeatCount.I32 = 1;
  1213. }
  1214. }
  1215. else
  1216. {
  1217. ExtErr("Couldn't lookup 0x%p in Session %s.\n", Offset.I64, SessionStr);
  1218. }
  1219. }
  1220. if (Hr == S_OK)
  1221. {
  1222. if (Offset.I64 == 0 && !Physical && RepeatCount.I32 != 1)
  1223. {
  1224. ExtWarn("No valid offset was found so array dump has been overridden.\n");
  1225. RepeatCount.I32 = 1;
  1226. }
  1227. while (RepeatCount.I32 > 0 && Hr == S_OK)
  1228. {
  1229. if ((Offset.I64 == 0 && !Physical) || NotGDIType)
  1230. {
  1231. ExtVerb("OutputTypedData(DEBUG_OUTCTL_THIS_CLIENT, 0x%p, %p, %lx, 0)\n",
  1232. Offset.I64, DSP.Module, DSP.TypeId);
  1233. if (Physical)
  1234. {
  1235. Hr = g_pExtSymbols->OutputTypedDataPhysical((AllClients ? DEBUG_OUTCTL_ALL_CLIENTS : DEBUG_OUTCTL_THIS_CLIENT),
  1236. Offset.I64,
  1237. DSP.Module,
  1238. DSP.TypeId,
  1239. 0);
  1240. }
  1241. else
  1242. {
  1243. Hr = g_pExtSymbols->OutputTypedDataVirtual((AllClients ? DEBUG_OUTCTL_ALL_CLIENTS : DEBUG_OUTCTL_THIS_CLIENT),
  1244. Offset.I64,
  1245. DSP.Module,
  1246. DSP.TypeId,
  1247. 0);
  1248. }
  1249. }
  1250. else
  1251. {
  1252. Hr = DumpType(Client, TypeSym, Offset.I64, DEBUG_OUTTYPE_DEFAULT, NULL, Physical);
  1253. }
  1254. if (--RepeatCount.I32 > 0)
  1255. {
  1256. Offset.I64 += Size;
  1257. }
  1258. }
  1259. if (Hr != S_OK)
  1260. {
  1261. ExtErr("Type dump returned %s.\n", pszHRESULT(Hr));
  1262. }
  1263. }
  1264. }
  1265. EXIT_API(Hr);
  1266. }