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.

2858 lines
82 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. regext.c
  5. Abstract:
  6. Kernel debugger extensions useful for the registry
  7. Author:
  8. John Vert (jvert) 7-Sep-1993
  9. Environment:
  10. Loaded as a kernel debugger extension
  11. Revision History:
  12. John Vert (jvert) 7-Sep-1993
  13. created
  14. Dragos C. Sambotin (dragoss) 05-May-2000
  15. updated to support new registry layout
  16. enhanced with new commands
  17. --*/
  18. #include "precomp.h"
  19. #pragma hdrstop
  20. ULONG TotalPages;
  21. ULONG TotalPresentPages;
  22. PCHAR pc;
  23. BOOLEAN SavePages;
  24. BOOLEAN RestorePages;
  25. HANDLE TempFile;
  26. ULONG64 gHiveListAddr;
  27. static ULONG DirectoryOffset, TableOffset, BlockAddrOffset, PtrSize, ULongSize, HMapSize, GotOnce = FALSE;
  28. void
  29. poolDumpHive(
  30. IN ULONG64 Hive
  31. );
  32. VOID
  33. poolDumpMap(
  34. IN ULONG Length,
  35. IN ULONG64 Map
  36. );
  37. void
  38. dumpHiveFromFile(
  39. HANDLE hFile
  40. );
  41. void
  42. regdumppool(
  43. LPSTR args
  44. )
  45. /*++
  46. Routine Description:
  47. Goes through all the paged pool allocated to registry space and
  48. determines which pages are present and which are not.
  49. Called as:
  50. !regpool [s|r]
  51. s Save list of registry pages to temporary file
  52. r Restore list of registry pages from temp. file
  53. Arguments:
  54. CurrentPc - Supplies the current pc at the time the extension is
  55. called.
  56. lpExtensionApis - Supplies the address of the functions callable
  57. by this extension.
  58. lpArgumentString - Supplies the pattern and expression for this
  59. command.
  60. Return Value:
  61. None.
  62. --*/
  63. {
  64. ULONG64 pCmpHiveListHead;
  65. ULONG64 pNextHiveList;
  66. ULONG64 pHiveListEntry;
  67. ULONG BytesRead;
  68. ULONG64 CmHive;
  69. BYTE HiveList[1024];
  70. CHAR Dummy1[ 256 ],Dummy2[64];
  71. if (sscanf(args,"%s %I64lX",Dummy1,Dummy2)) {
  72. Dummy2[0] = 0;
  73. }
  74. if (toupper(Dummy2[0])=='S') {
  75. SavePages = TRUE;
  76. } else {
  77. SavePages = FALSE;
  78. }
  79. if (toupper(Dummy2[0])=='R') {
  80. RestorePages = TRUE;
  81. } else {
  82. RestorePages = FALSE;
  83. }
  84. //
  85. // Go get the hivelist.
  86. //
  87. // memset(HiveList,0,sizeof(HiveList));
  88. pHiveListEntry = GetExpression("nt!CmpMachineHiveList");
  89. gHiveListAddr = pHiveListEntry;
  90. if (pHiveListEntry != 0) {
  91. // Kd caches hive list
  92. ReadMemory(pHiveListEntry,
  93. HiveList,
  94. 8 * GetTypeSize("_HIVE_LIST_ENTRY"),
  95. &BytesRead);
  96. }
  97. //
  98. // First go and get the hivelisthead
  99. //
  100. pCmpHiveListHead = GetExpression("nt!CmpHiveListHead");
  101. if (pCmpHiveListHead==0) {
  102. dprintf("CmpHiveListHead couldn't be read\n");
  103. return;
  104. }
  105. if (!ReadPointer(pCmpHiveListHead, &pNextHiveList)) {
  106. dprintf("Couldn't read first Flink (%p) of CmpHiveList\n",
  107. pCmpHiveListHead);
  108. return;
  109. }
  110. TotalPages = TotalPresentPages = 0;
  111. if (SavePages || RestorePages) {
  112. TempFile = CreateFile( "regext.dat",
  113. GENERIC_READ | GENERIC_WRITE,
  114. 0,
  115. NULL,
  116. OPEN_ALWAYS,
  117. 0,
  118. NULL
  119. );
  120. if (TempFile == INVALID_HANDLE_VALUE) {
  121. dprintf("Couldn't open regext.dat\n");
  122. return;
  123. }
  124. }
  125. if (RestorePages) {
  126. dumpHiveFromFile(TempFile);
  127. } else {
  128. ULONG HiveListOffset;
  129. FIELD_INFO offField = {"HiveList", NULL, 0, DBG_DUMP_FIELD_RETURN_ADDRESS, 0, NULL};
  130. SYM_DUMP_PARAM TypeSym ={
  131. sizeof (SYM_DUMP_PARAM), "_CMHIVE", DBG_DUMP_NO_PRINT, 0,
  132. NULL, NULL, NULL, 1, &offField
  133. };
  134. // Get The offset
  135. if (Ioctl(IG_DUMP_SYMBOL_INFO, &TypeSym, TypeSym.size)) {
  136. return;
  137. }
  138. HiveListOffset = (ULONG) offField.address;
  139. while (pNextHiveList != pCmpHiveListHead) {
  140. CmHive = pNextHiveList - HiveListOffset;
  141. poolDumpHive(CmHive);
  142. if (GetFieldValue(pNextHiveList, "_LIST_ENTRY", "Flink", pNextHiveList)) {
  143. dprintf("Couldn't read Flink (%p) of %p\n",
  144. pCmpHiveListHead,pNextHiveList);
  145. break;
  146. }
  147. if (CheckControlC()) {
  148. return;
  149. }
  150. }
  151. }
  152. dprintf("Total pages present = %d / %d\n",
  153. TotalPresentPages,
  154. TotalPages);
  155. if (SavePages || RestorePages) {
  156. CloseHandle( TempFile );
  157. }
  158. }
  159. BOOLEAN
  160. GetHiveMaps(
  161. ULONG64 pHive,
  162. ULONG64 *pStableMap,
  163. ULONG *pStableLength,
  164. ULONG64 *pVolatileMap,
  165. ULONG *pVolatileLength
  166. )
  167. {
  168. ULONG BytesRead;
  169. ULONG Stable_Length=0, Volatile_Length=0;
  170. ULONG64 Stable_Map=0, Volatile_Map=0;
  171. ULONG StorageOffset, DUAL_Size;
  172. FIELD_INFO offField = {"Hive.Storage", NULL, 0, DBG_DUMP_FIELD_RETURN_ADDRESS, 0, NULL};
  173. SYM_DUMP_PARAM TypeSym ={
  174. sizeof (SYM_DUMP_PARAM), "_CMHIVE", DBG_DUMP_NO_PRINT, 0,
  175. NULL, NULL, NULL, 1, &offField
  176. };
  177. // Get the offset of Hive.Storage in _CMHIVE
  178. if (Ioctl(IG_DUMP_SYMBOL_INFO, &TypeSym, TypeSym.size)) {
  179. dprintf("Cannot find _CMHIVE type.\n");
  180. return FALSE;
  181. }
  182. StorageOffset = (ULONG) offField.address;
  183. DUAL_Size = GetTypeSize("_DUAL");
  184. GetFieldValue(pHive + StorageOffset + Stable*DUAL_Size, "_DUAL", "Length", Stable_Length);
  185. GetFieldValue(pHive + StorageOffset + Volatile*DUAL_Size, "_DUAL", "Length", Volatile_Length);
  186. GetFieldValue(pHive + StorageOffset + Stable*DUAL_Size, "_DUAL", "Map", Stable_Map);
  187. GetFieldValue(pHive + StorageOffset + Volatile*DUAL_Size, "_DUAL", "Map", Volatile_Map);
  188. (*pStableMap) = Stable_Map;
  189. (*pStableLength) = Stable_Length;
  190. (*pVolatileMap) = Volatile_Map;
  191. (*pVolatileLength) = Volatile_Length;
  192. return TRUE;
  193. }
  194. BOOLEAN
  195. USE_OLD_CELL(
  196. ULONG64 pHive
  197. )
  198. {
  199. ULONG Version;
  200. if(!GetFieldValue(pHive, "_CMHIVE", "Hive.Version", Version)) {
  201. return (Version==1);
  202. }
  203. return FALSE;
  204. }
  205. ULONG64
  206. MyHvpGetCellPaged(
  207. ULONG64 pHive,
  208. ULONG Cell
  209. )
  210. /*++
  211. Routine Description:
  212. Returns the memory address for the specified Cell. Will never
  213. return failure, but may assert. Use HvIsCellAllocated to check
  214. validity of Cell.
  215. This routine should never be called directly, always call it
  216. via the HvGetCell() macro.
  217. This routine provides GetCell support for hives with full maps.
  218. It is the normal version of the routine.
  219. Arguments:
  220. Hive - supplies a pointer to the hive control structure for the
  221. hive of interest
  222. Cell - supplies HCELL_INDEX of cell to return address for
  223. Return Value:
  224. Address of Cell in memory. Assert or BugCheck if error.
  225. --*/
  226. {
  227. ULONG Type;
  228. ULONG Table;
  229. ULONG Block;
  230. ULONG Offset;
  231. ULONG Stable_Length=0, Volatile_Length=0;
  232. ULONG64 Stable_Map=0, Volatile_Map=0;
  233. ULONG64 MapTable;
  234. ULONG64 Map;
  235. ULONG64 MapEntryAddress, BlockAddress=0;
  236. ULONG64 lRez;
  237. ULONG64 pcell;
  238. if(!GetHiveMaps(pHive,&Stable_Map,&Stable_Length,&Volatile_Map,&Volatile_Length) ) {
  239. return 0;
  240. }
  241. Type = ((ULONG)((Cell & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT));
  242. Table = (Cell & HCELL_TABLE_MASK) >> HCELL_TABLE_SHIFT;
  243. Block = (Cell & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT;
  244. Offset = (Cell & HCELL_OFFSET_MASK);
  245. if( Type == 0 ) {
  246. Map = Stable_Map;
  247. } else {
  248. Map = Volatile_Map;
  249. }
  250. dprintf("Map = %p Type = %lx Table = %lx Block = %lx Offset = %lx\n",Map,Type,Table,Block,Offset);
  251. if (!ReadPointer(Map + DirectoryOffset + Table*PtrSize,
  252. &MapTable))
  253. return 0;
  254. dprintf("MapTable = %p \n",MapTable);
  255. MapEntryAddress = MapTable + Block * HMapSize + BlockAddrOffset;
  256. if (!ReadPointer(MapEntryAddress, &BlockAddress)) {
  257. dprintf(" can't read HMAP_ENTRY at %p\n",
  258. MapEntryAddress);
  259. return 0;
  260. }
  261. dprintf("BlockAddress = %p \n\n",BlockAddress);
  262. pcell = ((ULONG64)(BlockAddress) + Offset);
  263. lRez = (ULONG64)pcell;
  264. if (USE_OLD_CELL(pHive)) {
  265. return lRez + ULongSize + ULongSize;
  266. //return (struct _CELL_DATA *)&(hcell.u.OldCell.u.UserData);
  267. } else {
  268. return lRez + ULongSize;
  269. //return (struct _CELL_DATA *)&(hcell.u.NewCell.u.UserData);
  270. }
  271. return 0;
  272. }
  273. ULONG64
  274. MyHvpGetCellFlat(
  275. ULONG64 pHive,
  276. ULONG Cell
  277. )
  278. /*++
  279. Routine Description:
  280. Returns the memory address for the specified Cell. Will never
  281. return failure, but may assert. Use HvIsCellAllocated to check
  282. validity of Cell.
  283. This routine should never be called directly, always call it
  284. via the HvGetCell() macro.
  285. This routine provides GetCell support for read only hives with
  286. single allocation flat images. Such hives do not have cell
  287. maps ("page tables"), instead, we compute addresses by
  288. arithmetic against the base image address.
  289. Such hives cannot have volatile cells.
  290. Arguments:
  291. Hive - supplies a pointer to the hive control structure for the
  292. hive of interest
  293. Cell - supplies HCELL_INDEX of cell to return address for
  294. Return Value:
  295. Address of Cell in memory. Assert or BugCheck if error.
  296. --*/
  297. {
  298. ULONG64 BaseBlock;
  299. ULONG64 lRez;
  300. if (GetFieldValue(pHive, "_CMHIVE", "Hive.BaseBlock", BaseBlock)) {
  301. dprintf("\tCan't CMHIVE Read from %p\n",pHive);
  302. return 0;
  303. }
  304. //
  305. // Address is base of Hive image + Cell
  306. //
  307. lRez = (ULONG64)BaseBlock + HBLOCK_SIZE + Cell;
  308. if (USE_OLD_CELL(pHive)) {
  309. return lRez + ULongSize + ULongSize;
  310. //return (struct _CELL_DATA *)&(pcell->u.OldCell.u.UserData);
  311. } else {
  312. return lRez + ULongSize;
  313. //return (struct _CELL_DATA *)&(pcell->u.NewCell.u.UserData);
  314. }
  315. return 0;
  316. }
  317. void
  318. poolDumpHive(
  319. IN ULONG64 pHive
  320. )
  321. {
  322. ULONG BytesRead;
  323. WCHAR FileName[HBASE_NAME_ALLOC/2 + 1];
  324. CHAR buf[512];
  325. ULONG cb;
  326. ULONG Stable_Length=0, Volatile_Length=0;
  327. ULONG64 Stable_Map=0, Volatile_Map=0;
  328. ULONG64 BaseBlock;
  329. ULONG StorageOffset, DUAL_Size;
  330. FIELD_INFO offField = {"Hive.Storage", NULL, 0, DBG_DUMP_FIELD_RETURN_ADDRESS, 0, NULL};
  331. SYM_DUMP_PARAM TypeSym ={
  332. sizeof (SYM_DUMP_PARAM), "_CMHIVE", DBG_DUMP_NO_PRINT, 0,
  333. NULL, NULL, NULL, 1, &offField
  334. };
  335. // Get the offset of Hive.Storage in _CMHIVE
  336. if (Ioctl(IG_DUMP_SYMBOL_INFO, &TypeSym, TypeSym.size)) {
  337. dprintf("Cannot find _CMHIVE type.\n");
  338. return ;
  339. }
  340. StorageOffset = (ULONG) offField.address;
  341. dprintf("\ndumping hive at %p ",pHive);
  342. if (GetFieldValue(pHive, "_CMHIVE", "Hive.BaseBlock", BaseBlock)) {
  343. dprintf("\tCan't CMHIVE Read from %p\n",pHive);
  344. return;
  345. }
  346. if (GetFieldValue( BaseBlock, "_HBASE_BLOCK", "FileName", FileName )) {
  347. wcscpy(FileName, L"UNKNOWN");
  348. } else {
  349. if (FileName[0]==L'\0') {
  350. wcscpy(FileName, L"NONAME");
  351. } else {
  352. FileName[HBASE_NAME_ALLOC/2]=L'\0';
  353. }
  354. }
  355. dprintf("(%ws)\n",FileName);
  356. DUAL_Size = GetTypeSize("_DUAL");
  357. GetFieldValue(pHive + StorageOffset + Stable*DUAL_Size, "_DUAL", "Length", Stable_Length);
  358. GetFieldValue(pHive + StorageOffset + Volatile*DUAL_Size, "_DUAL", "Length", Volatile_Length);
  359. GetFieldValue(pHive + StorageOffset + Stable*DUAL_Size, "_DUAL", "Map", Stable_Map);
  360. GetFieldValue(pHive + StorageOffset + Volatile*DUAL_Size, "_DUAL", "Map", Volatile_Map);
  361. dprintf(" Stable Length = %lx\n",Stable_Length);
  362. if (SavePages) {
  363. sprintf(buf,
  364. "%ws %d %d\n",
  365. FileName,
  366. Stable_Length,
  367. Volatile_Length);
  368. WriteFile( TempFile, buf, strlen(buf), &cb, NULL );
  369. }
  370. poolDumpMap(Stable_Length, Stable_Map);
  371. dprintf(" Volatile Length = %lx\n",Volatile_Length);
  372. poolDumpMap(Volatile_Length, Volatile_Map);
  373. }
  374. VOID
  375. poolDumpMap(
  376. IN ULONG Length,
  377. IN ULONG64 Map
  378. )
  379. {
  380. ULONG Tables;
  381. ULONG MapSlots;
  382. ULONG i;
  383. ULONG BytesRead;
  384. ULONG64 MapTable;
  385. ULONG Garbage;
  386. ULONG Present=0;
  387. CHAR buf[512];
  388. ULONG cb;
  389. // Get the offsets
  390. if (!GotOnce) {
  391. if (GetFieldOffset("_HMAP_DIRECTORY", "Directory", &DirectoryOffset)){
  392. return;
  393. }
  394. if (GetFieldOffset("_HMAP_ENTRY", "BlockAddress", &BlockAddrOffset)) {
  395. return;
  396. }
  397. if (GetFieldOffset("_HMAP_TABLE", "Table", &TableOffset)) {
  398. return;
  399. }
  400. PtrSize = DBG_PTR_SIZE;
  401. ULongSize = sizeof(ULONG); // This doesn't change with target GetTypeSize("ULONG");
  402. HMapSize = GetTypeSize("_HMAP_ENTRY");
  403. GotOnce = TRUE;
  404. }
  405. if (Length==0) {
  406. return;
  407. }
  408. MapSlots = Length / HBLOCK_SIZE;
  409. Tables = 1+ ((MapSlots-1) / HTABLE_SLOTS);
  410. //
  411. // read in map directory
  412. //
  413. // ReadMemory((DWORD)Map,
  414. // &MapDirectory,
  415. // Tables * sizeof(PHMAP_TABLE),
  416. // &BytesRead);
  417. /* if (BytesRead < (Tables * sizeof(PHMAP_TABLE))) {
  418. dprintf("Only read %lx/%lx bytes from %lx\n",
  419. BytesRead,
  420. Tables * sizeof(PHMAP_TABLE),
  421. Map);
  422. return;
  423. }*/
  424. //
  425. // check out each map entry
  426. //
  427. for (i=0; i<MapSlots; i++) {
  428. ULONG64 MapEntryAddress, BlockAddress=0;
  429. if (!ReadPointer(Map + DirectoryOffset + (i/HTABLE_SLOTS)*PtrSize,
  430. &MapTable))
  431. return;
  432. MapEntryAddress = MapTable + TableOffset + (i%HTABLE_SLOTS) * PtrSize;
  433. if (!ReadPointer(MapEntryAddress, &BlockAddress)) {
  434. dprintf(" can't read HMAP_ENTRY at %p\n",
  435. MapEntryAddress);
  436. }
  437. if (SavePages) {
  438. sprintf(buf, "%p\n",BlockAddress);
  439. WriteFile( TempFile, buf, strlen(buf), &cb, NULL );
  440. }
  441. //
  442. // probe the HBLOCK
  443. //
  444. ReadMemory( BlockAddress,
  445. &Garbage,
  446. sizeof(ULONG),
  447. &BytesRead);
  448. if (BytesRead > 0) {
  449. ++Present;
  450. }
  451. if (CheckControlC()) {
  452. return;
  453. }
  454. }
  455. dprintf(" %d/%d pages present\n",
  456. Present,
  457. MapSlots);
  458. TotalPages += MapSlots;
  459. TotalPresentPages += Present;
  460. }
  461. void
  462. dumpHiveFromFile(
  463. HANDLE hFile
  464. )
  465. /*++
  466. Routine Description:
  467. Takes a list of the registry hives and pages from a file and
  468. checks to see how many of the pages are in memory.
  469. The format of the file is as follows
  470. hivename stablelength volatilelength
  471. stable page address
  472. stable page address
  473. .
  474. .
  475. .
  476. volatile page address
  477. volatile page address
  478. .
  479. .
  480. .
  481. hivename stablelength volatilelength
  482. .
  483. .
  484. .
  485. Arguments:
  486. File - Supplies a file.
  487. Return Value:
  488. None.
  489. --*/
  490. {
  491. #if 0
  492. CHAR Hivename[33];
  493. ULONG StableLength;
  494. ULONG VolatileLength;
  495. ULONG64 Page;
  496. ULONG NumFields;
  497. ULONG Garbage;
  498. ULONG Present;
  499. ULONG Total;
  500. ULONG BytesRead;
  501. BYTE buf[512];
  502. while (!feof(File)) {
  503. NumFields = fscanf(File,"%s %d %d\n",
  504. Hivename,
  505. &StableLength,
  506. &VolatileLength);
  507. if (NumFields != 3) {
  508. dprintf("fscanf returned %d\n",NumFields);
  509. return;
  510. }
  511. dprintf("\ndumping hive %s\n",Hivename);
  512. dprintf(" Stable Length = %lx\n",StableLength);
  513. Present = 0;
  514. Total = 0;
  515. while (StableLength > 0) {
  516. fscanf(File, "%I64lx\n",&Page);
  517. ReadMemory((DWORD)Page,
  518. &Garbage,
  519. sizeof(ULONG),
  520. &BytesRead);
  521. if (BytesRead > 0) {
  522. ++Present;
  523. }
  524. ++Total;
  525. StableLength -= HBLOCK_SIZE;
  526. }
  527. if (Total > 0) {
  528. dprintf(" %d/%d stable pages present\n",
  529. Present,Total);
  530. }
  531. TotalPages += Total;
  532. TotalPresentPages += Present;
  533. dprintf(" Volatile Length = %lx\n",VolatileLength);
  534. Present = 0;
  535. Total = 0;
  536. while (VolatileLength > 0) {
  537. fscanf(File, "%lx\n",&Page);
  538. ReadMemory(Page,
  539. &Garbage,
  540. sizeof(ULONG),
  541. &BytesRead);
  542. if (BytesRead > 0) {
  543. ++Present;
  544. }
  545. ++Total;
  546. VolatileLength -= HBLOCK_SIZE;
  547. }
  548. if (Total > 0) {
  549. dprintf(" %d/%d volatile pages present\n",
  550. Present,Total);
  551. }
  552. TotalPages += Total;
  553. TotalPresentPages += Present;
  554. }
  555. #endif //0
  556. }
  557. USHORT
  558. GetKcbName(
  559. ULONG64 KcbAddr,
  560. PWCHAR NameBuffer,
  561. ULONG BufferSize
  562. )
  563. /*++
  564. Routine Description:
  565. Takes a kcb and dump its complete name.
  566. Arguments:
  567. KcbAddr - Address of key control block.
  568. NameBuffer - The Name buffer to fill in the name.
  569. BufferSize - Size of Buffer.
  570. Return Value:
  571. Size of Name String.
  572. --*/
  573. {
  574. WCHAR Name[ 256 ];
  575. ULONG64 TmpKcbAddr;
  576. ULONG64 NameBlockAddr;
  577. DWORD BytesRead;
  578. ULONG Length;
  579. ULONG TotalLength;
  580. ULONG size;
  581. ULONG i;
  582. ULONG BeginPosition;
  583. ULONG NameOffset;
  584. WCHAR *w1, *w2;
  585. WCHAR *BufferEnd;
  586. UCHAR *u2;
  587. //
  588. // Calculate the total string length.
  589. //
  590. TotalLength = 0;
  591. TmpKcbAddr = KcbAddr;
  592. // dprintf("Kcb %p ", KcbAddr);
  593. while (TmpKcbAddr) {
  594. ULONG Compressed=0, NameLength=0;
  595. if (GetFieldValue(TmpKcbAddr, "CM_KEY_CONTROL_BLOCK", "NameBlock", NameBlockAddr)) {
  596. dprintf("Cannot find CM_KEY_CONTROL_BLOCK type.\n");
  597. return 0;
  598. }
  599. if (GetFieldValue(NameBlockAddr, "_CM_NAME_CONTROL_BLOCK", "Compressed", Compressed) ||
  600. GetFieldValue(NameBlockAddr, "_CM_NAME_CONTROL_BLOCK", "NameLength", NameLength)) {
  601. dprintf("Cannot find type _CM_NAME_CONTROL_BLOCK.\n");
  602. return 0;
  603. }
  604. if (Compressed) {
  605. Length = NameLength * sizeof(WCHAR);
  606. } else {
  607. Length = NameLength;
  608. }
  609. TotalLength += Length;
  610. //
  611. // Add the sapce for OBJ_NAME_PATH_SEPARATOR;
  612. //
  613. TotalLength += sizeof(WCHAR);
  614. GetFieldValue(TmpKcbAddr, "CM_KEY_CONTROL_BLOCK", "ParentKcb", TmpKcbAddr);
  615. if (CheckControlC()) {
  616. return 0;
  617. }
  618. }
  619. BufferEnd = &(NameBuffer[BufferSize/sizeof(WCHAR) - 1]);
  620. if (TotalLength < BufferSize) {
  621. NameBuffer[TotalLength/sizeof(WCHAR)] = UNICODE_NULL;
  622. } else {
  623. *BufferEnd = UNICODE_NULL;
  624. }
  625. //
  626. // Now fill the name into the buffer.
  627. //
  628. TmpKcbAddr = KcbAddr;
  629. BeginPosition = TotalLength;
  630. GetFieldOffset("CM_NAME_CONTROL_BLOCK", "Name", &NameOffset);
  631. while (TmpKcbAddr) {
  632. ULONG NameLength=0, Compressed=0;
  633. //
  634. // Read the information.
  635. //
  636. if (GetFieldValue(TmpKcbAddr, "CM_KEY_CONTROL_BLOCK", "NameBlock", NameBlockAddr)) {
  637. dprintf("Cannot find CM_KEY_CONTROL_BLOCK type.\n");
  638. return 0;
  639. }
  640. if (GetFieldValue(NameBlockAddr, "_CM_NAME_CONTROL_BLOCK", "Compressed", Compressed) ||
  641. GetFieldValue(NameBlockAddr, "_CM_NAME_CONTROL_BLOCK", "NameLength", NameLength)) {
  642. dprintf("Cannot find type _CM_NAME_CONTROL_BLOCK.\n");
  643. return 0;
  644. }
  645. if (NameLength > sizeof(Name)) {
  646. NameLength = sizeof(Name);
  647. }
  648. ReadMemory(NameBlockAddr + NameOffset,// FIELD_OFFSET(CM_NAME_CONTROL_BLOCK, Name),
  649. Name,
  650. NameLength,
  651. &BytesRead);
  652. if (BytesRead < NameLength) {
  653. dprintf("Could not read Name BUFFER: 5\n");
  654. return (0);
  655. }
  656. //
  657. // Calculate the begin position of each subkey. Then fill in the char.
  658. //
  659. if (Compressed) {
  660. BeginPosition -= (NameLength + 1) * sizeof(WCHAR);
  661. w1 = &(NameBuffer[BeginPosition/sizeof(WCHAR)]);
  662. if (w1 < BufferEnd) {
  663. *w1 = OBJ_NAME_PATH_SEPARATOR;
  664. }
  665. w1++;
  666. u2 = (UCHAR *) &(Name[0]);
  667. for (i=0; i<NameLength; i++) {
  668. if (w1 < BufferEnd) {
  669. *w1 = (WCHAR)(*u2);
  670. } else {
  671. break;
  672. }
  673. w1++;
  674. u2++;
  675. }
  676. } else {
  677. BeginPosition -= (NameLength + sizeof(WCHAR));
  678. w1 = &(NameBuffer[BeginPosition/sizeof(WCHAR)]);
  679. if (w1 < BufferEnd) {
  680. *w1 = OBJ_NAME_PATH_SEPARATOR;
  681. }
  682. w1++;
  683. w2 = Name;
  684. for (i=0; i<NameLength; i=i+sizeof(WCHAR)) {
  685. if (w1 < BufferEnd) {
  686. *w1 = *w2;
  687. } else {
  688. break;
  689. }
  690. w1++;
  691. w2++;
  692. }
  693. }
  694. GetFieldValue(TmpKcbAddr, "CM_KEY_CONTROL_BLOCK", "ParentKcb", TmpKcbAddr);
  695. }
  696. // dprintf("\n%5d, %ws\n", TotalLength, NameBuffer);
  697. return ((USHORT) TotalLength);
  698. }
  699. #define CMP_CELL_CACHED_MASK 1
  700. #define CMP_IS_CELL_CACHED(Cell) ((ULONG64) (Cell) & CMP_CELL_CACHED_MASK)
  701. #define CMP_GET_CACHED_ADDRESS(Cell) (((ULONG64) (Cell)) & ~CMP_CELL_CACHED_MASK)
  702. void
  703. regkcb(
  704. LPSTR args
  705. )
  706. /*++
  707. Routine Description:
  708. Dumps the name when given a KCB address
  709. Called as:
  710. !regkcb KCB_Address
  711. Arguments:
  712. args - Supplies the address of the KCB.
  713. Return Value:
  714. .
  715. --*/
  716. {
  717. WCHAR KeyName[ 256 ];
  718. ULONG64 KcbAddr, ParentKcbAddr, KeyHiveAddr, IndexHintAddr,RealKcb;
  719. DWORD BytesRead;
  720. ULONG ExtFlags, Delete, Flags, KeyCell, KcbMaxNameLen, KcbMaxValueNameLen,KcbMaxValueDataLen,SubKeyCount,ValueCount;
  721. ULONG ValueCacheOffset,i,CellIndex;
  722. ULONG64 ValueList,ValueAddr,CellData;
  723. USHORT RefCount, TotalLevels;
  724. SHORT DelayedCloseIndex;
  725. LARGE_INTEGER KcbLastWriteTime;
  726. CHAR Dummy[ 256 ];
  727. ULONG KeyBodyListHeadOffset;
  728. if (sscanf(args,"%s %lX",Dummy,&KcbAddr)) {
  729. KcbAddr = GetExpression(args + strlen(Dummy));
  730. }
  731. if (GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "ExtFlags", ExtFlags) ||
  732. GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "Flags", Flags) ||
  733. GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "Delete", Delete) ||
  734. GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "RefCount", RefCount) ||
  735. GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "ParentKcb", ParentKcbAddr) ||
  736. GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "KeyHive", KeyHiveAddr) ||
  737. GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "KeyCell", KeyCell) ||
  738. GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "TotalLevels", TotalLevels) ||
  739. GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "DelayedCloseIndex", DelayedCloseIndex)
  740. ) {
  741. dprintf("Could not read Kcb\n");
  742. return;
  743. }
  744. if(GetKcbName(KcbAddr, KeyName, sizeof(KeyName))) {
  745. dprintf("Key : %ws\n", KeyName);
  746. } else {
  747. dprintf("Could not read key name\n");
  748. return;
  749. }
  750. dprintf("RefCount : %lx\n", RefCount);
  751. dprintf("Flags :");
  752. if (Delete) {
  753. dprintf(" Deleted,");
  754. }
  755. if (Flags & KEY_COMP_NAME) {
  756. dprintf(" CompressedName,");
  757. }
  758. if (Flags & KEY_PREDEF_HANDLE) {
  759. dprintf(" PredefinedHandle,");
  760. }
  761. if (Flags & KEY_SYM_LINK) {
  762. dprintf(" SymbolicLink,");
  763. }
  764. if (Flags & KEY_NO_DELETE) {
  765. dprintf(" NoDelete,");
  766. }
  767. if (Flags & KEY_HIVE_EXIT) {
  768. dprintf(" HiveExit,");
  769. }
  770. if (Flags & KEY_HIVE_ENTRY) {
  771. dprintf(" HiveEntry,");
  772. }
  773. if (Flags & KEY_VOLATILE) {
  774. dprintf(" Volatile");
  775. } else {
  776. dprintf(" Stable");
  777. }
  778. dprintf("\n");
  779. dprintf("ExtFlags :");
  780. if (ExtFlags & CM_KCB_KEY_NON_EXIST) {
  781. dprintf(" Fake,");
  782. }
  783. if (ExtFlags & CM_KCB_SYM_LINK_FOUND) {
  784. dprintf(" SymbolicLinkFound,");
  785. }
  786. if (ExtFlags & CM_KCB_NO_DELAY_CLOSE) {
  787. dprintf(" NoDelayClose,");
  788. }
  789. if (ExtFlags & CM_KCB_INVALID_CACHED_INFO) {
  790. dprintf(" InvalidCachedInfo,");
  791. }
  792. if (ExtFlags & CM_KCB_NO_SUBKEY) {
  793. dprintf(" NoSubKey,");
  794. }
  795. if (ExtFlags & CM_KCB_SUBKEY_ONE) {
  796. dprintf(" SubKeyOne,");
  797. }
  798. if (ExtFlags & CM_KCB_SUBKEY_HINT) {
  799. dprintf(" SubKeyHint");
  800. }
  801. dprintf("\n");
  802. dprintf("Parent : 0x%p\n", ParentKcbAddr);
  803. dprintf("KeyHive : 0x%p\n", KeyHiveAddr);
  804. dprintf("KeyCell : 0x%lx [cell index]\n", KeyCell);
  805. dprintf("TotalLevels : %u\n", TotalLevels);
  806. dprintf("DelayedCloseIndex: %d\n", DelayedCloseIndex);
  807. if(!GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "KcbMaxNameLen", KcbMaxNameLen)) {
  808. dprintf("MaxNameLen : 0x%lx\n", KcbMaxNameLen);
  809. }
  810. if(!GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "KcbMaxValueNameLen", KcbMaxValueNameLen)) {
  811. dprintf("MaxValueNameLen : 0x%lx\n", KcbMaxValueNameLen);
  812. }
  813. if(!GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "KcbMaxValueDataLen", KcbMaxValueDataLen)) {
  814. dprintf("MaxValueDataLen : 0x%lx\n", KcbMaxValueDataLen);
  815. }
  816. if(!GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "KcbLastWriteTime", KcbLastWriteTime)) {
  817. dprintf("LastWriteTime : 0x%8lx:0x%8lx\n", KcbLastWriteTime.HighPart,KcbLastWriteTime.LowPart);
  818. }
  819. if( !GetFieldOffset("CM_KEY_CONTROL_BLOCK", "KeyBodyListHead", &KeyBodyListHeadOffset) ) {
  820. ParentKcbAddr = KcbAddr + KeyBodyListHeadOffset;
  821. dprintf("KeyBodyListHead : ");
  822. if (!GetFieldValue(ParentKcbAddr, "_LIST_ENTRY", "Flink", KeyHiveAddr)) {
  823. dprintf("0x%p ", KeyHiveAddr);
  824. }
  825. if (!GetFieldValue(ParentKcbAddr, "_LIST_ENTRY", "Blink", KeyHiveAddr)) {
  826. dprintf("0x%p", KeyHiveAddr);
  827. }
  828. dprintf("\n");
  829. }
  830. if(!(Flags&KEY_HIVE_ENTRY)) {
  831. dprintf("SubKeyCount : ");
  832. if( !(ExtFlags & CM_KCB_INVALID_CACHED_INFO) ) {
  833. if (ExtFlags & CM_KCB_NO_SUBKEY ) {
  834. dprintf("0");
  835. } else if (ExtFlags & CM_KCB_SUBKEY_ONE ) {
  836. dprintf("1");
  837. } else if (ExtFlags & CM_KCB_SUBKEY_HINT ) {
  838. if( !GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "IndexHint", IndexHintAddr) ) {
  839. if( !GetFieldValue(IndexHintAddr, "CM_INDEX_HINT_BLOCK", "Count", SubKeyCount) ) {
  840. dprintf("%lu",SubKeyCount);
  841. }
  842. }
  843. } else {
  844. if( !GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", "SubKeyCount", SubKeyCount) ) {
  845. dprintf("%lu",SubKeyCount);
  846. }
  847. }
  848. } else {
  849. dprintf("hint not valid");
  850. }
  851. dprintf("\n");
  852. }
  853. GetFieldOffset("CM_KEY_CONTROL_BLOCK", "ValueCache", &ValueCacheOffset);
  854. if( ExtFlags & CM_KCB_SYM_LINK_FOUND ) {
  855. if(!GetFieldValue(KcbAddr + ValueCacheOffset, "_CACHED_CHILD_LIST", "RealKcb", RealKcb)) {
  856. dprintf("RealKcb : 0x%p\n", RealKcb);
  857. }
  858. } else {
  859. if(!GetFieldValue(KcbAddr + ValueCacheOffset, "_CACHED_CHILD_LIST", "Count", ValueCount)) {
  860. dprintf("ValueCache.Count : %lu\n", ValueCount);
  861. if(!GetFieldValue(KcbAddr + ValueCacheOffset, "_CACHED_CHILD_LIST", "ValueList", ValueList)) {
  862. if (CMP_IS_CELL_CACHED(ValueList)) {
  863. ValueList = CMP_GET_CACHED_ADDRESS(ValueList);
  864. if(!GetFieldValue(ValueList, "_CM_CACHED_VALUE_INDEX", "CellIndex", CellIndex) ) {
  865. dprintf("ValueList : 0x%lx\n", CellIndex);
  866. GetFieldOffset("_CM_CACHED_VALUE_INDEX", "Data.CellData", &ValueCacheOffset);
  867. ValueList += ValueCacheOffset;
  868. for (i = 0; i < ValueCount; i++) {
  869. dprintf(" ValueList[%2lu] = ",i);
  870. ReadMemory(ValueList + i*PtrSize, &ValueAddr, PtrSize, &BytesRead);
  871. if (BytesRead < PtrSize) {
  872. dprintf("Couldn't read memory\n");
  873. } else {
  874. dprintf(" 0x%p\n",ValueAddr);
  875. }
  876. }
  877. }
  878. } else {
  879. dprintf("ValueCache.List : 0x%p\n", ValueList);
  880. }
  881. }
  882. }
  883. }
  884. }
  885. //
  886. // Miscelaneous Hash routines
  887. //
  888. ULONG CmpHashTableSize = 0;
  889. #define RNDM_CONSTANT 314159269 /* default value for "scrambling constant" */
  890. #define RNDM_PRIME 1000000007 /* prime number, also used for scrambling */
  891. #define HASH_KEY(_convkey_) ((RNDM_CONSTANT * (_convkey_)) % RNDM_PRIME)
  892. #define GET_HASH_INDEX(Key) HASH_KEY(Key) % CmpHashTableSize
  893. #define GET_HASH_ENTRY(Table, Key) Table[GET_HASH_INDEX(Key)]
  894. void
  895. regopenkeys(
  896. LPSTR args,
  897. LPSTR subkey
  898. )
  899. /*++
  900. Routine Description:
  901. Dumps the registry hash table
  902. Called as:
  903. !openkeys <HiveAddr|0>
  904. Arguments:
  905. CurrentPc - Supplies the current pc at the time the extension is
  906. called.
  907. lpExtensionApis - Supplies the address of the functions callable
  908. by this extension.
  909. lpArgumentString - Supplies the pattern and expression for this
  910. command.
  911. Return Value:
  912. None.
  913. --*/
  914. {
  915. DWORD64 TableSizeAddr;
  916. DWORD64 HashTableAddr;
  917. ULONG64 HashTable;
  918. DWORD i;
  919. ULONG64 KcbAddr;
  920. WCHAR KeyName[ 256 ];
  921. ULONG64 HashEntryAddr;
  922. DWORD BytesRead;
  923. ULONG KeyHashOffset;
  924. BOOLEAN First;
  925. ULONG64 TargetHive = 0;
  926. CHAR Dummy[ 256 ];
  927. ULONG ConvKey = 0;
  928. ULONG j,Count;
  929. ULONG SearchedIndex;
  930. WCHAR FullKeyName[ 512 ];
  931. TableSizeAddr = GetExpression("nt!CmpHashTableSize");
  932. if (TableSizeAddr == 0) {
  933. dprintf("Couldn't find address of CmpHashTableSize\n");
  934. return;
  935. }
  936. HashTableAddr = GetExpression("nt!CmpCacheTable");
  937. if (HashTableAddr == 0) {
  938. dprintf("Couldn't find address of CmpCacheTable\n");
  939. return;
  940. }
  941. ReadMemory(TableSizeAddr, &CmpHashTableSize, sizeof(CmpHashTableSize), &BytesRead);
  942. if (BytesRead < sizeof(CmpHashTableSize)) {
  943. dprintf("Couldn't get CmpHashTableSize from %08p\n",TableSizeAddr);
  944. return;
  945. }
  946. if (!ReadPointer(HashTableAddr, &HashTable)) {
  947. dprintf("Couldn't get CmpCacheTable from %08p\n",HashTableAddr);
  948. return;
  949. }
  950. if( subkey == NULL ) {
  951. if (sscanf(args,"%s %lX",Dummy,&TargetHive)) {
  952. TargetHive = GetExpression(args + strlen(Dummy));
  953. }
  954. i=0;
  955. SearchedIndex = CmpHashTableSize - 1;
  956. } else {
  957. for( Count=0;subkey[Count];Count++) {
  958. FullKeyName[Count] = (WCHAR)subkey[Count];
  959. if( FullKeyName[Count] != OBJ_NAME_PATH_SEPARATOR ) {
  960. ConvKey = 37 * ConvKey + (ULONG) RtlUpcaseUnicodeChar(FullKeyName[Count]);
  961. }
  962. }
  963. FullKeyName[Count] = UNICODE_NULL;
  964. SearchedIndex = GET_HASH_INDEX(ConvKey);
  965. i=SearchedIndex;
  966. }
  967. GetFieldOffset("CM_KEY_CONTROL_BLOCK", "KeyHash", &KeyHashOffset);
  968. for (; i<=SearchedIndex; i++) {
  969. if (CheckControlC()) {
  970. return;
  971. }
  972. if (!ReadPointer(HashTable + i*PtrSize,&HashEntryAddr)) {
  973. dprintf("Couldn't get HashEntryAddr from %08p\n", HashTable + i*PtrSize);
  974. continue;
  975. }
  976. if (HashEntryAddr != 0) {
  977. First = TRUE;
  978. while (HashEntryAddr != 0) {
  979. #define KcbFld(F) GetFieldValue(KcbAddr, "CM_KEY_CONTROL_BLOCK", #F, F)
  980. ULONG64 KeyHive, NextHash;
  981. ULONG ConvKey, KeyCell, Flags, ExtFlags;
  982. KcbAddr = HashEntryAddr - KeyHashOffset;
  983. if (KcbFld(ConvKey)) {
  984. dprintf("Couldn't get HashEntry from %08lx\n", HashEntryAddr);
  985. break;
  986. }
  987. KcbFld(KeyHive); KcbFld(KeyCell);
  988. KcbFld(Flags); KcbFld(ExtFlags); KcbFld(NextHash);
  989. if( subkey == NULL ) {
  990. if( (TargetHive == 0) || ((ULONG64)TargetHive == (ULONG64)KeyHive) ) {
  991. if( !First ) {
  992. dprintf("\t");
  993. } else {
  994. dprintf("Index %x: ",i);
  995. }
  996. dprintf("\t %08lx kcb=%p cell=%08lx f=%04lx%04lx ",
  997. ConvKey,
  998. KcbAddr,
  999. KeyCell,
  1000. Flags,
  1001. ExtFlags);
  1002. First = FALSE;
  1003. if (GetKcbName(KcbAddr, KeyName, sizeof(KeyName))) {
  1004. dprintf("%ws\n", KeyName);
  1005. }
  1006. }
  1007. } else {
  1008. //
  1009. // findkcb case
  1010. //
  1011. if (GetKcbName(KcbAddr, KeyName, sizeof(KeyName))) {
  1012. for(j=0;KeyName[j] != UNICODE_NULL;j++);
  1013. if( (j == Count) && (_wcsnicmp(FullKeyName,KeyName,Count) == 0) ) {
  1014. dprintf("\nFound KCB = %p :: %ws\n\n",KcbAddr,KeyName);
  1015. return;
  1016. }
  1017. }
  1018. }
  1019. HashEntryAddr = NextHash;
  1020. if (CheckControlC()) {
  1021. return;
  1022. }
  1023. #undef KcbFld
  1024. }
  1025. }
  1026. }
  1027. if( subkey != NULL ) {
  1028. dprintf("\nSorry <%ws> is not cached \n\n",FullKeyName);
  1029. }
  1030. }
  1031. void
  1032. regcellindex(
  1033. LPSTR args
  1034. )
  1035. /*++
  1036. Routine Description:
  1037. Dumps the name when given a KCB address
  1038. Called as:
  1039. !cellindex HiveAddr HCELL_INDEX
  1040. Arguments:
  1041. args - Supplies the address of the HCELL_INDEX.
  1042. Return Value:
  1043. .
  1044. --*/
  1045. {
  1046. ULONG64 HiveAddr;
  1047. ULONG IdxAddr;
  1048. ULONG64 pcell;
  1049. BOOLEAN Flat;
  1050. CHAR Dummy[ 256 ];
  1051. if (sscanf(args,"%s %lX %lx",Dummy,&HiveAddr,&IdxAddr)) {
  1052. if (GetExpressionEx(args + strlen(Dummy), &HiveAddr, &args)) {
  1053. IdxAddr = (ULONG) GetExpression(args);
  1054. }
  1055. }
  1056. if(!GetFieldValue(HiveAddr, "HHIVE", "Flat", Flat) ){
  1057. if(Flat) {
  1058. pcell = MyHvpGetCellFlat(HiveAddr,IdxAddr);
  1059. } else {
  1060. pcell = MyHvpGetCellPaged(HiveAddr,IdxAddr);
  1061. }
  1062. dprintf("pcell: %p\n",pcell);
  1063. } else {
  1064. dprintf("could not read hive\n");
  1065. }
  1066. }
  1067. void
  1068. reghashindex (
  1069. LPSTR args
  1070. )
  1071. /*++
  1072. Routine Description:
  1073. display the index for the convkey
  1074. Called as:
  1075. !hashindex conv_key
  1076. Arguments:
  1077. args - convkey.
  1078. Return Value:
  1079. .
  1080. --*/
  1081. {
  1082. ULONG ConvKey;
  1083. CHAR Dummy[ 256 ];
  1084. DWORD64 TableSizeAddr;
  1085. DWORD64 HashTableAddr;
  1086. ULONG64 HashTable;
  1087. DWORD BytesRead;
  1088. ULONG Index;
  1089. if (!sscanf(args,"%s %lx",Dummy,&ConvKey)) {
  1090. ConvKey = 0;
  1091. }
  1092. TableSizeAddr = GetExpression("nt!CmpHashTableSize");
  1093. if (TableSizeAddr == 0) {
  1094. dprintf("Couldn't find address of CmpHashTableSize\n");
  1095. return;
  1096. }
  1097. ReadMemory(TableSizeAddr, &CmpHashTableSize, sizeof(CmpHashTableSize), &BytesRead);
  1098. if (BytesRead < sizeof(CmpHashTableSize)) {
  1099. dprintf("Couldn't get CmpHashTableSize from %08p\n",TableSizeAddr);
  1100. return;
  1101. }
  1102. HashTableAddr = GetExpression("nt!CmpCacheTable");
  1103. if (HashTableAddr == 0) {
  1104. dprintf("Couldn't find address of CmpCacheTable\n");
  1105. return ;
  1106. }
  1107. if (!ReadPointer(HashTableAddr, &HashTable)) {
  1108. dprintf("Couldn't get CmpCacheTable from %08p\n",HashTableAddr);
  1109. return;
  1110. } else {
  1111. dprintf("CmpCacheTable = %p\n\n",HashTable);
  1112. }
  1113. Index = GET_HASH_INDEX(ConvKey);
  1114. HashTable += Index*PtrSize;
  1115. dprintf("Hash Index[%8lx] : %lx\n",ConvKey,Index);
  1116. dprintf("Hash Entry[%8lx] : %p\n",ConvKey,HashTable);
  1117. }
  1118. void
  1119. regknode(
  1120. LPSTR args
  1121. )
  1122. /*++
  1123. Routine Description:
  1124. Dumps the name when given a KCB address
  1125. Called as:
  1126. !knode KNode_Address
  1127. Arguments:
  1128. args - Supplies the address of the CM_KEY_NODE.
  1129. Return Value:
  1130. .
  1131. --*/
  1132. {
  1133. char KeyName[ 256 ];
  1134. ULONG64 KnodeAddr;
  1135. DWORD BytesRead;
  1136. CHAR Dummy[ 256 ];
  1137. USHORT Signature,Flags,NameLength;
  1138. LARGE_INTEGER LastWriteTime;
  1139. ULONG Parent,MaxNameLen,MaxClassLen,MaxValueNameLen,MaxValueDataLen,Security,Class;
  1140. ULONG KeyNameOffset,Count,ValueList;
  1141. ULONG SubKeys[4];
  1142. if (sscanf(args,"%s %lX",Dummy,&KnodeAddr)) {
  1143. KnodeAddr = GetExpression(args + strlen(Dummy));
  1144. }
  1145. if (!GetFieldValue(KnodeAddr, "CM_KEY_NODE", "Signature", Signature) ) {
  1146. if( Signature == CM_KEY_NODE_SIGNATURE) {
  1147. dprintf("Signature: CM_KEY_NODE_SIGNATURE (kn)\n");
  1148. } else if(Signature == CM_LINK_NODE_SIGNATURE) {
  1149. dprintf("Signature: CM_LINK_NODE_SIGNATURE (kl)\n");
  1150. } else {
  1151. dprintf("Invalid Signature %u\n",Signature);
  1152. }
  1153. }
  1154. if (!GetFieldValue(KnodeAddr, "CM_KEY_NODE", "NameLength", NameLength) ) {
  1155. GetFieldOffset("CM_KEY_NODE", "Name", &KeyNameOffset);
  1156. if( !ReadMemory(KnodeAddr + KeyNameOffset,
  1157. KeyName,
  1158. NameLength,
  1159. &BytesRead) ) {
  1160. dprintf("Could not read KeyName\n");
  1161. } else {
  1162. KeyName[NameLength] = '\0';
  1163. dprintf("Name : %s\n", KeyName);
  1164. }
  1165. }
  1166. if (!GetFieldValue(KnodeAddr, "CM_KEY_NODE", "Parent", Parent) ) {
  1167. dprintf("ParentCell : 0x%lx\n", Parent);
  1168. }
  1169. if (!GetFieldValue(KnodeAddr, "CM_KEY_NODE", "Security", Security) ) {
  1170. dprintf("Security : 0x%lx [cell index]\n", Security);
  1171. }
  1172. if (!GetFieldValue(KnodeAddr, "CM_KEY_NODE", "Class", Class) ) {
  1173. dprintf("Class : 0x%lx [cell index]\n", Class);
  1174. }
  1175. if (!GetFieldValue(KnodeAddr, "CM_KEY_NODE", "Flags", Flags) ) {
  1176. dprintf("Flags : 0x%lx\n", Flags);
  1177. }
  1178. if (!GetFieldValue(KnodeAddr, "CM_KEY_NODE", "MaxNameLen", MaxNameLen) ) {
  1179. dprintf("MaxNameLen : 0x%lx\n", MaxNameLen);
  1180. }
  1181. if (!GetFieldValue(KnodeAddr, "CM_KEY_NODE", "MaxClassLen", MaxClassLen) ) {
  1182. dprintf("MaxClassLen : 0x%lx\n", MaxClassLen);
  1183. }
  1184. if (!GetFieldValue(KnodeAddr, "CM_KEY_NODE", "MaxValueNameLen", MaxValueNameLen) ) {
  1185. dprintf("MaxValueNameLen : 0x%lx\n", MaxValueNameLen);
  1186. }
  1187. if (!GetFieldValue(KnodeAddr, "CM_KEY_NODE", "MaxValueDataLen", MaxValueDataLen) ) {
  1188. dprintf("MaxValueDataLen : 0x%lx\n", MaxValueDataLen);
  1189. }
  1190. if (!GetFieldValue(KnodeAddr, "CM_KEY_NODE", "LastWriteTime", LastWriteTime) ) {
  1191. dprintf("LastWriteTime : 0x%8lx:0x%8lx\n", LastWriteTime.HighPart,LastWriteTime.LowPart);
  1192. }
  1193. if(!(Flags&KEY_HIVE_ENTRY)) {
  1194. GetFieldOffset("CM_KEY_NODE", "SubKeyCounts", &KeyNameOffset);
  1195. if( !ReadMemory(KnodeAddr + KeyNameOffset,
  1196. SubKeys,
  1197. 4*ULongSize,
  1198. &BytesRead) ) {
  1199. dprintf("Could not read SubKey Info\n");
  1200. } else {
  1201. dprintf("SubKeyCount[Stable ]: 0x%lx\n", SubKeys[0]);
  1202. dprintf("SubKeyLists[Stable ]: 0x%lx\n", SubKeys[2]);
  1203. dprintf("SubKeyCount[Volatile]: 0x%lx\n", SubKeys[1]);
  1204. dprintf("SubKeyLists[Volatile]: 0x%lx\n", SubKeys[3]);
  1205. }
  1206. if (!GetFieldValue(KnodeAddr, "CM_KEY_NODE", "ValueList.Count", Count)) {
  1207. dprintf("ValueList.Count : 0x%lx\n", Count);
  1208. if (!GetFieldValue(KnodeAddr, "CM_KEY_NODE", "ValueList.List", ValueList)) {
  1209. dprintf("ValueList.List : 0x%lx\n", ValueList);
  1210. }
  1211. }
  1212. }
  1213. }
  1214. void
  1215. regkbody(
  1216. LPSTR args
  1217. )
  1218. /*++
  1219. Routine Description:
  1220. displays a CM_KEY_BODY
  1221. Called as:
  1222. !kbody KBody_Address
  1223. Arguments:
  1224. args - Supplies the address of the CM_KEY_BODY.
  1225. Return Value:
  1226. .
  1227. --*/
  1228. {
  1229. ULONG64 KbodyAddr,KeyControlBlock,NotifyBlock,Process,KeyBodyList,CallerAddress;
  1230. DWORD BytesRead;
  1231. CHAR Dummy[ 256 ];
  1232. ULONG Type,Offset,Callers,i;
  1233. if (sscanf(args,"%s %lX",Dummy,&KbodyAddr)) {
  1234. KbodyAddr = GetExpression(args+ strlen(Dummy));
  1235. }
  1236. if (!GetFieldValue(KbodyAddr, "CM_KEY_BODY", "Type", Type) ) {
  1237. if( Type == KEY_BODY_TYPE) {
  1238. dprintf("Type : KEY_BODY_TYPE\n");
  1239. } else {
  1240. dprintf("Invalid Type %lx\n",Type);
  1241. return;
  1242. }
  1243. }
  1244. if (!GetFieldValue(KbodyAddr, "CM_KEY_BODY", "KeyControlBlock", KeyControlBlock) ) {
  1245. dprintf("KCB : %p\n", KeyControlBlock);
  1246. }
  1247. if (!GetFieldValue(KbodyAddr, "CM_KEY_BODY", "NotifyBlock", NotifyBlock) ) {
  1248. dprintf("NotifyBlock : %p\n", NotifyBlock);
  1249. }
  1250. if (!GetFieldValue(KbodyAddr, "CM_KEY_BODY", "Process", Process) ) {
  1251. dprintf("Process : %p\n", Process);
  1252. }
  1253. if (!GetFieldValue(KbodyAddr, "CM_KEY_BODY", "KeyBodyList", KeyBodyList) ) {
  1254. GetFieldOffset("CM_KEY_BODY", "KeyBodyList", &Offset);
  1255. dprintf("KeyBodyList : ");
  1256. if (!GetFieldValue(KbodyAddr + Offset, "_LIST_ENTRY", "Flink", KeyBodyList)) {
  1257. dprintf("0x%p ", KeyBodyList);
  1258. }
  1259. if (!GetFieldValue(KbodyAddr + Offset, "_LIST_ENTRY", "Blink", KeyBodyList)) {
  1260. dprintf("0x%p", KeyBodyList);
  1261. }
  1262. dprintf("\n");
  1263. }
  1264. if (!GetFieldValue(KbodyAddr, "CM_KEY_BODY", "Callers", Callers) ) {
  1265. GetFieldOffset("CM_KEY_BODY", "CallerAddress", &Offset);
  1266. if( Callers ) {
  1267. dprintf("Callers Stack: ");
  1268. }
  1269. for(i = 0;i< Callers;i++) {
  1270. dprintf("[%lu] ",i);
  1271. if( !ReadMemory(KbodyAddr + Offset + i*PtrSize,
  1272. &CallerAddress,
  1273. sizeof(CallerAddress),
  1274. &BytesRead) ) {
  1275. dprintf("Could not memory\n");
  1276. } else {
  1277. dprintf(" %p\n", CallerAddress);
  1278. }
  1279. }
  1280. }
  1281. }
  1282. void
  1283. regkvalue(
  1284. LPSTR args
  1285. )
  1286. /*++
  1287. Routine Description:
  1288. Dumps the name when given a KCB address
  1289. Called as:
  1290. !kvalue KValue_Address
  1291. Arguments:
  1292. args - Supplies the address of the CM_KEY_NODE.
  1293. Return Value:
  1294. .
  1295. --*/
  1296. {
  1297. char ValName[ 256 ];
  1298. ULONG64 KvalAddr;
  1299. DWORD BytesRead;
  1300. CHAR Dummy[ 256 ];
  1301. ULONG Offset,DataLength,Data,Type;
  1302. USHORT Signature,Flags,NameLength;
  1303. if (sscanf(args,"%s %lX",Dummy,&KvalAddr)) {
  1304. KvalAddr = GetExpression(args+ strlen(Dummy));
  1305. }
  1306. if (!GetFieldValue(KvalAddr, "CM_KEY_VALUE", "Signature", Signature) ) {
  1307. if( Signature == CM_KEY_VALUE_SIGNATURE) {
  1308. dprintf("Signature: CM_KEY_VALUE_SIGNATURE (kv)\n");
  1309. } else {
  1310. dprintf("Invalid Signature %lx\n",Signature);
  1311. }
  1312. }
  1313. if (!GetFieldValue(KvalAddr, "CM_KEY_VALUE", "Flags", Flags) ) {
  1314. if( (Flags & VALUE_COMP_NAME) &&
  1315. !GetFieldValue(KvalAddr, "CM_KEY_VALUE", "NameLength", NameLength)
  1316. ) {
  1317. GetFieldOffset("CM_KEY_VALUE", "Name", &Offset);
  1318. ReadMemory(KvalAddr + Offset,
  1319. ValName,
  1320. NameLength,
  1321. &BytesRead);
  1322. ValName[NameLength] = '\0';
  1323. dprintf("Name : %s {compressed}\n", ValName);
  1324. }
  1325. }
  1326. if (!GetFieldValue(KvalAddr, "CM_KEY_VALUE", "DataLength", DataLength) ) {
  1327. dprintf("DataLength: %lx\n", DataLength);
  1328. }
  1329. if (!GetFieldValue(KvalAddr, "CM_KEY_VALUE", "Data", Data) ) {
  1330. dprintf("Data : %lx [cell index]\n", Data);
  1331. }
  1332. if (!GetFieldValue(KvalAddr, "CM_KEY_VALUE", "Type", Type) ) {
  1333. dprintf("Type : %lx\n", Type);
  1334. }
  1335. }
  1336. void
  1337. regbaseblock(
  1338. LPSTR args
  1339. )
  1340. /*++
  1341. Routine Description:
  1342. displays the base block structure
  1343. Called as:
  1344. !baseblock HiveAddress
  1345. Arguments:
  1346. args - convkey.
  1347. Return Value:
  1348. .
  1349. --*/
  1350. {
  1351. WCHAR FileName[HBASE_NAME_ALLOC/sizeof(WCHAR) + 1];
  1352. ULONG64 BaseBlock,HiveAddr;
  1353. DWORD BytesRead;
  1354. CHAR Dummy[ 256 ];
  1355. ULONG Work;
  1356. LARGE_INTEGER TimeStamp;
  1357. if (sscanf(args,"%s %lX",Dummy,&HiveAddr)) {
  1358. HiveAddr = GetExpression(args+ strlen(Dummy));
  1359. }
  1360. if (GetFieldValue(HiveAddr, "_CMHIVE", "Hive.BaseBlock", BaseBlock)) {
  1361. dprintf("\tCan't CMHIVE Read from %p\n",HiveAddr);
  1362. return;
  1363. }
  1364. if (GetFieldValue( BaseBlock, "_HBASE_BLOCK", "FileName", FileName )) {
  1365. wcscpy(FileName, L"UNKNOWN");
  1366. } else {
  1367. if (FileName[0]==L'\0') {
  1368. wcscpy(FileName, L"NONAME");
  1369. } else {
  1370. FileName[HBASE_NAME_ALLOC/sizeof(WCHAR)]=L'\0';
  1371. }
  1372. }
  1373. dprintf("FileName : %ws\n",FileName);
  1374. if(!GetFieldValue( BaseBlock, "_HBASE_BLOCK", "Signature", Work )) {
  1375. if( Work == HBASE_BLOCK_SIGNATURE ) {
  1376. dprintf("Signature: HBASE_BLOCK_SIGNATURE\n");
  1377. } else {
  1378. dprintf("Signature: %lx\n",Work);
  1379. }
  1380. }
  1381. if(!GetFieldValue( BaseBlock, "_HBASE_BLOCK", "Sequence1", Work )) {
  1382. dprintf("Sequence1: %lx\n",Work);
  1383. }
  1384. if(!GetFieldValue( BaseBlock, "_HBASE_BLOCK", "Sequence2", Work )) {
  1385. dprintf("Sequence2: %lx\n",Work);
  1386. }
  1387. if(!GetFieldValue( BaseBlock, "_HBASE_BLOCK", "TimeStamp", TimeStamp )) {
  1388. dprintf("TimeStamp: %lx %lx\n",TimeStamp.HighPart,TimeStamp.LowPart);
  1389. }
  1390. if(!GetFieldValue( BaseBlock, "_HBASE_BLOCK", "Major", Work )) {
  1391. dprintf("Major : %lx\n",Work);
  1392. }
  1393. if(!GetFieldValue( BaseBlock, "_HBASE_BLOCK", "Minor", Work )) {
  1394. dprintf("Minor : %lx\n",Work);
  1395. }
  1396. if(!GetFieldValue( BaseBlock, "_HBASE_BLOCK", "Type", Work )) {
  1397. switch(Work) {
  1398. case HFILE_TYPE_PRIMARY:
  1399. dprintf("Type : HFILE_TYPE_PRIMARY\n");
  1400. break;
  1401. case HFILE_TYPE_LOG:
  1402. dprintf("Type : HFILE_TYPE_LOG\n");
  1403. break;
  1404. case HFILE_TYPE_EXTERNAL:
  1405. dprintf("Type : HFILE_TYPE_EXTERNAL\n");
  1406. break;
  1407. default:
  1408. dprintf("Type : %lx\n",Work);
  1409. break;
  1410. }
  1411. }
  1412. if(!GetFieldValue( BaseBlock, "_HBASE_BLOCK", "Format", Work )) {
  1413. if( Work == HBASE_FORMAT_MEMORY ) {
  1414. dprintf("Format : HBASE_FORMAT_MEMORY\n");
  1415. } else {
  1416. dprintf("Format : %lx\n",Work);
  1417. }
  1418. }
  1419. if(!GetFieldValue( BaseBlock, "_HBASE_BLOCK", "RootCell", Work )) {
  1420. dprintf("RootCell : %lx\n",Work);
  1421. }
  1422. if(!GetFieldValue( BaseBlock, "_HBASE_BLOCK", "Length", Work )) {
  1423. dprintf("Length : %lx\n",Work);
  1424. }
  1425. if(!GetFieldValue( BaseBlock, "_HBASE_BLOCK", "Cluster", Work )) {
  1426. dprintf("Cluster : %lx\n",Work);
  1427. }
  1428. if(!GetFieldValue( BaseBlock, "_HBASE_BLOCK", "CheckSum", Work )) {
  1429. dprintf("CheckSum : %lx\n",Work);
  1430. }
  1431. }
  1432. void
  1433. reghivelist(
  1434. )
  1435. /*++
  1436. Routine Description:
  1437. dumps all the hives in the system
  1438. Called as:
  1439. !hivelist
  1440. Arguments:
  1441. Return Value:
  1442. .
  1443. --*/
  1444. {
  1445. ULONG64 pCmpHiveListHead;
  1446. ULONG64 pNextHiveList;
  1447. ULONG BytesRead, WorkVar;
  1448. ULONG64 CmHive;
  1449. USHORT Count;
  1450. ULONG HiveListOffset;
  1451. FIELD_INFO offField = {"HiveList", NULL, 0, DBG_DUMP_FIELD_RETURN_ADDRESS, 0, NULL};
  1452. SYM_DUMP_PARAM TypeSym ={
  1453. sizeof (SYM_DUMP_PARAM), "_CMHIVE", DBG_DUMP_NO_PRINT, 0,
  1454. NULL, NULL, NULL, 1, &offField
  1455. };
  1456. ULONG Stable_Length=0, Volatile_Length=0;
  1457. ULONG64 Stable_Map=0, Volatile_Map=0;
  1458. WCHAR FileName[HBASE_NAME_ALLOC/sizeof(WCHAR) + 1];
  1459. ULONG64 BaseBlock;
  1460. //
  1461. // First go and get the hivelisthead
  1462. //
  1463. pCmpHiveListHead = GetExpression("nt!CmpHiveListHead");
  1464. if (pCmpHiveListHead==0) {
  1465. dprintf("CmpHiveListHead couldn't be read\n");
  1466. return;
  1467. }
  1468. if (!ReadPointer(pCmpHiveListHead, &pNextHiveList)) {
  1469. dprintf("Couldn't read first Flink (%p) of CmpHiveList\n",
  1470. pCmpHiveListHead);
  1471. return;
  1472. }
  1473. TotalPages = TotalPresentPages = 0;
  1474. // Get The offset
  1475. if (Ioctl(IG_DUMP_SYMBOL_INFO, &TypeSym, TypeSym.size)) {
  1476. return;
  1477. }
  1478. HiveListOffset = (ULONG) offField.address;
  1479. dprintf("-------------------------------------------------------------------------------------------------------------\n");
  1480. dprintf("| HiveAddr |Stable Length|Stable Map|Volatile Length|Volatile Map|MappedViews|PinnedViews|U(Cnt)| BaseBlock | FileName \n");
  1481. dprintf("-------------------------------------------------------------------------------------------------------------\n");
  1482. while (pNextHiveList != pCmpHiveListHead) {
  1483. if (CheckControlC()) {
  1484. break;
  1485. }
  1486. CmHive = pNextHiveList - HiveListOffset;
  1487. if(!GetFieldValue(CmHive, "_CMHIVE", "Hive.Signature", WorkVar)) {
  1488. if( WorkVar != HHIVE_SIGNATURE ) {
  1489. dprintf("Invalid Hive signature: %lx\n",WorkVar);
  1490. break;
  1491. }
  1492. }
  1493. dprintf("| %p ",CmHive);
  1494. if(!GetHiveMaps(CmHive,&Stable_Map,&Stable_Length,&Volatile_Map,&Volatile_Length) ) {
  1495. break;
  1496. }
  1497. dprintf("| %8lx ",Stable_Length);
  1498. dprintf("| %p ",Stable_Map);
  1499. dprintf("| %8lx ",Volatile_Length);
  1500. dprintf("| %p ",Volatile_Map);
  1501. if (!GetFieldValue(CmHive, "CMHIVE", "MappedViews", Count)) {
  1502. dprintf("| %8u ",Count);
  1503. }
  1504. if (!GetFieldValue(CmHive, "CMHIVE", "PinnedViews", Count)) {
  1505. dprintf("| %8u ",Count);
  1506. }
  1507. if (!GetFieldValue(CmHive, "CMHIVE", "UseCount", WorkVar)) {
  1508. dprintf("| %5u",WorkVar);
  1509. }
  1510. if (GetFieldValue(CmHive, "_CMHIVE", "Hive.BaseBlock", BaseBlock)) {
  1511. dprintf("\tCan't CMHIVE Read from %p\n",CmHive);
  1512. continue;
  1513. }
  1514. dprintf("| %p |",BaseBlock);
  1515. if (GetFieldValue( BaseBlock, "_HBASE_BLOCK", "FileName", FileName )) {
  1516. wcscpy(FileName, L"<UNKNOWN>");
  1517. } else {
  1518. if (FileName[0]==L'\0') {
  1519. wcscpy(FileName, L"<NONAME>");
  1520. } else {
  1521. FileName[HBASE_NAME_ALLOC/sizeof(WCHAR)]=L'\0';
  1522. }
  1523. }
  1524. dprintf(" %ws\n",FileName);
  1525. if (GetFieldValue(pNextHiveList, "_LIST_ENTRY", "Flink", pNextHiveList)) {
  1526. dprintf("Couldn't read Flink (%p) of %p\n",
  1527. pCmpHiveListHead,pNextHiveList);
  1528. break;
  1529. }
  1530. }
  1531. dprintf("-------------------------------------------------------------------------------------------------------------\n");
  1532. dprintf("\n");
  1533. }
  1534. void
  1535. regviewlist(
  1536. LPSTR args
  1537. )
  1538. /*++
  1539. Routine Description:
  1540. dumps all the views mapped/pinned for the specified hive
  1541. Called as:
  1542. !viewlist <HiveAddr>
  1543. Arguments:
  1544. args - hive.
  1545. Return Value:
  1546. .
  1547. --*/
  1548. {
  1549. ULONG64 CmHive,PinViewListHead,LRUViewListHead,Flink,Blink,ViewAddr,Address;
  1550. ULONG64 List1,List2;
  1551. DWORD BytesRead;
  1552. CHAR Dummy[ 256 ];
  1553. ULONG WorkVar,OffsetPinned,OffsetMapped,OffsetPinnedHead,OffsetMappedHead;
  1554. USHORT MappedViews,PinnedViews;
  1555. if (sscanf(args,"%s %lX",Dummy,&CmHive)) {
  1556. CmHive = GetExpression(args+ strlen(Dummy));
  1557. }
  1558. if(!GetFieldValue(CmHive, "_CMHIVE", "Hive.Signature", WorkVar)) {
  1559. if( WorkVar != HHIVE_SIGNATURE ) {
  1560. dprintf("Invalid Hive signature: %lx\n",WorkVar);
  1561. return;
  1562. }
  1563. } else {
  1564. dprintf("Could not read hive at %p\n",CmHive);
  1565. return;
  1566. }
  1567. if (GetFieldValue(CmHive, "CMHIVE", "MappedViews", MappedViews) ||
  1568. GetFieldValue(CmHive, "CMHIVE", "PinnedViews", PinnedViews) ||
  1569. GetFieldOffset("_CMHIVE", "PinViewListHead", &OffsetPinnedHead) ||
  1570. GetFieldOffset("_CMHIVE", "LRUViewListHead", &OffsetMappedHead) ||
  1571. GetFieldOffset("_CM_VIEW_OF_FILE", "PinViewList", &OffsetPinned) ||
  1572. GetFieldOffset("_CM_VIEW_OF_FILE", "LRUViewList", &OffsetMapped)
  1573. ) {
  1574. dprintf("Could not read hive at %p\n",CmHive);
  1575. return;
  1576. }
  1577. PinViewListHead = CmHive + OffsetPinnedHead;
  1578. LRUViewListHead = CmHive + OffsetMappedHead;
  1579. if ( !GetFieldValue(PinViewListHead, "_LIST_ENTRY", "Flink", Flink) &&
  1580. !GetFieldValue(PinViewListHead, "_LIST_ENTRY", "Blink", Blink)
  1581. ) {
  1582. dprintf("%4u Pinned Views ; PinViewListHead = %p %p\n",PinnedViews,Flink,Blink);
  1583. if( PinnedViews ) {
  1584. dprintf("--------------------------------------------------------------------------------------------------------------\n");
  1585. dprintf("| ViewAddr |FileOffset| Size |ViewAddress| Bcb | LRUViewList | PinViewList | UseCount |\n");
  1586. dprintf("--------------------------------------------------------------------------------------------------------------\n");
  1587. for(;PinnedViews;PinnedViews--) {
  1588. if (CheckControlC()) {
  1589. break;
  1590. }
  1591. ViewAddr = Flink;
  1592. ViewAddr -= OffsetPinned;
  1593. dprintf("| %p ",ViewAddr);
  1594. if( !GetFieldValue(ViewAddr, "_CM_VIEW_OF_FILE", "FileOffset", WorkVar) ) {
  1595. dprintf("| %8lx ",WorkVar);
  1596. }
  1597. if( !GetFieldValue(ViewAddr, "_CM_VIEW_OF_FILE", "Size", WorkVar) ) {
  1598. dprintf("| %8lx ",WorkVar);
  1599. }
  1600. if( !GetFieldValue(ViewAddr, "_CM_VIEW_OF_FILE", "ViewAddress", Address) ) {
  1601. dprintf("| %p ",Address);
  1602. }
  1603. if( Address == 0 ) {
  1604. dprintf("could not read memory - paged out\n");
  1605. break;
  1606. }
  1607. if( !GetFieldValue(ViewAddr, "_CM_VIEW_OF_FILE", "Bcb", Address) ) {
  1608. dprintf("| %p ",Address);
  1609. }
  1610. if( !GetFieldValue(ViewAddr + OffsetMapped, "_LIST_ENTRY", "Flink", List1) ) {
  1611. dprintf("| %p",List1);
  1612. }
  1613. if( !GetFieldValue(ViewAddr + OffsetMapped, "_LIST_ENTRY", "Blink", List2) ) {
  1614. dprintf(" %p ",List2);
  1615. }
  1616. if( !GetFieldValue(ViewAddr + OffsetPinned, "_LIST_ENTRY", "Flink", Flink) ) {
  1617. dprintf("| %p",Flink);
  1618. }
  1619. if( !GetFieldValue(ViewAddr + OffsetPinned, "_LIST_ENTRY", "Blink", Blink) ) {
  1620. dprintf(" %p |",Blink);
  1621. }
  1622. if( !GetFieldValue(ViewAddr, "_CM_VIEW_OF_FILE", "UseCount", WorkVar) ) {
  1623. dprintf(" %8lx |\n",WorkVar);
  1624. }
  1625. }
  1626. dprintf("--------------------------------------------------------------------------------------------------------------\n");
  1627. }
  1628. }
  1629. dprintf("\n");
  1630. if ( !GetFieldValue(LRUViewListHead, "_LIST_ENTRY", "Flink", Flink) &&
  1631. !GetFieldValue(LRUViewListHead, "_LIST_ENTRY", "Blink", Blink)
  1632. ) {
  1633. dprintf("%4u Mapped Views ; LRUViewListHead = %p %p\n",MappedViews,Flink,Blink);
  1634. if( MappedViews ) {
  1635. dprintf("--------------------------------------------------------------------------------------------------------------\n");
  1636. dprintf("| ViewAddr |FileOffset| Size |ViewAddress| Bcb | LRUViewList | PinViewList | UseCount |\n");
  1637. dprintf("--------------------------------------------------------------------------------------------------------------\n");
  1638. for(;MappedViews;MappedViews--) {
  1639. if (CheckControlC()) {
  1640. break;
  1641. }
  1642. ViewAddr = Flink;
  1643. ViewAddr -= OffsetMapped;
  1644. dprintf("| %p ",ViewAddr);
  1645. if( !GetFieldValue(ViewAddr, "_CM_VIEW_OF_FILE", "FileOffset", WorkVar) ) {
  1646. dprintf("| %8lx ",WorkVar);
  1647. }
  1648. if( !GetFieldValue(ViewAddr, "_CM_VIEW_OF_FILE", "Size", WorkVar) ) {
  1649. dprintf("| %8lx ",WorkVar);
  1650. }
  1651. if( !GetFieldValue(ViewAddr, "_CM_VIEW_OF_FILE", "ViewAddress", Address) ) {
  1652. dprintf("| %p ",Address);
  1653. }
  1654. if( Address == 0 ) {
  1655. dprintf("could not read memory - paged out\n");
  1656. break;
  1657. }
  1658. if( !GetFieldValue(ViewAddr, "_CM_VIEW_OF_FILE", "Bcb", Address) ) {
  1659. dprintf("| %p ",Address);
  1660. }
  1661. if( !GetFieldValue(ViewAddr + OffsetMapped, "_LIST_ENTRY", "Flink", Flink) ) {
  1662. dprintf("| %p",Flink);
  1663. }
  1664. if( !GetFieldValue(ViewAddr + OffsetMapped, "_LIST_ENTRY", "Blink", Blink) ) {
  1665. dprintf(" %p ",Blink);
  1666. }
  1667. if( !GetFieldValue(ViewAddr + OffsetPinned, "_LIST_ENTRY", "Flink", List1) ) {
  1668. dprintf("| %p",List1);
  1669. }
  1670. if( !GetFieldValue(ViewAddr + OffsetPinned, "_LIST_ENTRY", "Blink", List2) ) {
  1671. dprintf(" %p |",List2);
  1672. }
  1673. if( !GetFieldValue(ViewAddr, "_CM_VIEW_OF_FILE", "UseCount", WorkVar) ) {
  1674. dprintf(" %8lx |\n",WorkVar);
  1675. }
  1676. }
  1677. dprintf("--------------------------------------------------------------------------------------------------------------\n");
  1678. }
  1679. }
  1680. dprintf("\n");
  1681. }
  1682. void
  1683. regfreebins(
  1684. LPSTR args
  1685. )
  1686. /*++
  1687. Routine Description:
  1688. dumps all the free bins for the specified hive
  1689. Called as:
  1690. !freebins <HiveAddr>
  1691. Arguments:
  1692. args - hive.
  1693. Return Value:
  1694. .
  1695. --*/
  1696. {
  1697. ULONG64 CmHive,AnchorAddr,BinAddr,Flink,Blink;
  1698. DWORD BytesRead;
  1699. CHAR Dummy[ 256 ];
  1700. ULONG WorkVar,OffsetFreeBins,Offset;
  1701. ULONG DUAL_Size,StorageOffset;
  1702. FIELD_INFO offField = {"Hive.Storage", NULL, 0, DBG_DUMP_FIELD_RETURN_ADDRESS, 0, NULL};
  1703. SYM_DUMP_PARAM TypeSym ={
  1704. sizeof (SYM_DUMP_PARAM), "_CMHIVE", DBG_DUMP_NO_PRINT, 0,
  1705. NULL, NULL, NULL, 1, &offField
  1706. };
  1707. USHORT Nr = 0;
  1708. if (sscanf(args,"%s %lX",Dummy,&CmHive)) {
  1709. CmHive = GetExpression(args+ strlen(Dummy));
  1710. }
  1711. if(!GetFieldValue(CmHive, "_CMHIVE", "Hive.Signature", WorkVar)) {
  1712. if( WorkVar != HHIVE_SIGNATURE ) {
  1713. dprintf("Invalid Hive signature: %lx\n",WorkVar);
  1714. return;
  1715. }
  1716. } else {
  1717. dprintf("Could not read hive at %p\n",CmHive);
  1718. return;
  1719. }
  1720. // Get the offset of Hive.Storage in _CMHIVE
  1721. if (Ioctl(IG_DUMP_SYMBOL_INFO, &TypeSym, TypeSym.size)) {
  1722. dprintf("Cannot find _CMHIVE type.\n");
  1723. return;
  1724. }
  1725. StorageOffset = (ULONG) offField.address;
  1726. DUAL_Size = GetTypeSize("_DUAL");
  1727. GetFieldOffset("_FREE_HBIN", "ListEntry", &Offset);
  1728. GetFieldOffset("_DUAL", "FreeBins", &OffsetFreeBins);
  1729. dprintf("Stable Storage ... \n");
  1730. dprintf("-------------------------------------------------------------------\n");
  1731. dprintf("| Address |FileOffset| Size | Flags | Flink | Blink |\n");
  1732. dprintf("-------------------------------------------------------------------\n");
  1733. Nr = 0;
  1734. AnchorAddr = CmHive + StorageOffset + OffsetFreeBins;
  1735. if ( !GetFieldValue(AnchorAddr, "_LIST_ENTRY", "Flink", Flink) &&
  1736. !GetFieldValue(AnchorAddr, "_LIST_ENTRY", "Blink", Blink)
  1737. ) {
  1738. while((ULONG64)Flink != (ULONG64)AnchorAddr ) {
  1739. if (CheckControlC()) {
  1740. break;
  1741. }
  1742. BinAddr = Flink - Offset;
  1743. dprintf("| %p ",BinAddr);
  1744. if(!GetFieldValue(BinAddr, "_FREE_HBIN", "FileOffset", WorkVar)) {
  1745. dprintf("| %8lx ",WorkVar);
  1746. }
  1747. if(!GetFieldValue(BinAddr, "_FREE_HBIN", "Size", WorkVar)) {
  1748. dprintf("| %8lx ",WorkVar);
  1749. }
  1750. if(!GetFieldValue(BinAddr, "_FREE_HBIN", "Flags", WorkVar)) {
  1751. dprintf("| %8lx ",WorkVar);
  1752. }
  1753. if( !GetFieldValue(BinAddr + Offset, "_LIST_ENTRY", "Flink", Flink) ) {
  1754. dprintf("| %p ",Flink);
  1755. }
  1756. if( !GetFieldValue(BinAddr + Offset, "_LIST_ENTRY", "Blink", Blink) ) {
  1757. dprintf("| %p |\n",Blink);
  1758. }
  1759. Nr++;
  1760. }
  1761. }
  1762. dprintf("-------------------------------------------------------------------\n");
  1763. dprintf("%4u FreeBins\n",Nr);
  1764. dprintf("\n");
  1765. dprintf("Volatile Storage ... \n");
  1766. dprintf("-------------------------------------------------------------------\n");
  1767. dprintf("| Address |FileOffset| Size | Flags | Flink | Blink |\n");
  1768. dprintf("-------------------------------------------------------------------\n");
  1769. AnchorAddr = CmHive + StorageOffset + DUAL_Size + OffsetFreeBins;
  1770. Nr = 0;
  1771. if ( !GetFieldValue(AnchorAddr, "_LIST_ENTRY", "Flink", Flink) &&
  1772. !GetFieldValue(AnchorAddr, "_LIST_ENTRY", "Blink", Blink)
  1773. ) {
  1774. while((ULONG64)Flink != (ULONG64)AnchorAddr ) {
  1775. if (CheckControlC()) {
  1776. break;
  1777. }
  1778. BinAddr = Flink - Offset;
  1779. dprintf("| %p ",BinAddr);
  1780. if(!GetFieldValue(BinAddr, "_FREE_HBIN", "FileOffset", WorkVar)) {
  1781. dprintf("| %8lx ",WorkVar);
  1782. }
  1783. if(!GetFieldValue(BinAddr, "_FREE_HBIN", "Size", WorkVar)) {
  1784. dprintf("| %8lx ",WorkVar);
  1785. }
  1786. if(!GetFieldValue(BinAddr, "_FREE_HBIN", "Flags", WorkVar)) {
  1787. dprintf("| %8lx ",WorkVar);
  1788. }
  1789. if( !GetFieldValue(BinAddr + Offset, "_LIST_ENTRY", "Flink", Flink) ) {
  1790. dprintf("| %p ",Flink);
  1791. }
  1792. if( !GetFieldValue(BinAddr + Offset, "_LIST_ENTRY", "Blink", Blink) ) {
  1793. dprintf("| %p |\n",Blink);
  1794. }
  1795. Nr++;
  1796. }
  1797. }
  1798. dprintf("-------------------------------------------------------------------\n");
  1799. dprintf("%4u FreeBins\n",Nr);
  1800. dprintf("\n");
  1801. }
  1802. void
  1803. regdirtyvector(
  1804. LPSTR args
  1805. )
  1806. /*++
  1807. Routine Description:
  1808. displays the dirty vector of the hive
  1809. Called as:
  1810. !dirtyvector <HiveAddr>
  1811. Arguments:
  1812. args - convkey.
  1813. Return Value:
  1814. .
  1815. --*/
  1816. {
  1817. ULONG64 CmHive,BufferAddr;
  1818. DWORD BytesRead;
  1819. CHAR Dummy[ 256 ];
  1820. ULONG WorkVar,SizeOfBitMap,i;
  1821. ULONG BitsPerULONG;
  1822. ULONG BitsPerBlock;
  1823. ULONG DirtyBuffer;
  1824. ULONG Mask;
  1825. if (sscanf(args,"%s %lX",Dummy,&CmHive)) {
  1826. CmHive = GetExpression(args+ strlen(Dummy));
  1827. }
  1828. if(!GetFieldValue(CmHive, "_CMHIVE", "Hive.Signature", WorkVar)) {
  1829. if( WorkVar != HHIVE_SIGNATURE ) {
  1830. dprintf("Invalid Hive signature: %lx\n",WorkVar);
  1831. return;
  1832. }
  1833. } else {
  1834. dprintf("Could not read hive at %p\n",CmHive);
  1835. return;
  1836. }
  1837. dprintf("HSECTOR_SIZE = %lx\n",HSECTOR_SIZE);
  1838. dprintf("HBLOCK_SIZE = %lx\n",HBLOCK_SIZE);
  1839. dprintf("PAGE_SIZE = %lx\n",PageSize);
  1840. dprintf("\n");
  1841. if(!GetFieldValue(CmHive, "_CMHIVE", "Hive.DirtyAlloc", WorkVar)) {
  1842. dprintf("DirtyAlloc = : 0x%lx\n",WorkVar);
  1843. }
  1844. if(!GetFieldValue(CmHive, "_CMHIVE", "Hive.DirtyCount", WorkVar)) {
  1845. dprintf("DirtyCount = : 0x%lx\n",WorkVar);
  1846. }
  1847. if(!GetFieldValue(CmHive, "_CMHIVE", "Hive.DirtyVector.Buffer", BufferAddr)) {
  1848. dprintf("Buffer = : 0x%p\n",BufferAddr);
  1849. }
  1850. dprintf("\n");
  1851. if(GetFieldValue(CmHive, "_CMHIVE", "Hive.DirtyVector.SizeOfBitMap", SizeOfBitMap)) {
  1852. return;
  1853. }
  1854. BitsPerULONG = 8*ULongSize;
  1855. BitsPerBlock = HBLOCK_SIZE / HSECTOR_SIZE;
  1856. dprintf(" Address 32k 32k");
  1857. for(i=0;i<SizeOfBitMap;i++) {
  1858. if (CheckControlC()) {
  1859. break;
  1860. }
  1861. if( !(i%(2*BitsPerULONG ) ) ){
  1862. dprintf("\n 0x%8lx ",i*HSECTOR_SIZE);
  1863. }
  1864. if( !(i%BitsPerBlock) ) {
  1865. dprintf(" ");
  1866. }
  1867. if( !(i%BitsPerULONG) ) {
  1868. //
  1869. // fetch in a new DWORD
  1870. //
  1871. if( !ReadMemory(BufferAddr,
  1872. &DirtyBuffer,
  1873. ULongSize,
  1874. &BytesRead)) {
  1875. dprintf("\tRead %lx bytes from %lx\n",BytesRead,BufferAddr);
  1876. return;
  1877. }
  1878. BufferAddr += ULongSize;
  1879. dprintf("\t");
  1880. }
  1881. Mask = ((DirtyBuffer >> (i%BitsPerULONG)) & 0x1);
  1882. //Mask <<= (BitsPerULONG - (i%BitsPerULONG) - 1);
  1883. //Mask &= DirtyBuffer;
  1884. dprintf("%s",Mask?"1":"0");
  1885. }
  1886. dprintf("\n\n");
  1887. }
  1888. CCHAR CmKDFindFirstSetLeft[256] = {
  1889. 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
  1890. 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  1891. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
  1892. 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
  1893. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  1894. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  1895. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  1896. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  1897. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  1898. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  1899. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  1900. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  1901. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  1902. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  1903. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  1904. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};
  1905. #define CmKDComputeIndex(Index, Size) \
  1906. { \
  1907. Index = (Size >> HHIVE_FREE_DISPLAY_SHIFT) - 1; \
  1908. if (Index >= HHIVE_LINEAR_INDEX ) { \
  1909. \
  1910. /* \
  1911. ** Too big for the linear lists, compute the exponential \
  1912. ** list. \
  1913. */ \
  1914. \
  1915. if (Index > 255) { \
  1916. /* \
  1917. ** Too big for all the lists, use the last index. \
  1918. */ \
  1919. Index = HHIVE_FREE_DISPLAY_SIZE-1; \
  1920. } else { \
  1921. Index = CmKDFindFirstSetLeft[Index] + \
  1922. HHIVE_FREE_DISPLAY_BIAS; \
  1923. } \
  1924. } \
  1925. }
  1926. void
  1927. regfreecells(
  1928. LPSTR args
  1929. )
  1930. /*++
  1931. Routine Description:
  1932. displays the free cells map in a bin
  1933. Called as:
  1934. !freecells <BinAddr>
  1935. Arguments:
  1936. args - convkey.
  1937. Return Value:
  1938. .
  1939. --*/
  1940. {
  1941. ULONG64 BinAddr;
  1942. DWORD BytesRead;
  1943. CHAR Dummy[ 256 ];
  1944. ULONG WorkVar,FileOffset,Size,BinHeaderSize;
  1945. ULONG NrOfCellsPerIndex;
  1946. ULONG NrOfCellsTotal;
  1947. ULONG TotalFreeSize;
  1948. ULONG Index;
  1949. ULONG CurrIndex,Offset;
  1950. LONG Current;
  1951. if (sscanf(args,"%s %lX",Dummy,&BinAddr)) {
  1952. BinAddr = GetExpression(args+ strlen(Dummy));
  1953. }
  1954. if(!GetFieldValue(BinAddr, "_HBIN", "Signature", WorkVar)) {
  1955. if( WorkVar != HBIN_SIGNATURE ) {
  1956. dprintf("\tInvalid Bin signature %lx \n",WorkVar);
  1957. return;
  1958. }
  1959. } else {
  1960. dprintf("Could not read bin at %p\n",BinAddr);
  1961. return;
  1962. }
  1963. if(GetFieldValue(BinAddr, "_HBIN", "FileOffset", FileOffset) ||
  1964. GetFieldValue(BinAddr, "_HBIN", "Size", Size)
  1965. ) {
  1966. dprintf("Could not read bin at %p\n",BinAddr);
  1967. }
  1968. BinHeaderSize = GetTypeSize("_HBIN");
  1969. dprintf("Bin Offset = 0x%lx Size = 0x%lx\n",FileOffset,Size);
  1970. NrOfCellsTotal = 0;
  1971. TotalFreeSize = 0;
  1972. for(CurrIndex = 0;CurrIndex<HHIVE_FREE_DISPLAY_SIZE;CurrIndex++) {
  1973. dprintf("\n FreeDisplay[%2lu] :: ",CurrIndex);
  1974. NrOfCellsPerIndex = 0;
  1975. Offset = BinHeaderSize;
  1976. while( Offset < Size ) {
  1977. if (CheckControlC()) {
  1978. break;
  1979. }
  1980. if( !ReadMemory(BinAddr + Offset,
  1981. &Current,
  1982. ULongSize,
  1983. &BytesRead) ) {
  1984. dprintf("\tRead %lx bytes from %lx\n",BytesRead,BinAddr + Offset);
  1985. return;
  1986. }
  1987. if(Current>0) {
  1988. //
  1989. // free cell
  1990. //
  1991. CmKDComputeIndex(Index, Current);
  1992. if( Index == CurrIndex ) {
  1993. //
  1994. // dum it here as this is the right index
  1995. //
  1996. NrOfCellsTotal++;
  1997. NrOfCellsPerIndex++;
  1998. TotalFreeSize += Current;
  1999. dprintf(" %lx [%lx]",Offset,Current);
  2000. if( !(NrOfCellsPerIndex % 8) && ((Offset + Current) < Size) ) {
  2001. dprintf("\n");
  2002. }
  2003. }
  2004. } else {
  2005. Current *= -1;
  2006. }
  2007. Offset += Current;
  2008. }
  2009. }
  2010. dprintf("\nTotal: FreeCells = %lu, FreeSpace = 0x%lx BinUsage = %.2f%%\n",NrOfCellsTotal,TotalFreeSize,
  2011. (float)(((float)(Size-BinHeaderSize-TotalFreeSize)/(float)(Size-BinHeaderSize))*100.00)
  2012. );
  2013. }
  2014. void
  2015. regfreehints(
  2016. LPSTR args
  2017. )
  2018. /*++
  2019. Routine Description:
  2020. displays the freehints information for the hive
  2021. Called as:
  2022. !freehints <HiveAddr> <StorageCount> <DisplayCount>
  2023. Arguments:
  2024. args - convkey.
  2025. Return Value:
  2026. .
  2027. --*/
  2028. {
  2029. ULONG64 CmHive,BufferAddr;
  2030. DWORD BytesRead;
  2031. CHAR Dummy[ 256 ];
  2032. ULONG WorkVar;
  2033. ULONG Mask;
  2034. ULONG BitsPerULONG;
  2035. ULONG BitsPerBlock;
  2036. ULONG BitsPerLine;
  2037. ULONG Stable_Length=0, Volatile_Length=0;
  2038. ULONG64 Stable_Map=0, Volatile_Map=0;
  2039. ULONG DisplayCount;
  2040. ULONG StorageCount;
  2041. ULONG SizeOfBitmap;
  2042. ULONG i;
  2043. FIELD_INFO offField = {"Hive.Storage", NULL, 0, DBG_DUMP_FIELD_RETURN_ADDRESS, 0, NULL};
  2044. SYM_DUMP_PARAM TypeSym ={
  2045. sizeof (SYM_DUMP_PARAM), "_CMHIVE", DBG_DUMP_NO_PRINT, 0,
  2046. NULL, NULL, NULL, 1, &offField
  2047. };
  2048. ULONG DUAL_Size,StorageOffset,RTL_BITMAP_Size,OffsetFreeDisplay;
  2049. ULONG64 DirtyBufferAddr;
  2050. ULONG DirtyBuffer;
  2051. if (sscanf(args,"%s %lX",Dummy,&CmHive)) {
  2052. if (GetExpressionEx(args+ strlen(Dummy), &CmHive, &args)) {
  2053. if (!sscanf(args,"%lu %lu",&StorageCount,&DisplayCount)) {
  2054. StorageCount = DisplayCount = 0;
  2055. }
  2056. }
  2057. }
  2058. if(!GetFieldValue(CmHive, "_CMHIVE", "Hive.Signature", WorkVar)) {
  2059. if( WorkVar != HHIVE_SIGNATURE ) {
  2060. dprintf("Invalid Hive signature: %lx\n",WorkVar);
  2061. return;
  2062. }
  2063. } else {
  2064. dprintf("Could not read hive at %p\n",CmHive);
  2065. return;
  2066. }
  2067. dprintf("HSECTOR_SIZE = %lx\n",HSECTOR_SIZE);
  2068. dprintf("HBLOCK_SIZE = %lx\n",HBLOCK_SIZE);
  2069. dprintf("PAGE_SIZE = %lx\n",PageSize);
  2070. dprintf("\n");
  2071. BitsPerULONG = 8*ULongSize;
  2072. BitsPerBlock = 0x10000 / HBLOCK_SIZE; // 64k blocks
  2073. BitsPerLine = 0x40000 / HBLOCK_SIZE; // 256k lines (vicinity reasons)
  2074. if(!GetHiveMaps(CmHive,&Stable_Map,&Stable_Length,&Volatile_Map,&Volatile_Length) ) {
  2075. return;
  2076. }
  2077. if( StorageCount == 0 ) {
  2078. SizeOfBitmap = Stable_Length / HBLOCK_SIZE;
  2079. } else {
  2080. SizeOfBitmap = Volatile_Length / HBLOCK_SIZE;
  2081. }
  2082. // Get the offset of Hive.FreeDisplay in _CMHIVE
  2083. if (Ioctl(IG_DUMP_SYMBOL_INFO, &TypeSym, TypeSym.size)) {
  2084. dprintf("Cannot find _CMHIVE type.\n");
  2085. return;
  2086. }
  2087. StorageOffset = (ULONG) offField.address;
  2088. DUAL_Size = GetTypeSize("_DUAL");
  2089. RTL_BITMAP_Size = GetTypeSize("RTL_BITMAP");
  2090. dprintf("bitmap size = %lu\n",RTL_BITMAP_Size);
  2091. GetFieldOffset("_DUAL", "FreeDisplay", &OffsetFreeDisplay);
  2092. BufferAddr = CmHive + StorageOffset + DUAL_Size * StorageCount + OffsetFreeDisplay + DisplayCount * RTL_BITMAP_Size;
  2093. if(GetFieldValue(BufferAddr, "RTL_BITMAP", "Buffer", DirtyBufferAddr) ) {
  2094. dprintf("Cannot read bitmap address\n");
  2095. return;
  2096. }
  2097. dprintf("Storage = %s , FreeDisplay[%lu]: \n",StorageCount?"Volatile":"Stable",DisplayCount);
  2098. dprintf("\n%8s %16s %16s %16s %16s","Address","64K (0x10000)","64K (0x10000)","64K (0x10000)","64K (0x10000)");
  2099. for(i=0;i<SizeOfBitmap;i++) {
  2100. if (CheckControlC()) {
  2101. break;
  2102. }
  2103. if( !(i%BitsPerLine) ){
  2104. dprintf("\n 0x%8lx ",i*HBLOCK_SIZE);
  2105. }
  2106. if( !(i%BitsPerBlock) ) {
  2107. dprintf(" ");
  2108. }
  2109. if( !(i%BitsPerULONG) ) {
  2110. //
  2111. // fetch in a new DWORD
  2112. //
  2113. if( !ReadMemory(DirtyBufferAddr,
  2114. &DirtyBuffer,
  2115. ULongSize,
  2116. &BytesRead) ) {
  2117. dprintf("\tRead %lx bytes from %lx\n",BytesRead,DirtyBufferAddr);
  2118. return;
  2119. }
  2120. DirtyBufferAddr += ULongSize;
  2121. }
  2122. Mask = ((DirtyBuffer >> (i%BitsPerULONG)) & 0x1);
  2123. //Mask <<= (BitsPerULONG - (i%BitsPerULONG) - 1);
  2124. //Mask &= DirtyBuffer;
  2125. dprintf("%s",Mask?"1":"0");
  2126. }
  2127. dprintf("\n\n");
  2128. }
  2129. void
  2130. regseccache(
  2131. LPSTR args
  2132. )
  2133. /*++
  2134. Routine Description:
  2135. displays the base block structure
  2136. Called as:
  2137. !seccache <HiveAddr>
  2138. Arguments:
  2139. args - convkey.
  2140. Return Value:
  2141. .
  2142. --*/
  2143. {
  2144. ULONG64 HiveAddr,SecCache;
  2145. DWORD BytesRead;
  2146. CHAR Dummy[ 256 ];
  2147. ULONG WorkVar,i,Cell;
  2148. LONG WorkHint;
  2149. ULONG CacheEntrySize = GetTypeSize("_CM_KEY_SECURITY_CACHE_ENTRY");
  2150. ULONG64 CachedSec;
  2151. if (sscanf(args,"%s %lX",Dummy,&HiveAddr)) {
  2152. HiveAddr = GetExpression(args + strlen(Dummy));
  2153. }
  2154. if(!GetFieldValue(HiveAddr, "_CMHIVE", "Hive.Signature", WorkVar)) {
  2155. if( WorkVar != HHIVE_SIGNATURE ) {
  2156. dprintf("Invalid Hive signature: %lx\n",WorkVar);
  2157. return;
  2158. }
  2159. }
  2160. if (!GetFieldValue(HiveAddr, "CMHIVE", "SecurityCacheSize", WorkVar)) {
  2161. dprintf("SecurityCacheSize = : 0x%lx\n",WorkVar);
  2162. }
  2163. if (!GetFieldValue(HiveAddr, "CMHIVE", "SecurityCount", WorkVar)) {
  2164. dprintf("SecurityCount = : 0x%lx\n",WorkVar);
  2165. }
  2166. if (!GetFieldValue(HiveAddr, "CMHIVE", "SecurityHitHint", WorkHint)) {
  2167. dprintf("SecurityHitHint = : 0x%lx\n",WorkHint);
  2168. }
  2169. if (!GetFieldValue(HiveAddr, "CMHIVE", "SecurityCache", SecCache)) {
  2170. dprintf("SecurityCache = : 0x%p\n\n",SecCache);
  2171. dprintf("[Entry No.] [Security Cell] [Security Cache]\n",WorkHint);
  2172. for( i=0;i<WorkVar;i++) {
  2173. if (CheckControlC()) {
  2174. break;
  2175. }
  2176. if (GetFieldValue(SecCache + i*CacheEntrySize, "_CM_KEY_SECURITY_CACHE_ENTRY", "CachedSecurity", CachedSec)) {
  2177. continue;
  2178. }
  2179. if (GetFieldValue(SecCache + i*CacheEntrySize, "_CM_KEY_SECURITY_CACHE_ENTRY", "Cell", Cell)) {
  2180. continue;
  2181. }
  2182. dprintf("%[%8lu] 0x%8lx 0x%p\n",i,Cell,CachedSec);
  2183. }
  2184. }
  2185. }
  2186. void ParseArgs(
  2187. LPSTR args,
  2188. LPSTR Dummy
  2189. )
  2190. {
  2191. ULONG i =0;
  2192. while( (args[i]!= 0) && (args[i] != ' ') ) {
  2193. Dummy[i] = args[i];
  2194. i++;
  2195. }
  2196. Dummy[i] = 0;
  2197. }
  2198. void ParseKcbNameInArg(
  2199. LPSTR args,
  2200. LPSTR KcbName
  2201. )
  2202. {
  2203. ULONG i =0;
  2204. ULONG j =0;
  2205. while( (args[i]!= 0) && (args[i] != ' ') ) {
  2206. i++;
  2207. }
  2208. while( args[i] == ' ' ) {
  2209. i++;
  2210. }
  2211. while( args[i]!= 0 ) {
  2212. KcbName[j] = args[i];
  2213. i++;j++;
  2214. }
  2215. KcbName[j] = 0;
  2216. }
  2217. DECLARE_API( reg )
  2218. /*++
  2219. Routine Description:
  2220. Dispatch point for all registry extensions
  2221. Called as:
  2222. !reg <command> <params>
  2223. Arguments:
  2224. args - Supplies the address of the HCELL_INDEX.
  2225. Return Value:
  2226. .
  2227. --*/
  2228. {
  2229. CHAR Dummy[ 512 ];
  2230. ParseArgs((LPSTR)args,(LPSTR)Dummy);
  2231. // Get the offsets
  2232. if (!GotOnce) {
  2233. if (GetFieldOffset("_HMAP_DIRECTORY", "Directory", &DirectoryOffset)){
  2234. return E_INVALIDARG;
  2235. }
  2236. if (GetFieldOffset("_HMAP_ENTRY", "BlockAddress", &BlockAddrOffset)) {
  2237. return E_INVALIDARG;
  2238. }
  2239. if (GetFieldOffset("_HMAP_TABLE", "Table", &TableOffset)) {
  2240. return E_INVALIDARG;
  2241. }
  2242. PtrSize = DBG_PTR_SIZE;
  2243. ULongSize = sizeof(ULONG); //
  2244. HMapSize = GetTypeSize("_HMAP_ENTRY");
  2245. GotOnce = TRUE;
  2246. }
  2247. dprintf("\n");
  2248. if (!strcmp(Dummy, "kcb")) {
  2249. regkcb((LPSTR)args);
  2250. } else if (!strcmp(Dummy, "cellindex")) {
  2251. regcellindex((LPSTR)args);
  2252. } else if( !strcmp(Dummy, "hashindex")) {
  2253. reghashindex((LPSTR)args);
  2254. } else if( !strcmp(Dummy, "openkeys")) {
  2255. regopenkeys((LPSTR)args,NULL);
  2256. } else if( !strcmp(Dummy, "knode")) {
  2257. regknode((LPSTR)args);
  2258. } else if( !strcmp(Dummy, "kbody")) {
  2259. regkbody((LPSTR)args);
  2260. } else if( !strcmp(Dummy, "kvalue")) {
  2261. regkvalue((LPSTR)args);
  2262. } else if( !strcmp(Dummy, "baseblock")) {
  2263. regbaseblock((LPSTR)args);
  2264. } else if( !strcmp(Dummy, "findkcb")) {
  2265. ParseKcbNameInArg((LPSTR)args,(LPSTR)Dummy);
  2266. regopenkeys((LPSTR)args,(LPSTR)Dummy);
  2267. } else if( !strcmp(Dummy, "hivelist")) {
  2268. reghivelist();
  2269. } else if( !strcmp(Dummy, "seccache")) {
  2270. regseccache((LPSTR)args);
  2271. } else if( !strcmp(Dummy, "viewlist")) {
  2272. regviewlist((LPSTR)args);
  2273. } else if( !strcmp(Dummy, "freebins")) {
  2274. regfreebins((LPSTR)args);
  2275. } else if( !strcmp(Dummy, "dirtyvector")) {
  2276. regdirtyvector((LPSTR)args);
  2277. } else if( !strcmp(Dummy, "freecells")) {
  2278. regfreecells((LPSTR)args);
  2279. } else if( !strcmp(Dummy, "freehints")) {
  2280. regfreehints((LPSTR)args);
  2281. } else if( !strcmp(Dummy, "dumppool")) {
  2282. regdumppool((LPSTR)args);
  2283. } else {
  2284. // dump general usage
  2285. dprintf("reg <command> <params> - Registry extensions\n");
  2286. dprintf(" kcb <Address> - Dump registry key-control-blocks\n");
  2287. dprintf(" knode <Address> - Dump registry key-node struct\n");
  2288. dprintf(" kbody <Address> - Dump registry key-body struct\n");
  2289. dprintf(" kvalue <Address> - Dump registry key-value struct\n");
  2290. dprintf(" baseblock <HiveAddr> - Dump the baseblock for the specified hive\n");
  2291. dprintf(" seccache <HiveAddr> - Dump the security cache for the specified hive\n");
  2292. dprintf(" hashindex <conv_key> - Find the hash entry given a Kcb ConvKey\n");
  2293. dprintf(" openkeys <HiveAddr|0> - Dump the keys opened inside the specified hive\n");
  2294. dprintf(" findkcb <FullKeyPath> - Find the kcb for the corresponding path\n");
  2295. dprintf(" hivelist - Displays the list of the hives in the system\n");
  2296. dprintf(" viewlist <HiveAddr> - Dump the pinned/mapped view list for the specified hive\n");
  2297. dprintf(" freebins <HiveAddr> - Dump the free bins for the specified hive\n");
  2298. dprintf(" freeceells <BinAddr> - Dump the free free cells in the specified bin\n");
  2299. dprintf(" dirtyvector<HiveAddr> - Dump the dirty vector for the specified hive\n");
  2300. dprintf(" cellindex <HiveAddr> <cellindex> - Finds the VA for a specified cell index\n");
  2301. dprintf(" freehints <HiveAddr> <Storage> <Display> - Dumps freehint info\n");
  2302. dprintf(" dumppool [s|r] - Dump registry allocated paged pool\n");
  2303. dprintf(" s - Save list of registry pages to temporary file\n");
  2304. dprintf(" r - Restore list of registry pages from temp. file\n");
  2305. }
  2306. return S_OK;
  2307. }