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.

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