Source code of Windows XP (NT5)
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.

747 lines
21 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. ntsdexts.c
  5. Abstract:
  6. This function contains the default ntsd debugger extensions
  7. Author:
  8. Mark Lucovsky (markl) 09-Apr-1991
  9. Revision History:
  10. --*/
  11. #include "ntsdextp.h"
  12. WINDBG_EXTENSION_APIS ExtensionApis;
  13. HANDLE ExtensionCurrentProcess;
  14. DECLARE_API( version )
  15. {
  16. OSVERSIONINFOA VersionInformation;
  17. HKEY hkey;
  18. DWORD cb, dwType;
  19. CHAR szCurrentType[128];
  20. CHAR szCSDString[3+128];
  21. INIT_API();
  22. VersionInformation.dwOSVersionInfoSize = sizeof(VersionInformation);
  23. if (!GetVersionEx( &VersionInformation )) {
  24. dprintf("GetVersionEx failed - %u\n", GetLastError());
  25. return;
  26. }
  27. szCurrentType[0] = '\0';
  28. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  29. "Software\\Microsoft\\Windows NT\\CurrentVersion",
  30. 0,
  31. KEY_READ,
  32. &hkey
  33. ) == NO_ERROR
  34. ) {
  35. cb = sizeof(szCurrentType);
  36. if (RegQueryValueEx(hkey, "CurrentType", NULL, &dwType, szCurrentType, &cb ) != 0) {
  37. szCurrentType[0] = '\0';
  38. }
  39. RegCloseKey(hkey);
  40. }
  41. if (VersionInformation.szCSDVersion[0]) {
  42. sprintf(szCSDString, ": %s", VersionInformation.szCSDVersion);
  43. }
  44. else {
  45. szCSDString[0] = '\0';
  46. }
  47. dprintf("Version %d.%d (Build %d%s) %s\n",
  48. VersionInformation.dwMajorVersion,
  49. VersionInformation.dwMinorVersion,
  50. VersionInformation.dwBuildNumber,
  51. szCSDString,
  52. szCurrentType
  53. );
  54. return;
  55. }
  56. DECLARE_API( help )
  57. {
  58. INIT_API();
  59. while (*lpArgumentString == ' ')
  60. lpArgumentString++;
  61. if (*lpArgumentString == '\0') {
  62. dprintf("setupexts help:\n\n");
  63. dprintf("!version - Dump system version and build number\n");
  64. dprintf("!help - This message\n");
  65. dprintf("!ocm [address] [opt. flag] - Dump the OC_MANAGER structure at address, flag increased verbosity\n");
  66. dprintf("!space [address] [opt. flag] - Dump the DISK_SPACE_LIST structure at specified address\n");
  67. dprintf("!st [address] - Dump the contents of a STRING_TABLE structure at specified address\n");
  68. dprintf("!stfind [address] [element] - Dump the specified string table element\n");
  69. dprintf("!queue [address] [opt. flag] - Dump the specified file queue\n");
  70. dprintf("!qcontext [address] - Dump the specified default queue context \n");
  71. dprintf("!infdump [addr] [opt. flag] - Dump the specified hinf \n");
  72. dprintf("!winntflags - Dump some winnt32 global flags \n");
  73. dprintf("!winntstr - Dump some winnt32 global strings\n");
  74. }
  75. }
  76. BOOL
  77. CheckInterupted(
  78. VOID
  79. )
  80. {
  81. if ( CheckControlC() ) {
  82. dprintf( "\nInterrupted\n\n" );
  83. return TRUE;
  84. }
  85. return FALSE;
  86. }
  87. //
  88. // Simple routine to convert from hex into a string of characters.
  89. // Used by debugger extensions.
  90. //
  91. // by scottlu
  92. //
  93. char *
  94. HexToString(
  95. ULONG dw,
  96. CHAR *pch
  97. )
  98. {
  99. if (dw > 0xf) {
  100. pch = HexToString(dw >> 4, pch);
  101. dw &= 0xf;
  102. }
  103. *pch++ = ((dw >= 0xA) ? ('A' - 0xA) : '0') + (CHAR)dw;
  104. *pch = 0;
  105. return pch;
  106. }
  107. VOID
  108. DumpStringTableHeader(
  109. PSTRING_TABLE st
  110. )
  111. {
  112. //
  113. // dump the string table header
  114. //
  115. dprintf("\tBase Data ptr:\t0x%08x\n", st->Data);
  116. dprintf("\tDataSize:\t0x%08x\n", st->DataSize);
  117. dprintf("\tBufferSize:\t0x%08x\n", st->BufferSize);
  118. dprintf("\tExtraDataSize:\t0x%08x\n", st->ExtraDataSize);
  119. }
  120. VOID
  121. DumpOcComponent(
  122. ULONG_PTR offset,
  123. PSTRING_NODEW node,
  124. deb_POPTIONAL_COMPONENTW pcomp
  125. )
  126. {
  127. DWORD i;
  128. PLONG count;
  129. dprintf("OC_COMPONENT Data for node %ws : 0x%p\n", node->String, offset );
  130. dprintf( "\t InfStringId:\t\t0x%08x\n", pcomp->InfStringId );
  131. dprintf( "\t TopLevelStringId:\t0x%08x\n", pcomp->TopLevelStringId );
  132. dprintf( "\t ParentStringId:\t0x%08x\n", pcomp->ParentStringId );
  133. dprintf( "\t FirstChildStringId:\t0x%08x\n", pcomp->FirstChildStringId );
  134. dprintf( "\t ChildrenCount:\t\t0x%08x\n", pcomp->ChildrenCount );
  135. dprintf( "\t NextSiblingStringId:\t0x%08x\n", pcomp->NextSiblingStringId );
  136. dprintf( "\t NeedsCount:\t\t%d\n", pcomp->NeedsCount );
  137. count = malloc ( pcomp->NeedsCount * sizeof(LONG) );
  138. if (count) {
  139. // read and dump needs list
  140. ReadMemory((DWORD_PTR) pcomp->NeedsStringIds, count, pcomp->NeedsCount*sizeof(LONG), NULL);
  141. for (i = 0; i < pcomp->NeedsCount; i++) {
  142. dprintf("\t NeedsStringIds #%d:\t0x%08x\n", i, count[i]);
  143. if (CheckInterupted()) {
  144. return;
  145. }
  146. }
  147. free(count);
  148. }
  149. dprintf( "\t NeededByCount:\t\t%d\n", pcomp->NeededByCount );
  150. count = malloc ( pcomp->NeededByCount * sizeof(LONG) );
  151. if (count) {
  152. // read and dump needs list
  153. ReadMemory((DWORD_PTR) pcomp->NeededByStringIds, count, pcomp->NeededByCount*sizeof(LONG), NULL);
  154. for (i = 0; i < pcomp->NeededByCount; i++) {
  155. dprintf("\t NeededByStringIds #%d: 0x%08x\n", i, count[i]);
  156. if (CheckInterupted()) {
  157. return;
  158. }
  159. }
  160. free(count);
  161. }
  162. dprintf( "\t ExcludeCount:\t\t%d\n", pcomp->ExcludeCount );
  163. count = malloc ( pcomp->ExcludeCount * sizeof(LONG) );
  164. if (count) {
  165. // read and dump Excludes list
  166. ReadMemory((DWORD_PTR) pcomp->ExcludeStringIds, count, pcomp->ExcludeCount*sizeof(LONG), NULL);
  167. for (i = 0; i < pcomp->ExcludeCount; i++) {
  168. dprintf("\t ExcludeStringIds #%d: 0x%08x\n", i, count[i]);
  169. if (CheckInterupted()) {
  170. return;
  171. }
  172. }
  173. free(count);
  174. }
  175. dprintf( "\t ExcludedByCount:\t%d\n", pcomp->ExcludedByCount );
  176. count = malloc ( pcomp->ExcludedByCount * sizeof(LONG) );
  177. if (count) {
  178. // read and dump Excludes list
  179. ReadMemory((DWORD_PTR) pcomp->ExcludedByStringIds, count, pcomp->ExcludedByCount*sizeof(LONG), NULL);
  180. for (i = 0; i < pcomp->ExcludedByCount; i++) {
  181. dprintf("\t ExcludesStringIds #%d:\t0x%08x\n", i, count[i]);
  182. if (CheckInterupted()) {
  183. return;
  184. }
  185. }
  186. free(count);
  187. }
  188. dprintf( "\t InternalFlags:\t\t0x%08x\n", pcomp->InternalFlags );
  189. dprintf( "\t SizeApproximation:\t0x%08x\n", pcomp->SizeApproximation );
  190. dprintf( "\t IconIndex:\t\t0x%08x\n", pcomp->IconIndex );
  191. dprintf( "\t IconDll:\t\t%ws\n", pcomp->IconDll);
  192. dprintf( "\t IconResource:\t\t%ws\n", pcomp->IconResource);
  193. dprintf( "\t SelectionState:\t0x%08x\n", pcomp->SelectionState );
  194. dprintf( "\t OriginalSelectionState:0x%08x\n", pcomp->OriginalSelectionState );
  195. dprintf( "\t InstalledState:\t0x%08x\n", pcomp->InstalledState );
  196. dprintf( "\t ModeBits:\t\t0x%08x\n", pcomp->ModeBits );
  197. dprintf( "\t Description:\t\t%ws\n", pcomp->Description );
  198. dprintf( "\t Tip:\t\t\t%ws\n", pcomp->Tip );
  199. dprintf( "\t InstallationDllName:\t%ws\n", pcomp->InstallationDllName );
  200. dprintf( "\t InterfaceFunctionName:\t%s\n", pcomp->InterfaceFunctionName );
  201. dprintf( "\t InstallationDll:\t0x%08x\n", pcomp->InstallationDll );
  202. //dprintf( "\t InstallationRoutine:\t%s\n", pcomp->InstallationRoutine );
  203. dprintf( "\t ExpectedVersion:\t0x%08x\n", pcomp->ExpectedVersion );
  204. dprintf( "\t Exists:\t\t0x%08x\n", pcomp->Exists );
  205. dprintf( "\t Flags:\t\t\t0x%08x\n\n\n", pcomp->Flags );
  206. }
  207. PVOID
  208. GetStringTableData(
  209. PSTRING_TABLE st
  210. )
  211. {
  212. LPVOID stdata;
  213. stdata = (PVOID) malloc( st->DataSize );
  214. if (!stdata) {
  215. dprintf("error allocation memory (size 0x%08x\n", (ULONG_PTR) st->DataSize);
  216. return NULL;
  217. }
  218. try {
  219. ReadMemory((DWORD_PTR) st->Data, stdata, st->DataSize, NULL);
  220. } except (EXCEPTION_EXECUTE_HANDLER) {
  221. free( stdata );
  222. return NULL;
  223. }
  224. return stdata;
  225. }
  226. PVOID
  227. GetStringNodeExtraData(
  228. PSTRING_NODEW node
  229. )
  230. {
  231. PVOID extraData;
  232. extraData = node->String + wcslen(node->String) + 1;
  233. return extraData;
  234. }
  235. PSTRING_NODEW
  236. GetNextNode(
  237. PVOID stdata,
  238. PSTRING_NODEW node,
  239. PULONG_PTR offset
  240. )
  241. {
  242. PVOID next;
  243. if (node->NextOffset == -1) {
  244. *offset = 0;
  245. return NULL;
  246. }
  247. next = (PSTRING_NODEW)((LPBYTE)stdata + node->NextOffset);
  248. *offset = node->NextOffset;
  249. return next;
  250. }
  251. PSTRING_NODEW
  252. GetFirstNode(
  253. PVOID stdata,
  254. ULONG_PTR offset,
  255. PULONG_PTR poffset
  256. )
  257. {
  258. PSTRING_NODEW node;
  259. if (offset == -1) {
  260. return NULL;
  261. }
  262. node = (PSTRING_NODEW) ((LPBYTE)stdata + offset);
  263. *poffset = offset;
  264. return node;
  265. }
  266. LPCSTR
  267. GetWizPage(
  268. DWORD i
  269. )
  270. {
  271. LPCSTR WizPage[] = {
  272. "WizPagesWelcome", // welcome page
  273. "WizPagesMode", // setup mode page
  274. "WizPagesEarly", // pages that come after the mode page and before prenet pages
  275. "WizPagesPrenet", // pages that come before network setup
  276. "WizPagesPostnet", // pages that come after network setup
  277. "WizPagesLate", // pages that come after postnet pages and before the final page
  278. "WizPagesFinal", // final page
  279. "WizPagesTypeMax"
  280. };
  281. return WizPage[i];
  282. }
  283. DECLARE_API( st )
  284. /*++
  285. Routine Description:
  286. This debugger extension dumps a string table at the address specified.
  287. Arguments:
  288. Return Value:
  289. --*/
  290. {
  291. DWORD ReturnLength;
  292. PVOID pst;
  293. STRING_TABLE st;
  294. DWORD i;
  295. DWORD_PTR offset;
  296. PVOID stdata,pextradata;
  297. PSTRING_NODEW node;//, prev;
  298. INIT_API();
  299. while (*lpArgumentString == ' ') {
  300. lpArgumentString++;
  301. }
  302. pst = (PVOID)GetExpression( lpArgumentString );
  303. move( st, pst );
  304. dprintf("Base String Table Address:\t0x%p\n", pst);
  305. DumpStringTableHeader( &st );
  306. stdata = GetStringTableData( &st );
  307. if (!stdata) {
  308. dprintf("error retrieving string table data!\n");
  309. return;
  310. }
  311. //
  312. // now, dump each node in the string table
  313. //
  314. for (i = 0; i<HASH_BUCKET_COUNT; i++ ) {
  315. node = GetFirstNode(stdata, ((PULONG_PTR)stdata)[i], &offset );
  316. if (!node) {
  317. // dprintf("No data at hash bucket %d\n", i);
  318. } else {
  319. dprintf("Data at hash bucket %d\n", i);
  320. while (node) {
  321. dprintf("\tEntry Name:\t%ws (0x%08x)\n", node->String, offset);
  322. pextradata = st.Data + offset + (wcslen(node->String) + 1)*sizeof(WCHAR) + sizeof(DWORD);
  323. dprintf("\tExtra Data:\t0x%08x\n", pextradata );
  324. //((LPBYTE)node->String + wcslen(node->String) + 1));
  325. node = GetNextNode( stdata, node, &offset );
  326. if (CheckInterupted()) {
  327. return;
  328. }
  329. }
  330. }
  331. }
  332. free( stdata );
  333. }
  334. DECLARE_API( stfind )
  335. /*++
  336. Routine Description:
  337. This debugger extension dumps the data for a given string table number
  338. Arguments:
  339. Return Value:
  340. --*/
  341. {
  342. DWORD ReturnLength;
  343. PVOID pst;
  344. STRING_TABLE st;
  345. DWORD i;
  346. DWORD_PTR offset;
  347. PVOID stdata,pextradata;
  348. PSTRING_NODEW node;//, prev;
  349. DWORD_PTR element;
  350. INIT_API();
  351. while (*lpArgumentString == ' ') {
  352. lpArgumentString++;
  353. }
  354. pst = (PVOID)GetExpression( lpArgumentString );
  355. while (*lpArgumentString && (*lpArgumentString != ' ') ) {
  356. lpArgumentString++;
  357. }
  358. while (*lpArgumentString == ' ') {
  359. lpArgumentString++;
  360. }
  361. if (*lpArgumentString) {
  362. element = GetExpression( lpArgumentString );
  363. } else {
  364. dprintf("bogus usage\n");
  365. }
  366. move( st, pst );
  367. stdata = GetStringTableData( &st );
  368. if (!stdata) {
  369. dprintf("error retrieving string table data!\n");
  370. return;
  371. }
  372. //
  373. // search each node in the string table
  374. //
  375. for (i = 0; i<HASH_BUCKET_COUNT; i++ ) {
  376. node = GetFirstNode(stdata, ((PULONG_PTR)stdata)[i], &offset );
  377. if (!node) {
  378. } else {
  379. while (node) {
  380. if (element == offset) {
  381. dprintf("\tEntry Name:\t%ws (0x%08x)\n", node->String, offset);
  382. pextradata = st.Data + offset + (wcslen(node->String) + 1)*sizeof(WCHAR) + sizeof(DWORD);
  383. dprintf("\tExtra Data:\t0x%08x\n", pextradata );
  384. free( stdata );
  385. return;
  386. }
  387. node = GetNextNode( stdata, node, &offset );
  388. if (CheckInterupted()) {
  389. return;
  390. }
  391. }
  392. }
  393. }
  394. free( stdata );
  395. dprintf("Couldn't find element\n");
  396. }
  397. DECLARE_API( ocm )
  398. /*++
  399. Routine Description:
  400. This debugger extension dumps an OC_MANAGER (UNICODE!) structure at the specified address
  401. Arguments:
  402. Return Value:
  403. --*/
  404. {
  405. DWORD ReturnLength;
  406. deb_OC_MANAGERW ocm;
  407. PVOID pocm;
  408. DWORD i;
  409. DWORD_PTR offset;
  410. STRING_TABLE inftable,comptable;
  411. PVOID infdata,compdata;
  412. PSTRING_NODEW node;
  413. POC_INF pocinf;
  414. deb_POPTIONAL_COMPONENTW pcomp;
  415. DWORD Mask = 0;
  416. PLONG count;
  417. INIT_API();
  418. while (*lpArgumentString == ' ') {
  419. lpArgumentString++;
  420. }
  421. pocm = (PVOID)GetExpression( lpArgumentString );
  422. while (*lpArgumentString && (*lpArgumentString != ' ') ) {
  423. lpArgumentString++;
  424. }
  425. while (*lpArgumentString == ' ') {
  426. lpArgumentString++;
  427. }
  428. if (*lpArgumentString) {
  429. Mask = (DWORD)GetExpression( lpArgumentString );
  430. }
  431. move( ocm,(LPVOID)pocm);
  432. //
  433. // dump the OCM structure
  434. //
  435. dprintf("OC_MANAGER structure at Address:\t0x%08x\n", (ULONG_PTR) pocm);
  436. dprintf("\tCallbacks :\n");
  437. dprintf("\t\tFillInSetupDataA:\t0x%08x\n", (ULONG_PTR) ocm.Callbacks.FillInSetupDataA);
  438. dprintf("\t\tLogError:\t\t0x%08x\n", (ULONG_PTR) ocm.Callbacks.LogError);
  439. dprintf("\t\tSetReboot:\t\t0x%08x\n", (ULONG_PTR) ocm.Callbacks.SetReboot);
  440. dprintf("\t\tFillInSetupDataW:\t0x%08x\n", (ULONG_PTR) ocm.Callbacks.FillInSetupDataW);
  441. dprintf("\tMasterOcInf:\t\t0x%08x\n", ocm.MasterOcInf);
  442. dprintf("\tUnattendedInf:\t\t0x%08x\n", ocm.UnattendedInf);
  443. dprintf("\tMasterOcInfPath:\t%ws\n", ocm.MasterOcInfPath);
  444. dprintf("\tUnattendInfPath:\t%ws\n", ocm.UnattendedInfPath);
  445. dprintf("\tSourceDir:\t\t%ws\n", ocm.SourceDir);
  446. dprintf("\tSuiteName:\t\t%ws\n", ocm.SuiteName);
  447. dprintf("\tSetupPageTitle:\t\t%ws\n", ocm.SetupPageTitle);
  448. dprintf("\tWindowTitle:\t%ws\n", ocm.WindowTitle);
  449. dprintf("\tInfListStringTable:\t0x%08x\n", (ULONG_PTR)ocm.InfListStringTable);
  450. dprintf("\tComponentStringTable:\t0x%08x\n", (ULONG_PTR)ocm.ComponentStringTable);
  451. dprintf("\tComponentStringTable:\t0x%08x\n", (ULONG_PTR)ocm.OcSetupPage);
  452. dprintf("\tSetupMode:\t\t%d\n", ocm.SetupMode);
  453. dprintf("\tTopLevelOcCount:\t%d\n", ocm.TopLevelOcCount);
  454. // Issue-vijeshs-09/18/2000: from 1 to count
  455. count = malloc ( ocm.TopLevelOcCount * sizeof(LONG) );
  456. if (count) {
  457. // read and dump needs list
  458. ReadMemory((LPVOID) ocm.TopLevelOcStringIds, count, ocm.TopLevelOcCount *sizeof(LONG), NULL);
  459. for (i = 0; i < ocm.TopLevelOcCount; i++) {
  460. dprintf("\t TopLevelOcStringIds #%d:\t0x%08x\n", i, count[i]);
  461. if (CheckInterupted()) {
  462. return;
  463. }
  464. }
  465. free(count);
  466. }
  467. dprintf("\tTopLevelParenOcCount:\t%d\n", ocm.TopLevelParentOcCount);
  468. count = malloc ( ocm.TopLevelParentOcCount * sizeof(LONG) );
  469. if (count) {
  470. // read and dump needs list
  471. ReadMemory((LPVOID) ocm.TopLevelParentOcStringIds, count, ocm.TopLevelParentOcCount *sizeof(LONG), NULL);
  472. for (i = 0; i < ocm.TopLevelParentOcCount; i++) {
  473. dprintf("\t TopLevelParentOcStringIds #%d:\t0x%08x\n", i, count[i]);
  474. if (CheckInterupted()) {
  475. return;
  476. }
  477. }
  478. free(count);
  479. }
  480. dprintf("\tSubComponentsPresent:\t%d\n", ocm.SubComponentsPresent);
  481. //
  482. // Issue-vijeshs-09/18/2000:WizardPagesOrder there's not really any way to tell the exact upper bound of
  483. // each array, though we know that it's <= TopLevelParentOcCount...since this is the case
  484. // we just dump the point to each array of pages...
  485. //
  486. for (i = 0; i < WizPagesTypeMax; i++) {
  487. dprintf("\tWizardPagesOrder[%i] (%s)\t: 0x%08x\n",
  488. i,
  489. GetWizPage(i),
  490. ocm.WizardPagesOrder[i] );
  491. if (CheckInterupted()) {
  492. return;
  493. }
  494. }
  495. dprintf("\tPrivateDataSubkey:\t%ws\n", ocm.PrivateDataSubkey);
  496. dprintf("\thKeyPrivateData:\t0x%08x\n", ocm.hKeyPrivateData);
  497. dprintf("\thKeyPrivateDataRoot:\t0x%08x\n", ocm.hKeyPrivateDataRoot);
  498. dprintf("\tProgressTextWindow:\t0x%08x\n", ocm.ProgressTextWindow);
  499. dprintf("\tCurrentComponentStringId:\t0x%08x\n", ocm.CurrentComponentStringId);
  500. dprintf("\tAbortedCount:\t\t%d\n", ocm.AbortedCount);
  501. count = malloc ( ocm.AbortedCount * sizeof(LONG) );
  502. if (count) {
  503. // read and dump needs list
  504. ReadMemory((LPVOID) ocm.AbortedComponentIds, count, ocm.AbortedCount *sizeof(LONG), NULL);
  505. for (i = 0; i < (DWORD)ocm.AbortedCount; i++) {
  506. dprintf("\t AbortedComponentIds #%d:\t0x%08x\n", i, count[i]);
  507. if (CheckInterupted()) {
  508. return;
  509. }
  510. }
  511. free(count);
  512. }
  513. dprintf("\tInternalFlags:\t\t0x%08x\n\n\n", ocm.InternalFlags);
  514. dprintf("\tSetupData.SetupMode :\t0x%08x\n", ocm.SetupData.SetupMode );
  515. dprintf("\tSetupData.ProductType :\t0x%08x\n", ocm.SetupData.ProductType );
  516. dprintf("\tSetupData.OperationFlags :\t0x%08x\n", ocm.SetupData.OperationFlags );
  517. dprintf("\tSetupData.SourcePath :\t%ws\n", ocm.SetupData.SourcePath );
  518. dprintf("\tSetupData.UnattendFile :\t%ws\n", ocm.SetupData.UnattendFile );
  519. if ((Mask&1) && ocm.InfListStringTable) {
  520. dprintf("\t\t***InfListStringTable***\n");
  521. move (inftable, ocm.InfListStringTable);
  522. infdata = GetStringTableData( &inftable );
  523. if (!infdata) {
  524. dprintf("error retrieving string table data!\n");
  525. return;
  526. }
  527. // now, dump each node with data in the string table
  528. for (i = 0; i<HASH_BUCKET_COUNT; i++ ) {
  529. node = GetFirstNode(infdata, ((PULONG_PTR)infdata)[i], &offset );
  530. if (!node) {
  531. // dprintf("No data at hash bucket %d\n", i);
  532. } else {
  533. //dprintf("Data at hash bucket %d\n", i);
  534. while (node) {
  535. //dprintf("\tNode Name:%ws\n", node->String);
  536. pocinf = (POC_INF) GetStringNodeExtraData( node );
  537. if (pocinf) {
  538. dprintf("\tNode Data for %ws (0x%08x): 0x%08x\n",
  539. node->String,
  540. offset,
  541. pocinf->Handle
  542. );
  543. } else {
  544. dprintf("\tNo Node Data for %ws\n",
  545. node->String
  546. );
  547. }
  548. node = GetNextNode( infdata, node, &offset );
  549. if (CheckInterupted()) {
  550. return;
  551. }
  552. }
  553. }
  554. }
  555. free( infdata );
  556. dprintf("\n\n");
  557. }
  558. if ((Mask&1) && ocm.ComponentStringTable) {
  559. dprintf("\t\t***ComponentStringTable***\n");
  560. move (comptable, ocm.ComponentStringTable);
  561. compdata = GetStringTableData( &comptable );
  562. if (!compdata) {
  563. dprintf("error retrieving string table data!\n");
  564. return;
  565. }
  566. //
  567. // dump each node with data in the string table
  568. //
  569. for (i = 0; i<HASH_BUCKET_COUNT; i++ ) {
  570. node = GetFirstNode(infdata, ((PULONG_PTR)infdata)[i], &offset );
  571. if (!node) {
  572. // dprintf("No data at hash bucket %d\n", i);
  573. } else {
  574. //dprintf("Data at hash bucket %d\n", i);
  575. while (node) {
  576. //dprintf("\tNode Name:%ws\n", node->String);
  577. pcomp = (deb_POPTIONAL_COMPONENTW) GetStringNodeExtraData( node );
  578. if (pcomp) {
  579. DumpOcComponent( offset , node, pcomp );
  580. } else {
  581. dprintf("\tNo Node Data for %ws\n",
  582. node->String
  583. );
  584. }
  585. if (CheckInterupted()) {
  586. return;
  587. }
  588. node = GetNextNode( infdata, node, &offset );
  589. }
  590. }
  591. }
  592. free( compdata );
  593. }
  594. }