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.

1114 lines
29 KiB

  1. #include "pch.h"
  2. HANDLE g_hHeap;
  3. HINSTANCE g_hInst;
  4. #ifndef DEBUG
  5. #error MemDbt must be built with DEBUG defined
  6. #endif
  7. #define ONEBITSET(x) ((x) && !((x) & ((x) - 1)))
  8. typedef BOOL (WINAPI INITROUTINE_PROTOTYPE)(HINSTANCE, DWORD, LPVOID);
  9. INITROUTINE_PROTOTYPE MigUtil_Entry;
  10. INITROUTINE_PROTOTYPE MemDb_Entry;
  11. INITROUTINE_PROTOTYPE FileEnum_Entry;
  12. typedef struct {
  13. DWORD Bit;
  14. PCSTR Name;
  15. } PROPNAME, *PPROPNAME;
  16. #define DEFMAC(opbit,name,memdbname,prop_ct) {opbit,#name},
  17. PROPNAME g_PropNames[] = {
  18. PATH_OPERATIONS /* , */
  19. {0, NULL}
  20. };
  21. VOID
  22. HelpAndExit (
  23. VOID
  24. )
  25. {
  26. printf ("Brief Help:\n\n"
  27. "/A All values (or export as ANSI)\n"
  28. "/C Check internal consistency of memdb.\n"
  29. "/D:<n> Enumeration depth\n"
  30. "/E Dump file operation reference help.\n"
  31. "/E:<n> List all files in operation n.\n"
  32. "/ER:<r> Specifies export root\n"
  33. "/EF:<f> Specifies export file\n"
  34. "/F Find keys that have values equal to <value>\n"
  35. "/I Import an exported file\n"
  36. "/L:<f> List operations for file f\n"
  37. "/N GetFileStatusOnNt for <value>\n"
  38. "/NP GetFilePathOnNt for <value>\n"
  39. "/O List offsets in enumeration.\n"
  40. "/O:<n> Display key at offset n.\n"
  41. "/P:<p> Search pattern is p.\n"
  42. "/S Start level for enumeration.\n"
  43. "\n"
  44. "/?? Full Help\n"
  45. );
  46. exit(1);
  47. }
  48. VOID
  49. FullHelpAndExit (
  50. VOID
  51. )
  52. {
  53. printf ("Command line syntax:\n\n"
  54. "memdbt [file] [/P:pattern] [/D:depth] [/A] [/Z] [/H] [/K]\n"
  55. " [/F[U|A|O]:<value>] [/O]\n"
  56. "memdbt [file] /T\n"
  57. "memdbt [file] /O:<n> [/Z] [/K]\n"
  58. "memdbt [file] /G:<key> [/Z] [/K]\n"
  59. "memdbt [file] /C [/P:pattern]\n"
  60. "memdbt [file] /$\n"
  61. "memdbt [file] /[B|X]:<root1>,<root2> [/D:depth] [/A] [/Z] [/H] [/K]\n"
  62. "memdbt [file] /L:<9x_file>\n"
  63. "memdbt [file] /E:<fileop>\n"
  64. "memdbt [file] /N[P]:<path>\n"
  65. "memdbt [file] /ER:<root> /EF:<file> [/A]\n"
  66. "memdbt /I:<filename> [file to update]\n"
  67. "\n"
  68. "/A If specified, all levels are enumerated, including those\n"
  69. " that are not endpoints. If specified with /EX, export is\n"
  70. " saved in ANSI format."
  71. "/B Show keys in both <root1> and <root2>\n"
  72. "/C Check internal consistency of memdb.\n"
  73. "/D Specifies how many levels in the database to enumarate.\n"
  74. " If 0 (or not specified), all levels are enumarated.\n"
  75. "/E If <n> is specified, enumerates all entries in fileop.\n"
  76. " fileop is a numeric value.\n"
  77. " If <n> is not specified, lists all operation names with vals\n"
  78. "/ER Specifies root key to export\n"
  79. "/EF Specifies export output file\n"
  80. "/F Find keys that have values equal to <value>\n"
  81. "/FU Find keys that have user flags equal to <value>\n"
  82. "/FA Find keys that have user flags set to <value>\n"
  83. "/FO Find keys that have user flags not set to <value>\n"
  84. "/G MemDbGetValue <key>\n"
  85. "/H Hide binary dump\n"
  86. "/I Import an exported file\n"
  87. "/K Show only keys, not values or user flags.\n"
  88. "/L List operations for 9x_file\n"
  89. "/N GetFileStatusOnNt for <value>\n"
  90. "/NP GetFilePathOnNt for <value>\n"
  91. "/O If <n> is specified, dumps key at offset <n>\n"
  92. " If <n> is not specified, displays offset for each key\n"
  93. "/P Specifies the search pattern for enumaration, and can\n"
  94. " include a starting path (i.e. HKLM\\*)\n"
  95. "/S Specifies the starting level (the minimum number of levels\n"
  96. " before an entry is displayed). Must be less than /D option\n"
  97. " when a non-zero value is specified for /D. If not specified,\n"
  98. " all levels are displayed.\n"
  99. "/V Displays version of ntsetup.dat.\n"
  100. "/X Show keys in <root1> but not in <root2>\n"
  101. "/Z Show zero values (default is to show only non-zero values)\n"
  102. "/$ Dump the hash table\n"
  103. );
  104. exit(1);
  105. }
  106. VOID
  107. DumpData (
  108. BYTE const * Data,
  109. DWORD Count
  110. );
  111. DWORD
  112. pGetValue (
  113. IN PCSTR Arg
  114. )
  115. {
  116. INT Base = 10;
  117. PCSTR p;
  118. DWORD Value;
  119. if (Arg[0] == '0' && tolower (Arg[1]) == 'x') {
  120. Base = 16;
  121. } else {
  122. p = GetEndOfStringA (Arg);
  123. if (p > Arg) {
  124. p--;
  125. if (tolower (*p) == 'h') {
  126. Base = 16;
  127. }
  128. }
  129. }
  130. Value = strtoul (Arg, NULL, Base);
  131. return Value;
  132. }
  133. INT
  134. __cdecl
  135. main (
  136. INT argc,
  137. CHAR *argv[]
  138. )
  139. {
  140. MEMDB_ENUMA e;
  141. CHAR *szDepth;
  142. INT nDepth;
  143. INT nStartDepth;
  144. CHAR *szPattern;
  145. BOOL bNodesOnly = TRUE;
  146. CHAR *FileSpec;
  147. INT i;
  148. INT j;
  149. MEMDB_VERSION Version;
  150. DWORD dwReason = DLL_PROCESS_ATTACH;
  151. BOOL ShowZVals = FALSE;
  152. BOOL HideDump = FALSE;
  153. PCSTR NumericalArg;
  154. BOOL Offset = FALSE;
  155. DWORD OffsetVal;
  156. CHAR Key[MEMDB_MAX];
  157. DWORD RetVal;
  158. DWORD Flags;
  159. BOOL GetVal = FALSE;
  160. PCSTR GetValStr;
  161. BOOL Check = FALSE;
  162. PSTR p;
  163. BOOL KeysOnly = FALSE;
  164. PSTR DiffRootA = NULL;
  165. PSTR DiffRootB = NULL;
  166. BOOL DiffNot = FALSE;
  167. CHAR RootBuf[MEMDB_MAX * 2];
  168. CHAR RootPattern[MEMDB_MAX];
  169. CHAR CompareNode[MEMDB_MAX];
  170. BOOL Match;
  171. BOOL DumpHashTable = FALSE;
  172. BOOL DumpVersion = FALSE;
  173. HASHENUM HashEnum;
  174. BOOL FindValue = FALSE;
  175. DWORD ValueToFind;
  176. BOOL DisplayOffset = FALSE;
  177. BOOL UserFlags = FALSE;
  178. BOOL AndFlags = FALSE;
  179. BOOL NandFlags = FALSE;
  180. PCSTR ExportRoot = NULL;
  181. PCSTR ExportFile = NULL;
  182. PCSTR File9x = NULL;
  183. BOOL ListFileOps = FALSE;
  184. ALL_FILEOPS_ENUM FileOpEnum;
  185. FILEOP_ENUM eOp;
  186. FILEOP_PROP_ENUM eOpProp;
  187. OPERATION LastOperation;
  188. DWORD EnumOperation = 0;
  189. PCSTR ImportFile = NULL;
  190. BOOL AnsiFormat = FALSE;
  191. PCSTR FileStatusValue = NULL;
  192. BOOL FilePathWithStatus = FALSE;
  193. DWORD Status;
  194. //
  195. // Init
  196. //
  197. SuppressAllLogPopups (TRUE);
  198. g_hHeap = GetProcessHeap();
  199. g_hInst = GetModuleHandle(NULL);
  200. if (!MigUtil_Entry (g_hInst, dwReason, NULL)) {
  201. fprintf (stderr, "MigUtil could not init\n");
  202. return FALSE;
  203. }
  204. if (!MemDb_Entry (g_hInst, dwReason, NULL)) {
  205. fprintf (stderr, "MemDb could not init\n");
  206. return FALSE;
  207. }
  208. FileSpec = NULL;
  209. szPattern = "*";
  210. nDepth = 0;
  211. nStartDepth = 0;
  212. for (i = 1 ; i < argc ; i++) {
  213. if (argv[i][0] == '-' || argv[i][0] == '/') {
  214. switch (tolower (argv[i][1])) {
  215. case '?':
  216. if (argv[i][2] == '?') {
  217. FullHelpAndExit();
  218. }
  219. HelpAndExit();
  220. break;
  221. case '$':
  222. if (argv[i][2]) {
  223. HelpAndExit();
  224. }
  225. if (DumpHashTable) {
  226. HelpAndExit();
  227. }
  228. DumpHashTable = TRUE;
  229. break;
  230. case 'i':
  231. if (ImportFile) {
  232. HelpAndExit();
  233. }
  234. if (argv[i][2] == ':') {
  235. ImportFile = &argv[i][3];
  236. } else {
  237. i++;
  238. if (i < argc) {
  239. ImportFile = argv[i];
  240. } else {
  241. HelpAndExit();
  242. }
  243. }
  244. break;
  245. case 'k':
  246. if (argv[i][2]) {
  247. HelpAndExit();
  248. }
  249. if (KeysOnly) {
  250. HelpAndExit();
  251. }
  252. KeysOnly = TRUE;
  253. break;
  254. case 'l':
  255. if (ListFileOps) {
  256. HelpAndExit();
  257. }
  258. ListFileOps = TRUE;
  259. if (argv[i][2] == ':') {
  260. File9x = &argv[i][3];
  261. } else {
  262. i++;
  263. if (i < argc) {
  264. File9x = argv[i];
  265. } else {
  266. HelpAndExit();
  267. }
  268. }
  269. break;
  270. case 'n':
  271. if (FileStatusValue) {
  272. HelpAndExit();
  273. }
  274. if (tolower (argv[i][2]) == 'p') {
  275. p = &argv[i][3];
  276. FilePathWithStatus = TRUE;
  277. } else {
  278. p = &argv[i][2];
  279. }
  280. if (*p == ':') {
  281. FileStatusValue = p + 1;
  282. } else {
  283. i++;
  284. if (i < argc) {
  285. FileStatusValue = argv[i];
  286. } else {
  287. HelpAndExit();
  288. }
  289. }
  290. break;
  291. case 'p':
  292. if (DiffRootA) {
  293. HelpAndExit();
  294. }
  295. if (argv[i][2] == ':') {
  296. szPattern = &argv[i][3];
  297. } else {
  298. i++;
  299. if (i < argc) {
  300. szPattern = argv[i];
  301. } else {
  302. HelpAndExit();
  303. }
  304. }
  305. break;
  306. case 'd':
  307. if (argv[i][2] == ':') {
  308. szDepth = &argv[i][3];
  309. } else {
  310. i++;
  311. if (i < argc) {
  312. szDepth = argv[i];
  313. } else {
  314. HelpAndExit();
  315. }
  316. }
  317. nDepth = pGetValue (szDepth);
  318. break;
  319. case 's':
  320. if (argv[i][2] == ':') {
  321. szDepth = &argv[i][3];
  322. } else {
  323. i++;
  324. if (i < argc) {
  325. szDepth = argv[i];
  326. } else {
  327. HelpAndExit();
  328. }
  329. }
  330. nStartDepth = pGetValue (szDepth);
  331. break;
  332. case 'x':
  333. DiffNot = TRUE;
  334. // fall through
  335. case 'b':
  336. if (DiffRootA) {
  337. HelpAndExit();
  338. }
  339. if (argv[i][2] != ':') {
  340. HelpAndExit();
  341. }
  342. StringCopy (RootBuf, &argv[i][3]);
  343. DiffRootA = RootBuf;
  344. DiffRootB = _mbschr (DiffRootA, ',');
  345. if (!DiffRootB) {
  346. HelpAndExit();
  347. }
  348. *DiffRootB = 0;
  349. DiffRootB++;
  350. while (*DiffRootB == ' ') {
  351. DiffRootB++;
  352. }
  353. StringCopy (RootPattern, DiffRootA);
  354. StringCopy (AppendWackA (RootPattern), "*");
  355. szPattern = RootPattern;
  356. break;
  357. case 'a':
  358. if (!bNodesOnly) {
  359. HelpAndExit();
  360. }
  361. if (argv[i][2]) {
  362. HelpAndExit();
  363. }
  364. bNodesOnly = FALSE;
  365. break;
  366. case 'o':
  367. if (Offset || DisplayOffset) {
  368. HelpAndExit();
  369. }
  370. if (argv[i][2] == ':') {
  371. OffsetVal = pGetValue (&argv[i][3]);
  372. Offset = TRUE;
  373. } else {
  374. DisplayOffset = TRUE;
  375. }
  376. break;
  377. case 'e':
  378. if (tolower (argv[i][2]) == 'r') {
  379. if (ExportRoot) {
  380. HelpAndExit();
  381. }
  382. if (argv[i][3] == ':') {
  383. ExportRoot = &argv[i][4];
  384. } else {
  385. i++;
  386. if (i < argc) {
  387. ExportRoot = argv[i];
  388. } else {
  389. HelpAndExit();
  390. }
  391. }
  392. break;
  393. }
  394. if (tolower (argv[i][2]) == 'f') {
  395. if (ExportFile) {
  396. HelpAndExit();
  397. }
  398. if (argv[i][3] == ':') {
  399. ExportFile = &argv[i][4];
  400. } else {
  401. i++;
  402. if (i < argc) {
  403. ExportFile = argv[i];
  404. } else {
  405. HelpAndExit();
  406. }
  407. }
  408. break;
  409. }
  410. if (EnumOperation) {
  411. HelpAndExit();
  412. }
  413. if (argv[i][2] == ':') {
  414. for (j = 0 ; g_PropNames[j].Bit ; j++) {
  415. if (StringIMatch (&argv[i][3], g_PropNames[j].Name)) {
  416. EnumOperation = g_PropNames[j].Bit;
  417. break;
  418. }
  419. }
  420. if (!g_PropNames[j].Bit) {
  421. EnumOperation = pGetValue (&argv[i][3]);
  422. }
  423. } else {
  424. printf ("Operations:\n\n");
  425. for (j = 0 ; g_PropNames[j].Bit ; j++) {
  426. printf (" 0x%06X: %s\n", g_PropNames[j].Bit, g_PropNames[j].Name);
  427. }
  428. return 0;
  429. }
  430. if (!ONEBITSET (EnumOperation)) {
  431. HelpAndExit();
  432. }
  433. break;
  434. case 'f':
  435. if (FindValue) {
  436. HelpAndExit();
  437. }
  438. FindValue = TRUE;
  439. NumericalArg = &argv[i][2];
  440. switch (tolower (*NumericalArg)) {
  441. case 'o':
  442. NandFlags = TRUE;
  443. NumericalArg++;
  444. break;
  445. case 'a':
  446. AndFlags = TRUE;
  447. NumericalArg++;
  448. break;
  449. case 'u':
  450. UserFlags = TRUE;
  451. NumericalArg++;
  452. break;
  453. }
  454. if (*NumericalArg == ':') {
  455. NumericalArg++;
  456. } else {
  457. i++;
  458. if (i < argc) {
  459. NumericalArg = argv[i];
  460. } else {
  461. HelpAndExit();
  462. }
  463. }
  464. ValueToFind = pGetValue (NumericalArg);
  465. break;
  466. case 'z':
  467. if (argv[i][2]) {
  468. HelpAndExit();
  469. }
  470. if (ShowZVals) {
  471. HelpAndExit();
  472. }
  473. ShowZVals = TRUE;
  474. break;
  475. case 'h':
  476. if (argv[i][2]) {
  477. HelpAndExit();
  478. }
  479. if (HideDump) {
  480. HelpAndExit();
  481. }
  482. HideDump = TRUE;
  483. break;
  484. case 'c':
  485. if (argv[i][2]) {
  486. HelpAndExit();
  487. }
  488. if (Check) {
  489. HelpAndExit();
  490. }
  491. Check = TRUE;
  492. break;
  493. case 'g':
  494. if (GetVal) {
  495. HelpAndExit();
  496. }
  497. GetVal = TRUE;
  498. if (argv[i][2] == ':') {
  499. GetValStr = &argv[i][3];
  500. } else {
  501. i++;
  502. if (i < argc) {
  503. GetValStr = argv[i];
  504. } else {
  505. HelpAndExit();
  506. }
  507. }
  508. break;
  509. case 'v':
  510. if (argv[i][2]) {
  511. HelpAndExit();
  512. }
  513. if (DumpVersion) {
  514. HelpAndExit();
  515. }
  516. DumpVersion = TRUE;
  517. break;
  518. default:
  519. HelpAndExit();
  520. }
  521. } else {
  522. if (FileSpec) {
  523. HelpAndExit();
  524. }
  525. FileSpec = argv[i];
  526. }
  527. }
  528. if (!FileSpec) {
  529. if (ImportFile) {
  530. FileSpec = "";
  531. } else {
  532. FileSpec = "ntsetup.dat";
  533. }
  534. }
  535. if (nDepth < nStartDepth)
  536. HelpAndExit();
  537. if (!DumpVersion && !MemDbLoad(FileSpec) && !ImportFile) {
  538. fprintf(stderr, "MemDbLoad failed. Error: %d\n", GetLastError());
  539. return 0;
  540. }
  541. if (ExportRoot) {
  542. AnsiFormat = !bNodesOnly;
  543. }
  544. //
  545. // Validate combinations
  546. //
  547. // Mutually exclusive options, only one can be TRUE:
  548. if ((
  549. (EnumOperation != 0) +
  550. ListFileOps +
  551. DumpVersion +
  552. Offset +
  553. FindValue +
  554. GetVal +
  555. DumpHashTable +
  556. Check +
  557. (ImportFile != NULL) +
  558. (ExportRoot != NULL) +
  559. (FileStatusValue != NULL)
  560. ) > 1) {
  561. HelpAndExit();
  562. }
  563. // Strange combinations
  564. if (DiffRootA && FindValue) {
  565. HelpAndExit();
  566. }
  567. if (!ListFileOps && File9x) {
  568. HelpAndExit();
  569. }
  570. if ((ExportRoot && !ExportFile) ||
  571. (!ExportFile && ExportRoot)
  572. ) {
  573. HelpAndExit();
  574. }
  575. //
  576. // memdbt /n (NT file status)
  577. //
  578. if (FileStatusValue) {
  579. Status = GetFileStatusOnNt (FileStatusValue);
  580. if (Status & FILESTATUS_DELETED) {
  581. printf ("FILESTATUS_DELETED\n");
  582. }
  583. if (Status & FILESTATUS_MOVED) {
  584. printf ("FILESTATUS_MOVED\n");
  585. }
  586. if (Status & FILESTATUS_REPLACED) {
  587. printf ("FILESTATUS_REPLACED\n");
  588. }
  589. if (Status & FILESTATUS_NTINSTALLED) {
  590. printf ("FILESTATUS_NTINSTALLED\n");
  591. }
  592. if (FilePathWithStatus) {
  593. p = GetPathStringOnNt (FileStatusValue);
  594. if (p) {
  595. printf ("\nPath: %s\n\n", p);
  596. FreePathString (p);
  597. } else {
  598. printf ("\nPath: <not found>\n\n");
  599. }
  600. }
  601. return 0;
  602. }
  603. //
  604. // memdbt /i (import)
  605. //
  606. if (ImportFile) {
  607. if (!MemDbImport (ImportFile)) {
  608. fprintf (stderr, "MemDbImport failed for %s. Error: %d\n", ImportFile, GetLastError());
  609. return 0;
  610. }
  611. if (*FileSpec) {
  612. if (!MemDbSave (FileSpec)) {
  613. fprintf (stderr, "MemDbSave failed for %s. Error: %d\n", FileSpec, GetLastError());
  614. return 0;
  615. }
  616. }
  617. return 0;
  618. }
  619. //
  620. // memdbt /x (export)
  621. //
  622. if (ExportRoot) {
  623. if (!MemDbExport (ExportRoot, ExportFile, AnsiFormat)) {
  624. fprintf (stderr, "MemDbExport failed to export %s to %s. Error: %d\n", ExportRoot, FileSpec, GetLastError());
  625. return 0;
  626. }
  627. return 0;
  628. }
  629. //
  630. // memdbt /e (enumerate file ops)
  631. //
  632. if (EnumOperation) {
  633. for (i = 0 ; g_PropNames[i].Bit ; i++) {
  634. if (g_PropNames[i].Bit & EnumOperation) {
  635. printf ("Enumeration of %s (0x%06X)\n", g_PropNames[i].Name, g_PropNames[i].Bit);
  636. break;
  637. }
  638. }
  639. if (!g_PropNames[i].Bit) {
  640. HelpAndExit();
  641. }
  642. if (EnumFirstPathInOperation (&eOp, EnumOperation)) {
  643. i = 0;
  644. do {
  645. if (i) {
  646. printf ("\n");
  647. }
  648. i++;
  649. printf (" %s (seq: %u)\n", eOp.Path, eOp.Sequencer);
  650. if (EnumFirstFileOpProperty (&eOpProp, eOp.Sequencer, EnumOperation)) {
  651. do {
  652. printf (" %s=%s\n", eOpProp.PropertyName, eOpProp.Property);
  653. } while (EnumNextFileOpProperty (&eOpProp));
  654. }
  655. } while (EnumNextPathInOperation (&eOp));
  656. }
  657. return 0;
  658. }
  659. //
  660. // memdbt /l (list file ops)
  661. //
  662. if (ListFileOps) {
  663. //
  664. // Enumerate all the properties
  665. //
  666. if (EnumFirstFileOp (&FileOpEnum, ALL_OPERATIONS, File9x)) {
  667. CompareNode[0] = 0;
  668. do {
  669. if (!StringMatch (CompareNode, FileOpEnum.Path)) {
  670. //
  671. // Begin processing a new path
  672. //
  673. printf ("\n%s:\n", FileOpEnum.Path);
  674. StringCopy (CompareNode, FileOpEnum.Path);
  675. LastOperation = 0;
  676. }
  677. //
  678. // Print the operation name
  679. //
  680. if (LastOperation != FileOpEnum.CurrentOperation) {
  681. LastOperation = FileOpEnum.CurrentOperation;
  682. for (i = 0 ; g_PropNames[i].Bit ; i++) {
  683. if (g_PropNames[i].Bit & FileOpEnum.CurrentOperation) {
  684. printf (" %s (0x%06X)\n", g_PropNames[i].Name, g_PropNames[i].Bit);
  685. break;
  686. }
  687. }
  688. }
  689. //
  690. // Print the property value
  691. //
  692. if (FileOpEnum.PropertyValid) {
  693. printf (" %u: %s\n", FileOpEnum.PropertyNum, FileOpEnum.Property);
  694. }
  695. } while (EnumNextFileOp (&FileOpEnum));
  696. } else {
  697. printf ("%s:\n\n No operations.", File9x);
  698. }
  699. printf ("\n");
  700. return 0;
  701. }
  702. //
  703. // memdbt /v (dump version)
  704. //
  705. if (DumpVersion) {
  706. if (MemDbQueryVersion (FileSpec, &Version)) {
  707. printf (
  708. "Version: %u %s\n"
  709. "Type: %s\n",
  710. Version.Version,
  711. Version.CurrentVersion ? "(same as memdbt)" : "(not the same as memdbt)",
  712. Version.Debug ? "Checked Build" : "Free Build"
  713. );
  714. } else {
  715. fprintf (stderr, "%s is not a valid memdb file\n", FileSpec);
  716. }
  717. return 0;
  718. }
  719. //
  720. // memdbt /o:<offset> usage. (Get Key by offset)
  721. //
  722. if (Offset) {
  723. if (!MemDbBuildKeyFromOffset (OffsetVal, Key, 0, &RetVal)) {
  724. fprintf(stderr, "No key at specified offset.\n");
  725. } else {
  726. printf("%s", Key);
  727. if (RetVal || ShowZVals) {
  728. printf (" = %u (0x%X)", RetVal, RetVal);
  729. }
  730. printf ("\n");
  731. }
  732. return 0;
  733. }
  734. //
  735. // memdbt /g:<key> usage. (Get value of key)
  736. //
  737. if (GetVal) {
  738. if (!MemDbGetValue (GetValStr, &RetVal)) {
  739. fprintf (stderr, "%s does not exist", GetValStr);
  740. } else {
  741. printf ("Value of %s: %u\n", GetValStr, RetVal);
  742. }
  743. return 0;
  744. }
  745. //
  746. // memdbt /$ usage. (Dump hash table)
  747. //
  748. if (DumpHashTable) {
  749. if (EnumFirstHashEntry (&HashEnum)) {
  750. do {
  751. if (!MemDbBuildKeyFromOffset (HashEnum.BucketPtr->Offset, Key, 0, &RetVal)) {
  752. fprintf(stderr, "No key at offset %u.\n", HashEnum.BucketPtr->Offset);
  753. } else {
  754. printf("%s", Key);
  755. if (RetVal || ShowZVals) {
  756. printf (" = %u (0x%X)", RetVal, RetVal);
  757. }
  758. printf ("\n");
  759. }
  760. } while (EnumNextHashEntry (&HashEnum));
  761. }
  762. return 0;
  763. }
  764. //
  765. // memdbt /c usage. (Check consistency)
  766. //
  767. if (Check) {
  768. if (MemDbEnumFirstValue(&e, szPattern, 0, MEMDB_ENDPOINTS_ONLY)) {
  769. BOOL NoProblems = TRUE;
  770. do {
  771. if (!MemDbGetValueAndFlags(e.szName, &RetVal, &Flags)) {
  772. fprintf(stderr, "Error - MemDbGetValueAndFlags failed for %s.\n",e.szName);
  773. NoProblems = FALSE;
  774. }
  775. } while (MemDbEnumNextValue(&e));
  776. if (NoProblems) {
  777. fprintf(stderr, "Memdb consistency check completed. No problems detected.\n");
  778. }
  779. else {
  780. fprintf(stderr, "One or more problems were found during the memdb consistency check.\n");
  781. }
  782. }
  783. else {
  784. fprintf(stderr, "Memdb empty. Nothing to check.\n");
  785. }
  786. return 0;
  787. }
  788. //
  789. // normal usage and comparison option
  790. //
  791. if (MemDbEnumFirstValue (
  792. &e,
  793. szPattern,
  794. nDepth,
  795. bNodesOnly ? MEMDB_ENDPOINTS_ONLY : NO_FLAGS
  796. )) {
  797. do {
  798. //
  799. // Comparison option
  800. //
  801. if (DiffRootA) {
  802. //
  803. // Do a MemDbGetValue
  804. //
  805. StringCopy (CompareNode, DiffRootB);
  806. StringCopy (AppendWack (CompareNode), e.szName);
  807. Match = MemDbGetValue (CompareNode, NULL);
  808. //
  809. // Skip if (A) DiffNot is FALSE and no match
  810. // (B) DiffNot is TRUE and match
  811. //
  812. if (Match == DiffNot) {
  813. continue;
  814. }
  815. }
  816. //
  817. // Normal usage/find value
  818. //
  819. if (e.PosCount >= nStartDepth) {
  820. //
  821. // Find value option
  822. //
  823. if (FindValue) {
  824. if (UserFlags) {
  825. if (e.UserFlags != ValueToFind) {
  826. continue;
  827. }
  828. } else if (AndFlags) {
  829. if ((e.UserFlags & ValueToFind) == 0) {
  830. continue;
  831. }
  832. } else if (NandFlags) {
  833. if (e.UserFlags & ValueToFind) {
  834. continue;
  835. }
  836. } else if (e.dwValue != ValueToFind) {
  837. continue;
  838. }
  839. }
  840. //
  841. // Key output
  842. //
  843. if (DisplayOffset) {
  844. printf ("[%08X] ", e.Offset);
  845. }
  846. if (e.bBinary && !KeysOnly) {
  847. if (!HideDump) {
  848. printf ("%s: (%u byte%s)\n", e.szName, e.BinarySize, e.BinarySize == 1 ? "" : "s");
  849. DumpData (e.BinaryPtr, e.BinarySize);
  850. printf ("\n");
  851. } else {
  852. printf ("%s (%u byte%s)\n", e.szName, e.BinarySize, e.BinarySize == 1 ? "" : "s");
  853. }
  854. } else {
  855. if (!KeysOnly) {
  856. if (e.dwValue || ShowZVals) {
  857. printf("%s = 0x%02lX", e.szName, e.dwValue);
  858. } else {
  859. printf("%s", e.szName);
  860. }
  861. if (e.UserFlags || ShowZVals) {
  862. printf(", Flags: %04x", e.UserFlags);
  863. }
  864. } else {
  865. printf("%s", e.szName);
  866. }
  867. printf ("\n");
  868. }
  869. }
  870. } while (MemDbEnumNextValue(&e));
  871. }
  872. dwReason = DLL_PROCESS_DETACH;
  873. MemDb_Entry (g_hInst, dwReason, NULL);
  874. MigUtil_Entry (g_hInst, dwReason, NULL);
  875. return 0;
  876. }
  877. VOID
  878. DumpData (
  879. IN BYTE const * Data,
  880. IN DWORD Count
  881. )
  882. {
  883. DWORD i, j, k;
  884. for (i = 0 ; i < Count ; i = k) {
  885. printf (" %08X ", i);
  886. k = i + 16;
  887. for (j = i ; j < k && j < Count ; j++) {
  888. printf ("%02X ", Data[j]);
  889. }
  890. while (j < k) {
  891. printf (" ");
  892. j++;
  893. }
  894. for (j = i ; j < k && j < Count ; j++) {
  895. if (isprint (Data[j])) {
  896. printf ("%c", Data[j]);
  897. } else {
  898. printf (".");
  899. }
  900. }
  901. printf ("\n");
  902. }
  903. }