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.

591 lines
13 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. --*/
  15. #include "cmp.h"
  16. #include <windef.h>
  17. #include <ntkdexts.h>
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. HIVE_LIST_ENTRY HiveList[8];
  21. ULONG TotalPages;
  22. ULONG TotalPresentPages;
  23. ULONG TotalKcbs;
  24. ULONG TotalKcbName;
  25. BOOLEAN SavePages;
  26. BOOLEAN RestorePages;
  27. FILE *TempFile;
  28. PNTKD_OUTPUT_ROUTINE lpPrint;
  29. PNTKD_GET_EXPRESSION lpGetExpressionRoutine;
  30. PNTKD_GET_SYMBOL lpGetSymbolRoutine;
  31. PNTKD_CHECK_CONTROL_C lpCheckControlCRoutine;
  32. PNTKD_READ_VIRTUAL_MEMORY lpReadMem;
  33. void
  34. poolDumpHive(
  35. IN PCMHIVE Hive
  36. );
  37. VOID
  38. poolDumpMap(
  39. IN ULONG Length,
  40. IN PHMAP_DIRECTORY Map
  41. );
  42. void
  43. dumpHiveFromFile(
  44. IN FILE *File
  45. );
  46. VOID
  47. kcbWorker(
  48. IN PCM_KEY_CONTROL_BLOCK pKcb
  49. );
  50. VOID
  51. pool(
  52. DWORD dwCurrentPc,
  53. PNTKD_EXTENSION_APIS lpExtensionApis,
  54. LPSTR lpArgumentString
  55. )
  56. /*++
  57. Routine Description:
  58. Goes through all the paged pool allocated to registry space and
  59. determines which pages are present and which are not.
  60. Called as:
  61. !regext.pool [s|r]
  62. s Save list of registry pages to temporary file
  63. r Restore list of registry pages from temp. file
  64. Arguments:
  65. CurrentPc - Supplies the current pc at the time the extension is
  66. called.
  67. lpExtensionApis - Supplies the address of the functions callable
  68. by this extension.
  69. lpArgumentString - Supplies the pattern and expression for this
  70. command.
  71. Return Value:
  72. None.
  73. --*/
  74. {
  75. PLIST_ENTRY pCmpHiveListHead;
  76. PLIST_ENTRY pNextHiveList;
  77. HIVE_LIST_ENTRY *pHiveListEntry;
  78. ULONG BytesRead;
  79. PCMHIVE CmHive;
  80. lpPrint = lpExtensionApis->lpOutputRoutine;
  81. lpGetExpressionRoutine = lpExtensionApis->lpGetExpressionRoutine;
  82. lpGetSymbolRoutine = lpExtensionApis->lpGetSymbolRoutine;
  83. lpCheckControlCRoutine = lpExtensionApis->lpCheckControlCRoutine;
  84. lpReadMem = lpExtensionApis->lpReadVirtualMemRoutine;
  85. if (toupper(lpArgumentString[0])=='S') {
  86. SavePages = TRUE;
  87. } else {
  88. SavePages = FALSE;
  89. }
  90. if (toupper(lpArgumentString[0])=='R') {
  91. RestorePages = TRUE;
  92. } else {
  93. RestorePages = FALSE;
  94. }
  95. //
  96. // Go get the hivelist.
  97. //
  98. memset(HiveList,0,sizeof(HiveList));
  99. pHiveListEntry = (PHIVE_LIST_ENTRY)(lpGetExpressionRoutine)("CmpMachineHiveList");
  100. if (pHiveListEntry != NULL) {
  101. (lpReadMem)(pHiveListEntry,
  102. HiveList,
  103. sizeof(HiveList),
  104. &BytesRead);
  105. }
  106. //
  107. // First go and get the hivelisthead
  108. //
  109. pCmpHiveListHead = (PLIST_ENTRY)(lpGetExpressionRoutine)("CmpHiveListHead");
  110. if (pCmpHiveListHead==NULL) {
  111. (lpPrint)("CmpHiveListHead couldn't be read\n");
  112. return;
  113. }
  114. (lpReadMem)(&pCmpHiveListHead->Flink,
  115. &pNextHiveList,
  116. sizeof(pNextHiveList),
  117. &BytesRead);
  118. if (BytesRead != sizeof(pNextHiveList)) {
  119. (lpPrint)("Couldn't read first Flink (%lx) of CmpHiveList\n",
  120. &pCmpHiveListHead->Flink);
  121. return;
  122. }
  123. TotalPages = TotalPresentPages = 0;
  124. if (SavePages) {
  125. TempFile = fopen("regext.dat","w+");
  126. if (TempFile==NULL) {
  127. (lpPrint)("Couldn't create regext.dat for write\n");
  128. return;
  129. }
  130. } else if (RestorePages) {
  131. TempFile = fopen("regext.dat","r");
  132. if (TempFile==NULL) {
  133. (lpPrint)("Couldn't open regext.dat for read\n");
  134. return;
  135. }
  136. }
  137. if (RestorePages) {
  138. dumpHiveFromFile(TempFile);
  139. } else {
  140. while (pNextHiveList != pCmpHiveListHead) {
  141. CmHive = CONTAINING_RECORD(pNextHiveList, CMHIVE, HiveList);
  142. poolDumpHive(CmHive);
  143. (lpReadMem)(&pNextHiveList->Flink,
  144. &pNextHiveList,
  145. sizeof(pNextHiveList),
  146. &BytesRead);
  147. if (BytesRead != sizeof(pNextHiveList)) {
  148. (lpPrint)("Couldn't read Flink (%lx) of %lx\n",
  149. &pCmpHiveListHead->Flink,pNextHiveList);
  150. break;
  151. }
  152. }
  153. }
  154. (lpPrint)("Total pages present = %d / %d\n",
  155. TotalPresentPages,
  156. TotalPages);
  157. if (SavePages || RestorePages) {
  158. fclose(TempFile);
  159. }
  160. }
  161. void
  162. poolDumpHive(
  163. IN PCMHIVE pHive
  164. )
  165. {
  166. CMHIVE CmHive;
  167. ULONG BytesRead;
  168. WCHAR FileName[HBASE_NAME_ALLOC/2 + 1];
  169. ULONG i;
  170. (lpPrint)("\ndumping hive at %lx ",pHive);
  171. (lpReadMem)(pHive,
  172. &CmHive,
  173. sizeof(CmHive),
  174. &BytesRead);
  175. if (BytesRead < sizeof(CmHive)) {
  176. (lpPrint)("\tRead %lx bytes from %lx\n",BytesRead,pHive);
  177. return;
  178. }
  179. (lpReadMem)(&CmHive.Hive.BaseBlock->FileName,
  180. FileName,
  181. sizeof(FileName),
  182. &BytesRead);
  183. if (BytesRead < sizeof(FileName)) {
  184. wcscpy(FileName, L"UNKNOWN");
  185. } else {
  186. if (FileName[0]==L'\0') {
  187. wcscpy(FileName, L"NONAME");
  188. } else {
  189. FileName[HBASE_NAME_ALLOC/2]=L'\0';
  190. }
  191. }
  192. (lpPrint)("(%ws)\n",FileName);
  193. (lpPrint)(" %d KCBs open\n",CmHive.KcbCount);
  194. (lpPrint)(" Stable Length = %lx\n",CmHive.Hive.Storage[Stable].Length);
  195. if (SavePages) {
  196. fprintf(TempFile,
  197. "%ws %d %d\n",
  198. FileName,
  199. CmHive.Hive.Storage[Stable].Length,
  200. CmHive.Hive.Storage[Volatile].Length);
  201. }
  202. poolDumpMap(CmHive.Hive.Storage[Stable].Length,
  203. CmHive.Hive.Storage[Stable].Map);
  204. (lpPrint)(" Volatile Length = %lx\n",CmHive.Hive.Storage[Volatile].Length);
  205. poolDumpMap(CmHive.Hive.Storage[Volatile].Length,
  206. CmHive.Hive.Storage[Volatile].Map);
  207. }
  208. VOID
  209. poolDumpMap(
  210. IN ULONG Length,
  211. IN PHMAP_DIRECTORY Map
  212. )
  213. {
  214. ULONG Tables;
  215. ULONG MapSlots;
  216. ULONG i;
  217. ULONG BytesRead;
  218. HMAP_DIRECTORY MapDirectory;
  219. PHMAP_TABLE MapTable;
  220. HMAP_ENTRY MapEntry;
  221. ULONG Garbage;
  222. ULONG Present=0;
  223. if (Length==0) {
  224. return;
  225. }
  226. MapSlots = Length / HBLOCK_SIZE;
  227. Tables = 1+ ((MapSlots-1) / HTABLE_SLOTS);
  228. //
  229. // read in map directory
  230. //
  231. (lpReadMem)(Map,
  232. &MapDirectory,
  233. Tables * sizeof(PHMAP_TABLE),
  234. &BytesRead);
  235. if (BytesRead < (Tables * sizeof(PHMAP_TABLE))) {
  236. (lpPrint)("Only read %lx/%lx bytes from %lx\n",
  237. BytesRead,
  238. Tables * sizeof(PHMAP_TABLE),
  239. Map);
  240. return;
  241. }
  242. //
  243. // check out each map entry
  244. //
  245. for (i=0; i<MapSlots; i++) {
  246. MapTable = MapDirectory.Directory[i/HTABLE_SLOTS];
  247. (lpReadMem)(&(MapTable->Table[i%HTABLE_SLOTS]),
  248. &MapEntry,
  249. sizeof(HMAP_ENTRY),
  250. &BytesRead);
  251. if (BytesRead < sizeof(HMAP_ENTRY)) {
  252. (lpPrint)(" can't read HMAP_ENTRY at %lx\n",
  253. &(MapTable->Table[i%HTABLE_SLOTS]));
  254. }
  255. if (SavePages) {
  256. fprintf(TempFile, "%lx\n",MapEntry.BlockAddress);
  257. }
  258. //
  259. // probe the HBLOCK
  260. //
  261. (lpReadMem)(MapEntry.BlockAddress,
  262. &Garbage,
  263. sizeof(ULONG),
  264. &BytesRead);
  265. if (BytesRead > 0) {
  266. ++Present;
  267. }
  268. }
  269. (lpPrint)(" %d/%d pages present\n",
  270. Present,
  271. MapSlots);
  272. TotalPages += MapSlots;
  273. TotalPresentPages += Present;
  274. }
  275. void
  276. dumpHiveFromFile(
  277. IN FILE *File
  278. )
  279. /*++
  280. Routine Description:
  281. Takes a list of the registry hives and pages from a file and
  282. checks to see how many of the pages are in memory.
  283. The format of the file is as follows
  284. hivename stablelength volatilelength
  285. stable page address
  286. stable page address
  287. .
  288. .
  289. .
  290. volatile page address
  291. volatile page address
  292. .
  293. .
  294. .
  295. hivename stablelength volatilelength
  296. .
  297. .
  298. .
  299. Arguments:
  300. File - Supplies a file.
  301. Return Value:
  302. None.
  303. --*/
  304. {
  305. CHAR Hivename[33];
  306. ULONG StableLength;
  307. ULONG VolatileLength;
  308. ULONG Page;
  309. ULONG i;
  310. ULONG NumFields;
  311. ULONG Garbage;
  312. ULONG Present;
  313. ULONG Total;
  314. ULONG BytesRead;
  315. while (!feof(File)) {
  316. NumFields = fscanf(File,"%s %d %d\n",
  317. Hivename,
  318. &StableLength,
  319. &VolatileLength);
  320. if (NumFields != 3) {
  321. (lpPrint)("fscanf returned %d\n",NumFields);
  322. return;
  323. }
  324. (lpPrint)("\ndumping hive %s\n",Hivename);
  325. (lpPrint)(" Stable Length = %lx\n",StableLength);
  326. Present = 0;
  327. Total = 0;
  328. while (StableLength > 0) {
  329. fscanf(File, "%lx\n",&Page);
  330. (lpReadMem)(Page,
  331. &Garbage,
  332. sizeof(ULONG),
  333. &BytesRead);
  334. if (BytesRead > 0) {
  335. ++Present;
  336. }
  337. ++Total;
  338. StableLength -= HBLOCK_SIZE;
  339. }
  340. if (Total > 0) {
  341. (lpPrint)(" %d/%d stable pages present\n",
  342. Present,Total);
  343. }
  344. TotalPages += Total;
  345. TotalPresentPages += Present;
  346. (lpPrint)(" Volatile Length = %lx\n",VolatileLength);
  347. Present = 0;
  348. Total = 0;
  349. while (VolatileLength > 0) {
  350. fscanf(File, "%lx\n",&Page);
  351. (lpReadMem)(Page,
  352. &Garbage,
  353. sizeof(ULONG),
  354. &BytesRead);
  355. if (BytesRead > 0) {
  356. ++Present;
  357. }
  358. ++Total;
  359. VolatileLength -= HBLOCK_SIZE;
  360. }
  361. if (Total > 0) {
  362. (lpPrint)(" %d/%d volatile pages present\n",
  363. Present,Total);
  364. }
  365. TotalPages += Total;
  366. TotalPresentPages += Present;
  367. }
  368. }
  369. void
  370. kcb(
  371. DWORD dwCurrentPc,
  372. PNTKD_EXTENSION_APIS lpExtensionApis,
  373. LPSTR lpArgumentString
  374. )
  375. /*++
  376. Routine Description:
  377. Walks the kcb tree and prints the names of keys which have
  378. outstanding kcbs
  379. Called as:
  380. !regext.kcb
  381. Arguments:
  382. CurrentPc - Supplies the current pc at the time the extension is
  383. called.
  384. lpExtensionApis - Supplies the address of the functions callable
  385. by this extension.
  386. lpArgumentString - Supplies the pattern and expression for this
  387. command.
  388. Return Value:
  389. None.
  390. --*/
  391. {
  392. PCM_KEY_CONTROL_BLOCK pKCB;
  393. PCM_KEY_CONTROL_BLOCK Root;
  394. ULONG BytesRead;
  395. lpPrint = lpExtensionApis->lpOutputRoutine;
  396. lpGetExpressionRoutine = lpExtensionApis->lpGetExpressionRoutine;
  397. lpGetSymbolRoutine = lpExtensionApis->lpGetSymbolRoutine;
  398. lpCheckControlCRoutine = lpExtensionApis->lpCheckControlCRoutine;
  399. lpReadMem = lpExtensionApis->lpReadVirtualMemRoutine;
  400. Root = (PCM_KEY_CONTROL_BLOCK)(lpGetExpressionRoutine)("CmpKeyControlBlockRoot");
  401. if (Root == NULL) {
  402. (lpPrint)("Couldn't find address of CmpKeyControlBlockRoot\n");
  403. return;
  404. }
  405. (lpReadMem)(Root,
  406. &pKCB,
  407. sizeof(pKCB),
  408. &BytesRead);
  409. if (BytesRead < sizeof(pKCB)) {
  410. (lpPrint)("Couldn't get pKCB from CmpKeyControlBlockRoot\n");
  411. }
  412. TotalKcbs = 0;
  413. TotalKcbName = 0;
  414. kcbWorker(pKCB);
  415. (lpPrint)("%d KCBs\n",TotalKcbs);
  416. (lpPrint)("%d total bytes of FullNames\n",TotalKcbName);
  417. }
  418. VOID
  419. kcbWorker(
  420. IN PCM_KEY_CONTROL_BLOCK pKcb
  421. )
  422. /*++
  423. Routine Description:
  424. recursive worker for walking the kcb tree.
  425. Arguments:
  426. pKcb - Supplies pointer to kcb.
  427. Return Value:
  428. None.
  429. --*/
  430. {
  431. CM_KEY_CONTROL_BLOCK kcb;
  432. ULONG BytesRead;
  433. WCHAR *Buffer;
  434. ++TotalKcbs;
  435. (lpReadMem)(pKcb,
  436. &kcb,
  437. sizeof(kcb),
  438. &BytesRead);
  439. if (BytesRead < sizeof(kcb)) {
  440. (lpPrint)("Can't read kcb at %lx\n",pKcb);
  441. return;
  442. }
  443. TotalKcbName += kcb.FullName.Length;
  444. if (kcb.Left != NULL) {
  445. kcbWorker(kcb.Left);
  446. }
  447. (lpPrint)("%d - ",kcb.RefCount);
  448. Buffer = malloc(kcb.FullName.Length);
  449. if (Buffer != NULL) {
  450. (lpReadMem)(kcb.FullName.Buffer,
  451. Buffer,
  452. kcb.FullName.Length,
  453. &BytesRead);
  454. kcb.FullName.Length = BytesRead;
  455. kcb.FullName.Buffer = Buffer;
  456. (lpPrint)(" %wZ\n",&kcb.FullName);
  457. free(Buffer);
  458. } else {
  459. (lpPrint)(" ??? \n");
  460. }
  461. if (kcb.Right != NULL) {
  462. kcbWorker(kcb.Right);
  463. }
  464. }
  465.