Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

regext.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1992 Microsoft Corporation 00004 00005 Module Name: 00006 00007 regext.c 00008 00009 Abstract: 00010 00011 Kernel debugger extensions useful for the registry 00012 00013 Author: 00014 00015 John Vert (jvert) 7-Sep-1993 00016 00017 Environment: 00018 00019 Loaded as a kernel debugger extension 00020 00021 Revision History: 00022 00023 John Vert (jvert) 7-Sep-1993 00024 created 00025 00026 --*/ 00027 #include "cmp.h" 00028 #include <windef.h> 00029 #include <ntkdexts.h> 00030 #include <stdlib.h> 00031 #include <stdio.h> 00032 00033 HIVE_LIST_ENTRY HiveList[8]; 00034 00035 ULONG TotalPages; 00036 ULONG TotalPresentPages; 00037 00038 ULONG TotalKcbs; 00039 ULONG TotalKcbName; 00040 00041 BOOLEAN SavePages; 00042 BOOLEAN RestorePages; 00043 FILE *TempFile; 00044 00045 PNTKD_OUTPUT_ROUTINE lpPrint; 00046 PNTKD_GET_EXPRESSION lpGetExpressionRoutine; 00047 PNTKD_GET_SYMBOL lpGetSymbolRoutine; 00048 PNTKD_CHECK_CONTROL_C lpCheckControlCRoutine; 00049 PNTKD_READ_VIRTUAL_MEMORY lpReadMem; 00050 00051 void 00052 poolDumpHive( 00053 IN PCMHIVE Hive 00054 ); 00055 00056 VOID 00057 poolDumpMap( 00058 IN ULONG Length, 00059 IN PHMAP_DIRECTORY Map 00060 ); 00061 00062 void 00063 dumpHiveFromFile( 00064 IN FILE *File 00065 ); 00066 00067 VOID 00068 kcbWorker( 00069 IN PCM_KEY_CONTROL_BLOCK pKcb 00070 ); 00071 00072 VOID 00073 pool( 00074 DWORD dwCurrentPc, 00075 PNTKD_EXTENSION_APIS lpExtensionApis, 00076 LPSTR lpArgumentString 00077 ) 00078 00079 /*++ 00080 00081 Routine Description: 00082 00083 Goes through all the paged pool allocated to registry space and 00084 determines which pages are present and which are not. 00085 00086 Called as: 00087 00088 !regext.pool [s|r] 00089 00090 s Save list of registry pages to temporary file 00091 r Restore list of registry pages from temp. file 00092 00093 Arguments: 00094 00095 CurrentPc - Supplies the current pc at the time the extension is 00096 called. 00097 00098 lpExtensionApis - Supplies the address of the functions callable 00099 by this extension. 00100 00101 lpArgumentString - Supplies the pattern and expression for this 00102 command. 00103 00104 Return Value: 00105 00106 None. 00107 00108 --*/ 00109 00110 { 00111 PLIST_ENTRY pCmpHiveListHead; 00112 PLIST_ENTRY pNextHiveList; 00113 HIVE_LIST_ENTRY *pHiveListEntry; 00114 ULONG BytesRead; 00115 PCMHIVE CmHive; 00116 00117 lpPrint = lpExtensionApis->lpOutputRoutine; 00118 lpGetExpressionRoutine = lpExtensionApis->lpGetExpressionRoutine; 00119 lpGetSymbolRoutine = lpExtensionApis->lpGetSymbolRoutine; 00120 lpCheckControlCRoutine = lpExtensionApis->lpCheckControlCRoutine; 00121 lpReadMem = lpExtensionApis->lpReadVirtualMemRoutine; 00122 00123 if (toupper(lpArgumentString[0])=='S') { 00124 SavePages = TRUE; 00125 } else { 00126 SavePages = FALSE; 00127 } 00128 if (toupper(lpArgumentString[0])=='R') { 00129 RestorePages = TRUE; 00130 } else { 00131 RestorePages = FALSE; 00132 } 00133 00134 // 00135 // Go get the hivelist. 00136 // 00137 memset(HiveList,0,sizeof(HiveList)); 00138 pHiveListEntry = (PHIVE_LIST_ENTRY)(lpGetExpressionRoutine)("CmpMachineHiveList"); 00139 if (pHiveListEntry != NULL) { 00140 (lpReadMem)(pHiveListEntry, 00141 HiveList, 00142 sizeof(HiveList), 00143 &BytesRead); 00144 } 00145 00146 // 00147 // First go and get the hivelisthead 00148 // 00149 pCmpHiveListHead = (PLIST_ENTRY)(lpGetExpressionRoutine)("CmpHiveListHead"); 00150 if (pCmpHiveListHead==NULL) { 00151 (lpPrint)("CmpHiveListHead couldn't be read\n"); 00152 return; 00153 } 00154 00155 (lpReadMem)(&pCmpHiveListHead->Flink, 00156 &pNextHiveList, 00157 sizeof(pNextHiveList), 00158 &BytesRead); 00159 if (BytesRead != sizeof(pNextHiveList)) { 00160 (lpPrint)("Couldn't read first Flink (%lx) of CmpHiveList\n", 00161 &pCmpHiveListHead->Flink); 00162 return; 00163 } 00164 00165 TotalPages = TotalPresentPages = 0; 00166 00167 if (SavePages) { 00168 TempFile = fopen("regext.dat","w+"); 00169 if (TempFile==NULL) { 00170 (lpPrint)("Couldn't create regext.dat for write\n"); 00171 return; 00172 } 00173 } else if (RestorePages) { 00174 TempFile = fopen("regext.dat","r"); 00175 if (TempFile==NULL) { 00176 (lpPrint)("Couldn't open regext.dat for read\n"); 00177 return; 00178 } 00179 } 00180 00181 if (RestorePages) { 00182 dumpHiveFromFile(TempFile); 00183 } else { 00184 while (pNextHiveList != pCmpHiveListHead) { 00185 CmHive = CONTAINING_RECORD(pNextHiveList, CMHIVE, HiveList); 00186 poolDumpHive(CmHive); 00187 00188 (lpReadMem)(&pNextHiveList->Flink, 00189 &pNextHiveList, 00190 sizeof(pNextHiveList), 00191 &BytesRead); 00192 if (BytesRead != sizeof(pNextHiveList)) { 00193 (lpPrint)("Couldn't read Flink (%lx) of %lx\n", 00194 &pCmpHiveListHead->Flink,pNextHiveList); 00195 break; 00196 } 00197 00198 } 00199 } 00200 00201 (lpPrint)("Total pages present = %d / %d\n", 00202 TotalPresentPages, 00203 TotalPages); 00204 00205 if (SavePages || RestorePages) { 00206 fclose(TempFile); 00207 } 00208 } 00209 00210 void 00211 poolDumpHive( 00212 IN PCMHIVE pHive 00213 ) 00214 { 00215 CMHIVE CmHive; 00216 ULONG BytesRead; 00217 WCHAR FileName[HBASE_NAME_ALLOC/2 + 1]; 00218 ULONG i; 00219 00220 (lpPrint)("\ndumping hive at %lx ",pHive); 00221 (lpReadMem)(pHive, 00222 &CmHive, 00223 sizeof(CmHive), 00224 &BytesRead); 00225 00226 if (BytesRead < sizeof(CmHive)) { 00227 (lpPrint)("\tRead %lx bytes from %lx\n",BytesRead,pHive); 00228 return; 00229 } 00230 00231 (lpReadMem)(&CmHive.Hive.BaseBlock->FileName, 00232 FileName, 00233 sizeof(FileName), 00234 &BytesRead); 00235 00236 if (BytesRead < sizeof(FileName)) { 00237 wcscpy(FileName, L"UNKNOWN"); 00238 } else { 00239 if (FileName[0]==L'\0') { 00240 wcscpy(FileName, L"NONAME"); 00241 } else { 00242 FileName[HBASE_NAME_ALLOC/2]=L'\0'; 00243 } 00244 } 00245 00246 (lpPrint)("(%ws)\n",FileName); 00247 00248 (lpPrint)(" %d KCBs open\n",CmHive.KcbCount); 00249 (lpPrint)(" Stable Length = %lx\n",CmHive.Hive.Storage[Stable].Length); 00250 if (SavePages) { 00251 fprintf(TempFile, 00252 "%ws %d %d\n", 00253 FileName, 00254 CmHive.Hive.Storage[Stable].Length, 00255 CmHive.Hive.Storage[Volatile].Length); 00256 } 00257 poolDumpMap(CmHive.Hive.Storage[Stable].Length, 00258 CmHive.Hive.Storage[Stable].Map); 00259 00260 (lpPrint)(" Volatile Length = %lx\n",CmHive.Hive.Storage[Volatile].Length); 00261 poolDumpMap(CmHive.Hive.Storage[Volatile].Length, 00262 CmHive.Hive.Storage[Volatile].Map); 00263 00264 } 00265 00266 VOID 00267 poolDumpMap( 00268 IN ULONG Length, 00269 IN PHMAP_DIRECTORY Map 00270 ) 00271 { 00272 ULONG Tables; 00273 ULONG MapSlots; 00274 ULONG i; 00275 ULONG BytesRead; 00276 HMAP_DIRECTORY MapDirectory; 00277 PHMAP_TABLE MapTable; 00278 HMAP_ENTRY MapEntry; 00279 ULONG Garbage; 00280 ULONG Present=0; 00281 00282 if (Length==0) { 00283 return; 00284 } 00285 00286 MapSlots = Length / HBLOCK_SIZE; 00287 Tables = 1+ ((MapSlots-1) / HTABLE_SLOTS); 00288 00289 // 00290 // read in map directory 00291 // 00292 (lpReadMem)(Map, 00293 &MapDirectory, 00294 Tables * sizeof(PHMAP_TABLE), 00295 &BytesRead); 00296 if (BytesRead < (Tables * sizeof(PHMAP_TABLE))) { 00297 (lpPrint)("Only read %lx/%lx bytes from %lx\n", 00298 BytesRead, 00299 Tables * sizeof(PHMAP_TABLE), 00300 Map); 00301 return; 00302 00303 } 00304 00305 // 00306 // check out each map entry 00307 // 00308 for (i=0; i<MapSlots; i++) { 00309 00310 MapTable = MapDirectory.Directory[i/HTABLE_SLOTS]; 00311 00312 (lpReadMem)(&(MapTable->Table[i%HTABLE_SLOTS]), 00313 &MapEntry, 00314 sizeof(HMAP_ENTRY), 00315 &BytesRead); 00316 if (BytesRead < sizeof(HMAP_ENTRY)) { 00317 (lpPrint)(" can't read HMAP_ENTRY at %lx\n", 00318 &(MapTable->Table[i%HTABLE_SLOTS])); 00319 } 00320 00321 if (SavePages) { 00322 fprintf(TempFile, "%lx\n",MapEntry.BlockAddress); 00323 00324 } 00325 00326 // 00327 // probe the HBLOCK 00328 // 00329 (lpReadMem)(MapEntry.BlockAddress, 00330 &Garbage, 00331 sizeof(ULONG), 00332 &BytesRead); 00333 if (BytesRead > 0) { 00334 ++Present; 00335 } 00336 } 00337 (lpPrint)(" %d/%d pages present\n", 00338 Present, 00339 MapSlots); 00340 00341 TotalPages += MapSlots; 00342 TotalPresentPages += Present; 00343 00344 } 00345 00346 void 00347 dumpHiveFromFile( 00348 IN FILE *File 00349 ) 00350 00351 /*++ 00352 00353 Routine Description: 00354 00355 Takes a list of the registry hives and pages from a file and 00356 checks to see how many of the pages are in memory. 00357 00358 The format of the file is as follows 00359 hivename stablelength volatilelength 00360 stable page address 00361 stable page address 00362 . 00363 . 00364 . 00365 volatile page address 00366 volatile page address 00367 . 00368 . 00369 . 00370 hivename stablelength volatilelength 00371 . 00372 . 00373 . 00374 00375 00376 Arguments: 00377 00378 File - Supplies a file. 00379 00380 Return Value: 00381 00382 None. 00383 00384 --*/ 00385 00386 { 00387 CHAR Hivename[33]; 00388 ULONG StableLength; 00389 ULONG VolatileLength; 00390 ULONG Page; 00391 ULONG i; 00392 ULONG NumFields; 00393 ULONG Garbage; 00394 ULONG Present; 00395 ULONG Total; 00396 ULONG BytesRead; 00397 00398 while (!feof(File)) { 00399 NumFields = fscanf(File,"%s %d %d\n", 00400 Hivename, 00401 &StableLength, 00402 &VolatileLength); 00403 if (NumFields != 3) { 00404 (lpPrint)("fscanf returned %d\n",NumFields); 00405 return; 00406 } 00407 00408 (lpPrint)("\ndumping hive %s\n",Hivename); 00409 (lpPrint)(" Stable Length = %lx\n",StableLength); 00410 Present = 0; 00411 Total = 0; 00412 while (StableLength > 0) { 00413 fscanf(File, "%lx\n",&Page); 00414 (lpReadMem)(Page, 00415 &Garbage, 00416 sizeof(ULONG), 00417 &BytesRead); 00418 if (BytesRead > 0) { 00419 ++Present; 00420 } 00421 ++Total; 00422 StableLength -= HBLOCK_SIZE; 00423 } 00424 if (Total > 0) { 00425 (lpPrint)(" %d/%d stable pages present\n", 00426 Present,Total); 00427 } 00428 TotalPages += Total; 00429 TotalPresentPages += Present; 00430 00431 (lpPrint)(" Volatile Length = %lx\n",VolatileLength); 00432 Present = 0; 00433 Total = 0; 00434 while (VolatileLength > 0) { 00435 fscanf(File, "%lx\n",&Page); 00436 (lpReadMem)(Page, 00437 &Garbage, 00438 sizeof(ULONG), 00439 &BytesRead); 00440 if (BytesRead > 0) { 00441 ++Present; 00442 } 00443 ++Total; 00444 VolatileLength -= HBLOCK_SIZE; 00445 } 00446 if (Total > 0) { 00447 (lpPrint)(" %d/%d volatile pages present\n", 00448 Present,Total); 00449 } 00450 00451 TotalPages += Total; 00452 TotalPresentPages += Present; 00453 } 00454 00455 } 00456 00457 void 00458 kcb( 00459 DWORD dwCurrentPc, 00460 PNTKD_EXTENSION_APIS lpExtensionApis, 00461 LPSTR lpArgumentString 00462 ) 00463 00464 /*++ 00465 00466 Routine Description: 00467 00468 Walks the kcb tree and prints the names of keys which have 00469 outstanding kcbs 00470 00471 Called as: 00472 00473 !regext.kcb 00474 00475 Arguments: 00476 00477 CurrentPc - Supplies the current pc at the time the extension is 00478 called. 00479 00480 lpExtensionApis - Supplies the address of the functions callable 00481 by this extension. 00482 00483 lpArgumentString - Supplies the pattern and expression for this 00484 command. 00485 00486 Return Value: 00487 00488 None. 00489 00490 --*/ 00491 00492 { 00493 PCM_KEY_CONTROL_BLOCK pKCB; 00494 PCM_KEY_CONTROL_BLOCK Root; 00495 ULONG BytesRead; 00496 00497 lpPrint = lpExtensionApis->lpOutputRoutine; 00498 lpGetExpressionRoutine = lpExtensionApis->lpGetExpressionRoutine; 00499 lpGetSymbolRoutine = lpExtensionApis->lpGetSymbolRoutine; 00500 lpCheckControlCRoutine = lpExtensionApis->lpCheckControlCRoutine; 00501 lpReadMem = lpExtensionApis->lpReadVirtualMemRoutine; 00502 00503 Root = (PCM_KEY_CONTROL_BLOCK)(lpGetExpressionRoutine)("CmpKeyControlBlockRoot"); 00504 if (Root == NULL) { 00505 (lpPrint)("Couldn't find address of CmpKeyControlBlockRoot\n"); 00506 return; 00507 } 00508 (lpReadMem)(Root, 00509 &pKCB, 00510 sizeof(pKCB), 00511 &BytesRead); 00512 00513 if (BytesRead < sizeof(pKCB)) { 00514 (lpPrint)("Couldn't get pKCB from CmpKeyControlBlockRoot\n"); 00515 } 00516 00517 TotalKcbs = 0; 00518 TotalKcbName = 0; 00519 kcbWorker(pKCB); 00520 00521 (lpPrint)("%d KCBs\n",TotalKcbs); 00522 (lpPrint)("%d total bytes of FullNames\n",TotalKcbName); 00523 00524 } 00525 00526 VOID 00527 kcbWorker( 00528 IN PCM_KEY_CONTROL_BLOCK pKcb 00529 ) 00530 00531 /*++ 00532 00533 Routine Description: 00534 00535 recursive worker for walking the kcb tree. 00536 00537 Arguments: 00538 00539 pKcb - Supplies pointer to kcb. 00540 00541 Return Value: 00542 00543 None. 00544 00545 --*/ 00546 00547 { 00548 CM_KEY_CONTROL_BLOCK kcb; 00549 ULONG BytesRead; 00550 WCHAR *Buffer; 00551 00552 ++TotalKcbs; 00553 (lpReadMem)(pKcb, 00554 &kcb, 00555 sizeof(kcb), 00556 &BytesRead); 00557 if (BytesRead < sizeof(kcb)) { 00558 (lpPrint)("Can't read kcb at %lx\n",pKcb); 00559 return; 00560 } 00561 TotalKcbName += kcb.FullName.Length; 00562 00563 if (kcb.Left != NULL) { 00564 kcbWorker(kcb.Left); 00565 } 00566 00567 (lpPrint)("%d - ",kcb.RefCount); 00568 00569 Buffer = malloc(kcb.FullName.Length); 00570 if (Buffer != NULL) { 00571 (lpReadMem)(kcb.FullName.Buffer, 00572 Buffer, 00573 kcb.FullName.Length, 00574 &BytesRead); 00575 00576 kcb.FullName.Length = BytesRead; 00577 kcb.FullName.Buffer = Buffer; 00578 00579 (lpPrint)(" %wZ\n",&kcb.FullName); 00580 free(Buffer); 00581 00582 } else { 00583 (lpPrint)(" ??? \n"); 00584 } 00585 00586 if (kcb.Right != NULL) { 00587 kcbWorker(kcb.Right); 00588 } 00589 00590 00591 } 00592 

Generated on Sat May 15 19:41:37 2004 for test by doxygen 1.3.7