00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
#include "regutil.h"
00060
#include "edithive.h"
00061
00062
#include <stdio.h>
00063
#include <stdlib.h>
00064
#include <string.h>
00065
#include <windows.h>
00066
00067 UCHAR *
helptext[] = {
00068
"hivestat: ",
00069
"Statistics: ",
00070
" Short: # of bins ",
00071
" average bin size ",
00072
" max bin size ",
00073
" # of cells ",
00074
" # of free cells ",
00075
" # of allocated cells ",
00076
" average free cell size ",
00077
" total free size ",
00078
" max free cell size ",
00079
" average allocated size ",
00080
" total allocated size ",
00081
" max allocated cell size ",
00082
" overhead summary (header, bin headers, cell headers) ",
00083
" Long: bin#, offset, size ",
00084
" cell offset, size, allocated ",
00085
" cell offset, size, free ",
00086
"Usage: {[+|-][<option>]} <filename> ",
00087
" (+ = on by default, - = off by default) ",
00088
" +s = summary - all of the short statistics ",
00089
" -t[bafc] = trace, line per entry, bin, allocated, free, all cells",
00090
" (+tbc == +tbaf) ",
00091
" -c = cell type summary ",
00092
" -a[kvs] = Access Export (key nodes, values, SDs) ",
00093
NULL
00094 };
00095
00096
00097
VOID
00098
ParseArgs(
00099
int argc,
00100
char *argv[]
00101 );
00102
00103
VOID
00104
ScanHive(
00105 VOID
00106 );
00107
00108
VOID
00109
ScanCell(
00110
PHCELL Cell,
00111 ULONG CellSize
00112 );
00113
00114
VOID
00115
ScanKeyNode(
00116 IN
PCM_KEY_NODE Node,
00117 IN ULONG CellSize
00118 );
00119
00120
VOID
00121
ScanKeyValue(
00122 IN
PCM_KEY_VALUE Value,
00123 IN ULONG CellSize
00124 );
00125
00126
VOID
00127
ScanKeySD(
00128 IN
PCM_KEY_SECURITY Security,
00129 IN ULONG CellSize
00130 );
00131
00132
VOID
00133
ScanKeyIndex(
00134 IN
PCM_KEY_INDEX Index,
00135 IN ULONG CellSize
00136 );
00137
00138
VOID
00139
ScanUnknown(
00140 IN
PCELL_DATA Data,
00141 IN ULONG CellSize
00142 );
00143
00144
00145
00146
00147
00148 BOOLEAN
DoCellType =
FALSE;
00149 BOOLEAN
DoSummary =
TRUE;
00150 BOOLEAN
DoTraceBin =
FALSE;
00151 BOOLEAN
DoTraceFree =
FALSE;
00152 BOOLEAN
DoTraceAlloc =
FALSE;
00153
00154 BOOLEAN
AccessKeys =
FALSE;
00155 BOOLEAN
AccessValues =
FALSE;
00156 BOOLEAN
AccessSD =
FALSE;
00157 LPCTSTR
FileName =
NULL;
00158
00159 ULONG
HiveVersion;
00160
00161
00162
00163
00164 ULONG
SizeKeyData=0;
00165 ULONG
SizeValueData=0;
00166 ULONG
SizeSDData=0;
00167 ULONG
SizeIndexData=0;
00168 ULONG
SizeUnknownData=0;
00169
00170 ULONG
NumKeyData=0;
00171 ULONG
NumValueData=0;
00172 ULONG
NumSDData=0;
00173 ULONG
NumIndexData=0;
00174 ULONG
NumUnknownData=0;
00175
00176
void
00177 main(
00178
int argc,
00179
char *argv[]
00180 )
00181 {
00182
ParseArgs(argc, argv);
00183
ScanHive();
00184
exit(0);
00185 }
00186
00187
VOID
00188 ParseArgs(
00189
int argc,
00190
char *argv[]
00191 )
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 {
00208
char *p;
00209
int i;
00210 BOOLEAN command;
00211
00212
if (argc == 1) {
00213
for (i = 0;
helptext[i] !=
NULL; i++) {
00214 fprintf(stderr,
"%s\n",
helptext[i]);
00215 }
00216
exit(1);
00217 }
00218
00219
for (i = 1; i < argc; i++) {
00220 p = argv[i];
00221
00222
if (*p ==
'+') {
00223
00224 command =
TRUE;
00225
00226 }
else if (*p ==
'-') {
00227
00228 command =
FALSE;
00229
00230 }
else {
00231
FileName = p;
00232
continue;
00233 }
00234
00235 p++;
00236
if (*p ==
'\0')
00237
continue;
00238
00239
switch (*p) {
00240
case 's':
00241
case 'S':
00242
DoSummary = command;
00243
break;
00244
00245
case 'c':
00246
case 'C':
00247
DoCellType = command;
00248
break;
00249
00250
case 'a':
00251
case 'A':
00252 p++;
00253
while (*p !=
'\0') {
00254
switch (*p) {
00255
case 'k':
00256
case 'K':
00257
AccessKeys = command;
00258
break;
00259
00260
case 's':
00261
case 'S':
00262
AccessSD = command;
00263
break;
00264
00265
case 'v':
00266
case 'V':
00267
AccessValues = command;
00268
break;
00269
00270
default:
00271
break;
00272 }
00273 p++;
00274 }
00275
break;
00276
00277
case 't':
00278
case 'T':
00279 p++;
00280
while (*p !=
'\0') {
00281
00282
switch (*p) {
00283
case 'b':
00284
case 'B':
00285
DoTraceBin = command;
00286
break;
00287
00288
case 'a':
00289
case 'A':
00290
DoTraceAlloc = command;
00291
break;
00292
00293
case 'f':
00294
case 'F':
00295
DoTraceFree = command;
00296
break;
00297
00298
case 'c':
00299
case 'C':
00300
DoTraceAlloc = command;
00301
DoTraceFree = command;
00302
break;
00303
00304
default:
00305
break;
00306 }
00307
00308 p++;
00309 }
00310
break;
00311
00312
default:
00313
break;
00314 }
00315 }
00316
return;
00317 }
00318
00319
VOID
00320 ScanHive(
00321 )
00322
00323
00324
00325
00326
00327
00328
00329 {
00330
static char buffer[
HBLOCK_SIZE];
00331
PHBASE_BLOCK bbp;
00332 HANDLE filehandle;
00333
BOOL rf;
00334 ULONG readcount;
00335 ULONG hivelength;
00336 ULONG hiveposition;
00337
PHCELL cp;
00338
PHCELL guard;
00339
PHBIN hbp;
00340 ULONG hoff;
00341 ULONG StatBinCount = 0;
00342 ULONG StatBinTotal = 0;
00343 ULONG StatBinMax = 0;
00344 ULONG StatFreeCount = 0;
00345 ULONG StatFreeTotal = 0;
00346 ULONG StatFreeMax = 0;
00347 ULONG StatAllocCount = 0;
00348 ULONG StatAllocTotal = 0;
00349 ULONG StatAllocMax = 0;
00350 ULONG binread;
00351 ULONG binsize;
00352 ULONG cellsize;
00353 ULONG boff;
00354 ULONG lboff;
00355 ULONG SizeTotal;
00356
00357
00358
00359
00360 filehandle = CreateFile(
FileName, GENERIC_READ, FILE_SHARE_READ,
NULL,
00361
OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
00362
00363
if (filehandle ==
INVALID_HANDLE_VALUE) {
00364 fprintf(stderr,
00365
"hivestat: Could not open file '%s' error = %08lx\n",
00366
FileName, GetLastError()
00367 );
00368
exit(1);
00369 }
00370
00371
00372
00373
00374
00375 rf = ReadFile(filehandle, buffer,
HBLOCK_SIZE, &readcount,
NULL);
00376
if ( ( ! rf ) || (readcount !=
HBLOCK_SIZE) ) {
00377 fprintf(stderr,
"hivestat: '%s' - cannot read base block!\n",
FileName);
00378
exit(1);
00379 }
00380
00381 bbp = (
PHBASE_BLOCK)(&(buffer[0]));
00382
00383
if ((bbp->
Major !=
HSYS_MAJOR) ||
00384 (bbp->
Minor >
HSYS_MINOR))
00385 {
00386 fprintf(stderr,
00387
"hivestat: major/minor != %d/%d get newer hivestat\n",
00388
HSYS_MAJOR,
HSYS_MINOR
00389 );
00390
exit(1);
00391 }
00392
00393
HiveVersion = bbp->
Minor;
00394
00395 hivelength = bbp->
Length +
HBLOCK_SIZE;
00396 hiveposition =
HBLOCK_SIZE;
00397 hoff = 0;
00398
00399 printf(
"hivestat: '%s'\n",
FileName);
00400
if (
DoTraceBin ||
DoTraceFree ||
DoTraceAlloc) {
00401 printf(
"\nTrace\n");
00402 printf(
"bi=bin, fr=free, al=allocated\n");
00403 printf(
"offset is file offset, sub HBLOCK to get HCELL\n");
00404 printf(
"type,offset,size\n");
00405 printf(
"\n");
00406 }
00407
00408
00409
00410
00411 guard = (
PHCELL)(&(buffer[0]) +
HBLOCK_SIZE);
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
while (hiveposition < hivelength) {
00424
00425
00426
00427
00428 rf = ReadFile(filehandle, buffer,
HBLOCK_SIZE, &readcount,
NULL);
00429
if ( ( ! rf ) || (readcount !=
HBLOCK_SIZE) ) {
00430 fprintf(stderr,
"hivestat: '%s' read error @%08lx\n",
FileName, hiveposition);
00431
exit(1);
00432 }
00433 hbp = (
PHBIN)(&(buffer[0]));
00434
00435
if (hbp->
Signature !=
HBIN_SIGNATURE) {
00436 fprintf(stderr,
00437
"hivestat: '%s' bad bin sign. @%08lx\n",
FileName, hiveposition);
00438
exit(1);
00439 }
00440 hiveposition +=
HBLOCK_SIZE;
00441 hoff +=
HBLOCK_SIZE;
00442
ASSERT(hoff+
HBLOCK_SIZE == hiveposition);
00443
00444 StatBinCount++;
00445 binsize = hbp->
Size;
00446 StatBinTotal += binsize;
00447
if (binsize > StatBinMax) {
00448 StatBinMax = binsize;
00449 }
00450
00451
if (
DoTraceBin) {
00452 printf(
"bi,x%08lx,%ld\n", hoff, binsize);
00453 }
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463 cp = (
PHCELL)((PUCHAR)hbp +
sizeof(
HBIN));
00464 boff =
sizeof(
HBIN);
00465 lboff = -1;
00466 binread =
HBLOCK_SIZE;
00467
00468
while (binread <= binsize) {
00469
00470
00471
00472
00473
00474
00475
if (cp->
Size > 0) {
00476
00477
00478
00479 cellsize = cp->
Size;
00480 StatFreeCount++;
00481 StatFreeTotal += cellsize;
00482
if (cellsize > StatFreeMax) {
00483 StatFreeMax = cellsize;
00484 }
00485
00486
if (
DoTraceFree) {
00487 printf(
"fr,x%08lx,%ld\n",
00488 hoff+((PUCHAR)cp - &(buffer[0])), cellsize);
00489 }
00490
00491
00492 }
else {
00493
00494
00495
00496 cellsize = -1 * cp->
Size;
00497 StatAllocCount++;
00498 StatAllocTotal += cellsize;
00499
if (cellsize > StatAllocMax) {
00500 StatAllocMax = cellsize;
00501 }
00502
00503
if (
DoTraceAlloc) {
00504 printf(
"al,x%08lx,%ld\n",
00505 hoff+((PUCHAR)cp - &(buffer[0])), cellsize);
00506 }
00507
00508
ScanCell(cp,cellsize);
00509
00510 }
00511
00512
00513
00514
00515
#if 0
00516
if (cp->
Last != lboff) {
00517 printf(
"e!,x%08lx bad LAST pointer %08lx\n",
00518 hoff+((PUCHAR)cp - &(buffer[0])), cp->
Last);
00519 }
00520
#endif
00521
00522
00523
00524
00525 lboff = boff;
00526 cp = (
PHCELL)((PUCHAR)cp + cellsize);
00527 boff += cellsize;
00528
00529
00530
00531
00532
00533
00534
while ( (cp >= guard) && (binread < binsize) ) {
00535
00536 rf = ReadFile(filehandle, buffer,
HBLOCK_SIZE, &readcount,
NULL);
00537
if ( ( ! rf ) || (readcount !=
HBLOCK_SIZE) ) {
00538 fprintf(stderr,
"hivestat: '%s' read error @%08lx\n",
FileName, hiveposition);
00539
exit(1);
00540 }
00541 cp = (
PHCELL)((PUCHAR)cp -
HBLOCK_SIZE);
00542 hiveposition +=
HBLOCK_SIZE;
00543 hoff +=
HBLOCK_SIZE;
00544 binread +=
HBLOCK_SIZE;
00545
ASSERT(hoff+
HBLOCK_SIZE == hiveposition);
00546 }
00547
00548
if (boff >= binsize) {
00549
break;
00550 }
00551 }
00552 }
00553
00554
00555
00556
00557
if (
DoSummary) {
00558
00559 printf(
"\nSummary:\n");
00560 printf(
"type\tcount/max single/total space\n");
00561 printf(
"%s\t%7ld\t%7ld\t%7ld\n",
00562
"bin", StatBinCount, StatBinMax, StatBinTotal);
00563 printf(
"%s\t%7ld\t%7ld\t%7ld\n",
00564
"free", StatFreeCount, StatFreeMax, StatFreeTotal);
00565 printf(
"%s\t%7ld\t%7ld\t%7ld\n",
00566
"alloc", StatAllocCount, StatAllocMax, StatAllocTotal);
00567
00568 }
00569
00570
if (
DoSummary &&
DoCellType) {
00571
00572 printf(
"\n");
00573
00574 SizeTotal =
SizeKeyData +
00575
SizeValueData +
00576
SizeSDData +
00577
SizeIndexData +
00578
SizeUnknownData;
00579
00580 printf(
"Total Key Data %7d (%5.2f %%)\n",
SizeKeyData,
00581 (
float)
SizeKeyData*100/SizeTotal);
00582 printf(
"Total Value Data %7d (%5.2f %%)\n",
SizeValueData,
00583 (
float)
SizeValueData*100/SizeTotal);
00584 printf(
"Total SD Data %7d (%5.2f %%)\n",
SizeSDData,
00585 (
float)
SizeSDData*100/SizeTotal);
00586 printf(
"Total Index Data %7d (%5.2f %%)\n",
SizeIndexData,
00587 (
float)
SizeIndexData*100/SizeTotal);
00588 printf(
"Total Unknown Data %7d (%5.2f %%)\n",
SizeUnknownData,
00589 (
float)
SizeUnknownData*100/SizeTotal);
00590
00591 printf(
"\n");
00592 printf(
"Average Key Data %8.2f (%d cells)\n",
00593 (
float)
SizeKeyData/
NumKeyData,
00594
NumKeyData);
00595 printf(
"Average Value Data %8.2f (%d cells)\n",
00596 (
float)
SizeValueData/
NumValueData,
00597
NumValueData);
00598 printf(
"Average SD Data %8.2f (%d cells)\n",
00599 (
float)
SizeSDData/
NumSDData,
00600
NumSDData);
00601 printf(
"Average Index Data %8.2f (%d cells)\n",
00602 (
float)
SizeIndexData/
NumIndexData,
00603
NumIndexData);
00604 printf(
"Average Unknown Data %8.2f (%d cells)\n",
00605 (
float)
SizeUnknownData/
NumUnknownData,
00606
NumUnknownData);
00607 }
00608
return;
00609 }
00610
00611
VOID
00612 ScanCell(
00613 IN
PHCELL Cell,
00614 IN ULONG CellSize
00615 )
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637 {
00638
PCELL_DATA Data;
00639
00640
if (!
DoCellType) {
00641
return;
00642 }
00643
00644
if (
HiveVersion==1) {
00645 Data = (
PCELL_DATA)&
Cell->u.OldCell.u.UserData;
00646 }
else {
00647 Data = (
PCELL_DATA)&
Cell->u.NewCell.u.UserData;
00648 }
00649
00650
00651
00652
00653
if ((Data->
u.
KeyNode.
Signature ==
CM_KEY_NODE_SIGNATURE) &&
00654 (CellSize >
sizeof(
CM_KEY_NODE))) {
00655
00656
00657
00658
00659
ScanKeyNode(&Data->
u.
KeyNode, CellSize);
00660
00661 }
else if ((Data->
u.
KeyValue.
Signature ==
CM_KEY_VALUE_SIGNATURE) &&
00662 (CellSize >
sizeof(
CM_KEY_VALUE))) {
00663
00664
00665
00666
00667
ScanKeyValue(&Data->
u.
KeyValue, CellSize);
00668
00669 }
else if ((Data->
u.
KeySecurity.
Signature ==
CM_KEY_SECURITY_SIGNATURE) &&
00670 (CellSize >
sizeof(
CM_KEY_SECURITY))) {
00671
00672
00673
00674
00675
ScanKeySD(&Data->
u.
KeySecurity, CellSize);
00676
00677 }
else if ((Data->
u.
KeyIndex.
Signature ==
CM_KEY_INDEX_ROOT) ||
00678 (Data->
u.
KeyIndex.
Signature ==
CM_KEY_INDEX_LEAF)) {
00679
00680
00681
00682
ScanKeyIndex(&Data->
u.
KeyIndex, CellSize);
00683
00684 }
else {
00685
00686
00687
00688
00689
00690
00691
ScanUnknown(Data, CellSize);
00692
00693 }
00694 }
00695
00696
VOID
00697 ScanKeyNode(
00698 IN
PCM_KEY_NODE Node,
00699 IN ULONG CellSize
00700 )
00701 {
00702
int i;
00703
00704
SizeKeyData += CellSize;
00705
NumKeyData++;
00706
00707
if (
AccessKeys) {
00708 printf(
"%d, %d, %d, %d, \"",
00709 Node->SubKeyCounts[
Stable],
00710 Node->ValueList.Count,
00711 Node->NameLength,
00712 Node->ClassLength);
00713
00714
for (i=0; i < Node->NameLength/
sizeof(WCHAR); i++) {
00715 printf(
"%c",(
CHAR)Node->Name[i]);
00716 }
00717 printf(
"\"\n");
00718 }
00719
00720 }
00721
VOID
00722 ScanKeyValue(
00723 IN
PCM_KEY_VALUE Value,
00724 IN ULONG CellSize
00725 )
00726 {
00727
int i;
00728
int DataLength;
00729
00730
SizeValueData += CellSize;
00731
NumValueData++;
00732
if (
AccessValues) {
00733 DataLength = Value->DataLength;
00734
if (DataLength >=
CM_KEY_VALUE_SPECIAL_SIZE) {
00735 DataLength -=
CM_KEY_VALUE_SPECIAL_SIZE;
00736 }
00737 printf(
"%d, %d, \"",
00738 DataLength,
00739 Value->NameLength);
00740
00741
for (i=0; i < Value->NameLength/
sizeof(WCHAR); i++) {
00742 printf(
"%c",(
CHAR)Value->Name[i]);
00743 }
00744 printf(
"\"\n");
00745 }
00746
00747 }
00748
VOID
00749 ScanKeySD(
00750 IN
PCM_KEY_SECURITY Security,
00751 IN ULONG CellSize
00752 )
00753 {
00754
SizeSDData += CellSize;
00755
NumSDData++;
00756
00757
if (
AccessSD) {
00758 printf(
"%d,%d\n",
00759 Security->ReferenceCount,
00760 Security->DescriptorLength);
00761 }
00762
00763 }
00764
VOID
00765 ScanKeyIndex(
00766 IN
PCM_KEY_INDEX Index,
00767 IN ULONG CellSize
00768 )
00769 {
00770
SizeIndexData += CellSize;
00771
NumIndexData++;
00772
00773 }
00774
VOID
00775 ScanUnknown(
00776 IN
PCELL_DATA Data,
00777 IN ULONG CellSize
00778 )
00779 {
00780
SizeUnknownData += CellSize;
00781
NumUnknownData++;
00782
00783 }
00784