Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

563 lines
12 KiB

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
regext.c
Abstract:
Kernel debugger extensions useful for the registry
Author:
John Vert (jvert) 7-Sep-1993
Environment:
Loaded as a kernel debugger extension
Revision History:
John Vert (jvert) 7-Sep-1993
created
--*/
#include "precomp.h"
#pragma hdrstop
HIVE_LIST_ENTRY HiveList[8];
ULONG TotalPages;
ULONG TotalPresentPages;
BOOLEAN SavePages;
BOOLEAN RestorePages;
HANDLE TempFile;
void
poolDumpHive(
IN PCMHIVE Hive
);
VOID
poolDumpMap(
IN ULONG Length,
IN PHMAP_DIRECTORY Map
);
void
dumpHiveFromFile(
HANDLE hFile
);
VOID
kcbWorker(
IN PCM_KEY_CONTROL_BLOCK pKcb
);
DECLARE_API( regpool )
/*++
Routine Description:
Goes through all the paged pool allocated to registry space and
determines which pages are present and which are not.
Called as:
!regext.pool [s|r]
s Save list of registry pages to temporary file
r Restore list of registry pages from temp. file
Arguments:
CurrentPc - Supplies the current pc at the time the extension is
called.
lpExtensionApis - Supplies the address of the functions callable
by this extension.
lpArgumentString - Supplies the pattern and expression for this
command.
Return Value:
None.
--*/
{
PLIST_ENTRY pCmpHiveListHead;
PLIST_ENTRY pNextHiveList;
HIVE_LIST_ENTRY *pHiveListEntry;
ULONG BytesRead;
PCMHIVE CmHive;
if (toupper(args[0])=='S') {
SavePages = TRUE;
} else {
SavePages = FALSE;
}
if (toupper(args[0])=='R') {
RestorePages = TRUE;
} else {
RestorePages = FALSE;
}
//
// Go get the hivelist.
//
memset(HiveList,0,sizeof(HiveList));
pHiveListEntry = (PHIVE_LIST_ENTRY)GetExpression("CmpMachineHiveList");
if (pHiveListEntry != NULL) {
ReadMemory((DWORD)pHiveListEntry,
HiveList,
sizeof(HiveList),
&BytesRead);
}
//
// First go and get the hivelisthead
//
pCmpHiveListHead = (PLIST_ENTRY)GetExpression("CmpHiveListHead");
if (pCmpHiveListHead==NULL) {
dprintf("CmpHiveListHead couldn't be read\n");
return;
}
ReadMemory((DWORD)&pCmpHiveListHead->Flink,
&pNextHiveList,
sizeof(pNextHiveList),
&BytesRead);
if (BytesRead != sizeof(pNextHiveList)) {
dprintf("Couldn't read first Flink (%lx) of CmpHiveList\n",
&pCmpHiveListHead->Flink);
return;
}
TotalPages = TotalPresentPages = 0;
if (SavePages || RestorePages) {
TempFile = CreateFile( "regext.dat",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_ALWAYS,
0,
NULL
);
if (TempFile == INVALID_HANDLE_VALUE) {
dprintf("Couldn't open regext.dat\n");
return;
}
}
if (RestorePages) {
dumpHiveFromFile(TempFile);
} else {
while (pNextHiveList != pCmpHiveListHead) {
CmHive = CONTAINING_RECORD(pNextHiveList, CMHIVE, HiveList);
poolDumpHive(CmHive);
ReadMemory((DWORD)&pNextHiveList->Flink,
&pNextHiveList,
sizeof(pNextHiveList),
&BytesRead);
if (BytesRead != sizeof(pNextHiveList)) {
dprintf("Couldn't read Flink (%lx) of %lx\n",
&pCmpHiveListHead->Flink,pNextHiveList);
break;
}
if (CheckControlC()) {
return;
}
}
}
dprintf("Total pages present = %d / %d\n",
TotalPresentPages,
TotalPages);
if (SavePages || RestorePages) {
CloseHandle( TempFile );
}
}
void
poolDumpHive(
IN PCMHIVE pHive
)
{
CMHIVE CmHive;
ULONG BytesRead;
WCHAR FileName[HBASE_NAME_ALLOC/2 + 1];
CHAR buf[512];
ULONG cb;
dprintf("\ndumping hive at %lx ",pHive);
ReadMemory((DWORD)pHive,
&CmHive,
sizeof(CmHive),
&BytesRead);
if (BytesRead < sizeof(CmHive)) {
dprintf("\tRead %lx bytes from %lx\n",BytesRead,pHive);
return;
}
ReadMemory((DWORD)&CmHive.Hive.BaseBlock->FileName,
FileName,
sizeof(FileName),
&BytesRead);
if (BytesRead < sizeof(FileName)) {
wcscpy(FileName, L"UNKNOWN");
} else {
if (FileName[0]==L'\0') {
wcscpy(FileName, L"NONAME");
} else {
FileName[HBASE_NAME_ALLOC/2]=L'\0';
}
}
dprintf("(%ws)\n",FileName);
dprintf(" %d KCBs open\n",CmHive.KcbCount);
dprintf(" Stable Length = %lx\n",CmHive.Hive.Storage[Stable].Length);
if (SavePages) {
sprintf(buf,
"%ws %d %d\n",
FileName,
CmHive.Hive.Storage[Stable].Length,
CmHive.Hive.Storage[Volatile].Length);
WriteFile( TempFile, buf, strlen(buf), &cb, NULL );
}
poolDumpMap(CmHive.Hive.Storage[Stable].Length,
CmHive.Hive.Storage[Stable].Map);
dprintf(" Volatile Length = %lx\n",CmHive.Hive.Storage[Volatile].Length);
poolDumpMap(CmHive.Hive.Storage[Volatile].Length,
CmHive.Hive.Storage[Volatile].Map);
}
VOID
poolDumpMap(
IN ULONG Length,
IN PHMAP_DIRECTORY Map
)
{
ULONG Tables;
ULONG MapSlots;
ULONG i;
ULONG BytesRead;
HMAP_DIRECTORY MapDirectory;
PHMAP_TABLE MapTable;
HMAP_ENTRY MapEntry;
ULONG Garbage;
ULONG Present=0;
CHAR buf[512];
ULONG cb;
if (Length==0) {
return;
}
MapSlots = Length / HBLOCK_SIZE;
Tables = 1+ ((MapSlots-1) / HTABLE_SLOTS);
//
// read in map directory
//
ReadMemory((DWORD)Map,
&MapDirectory,
Tables * sizeof(PHMAP_TABLE),
&BytesRead);
if (BytesRead < (Tables * sizeof(PHMAP_TABLE))) {
dprintf("Only read %lx/%lx bytes from %lx\n",
BytesRead,
Tables * sizeof(PHMAP_TABLE),
Map);
return;
}
//
// check out each map entry
//
for (i=0; i<MapSlots; i++) {
MapTable = MapDirectory.Directory[i/HTABLE_SLOTS];
ReadMemory((DWORD)&(MapTable->Table[i%HTABLE_SLOTS]),
&MapEntry,
sizeof(HMAP_ENTRY),
&BytesRead);
if (BytesRead < sizeof(HMAP_ENTRY)) {
dprintf(" can't read HMAP_ENTRY at %lx\n",
&(MapTable->Table[i%HTABLE_SLOTS]));
}
if (SavePages) {
sprintf(buf, "%lx\n",MapEntry.BlockAddress);
WriteFile( TempFile, buf, strlen(buf), &cb, NULL );
}
//
// probe the HBLOCK
//
ReadMemory((DWORD)MapEntry.BlockAddress,
&Garbage,
sizeof(ULONG),
&BytesRead);
if (BytesRead > 0) {
++Present;
}
}
dprintf(" %d/%d pages present\n",
Present,
MapSlots);
TotalPages += MapSlots;
TotalPresentPages += Present;
}
void
dumpHiveFromFile(
HANDLE hFile
)
/*++
Routine Description:
Takes a list of the registry hives and pages from a file and
checks to see how many of the pages are in memory.
The format of the file is as follows
hivename stablelength volatilelength
stable page address
stable page address
.
.
.
volatile page address
volatile page address
.
.
.
hivename stablelength volatilelength
.
.
.
Arguments:
File - Supplies a file.
Return Value:
None.
--*/
{
#if 0
CHAR Hivename[33];
ULONG StableLength;
ULONG VolatileLength;
ULONG Page;
ULONG NumFields;
ULONG Garbage;
ULONG Present;
ULONG Total;
ULONG BytesRead;
BYTE buf[512]
while (!feof(File)) {
NumFields = fscanf(File,"%s %d %d\n",
Hivename,
&StableLength,
&VolatileLength);
if (NumFields != 3) {
dprintf("fscanf returned %d\n",NumFields);
return;
}
dprintf("\ndumping hive %s\n",Hivename);
dprintf(" Stable Length = %lx\n",StableLength);
Present = 0;
Total = 0;
while (StableLength > 0) {
fscanf(File, "%lx\n",&Page);
ReadMemory((DWORD)Page,
&Garbage,
sizeof(ULONG),
&BytesRead);
if (BytesRead > 0) {
++Present;
}
++Total;
StableLength -= HBLOCK_SIZE;
}
if (Total > 0) {
dprintf(" %d/%d stable pages present\n",
Present,Total);
}
TotalPages += Total;
TotalPresentPages += Present;
dprintf(" Volatile Length = %lx\n",VolatileLength);
Present = 0;
Total = 0;
while (VolatileLength > 0) {
fscanf(File, "%lx\n",&Page);
ReadMemory((DWORD)Page,
&Garbage,
sizeof(ULONG),
&BytesRead);
if (BytesRead > 0) {
++Present;
}
++Total;
VolatileLength -= HBLOCK_SIZE;
}
if (Total > 0) {
dprintf(" %d/%d volatile pages present\n",
Present,Total);
}
TotalPages += Total;
TotalPresentPages += Present;
}
#endif
}
DECLARE_API( regkcb )
/*++
Routine Description:
Walks the kcb tree and prints the names of keys which have
outstanding kcbs
Called as:
!regkcb
Arguments:
CurrentPc - Supplies the current pc at the time the extension is
called.
lpExtensionApis - Supplies the address of the functions callable
by this extension.
lpArgumentString - Supplies the pattern and expression for this
command.
Return Value:
None.
--*/
{
PCM_KEY_CONTROL_BLOCK pKCB;
PCM_KEY_CONTROL_BLOCK Root;
ULONG BytesRead;
Root = (PCM_KEY_CONTROL_BLOCK)GetExpression("CmpKeyControlBlockRoot");
if (Root == NULL) {
dprintf("Couldn't find address of CmpKeyControlBlockRoot\n");
return;
}
ReadMemory((DWORD)Root,
&pKCB,
sizeof(pKCB),
&BytesRead);
if (BytesRead < sizeof(pKCB)) {
dprintf("Couldn't get pKCB from CmpKeyControlBlockRoot\n");
}
kcbWorker(pKCB);
}
VOID
kcbWorker(
IN PCM_KEY_CONTROL_BLOCK pKcb
)
/*++
Routine Description:
recursive worker for walking the kcb tree.
Arguments:
pKcb - Supplies pointer to kcb.
Return Value:
None.
--*/
{
CM_KEY_CONTROL_BLOCK kcb;
ULONG BytesRead;
WCHAR *Buffer;
ReadMemory((DWORD)pKcb,
&kcb,
sizeof(kcb),
&BytesRead);
if (BytesRead < sizeof(kcb)) {
dprintf("Can't read kcb at %lx\n",pKcb);
return;
}
if (kcb.Left != NULL) {
kcbWorker(kcb.Left);
}
dprintf("%d - ",kcb.RefCount);
Buffer = LocalAlloc(LPTR, kcb.FullName.Length);
if (Buffer != NULL) {
ReadMemory((DWORD)kcb.FullName.Buffer,
Buffer,
kcb.FullName.Length,
&BytesRead);
kcb.FullName.Length = (USHORT)BytesRead;
kcb.FullName.Buffer = Buffer;
dprintf(" %wZ\n",&kcb.FullName);
LocalFree(Buffer);
} else {
dprintf(" ??? \n");
}
if (kcb.Right != NULL) {
kcbWorker(kcb.Right);
}
}