windows-nt/Source/XPSP1/NT/base/tools/setupext/setupext.c
2020-09-26 16:20:57 +08:00

2418 lines
66 KiB
C

/*++
Copyright (c) 1993-2000 Microsoft Corporation
Module Name:
setupext.c
Abstract:
This file contains the generic routines and initialization code
for the kernel debugger extensions dll.
--*/
#define KDEXT_64BIT
#include <windows.h>
#include <wdbgexts.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ntverp.h>
//
// BUGBUG - need to find better way to get these values
//
#define HASH_BUCKET_COUNT 509
#define WizPagesTypeMax 7
#define LOADED_INF_SIG 0x24666e49
#define INF_STYLE_NONE 0x00000000 // unrecognized or non-existent
#define INF_STYLE_OLDNT 0x00000001 // winnt 3.x
#define INF_STYLE_WIN4 0x00000002 // Win95
#define SPOST_NONE 0
#define SPOST_PATH 1
#define SPOST_URL 2
#define SPOST_MAX 3
#define DRIVERSIGN_NONE 0x00000000
#define DRIVERSIGN_WARNING 0x00000001
#define DRIVERSIGN_BLOCKING 0x00000002
#define SP_FILE_QUEUE_SIG 0xc78e1098
#define FILEOP_COPY 0
#define FILEOP_RENAME 1
#define FILEOP_DELETE 2
#define FILEOP_ABORT 0
#define FILEOP_DOIT 1
#define FILEOP_SKIP 2
#define FILEOP_RETRY FILEOP_DOIT
#define FILEOP_NEWPATH 4
//
// Local function prototypes
//
VOID
UtilGetWStringField (
ULONG64 Address,
PUCHAR Structure,
PUCHAR Field,
PWCHAR Buffer,
ULONG Size
);
VOID
UtilReadWString (
ULONG64 Address,
PWCHAR Buffer,
ULONG64 Size
);
VOID
UtilDumpHex (
PUCHAR Buffer,
ULONG Size
);
VOID
DumpUnwindList(
ULONG64 pun,
BOOL recursive
);
VOID
DumpTargetEnt(
ULONG64 pte
);
VOID
DumpDelayMoveList(
ULONG64 pdn,
BOOL recursive
);
VOID
DumpFileQueueNodeList(
ULONG64 pfqn,
ULONG64 mask,
BOOL recursive
);
VOID
DumpSourceMediaInfoList(
ULONG64 smi,
ULONG64 mask,
BOOL recursive
);
VOID
DumpCatalogInfoList(
ULONG64 ci,
ULONG64 mask,
BOOL recursive
);
VOID
DumpAltPlatformInfo(
ULONG64 api
);
VOID
DumpXFile(
ULONG64 pxf,
ULONG64 mask
);
VOID
DumpXDirectory(
ULONG64 pxdir,
ULONG64 mask
);
VOID
DumpXDrive(
ULONG64 pxd,
ULONG64 mask
);
VOID
DumpInfVersionNode(
ULONG64 ver
);
VOID
DumpInfLine(
ULONG64 line,
ULONG64 valuedata
);
VOID
DumpStringTableHeader(
ULONG64 st
);
VOID
DumpInfSection(
ULONG64 section,
ULONG64 linedata,
ULONG64 valuedata
);
ULONG64
GetStringTableData(
ULONG64 st
);
ULONG64
GetFirstNode(
ULONG64 stdata,
ULONG64 offset,
PULONG64 poffset
);
ULONG64
GetNextNode(
ULONG64 stdata,
ULONG64 node,
PULONG64 offset
);
BOOL
CheckInterupted(
VOID
);
LPCSTR
GetWizPage(
DWORD i
);
VOID
DumpOcComponent(
ULONG64 offset,
ULONG64 node,
ULONG64 pcomp
);
//
// globals
//
EXT_API_VERSION ApiVersion = { (VER_PRODUCTVERSION_W >> 8), (VER_PRODUCTVERSION_W & 0xff), EXT_API_VERSION_NUMBER64, 0 };
WINDBG_EXTENSION_APIS ExtensionApis;
USHORT SavedMajorVersion;
USHORT SavedMinorVersion;
ULONG64 EXPRLastDump = 0;
//
// this string is for supporting both the old and the new way of getting
// data from the kernel. Maybe it will go away soon.
//
char ___SillyString[200];
DllInit(
HANDLE hModule,
DWORD dwReason,
DWORD dwReserved
)
{
switch (dwReason) {
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
case DLL_PROCESS_ATTACH:
break;
}
return TRUE;
}
VOID
WinDbgExtensionDllInit(
PWINDBG_EXTENSION_APIS64 lpExtensionApis, // 64Bit Change
USHORT MajorVersion,
USHORT MinorVersion
)
{
ExtensionApis = *lpExtensionApis;
SavedMajorVersion = MajorVersion;
SavedMinorVersion = MinorVersion;
return;
}
VOID
CheckVersion(
VOID
)
{
return;
}
LPEXT_API_VERSION
ExtensionApiVersion(
VOID
)
{
return &ApiVersion;
}
VOID
UtilGetWStringField (
ULONG64 Address,
PUCHAR Structure,
PUCHAR Field,
PWCHAR Buffer,
ULONG Size
)
{
ULONG offset = 0;
GetFieldOffset (Structure, Field, &offset);
UtilReadWString (offset + Address, Buffer, Size);
}
VOID
UtilReadWString (
ULONG64 Address,
PWCHAR Buffer,
ULONG64 Size
)
{
ULONG64 count = 0;
ZeroMemory (Buffer, (ULONG) Size);
while (1)
{
if (count == (Size-1)) {
break;
}
ReadMemory (Address + (count * sizeof (WCHAR)),
Buffer + count,
sizeof (WCHAR),
NULL);
if (!Buffer[count]) {
break;
}
count ++;
}
}
ULONG64
UtilStringToUlong64 (
UCHAR *String
)
{
ULONG64 ReturnValue = 0;
sscanf (String, "%I64x", &ReturnValue);
return ReturnValue;
}
VOID
UtilDumpHex (
PUCHAR Buffer,
ULONG Size
)
{
ULONG count = 0, count2 = 0;
dprintf ("\n%08lx:", Buffer);
while (count < Size) {
if (! (count%16) && count) {
dprintf ("|");
for (count2 = 16; count2; count2--) {
if (Buffer[count - count2] >= 0x30) {
dprintf ("%c", (UCHAR) Buffer[count - count2]);
} else {
dprintf (".");
}
}
dprintf ("\n%08lx:", Buffer + count);
}
dprintf ("%02x ", (UCHAR) Buffer[count]);
count ++;
}
}
VOID
DumpUnwindList(
ULONG64 pun,
BOOL recursive
)
{
InitTypeRead (pun, SETUPAPI!SP_UNWIND_NODE);
dprintf( "\t\t***SP_UNWIND_NODE structure***\n" );
dprintf( "\t\t NextNode : 0x%I64x\n", ReadField (NextNode));
dprintf( "\t\t TargetID : 0x%I64x\n", ReadField (TargetID));
dprintf( "\t\t SecurityDesc : 0x%I64x\n", ReadField (SecurityDesc));
dprintf( "\t\t CreateTime : 0x%I64x 0x%I64x\n",
ReadField (CreateTime.dwLowDateTime),
ReadField (CreateTime.dwHighDateTime));
dprintf( "\t\t AccessTime : 0x%I64x 0x%I64x\n",
ReadField (AccessTime.dwLowDateTime),
ReadField (AccessTime.dwHighDateTime));
dprintf( "\t\t WriteTime : 0x%I64x 0x%I64x\n",
ReadField (WriteTime.dwLowDateTime),
ReadField (WriteTime.dwHighDateTime));
if (ReadField (NextNode) && recursive) {
if (CheckInterupted()) {
return;
}
DumpUnwindList(ReadField (NextNode), TRUE );
}
}
VOID
DumpTargetEnt(
ULONG64 pte
)
{
InitTypeRead (pte, SETUPAPI!SP_TARGET_ENT);
dprintf( "\t\t***SP_TARGET_ENT structure***\n" );
dprintf( "\t\t TargetRoot : 0x%I64x\n", ReadField (TargetRoot));
dprintf( "\t\t TargetSubDir : 0x%I64x\n", ReadField (TargetSubDir));
dprintf( "\t\t TargetFilename : 0x%I64\n", ReadField (TargetFilename));
dprintf( "\t\t BackupRoot : 0x%I64x\n", ReadField (BackupRoot));
dprintf( "\t\t BackupSubDir : 0x%I64x\n", ReadField (BackupSubDir));
dprintf( "\t\t BackupFilename : 0x%I64x\n", ReadField (BackupFilename));
dprintf( "\t\t NewTargetFilename : 0x%I64x\n", ReadField (NewTargetFilename));
dprintf( "\t\t InternalFlags : 0x%I64x\n", ReadField (InternalFlags));
}
VOID
DumpDelayMoveList(
ULONG64 pdn,
BOOL recursive
)
{
InitTypeRead (pdn, SETUPAPI!SP_DELAYMOVE_NODE);
dprintf( "\t\t***SP_DELAYMOVE_NODE structure***\n" );
dprintf( "\t\t NextNode : 0x%I64x\n", ReadField (NextNode));
dprintf( "\t\t SourceFilename : 0x%I64x\n", ReadField (SourceFilename));
dprintf( "\t\t TargetFilename : 0x%I64x\n", ReadField (TargetFilename));
dprintf( "\t\t SecurityDesc (stringtable index) : 0x%I64x\n", ReadField (SecurityDesc));
if (ReadField (NextNode) && recursive) {
if (CheckInterupted()) {
return;
}
DumpDelayMoveList( ReadField (Next), TRUE );
}
}
VOID
DumpFileQueueNodeList(
ULONG64 pfqn,
ULONG64 mask,
BOOL recursive
)
{
InitTypeRead (pfqn, SP_FILE_QUEUE_NODE);
dprintf( "\t\t***SP_FILE_QUEUE_NODE structure***\n" );
dprintf( "\t\t Next : 0x%I64x\n", ReadField (Next));
dprintf( "\t\t Operation : 0x%I64x ( %s )\n", ReadField (Operation),
(ReadField (Operation) == FILEOP_DELETE) ? "DELETE" :
(ReadField (Operation) == FILEOP_RENAME) ? "RENAME" :
"COPY" );
dprintf( "\t\t SourceRootPath : 0x%I64x\n", ReadField (SourceRootPath));
dprintf( "\t\t SourcePath : 0x%I64x\n", ReadField (SourcePath));
dprintf( "\t\t SourceFilename : 0x%I64x\n", ReadField (SourceFilename));
dprintf( "\t\t TargetDirectory : 0x%I64x\n", ReadField (TargetDirectory));
dprintf( "\t\t SecurityDesc : 0x%I64x\n", ReadField (SecurityDesc));
dprintf( "\t\t SourceMediaInfo : 0x%I64x\n", ReadField (SourceMediaInfo));
if (ReadField (SourceMediaInfo) && recursive) {
if (CheckInterupted()) {
return;
}
DumpSourceMediaInfoList( ReadField (SourceMediaInfo), mask, FALSE );
InitTypeRead (pfqn, SP_FILE_QUEUE_NODE);
}
dprintf( "\t\t StyleFlags : 0x%I64x\n", ReadField (StyleFlags));
dprintf( "\t\t InternalFlags : 0x%I64x\n", ReadField (InternalFlags));
dprintf( "\t\t CatalogInfo : 0x%I64x\n", ReadField (CatalogInfo));
if (ReadField (CatalogInfo) && recursive) {
if (CheckInterupted()) {
return;
}
DumpCatalogInfoList( ReadField (CatalogInfo), mask, FALSE );
InitTypeRead (pfqn, SP_FILE_QUEUE_NODE);
}
if (ReadField (Next) && recursive) {
DumpFileQueueNodeList( ReadField (Next), mask, TRUE );
}
}
VOID
DumpSourceMediaInfoList(
ULONG64 smi,
ULONG64 mask,
BOOL recursive
)
{
InitTypeRead (smi, SETUPAPI!SOURCE_MEDIA_INFO);
dprintf( "\t\t***SOURCE_MEDIA_INFO structure***\n" );
dprintf( "\t\t Next : 0x%I64x\n", ReadField (Next));
dprintf( "\t\t Description : 0x%I64x\n", ReadField (Description));
dprintf( "\t\t DescriptionDisplayName : 0x%I64x\n", ReadField (DescriptionDisplayName));
dprintf( "\t\t Tagfile : 0x%I64x\n", ReadField (Tagfile));
dprintf( "\t\t SourceRootPath : 0x%I64x\n", ReadField (SourceRootPath));
dprintf( "\t\t CopyQueue : 0x%I64x\n", ReadField (CopyQueue));
if (ReadField (CopyQueue) && (mask & 8) && recursive) {
if (CheckInterupted()) {
return;
}
DumpFileQueueNodeList( ReadField (CopyQueue), mask, FALSE );
InitTypeRead (smi, SETUPAPI!SOURCE_MEDIA_INFO);
}
dprintf( "\t\t CopyNodeCount : 0x%I64x\n", ReadField (CopyNodeCount));
dprintf( "\t\t Flags : 0x%I64x\n", ReadField (Flags));
if (ReadField (Next) && recursive) {
if (CheckInterupted()) {
return;
}
DumpSourceMediaInfoList( ReadField (next), mask, TRUE );
}
}
VOID
DumpCatalogInfoList(
ULONG64 ci,
ULONG64 mask,
BOOL recursive
)
{
WCHAR Buffer[200];
InitTypeRead (ci, SETUPAPI!SPQ_CATALOG_INFO);
dprintf( "\t\t***SPQ_CATALOG_INFO structure***\n" );
dprintf( "\t\t Next : 0x%I64x\n", ReadField (Next));
dprintf( "\t\t CatalogFileFromInf : 0x%I64x\n", ReadField (CatalogFileFromInf));
dprintf( "\t\t AltCatalogFileFromInf : 0x%I64x\n", ReadField (AltCatalogFileFromInf));
dprintf( "\t\t AltCatalogFileFromInfPending : 0x%I64x\n", ReadField (AltCatalogFileFromInfPending));
dprintf( "\t\t InfFullPath : 0x%I64x\n", ReadField (InfFullPath));
dprintf( "\t\t InfOriginalName : 0x%I64x\n", ReadField (InfOriginalName));
dprintf( "\t\t InfFinalPath : 0x%I64x\n", ReadField (InfFinalPath));
dprintf( "\t\t VerificationFailureError : 0x%I64x\n", ReadField (VerificationFailureError));
dprintf( "\t\t Flags : 0x%I64x\n", ReadField (Flags));
UtilGetWStringField (ci, "SETUPAPI!SPQ_CATALOG_INFO", "CatalogFilenameOnSystem", Buffer, sizeof (Buffer));
dprintf( "\t\t CatalogFilenameOnSystem : %ws\n", Buffer);
if (ReadField (Next) && recursive) {
if (CheckInterupted()) {
return;
}
DumpCatalogInfoList(ReadField (Next), mask, TRUE ) ;
}
}
VOID
DumpAltPlatformInfo(
ULONG64 api
)
{
InitTypeRead (api, SETUPAPI!SP_ALTPLATFORM_INFO);
dprintf( "\t\t***SP_ALT_PLATFORM_INFO structure***\n" );
dprintf( "\t\t cbSize : 0x%I64x\n", ReadField (cbSize));
dprintf( "\t\t Platform : 0x%I64x\n", ReadField (Platform));
dprintf( "\t\t MajorVersion : 0x%I64x\n", ReadField (MajorVersion));
dprintf( "\t\t MinorVersion : 0x%I64x\n", ReadField (MinorVersion));
dprintf( "\t\t ProcessorArchitecture : 0x%I64x\n", ReadField (ProcessorArchitecture));
dprintf( "\t\t Reserved : 0x%I64x\n", ReadField (Reserved));
}
VOID
DumpXFile(
ULONG64 pxf,
ULONG64 mask
)
{
if ((mask & 4) == 0 ) {
return;
}
InitTypeRead (pxf, SETUPAPI!XFILE);
dprintf( "\t\t ***XFILE structure***\n" );
dprintf( "\t\t CurrentSize : 0x%I64x", ReadField (CurrentSize));
if (ReadField (CurrentSize) == -1) {
dprintf( " (doesn't currently exist)" );
}
dprintf( "\n\t\t NewSize : 0x%I64x", ReadField (NewSize));
if (ReadField (NewSize) == -1) {
dprintf( " (will be deleted)" );
}
dprintf("\n");
}
VOID
DumpXDirectory(
ULONG64 pxdir,
ULONG64 mask
)
{
ULONG64 pst;
DWORD i;
ULONG64 offset;
ULONG64 stdata = 0,pextradata = 0;
//STRING_TABLE st;
//PSTRING_NODEW node;//, prev;
//PXFILE pxf;
ULONG64 node = 0, boffset = 0, count = 0;
WCHAR Buffer [200];
ULONG64 pxf = 0;
if ((mask & 2) == 0 ) {
return;
}
InitTypeRead (pxdir, SETUPAPI!XDIRECTORY);
dprintf( "\t\t ***XDIRECTORY structure***\n");
dprintf( "\t\t SpaceRequired : 0x%x\n", ReadField (SpaceRequired));
dprintf( "\t\t FilesTable : 08%08x\n", ReadField (FilesTable));
pst = ReadField (FilesTable);
DumpStringTableHeader (pst);
stdata = GetStringTableData (pst);
if (!stdata) {
dprintf("error retrieving string table data!\n");
return;
}
//
// now, dump each node in the string table
//
for (i = 0; i<HASH_BUCKET_COUNT; i++ ) {
node = GetFirstNode(stdata, (stdata + (GetTypeSize ("SETUPAPI!ULONG_PTR") * i)), &offset );
if (!node) {
// dprintf("No data at hash bucket %d\n", i);
} else {
dprintf("Data at hash bucket %d\n", i);
while (node) {
boffset = GetTypeSize ("SETUPAPI!ULONG_PTR");
count = 0;
while (1)
{
if (count == sizeof (Buffer)) {
break;
}
ReadMemory (node + boffset + count,
(PWCHAR) &Buffer + count/2,
sizeof (WCHAR),
NULL);
if (!Buffer[count/2]) {
break;
}
count +=2;
}
dprintf("\tEntry Name:\t%ws (0x%08x)\n", Buffer, offset);
InitTypeRead (pst, SETUPAPI!STRING_TABLE);
pxf = ReadField (Data) + offset + (wcslen(Buffer) + 1)*sizeof(WCHAR) + sizeof(DWORD);
DumpXFile(pxf, mask );
node = GetNextNode( stdata, node, &offset );
if (CheckInterupted()) {
return;
}
}
}
if (CheckInterupted()) {
return;
}
}
}
VOID
DumpXDrive(
ULONG64 pxd,
ULONG64 mask
)
{
DWORD i;
ULONG64 offset = 0;
ULONG64 stdata = 0, pextradata = 0, pst = 0;
//STRING_TABLE st;
//PSTRING_NODEW node;//, prev;
//PXDIRECTORY pxdir;
ULONG64 node = 0, pxdir = 0, boffset = 0, count = 0;
WCHAR Buffer [200];
if ((mask & 1) == 0) {
return;
}
InitTypeRead (pxd, SETUPAPI!XDRIVE);
dprintf( "\t\t***XDRIVE structure***\n");
dprintf( "\t\t SpaceRequired : 0x%I64x\n", ReadField (SpaceRequired));
dprintf( "\t\t BytesPerCluster : 0x%I64x\n", ReadField (BytesPerCluster));
dprintf( "\t\t Slop : 0x%I64x\n", ReadField (Slop));
dprintf( "\t\t DirsTable : 0x%016I64x\n", ReadField (DirsTable));
pst = ReadField (DirsTable);
DumpStringTableHeader (pst);
stdata = GetStringTableData(pst );
if (!stdata) {
dprintf("error retrieving string table data!\n");
return;
}
//
// now, dump each node in the string table
//
for (i = 0; i<HASH_BUCKET_COUNT; i++ ) {
node = GetFirstNode(stdata, (stdata + (GetTypeSize ("SETUPAPI!ULONG_PTR") * i)), &offset );
if (!node) {
// dprintf("No data at hash bucket %d\n", i);
} else {
dprintf("Data at hash bucket %d\n", i);
while (node) {
boffset = GetTypeSize ("SETUPAPI!ULONG_PTR");
count = 0;
while (1)
{
if (count == sizeof (Buffer)) {
break;
}
ReadMemory (node + boffset + count,
(PWCHAR) &Buffer + count/2,
sizeof (WCHAR),
NULL);
if (!Buffer[count/2]) {
break;
}
count +=2;
}
dprintf("\tEntry Name:\t%ws (0x%08x)\n", Buffer, offset);
InitTypeRead (pst, SETUPAPI!STRING_TABLE);
pxdir = ReadField (Data) + offset + (wcslen(Buffer) + 1)*sizeof(WCHAR) + sizeof(DWORD);
DumpXDirectory(pxdir, mask );
node = GetNextNode( stdata, node, &offset );
if (CheckInterupted()) {
return;
}
}
}
if (CheckInterupted()) {
return;
}
}
}
VOID
DumpInfVersionNode(
ULONG64 ver
)
{
WCHAR Buffer[200];
InitTypeRead (ver, SETUPAPI!INF_VERSION_NODE);
dprintf("***INF_VERSION_NODE***\n");
dprintf("\t FilenameSize : 0x%x\n", ReadField (FilenameSize));
dprintf("\t DataBlock : 0x%x\n", ReadField (DataBlock));
dprintf("\t DataSize : 0x%x\n", ReadField (DataSize));
dprintf("\t DatumCount : 0x%x\n", ReadField (DatumCount));
UtilGetWStringField (ver, "SETUPAPI!INF_VERSION_NODE", "Filename", Buffer, sizeof (Buffer));
dprintf("\t Filename : %ws\n", Buffer);
return;
}
VOID
DumpInfLine(
ULONG64 line,
ULONG64 valuedata
)
{
DWORD i;
ULONG64 ptr = 0;
ULONG64 data = 0;
ULONG ulongptrsize = GetTypeSize ("SETUPAPI!ULONG_PTR");
InitTypeRead (line, SETUPAPI!INF_LINE);
dprintf("\t ValueCount : 0x%I64x\n", ReadField (ValueCount));
dprintf("\t Flags : 0x%I64x\n", ReadField (Flags));
dprintf("\t Values : 0x%I64x\n", ReadField (Values));
if (ReadField (Flags) > 3) {
return;
}
for (i = 0; i< ReadField (ValueCount); i++) {
ptr = valuedata + (ReadField (Values) * ulongptrsize) + (i * ulongptrsize);
ReadMemory (ptr, &data, ulongptrsize, NULL);
dprintf("\t data [%ld] : 0x%I64x [0x%I64x]\n", i, ptr, data);
if (CheckInterupted()) {
return;
}
}
}
VOID
DumpInfSection(
ULONG64 section,
ULONG64 linedata,
ULONG64 valuedata
)
{
DWORD i;
//INF_LINE line;
ULONG64 line;
ULONG64 data;
InitTypeRead (section, SETUPAPI!INF_SECTION);
dprintf("***INF_SECTION***\n");
dprintf("\t SectionName : 0x%I64x\n", ReadField (SectionName));
dprintf("\t LineCount : 0x%I64x\n", ReadField (LineCount));
dprintf("\t Lines : 0x%I64x\n", ReadField (Lines));
for (i = 0; i< ReadField (LineCount); i++) {
data = linedata + (GetTypeSize ("SETUPAPI!INF_LINE") * ReadField (Lines)) + GetTypeSize ("SETUPAPI!INF_LINE") * i;
dprintf("***INF_LINE [%ld] at 0x%I64x***\n", i, data);
DumpInfLine (data, valuedata);
//
// Have to reinit type read because of DumpInfLine
//
InitTypeRead (section, SETUPAPI!INF_SECTION);
if (CheckInterupted()) {
return;
}
}
}
VOID
DumpStringTableHeader(
ULONG64 st
)
{
//
// dump the string table header
//
InitTypeRead (st, SETUPAPI!STRING_TABLE);
dprintf("\tBase Data ptr:\t0x%016I64x\n", ReadField (Data));
dprintf("\tDataSize:\t0x%016I64x\n", ReadField (DataSize));
dprintf("\tBufferSize:\t0x%016I64x\n", ReadField (BufferSize));
dprintf("\tExtraDataSize:\t0x%016I64x\n", ReadField (ExtraDataSize));
}
ULONG64
GetStringTableData(
ULONG64 st
)
{
InitTypeRead (st, SETUPAPI!STRING_TABLE);
return ReadField (Data);
}
ULONG64
GetFirstNode(
ULONG64 stdata,
ULONG64 offset,
PULONG64 poffset
)
{
ULONG64 NodeAddress = 0;
ReadPtr (offset, &NodeAddress);
*poffset = NodeAddress;
if (NodeAddress == -1) {
return 0;
}
return NodeAddress + stdata;
}
ULONG64
GetNextNode(
ULONG64 stdata,
ULONG64 node,
PULONG64 offset
)
{
ULONG64 next, nextoffset;
//
// BUG BUG: Hack for ptr - STRING_NODEW is not built into any file
// so I will cheat because I know that the offset is the first entry
//
ReadPtr (node, &nextoffset);
if (nextoffset == -1) {
*offset = 0;
return 0;
}
next = stdata + nextoffset;
*offset = nextoffset;
return next;
}
BOOL
CheckInterupted(
VOID
)
{
if ( CheckControlC() ) {
dprintf( "\nInterrupted\n\n" );
return TRUE;
}
return FALSE;
}
LPCSTR
GetWizPage(
DWORD i
)
{
LPCSTR WizPage[] = {
"WizPagesWelcome", // welcome page
"WizPagesMode", // setup mode page
"WizPagesEarly", // pages that come after the mode page and before prenet pages
"WizPagesPrenet", // pages that come before network setup
"WizPagesPostnet", // pages that come after network setup
"WizPagesLate", // pages that come after postnet pages and before the final page
"WizPagesFinal", // final page
"WizPagesTypeMax"
};
return WizPage[i];
}
VOID
DumpOcComponent(
ULONG64 offset,
ULONG64 node,
ULONG64 pcomp
)
{
DWORD i;
ULONG count;
WCHAR Buffer[200];
UtilReadWString (node + GetTypeSize ("SETUPAPI!ULONG_PTR"),
Buffer,
sizeof (Buffer));
InitTypeRead (pcomp, OCMANAGE!OPTIONAL_COMPONENT);
dprintf("OC_COMPONENT Data for node %ws : 0x%p\n", Buffer, offset );
dprintf( "\t InfStringId:\t\t0x%016I64x\n", ReadField (InfStringId));
dprintf( "\t TopLevelStringId:\t0x%016I64x\n", ReadField (TopLevelStringId));
dprintf( "\t ParentStringId:\t0x%016I64x\n", ReadField (ParentStringId));
dprintf( "\t FirstChildStringId:\t0x%016I64x\n", ReadField (FirstChildStringId));
dprintf( "\t ChildrenCount:\t\t0x%016I64x\n", ReadField (ChildrenCount));
dprintf( "\t NextSiblingStringId:\t0x%016I64x\n", ReadField (NextSiblingStringId));
dprintf( "\t NeedsCount:\t\t%d\n", ReadField (NeedsCount));
if (ReadField (NeedsCount)) {
// read and dump needs list
for (i = 0; i < ReadField (NeedsCount); i++) {
ReadMemory(ReadField (NeedsStringIds) + (i * sizeof (ULONG)), &count, sizeof (count), NULL);
dprintf("\t NeedsStringIds #%d:\t0x%08x\n", i, count);
if (CheckInterupted()) {
return;
}
}
}
dprintf( "\t NeededByCount:\t\t%d\n", ReadField (NeededByCount));
if (ReadField (NeededByCount)) {
// read and dump needs list
for (i = 0; i < ReadField (NeededByCount); i++) {
ReadMemory(ReadField (NeededByStringIds) + (i * sizeof (ULONG)), &count, sizeof (count), NULL);
dprintf("\t NeededByStringIds #%d: 0x%08x\n", i, count);
if (CheckInterupted()) {
return;
}
}
}
dprintf( "\t ExcludeCount:\t\t%d\n", ReadField (ExcludeCount));
if (ReadField (ExcludeCount)) {
// read and dump Excludes list
for (i = 0; i < ReadField (ExcludeCount); i++) {
ReadMemory(ReadField (ExcludeStringIds) + (i * sizeof (ULONG)), &count, sizeof (ULONG), NULL);
dprintf("\t ExcludeStringIds #%d: 0x%08x\n", i, count);
if (CheckInterupted()) {
return;
}
}
}
dprintf( "\t ExcludedByCount:\t%d\n", ReadField (ExcludedByCount));
if (ReadField (ExcludedByCount)) {
// read and dump Excludes list
for (i = 0; i < ReadField (ExcludedByCount); i++) {
ReadMemory(ReadField (ExcludedByStringIds) + (i * sizeof (ULONG)), &count, sizeof (ULONG), NULL);
dprintf("\t ExcludesStringIds #%d:\t0x%08x\n", i, count);
if (CheckInterupted()) {
return;
}
}
}
dprintf( "\t InternalFlags:\t\t0x%08x\n", ReadField (InternalFlags));
//
// bugbug correct identifier
//
dprintf( "\t SizeApproximation:\t0x%016I64x\n", ReadField (SizeApproximation));
dprintf( "\t IconIndex:\t\t0x%016I64x\n", ReadField (IconIndex));
UtilGetWStringField (pcomp, "OCMANAGE!OPTIONAL_COMPONENT", "IconDll", Buffer, sizeof (Buffer));
dprintf( "\t IconDll:\t\t%ws\n", Buffer);
UtilGetWStringField (pcomp, "OCMANAGE!OPTIONAL_COMPONENT", "IconResource", Buffer, sizeof (Buffer));
dprintf( "\t IconResource:\t\t%ws\n", Buffer);
dprintf( "\t SelectionState:\t0x%016I64x\n", ReadField (SelectionState));
dprintf( "\t OriginalSelectionState:0x%016I64x\n", ReadField (OriginalSelectionState));
dprintf( "\t InstalledState:\t0x%016I64x\n", ReadField (InstalledState));
dprintf( "\t ModeBits:\t\t0x%08x\n", ReadField (ModeBits));
UtilGetWStringField (pcomp, "OCMANAGE!OPTIONAL_COMPONENT", "Description", Buffer, sizeof (Buffer));
dprintf( "\t Description:\t\t%ws\n", Buffer);
UtilGetWStringField (pcomp, "OCMANAGE!OPTIONAL_COMPONENT", "Tip", Buffer, sizeof (Buffer));
dprintf( "\t Tip:\t\t\t%ws\n", Buffer);
UtilGetWStringField (pcomp, "OCMANAGE!OPTIONAL_COMPONENT", "InstallationDllName", Buffer, sizeof (Buffer));
dprintf( "\t InstallationDllName:\t%ws\n", Buffer);
UtilGetWStringField (pcomp, "OCMANAGE!OPTIONAL_COMPONENT", "InterfaceFunctionName", Buffer, sizeof (Buffer));
dprintf( "\t InterfaceFunctionName:\t%s\n", Buffer);
dprintf( "\t InstallationDll:\t0x%016I64x\n", ReadField (InstallationDll));
dprintf( "\t ExpectedVersion:\t0x%016I64x\n", ReadField (ExpectedVersion));
dprintf( "\t Exists:\t\t0x%016I64x\n", ReadField (Exists));
dprintf( "\t Flags:\t\t\t0x%016I64x\n\n\n", ReadField (Flags));
return;
}
DECLARE_API( setuphelp )
{
dprintf("setupexts help:\n\n");
dprintf("!setuphelp - This message\n");
dprintf("!ocm [address] [opt. flag] - Dump the OC_MANAGER structure at address, flag increased verbosity\n");
dprintf("!space [address] [opt. flag] - Dump the DISK_SPACE_LIST structure at specified address\n");
dprintf("!st [address] - Dump the contents of a STRING_TABLE structure at specified address\n");
dprintf("!stfind [address] [element] - Dump the specified string table element\n");
dprintf("!queue [address] [opt. flag] - Dump the specified file queue\n");
dprintf("!qcontext [address] - Dump the specified default queue context \n");
dprintf("!infdump [addr] [opt. flag] - Dump the specified hinf \n");
}
DECLARE_API( st )
/*++
Routine Description:
This debugger extension dumps a string table at the address specified.
Arguments:
Return Value:
--*/
{
ULONG64 pst;
DWORD i;
ULONG64 offset;
ULONG64 pextradata;
ULONG64 stdata;
WCHAR Buffer[200];
ULONG64 boffset, node;
ULONG count = 0;
if (args==0) {
dprintf ("st: no string table specified.\n");
return;
}
ZeroMemory (&Buffer, sizeof (Buffer));
pst = UtilStringToUlong64 ((UCHAR *)args);
dprintf("Base String Table Address:\t0x%p\n", pst);
DumpStringTableHeader(pst);
stdata = GetStringTableData(pst);
//
// now, dump each node in the string table
//
for (i = 0; i<HASH_BUCKET_COUNT; i++ ) {
node = GetFirstNode(stdata, (stdata + (GetTypeSize ("SETUPAPI!ULONG_PTR") * i)), &offset );
if (!node) {
// dprintf("No data at hash bucket %d\n", i);
} else {
dprintf("Data at hash bucket %d\n", i);
while (node) {
//
// BUG BUG: Hack for offset - STRING_NODEW is not built into any file
// so I will cheat because I know that the offset is after a ptr
//
boffset = GetTypeSize ("SETUPAPI!ULONG_PTR");
count = 0;
while (1)
{
if (count == sizeof (Buffer)) {
break;
}
ReadMemory (node + boffset + count,
(PWCHAR) &Buffer + count/2,
sizeof (WCHAR),
NULL);
if (!Buffer[count/2]) {
break;
}
count +=2;
}
dprintf("\tEntry Name:\t%ws (0x%08x)\n", Buffer, offset);
InitTypeRead (pst, SETUPAPI!STRING_TABLE);
pextradata = ReadField (Data) + offset + (wcslen(Buffer) + 1)*sizeof(WCHAR) + sizeof(DWORD);
dprintf("\tExtra Data:\t0x%016I64x\n", pextradata );
node = GetNextNode(stdata, node, &offset );
if (CheckInterupted()) {
return;
}
}
}
}
}
DECLARE_API( stfind )
/*++
Routine Description:
This debugger extension dumps the data for a given string table number
Arguments:
Return Value:
--*/
{
ULONG64 pst, element, stdata, boffset;
DWORD i;
ULONG64 offset;
ULONG64 pextradata;
ULONG64 node;
UCHAR arg[2][100];
WCHAR Buffer[200];
ULONG64 count = 0, argcount = 0;
PUCHAR argptr = (PUCHAR) args;
ZeroMemory (&arg, sizeof (arg));
ZeroMemory (&Buffer, sizeof (Buffer));
while (*argptr != 0) {
if (*argptr == ' ') {
argcount++;
count = 0;
argptr++;
}
if (argcount > 1) {
break;
}
arg[argcount][count] = *argptr;
count++;
argptr++;
}
if (!arg[0][0] || !arg[1][0]) {
dprintf ("stfind: missing one or more parameters\nusage:!stfind [address] [element]\n");
return;
}
pst = UtilStringToUlong64 (arg[0]);
element = UtilStringToUlong64 (arg[1]);
stdata = GetStringTableData(pst);
if (!stdata) {
dprintf("Error retrieving string table data!\n");
return;
}
//
// search each node in the string table
//
for (i = 0; i<HASH_BUCKET_COUNT; i++ ) {
node = GetFirstNode(stdata, (stdata + (GetTypeSize ("SETUPAPI!ULONG_PTR") * i)), &offset );
if (!node) {
} else {
while (node) {
if (element == offset) {
//
// BUG BUG: Hack for offset - STRING_NODEW is not built into any file
// so I will cheat because I know that the offset is after a ptr
//
boffset = GetTypeSize ("SETUPAPI!ULONG_PTR");
count = 0;
while (1)
{
if (count == sizeof (Buffer)) {
break;
}
ReadMemory (node + boffset + count,
(PWCHAR) &Buffer + count/2,
sizeof (WCHAR),
NULL);
if (!Buffer[count/2]) {
break;
}
count +=2;
}
dprintf("\tEntry Name:\t%ws (0x%08x)\n", Buffer, offset);
InitTypeRead (pst, SETUPAPI!STRING_TABLE);
pextradata = ReadField (Data) + offset + (wcslen(Buffer) + 1)*sizeof(WCHAR) + sizeof(DWORD);
dprintf("\tExtra Data:\t0x%016I64x\n", pextradata );
return;
}
node = GetNextNode( stdata, node, &offset );
if (CheckInterupted()) {
return;
}
}
}
}
dprintf("Couldn't find element\n");
}
DECLARE_API( ocm )
/*++
Routine Description:
This debugger extension dumps an OC_MANAGER (UNICODE!) structure at the specified address
Arguments:
Return Value:
--*/
{
ULONG64 pocm;
DWORD i;
ULONG64 infdata,compdata;
ULONG64 Mask = 0;
LONG count = 0;
UCHAR arg[2][100];
PUCHAR argptr = (PUCHAR) args;
ULONG64 offset = 0;
WCHAR Buffer[200];
ULONG argcount = 0;
ULONG64 node = 0, boffset = 0;
ZeroMemory (&arg, sizeof (arg));
while (*argptr != 0) {
if (*argptr == ' ') {
argcount++;
count = 0;
argptr++;
}
if (argcount > 1) {
break;
}
arg[argcount][count] = *argptr;
count++;
argptr++;
}
if (!arg[0][0]) {
dprintf ("ocm: missing one or more parameters\nusage:!ocm [address] [verbosity]\n");
return;
}
pocm = UtilStringToUlong64 (arg[0]);
Mask = UtilStringToUlong64 (arg[1]);
InitTypeRead (pocm, OCMANAGE!OC_MANAGER);
//
// dump the OCM structure
//
dprintf("OC_MANAGER structure at Address:\t0x%016I64x\n", pocm);
dprintf("\tCallbacks :\n");
dprintf("\t\tFillInSetupDataA:\t0x%016I64x\n", ReadField (Callbacks.FillInSetupDataA));
dprintf("\t\tLogError:\t\t0x%016I64x\n", ReadField (Callbacks.LogError));
dprintf("\t\tSetReboot:\t\t0x%016I64x\n", ReadField (Callbacks.SetReboot));
dprintf("\t\tFillInSetupDataW:\t0x%016I64x\n", ReadField (Callbacks.FillInSetupDataW));
dprintf("\tMasterOcInf:\t\t0x%016I64x\n", ReadField (MasterOcInf));
dprintf("\tUnattendedInf:\t\t0x%016I64x\n", ReadField (UnattendedInf));
UtilGetWStringField (pocm, "OCMANAGE!OC_MANAGER", "MasterOcInfPath", Buffer, sizeof (Buffer));
dprintf("\tMasterOcInfPath:\t%ws\n", Buffer);
UtilGetWStringField (pocm, "OCMANAGE!OC_MANAGER", "UnattendedInfPath", Buffer, sizeof (Buffer));
dprintf("\tUnattendInfPath:\t%ws\n", Buffer);
UtilGetWStringField (pocm, "OCMANAGE!OC_MANAGER", "SourceDir", Buffer, sizeof (Buffer));
dprintf("\tSourceDir:\t\t%ws\n", Buffer);
UtilGetWStringField (pocm, "OCMANAGE!OC_MANAGER", "SuiteName", Buffer, sizeof (Buffer));
dprintf("\tSuiteName:\t\t%ws\n", Buffer);
UtilGetWStringField (pocm, "OCMANAGE!OC_MANAGER", "SetupPageTitle", Buffer, sizeof (Buffer));
dprintf("\tSetupPageTitle:\t\t%ws\n", Buffer);
UtilGetWStringField (pocm, "OCMANAGE!OC_MANAGER", "WindowTitle", Buffer, sizeof (Buffer));
dprintf("\tWindowTitle:\t\t%ws\n", Buffer);
dprintf("\tInfListStringTable:\t0x%016I64x\n", ReadField (InfListStringTable));
dprintf("\tComponentStringTable:\t0x%016I64x\n", ReadField (ComponentStringTable));
dprintf("\tOcSetupPage:\t\t0x%016I64x\n", ReadField (OcSetupPage));
dprintf("\tSetupMode:\t\t%d\n", ReadField (SetupMode));
dprintf("\tTopLevelOcCount:\t%d\n", ReadField (TopLevelOcCount));
if (ReadField (TopLevelOcCount)) {
// read and dump needs list
for (i = 0; i < ReadField (TopLevelOcCount); i++) {
//
// BUG BUG - No way to read size of String Ids off target, so assume LONG
//
ReadMemory(ReadField (TopLevelOcStringIds) + (i * sizeof (LONG)), &count, sizeof (count), NULL);
dprintf("\t TopLevelOcStringIds #%d:\t0x%08x\n", i, count);
if (CheckInterupted()) {
return;
}
}
}
dprintf("\tTopLevelParenOcCount:\t%d\n", ReadField (TopLevelParentOcCount));
if (ReadField (TopLevelParentOcCount)) {
// read and dump needs list
for (i = 0; i < ReadField (TopLevelParentOcCount); i++) {
//
// BUG BUG - No way to read size of String Ids off target, so assume LONG
//
ReadMemory(ReadField (TopLevelParentOcStringIds) + (i * sizeof (LONG)), &count, sizeof (count), NULL);
dprintf("\t TopLevelParentOcStringIds #%d:\t0x%08x\n", i, count);
if (CheckInterupted()) {
return;
}
}
}
dprintf("\tSubComponentsPresent:\t%d\n", ReadField (SubComponentsPresent));
//
// BugBug WizardPagesOrder there's not really any way to tell the exact upper bound of
// each array, though we know that it's <= TopLevelParentOcCount...since this is the case
// we just dump the point to each array of pages...
//
for (i = 0; i < WizPagesTypeMax; i++) {
ULONG wizardpageorder = 0;
//
// BUG BUG - Again, assuming that this type will always be ULONG
//
GetFieldOffset ("OCMANAGE!OC_MANAGER", "WizardPagesOrder", (PULONG) &offset);
ReadMemory (pocm + offset + (i * sizeof (ULONG)), &wizardpageorder, sizeof (ULONG), NULL);
dprintf("\tWizardPagesOrder[%i] (%s)\t: 0x%08x\n",
i,
GetWizPage(i),
wizardpageorder);
if (CheckInterupted()) {
return;
}
}
UtilGetWStringField (pocm, "OCMANAGE!OC_MANAGER", "PrivateDataSubkey", Buffer, sizeof (Buffer));
dprintf("\tPrivateDataSubkey:\t\t%ws\n", Buffer);
dprintf("\thKeyPrivateData:\t\t0x%016I64x\n", ReadField (hKeyPrivateData));
dprintf("\thKeyPrivateDataRoot:\t\t0x%016I64x\n", ReadField (hKeyPrivateDataRoot));
dprintf("\tProgressTextWindow:\t\t0x%016I64x\n", ReadField (ProgressTextWindow));
dprintf("\tCurrentComponentStringId:\t0x%016I64x\n", ReadField(CurrentComponentStringId));
dprintf("\tAbortedCount:\t\t%d\n", ReadField (AbortedCount));
if (ReadField (AbortedCount)) {
// read and dump needs list
for (i = 0; i < ReadField (AbortedCount); i++) {
ReadMemory(ReadField (AbortedComponentIds) + (i * sizeof (LONG)), &count, sizeof(count), NULL);
dprintf("\t AbortedComponentIds #%d:\t0x%08x\n", i, count);
if (CheckInterupted()) {
return;
}
}
}
dprintf("\tInternalFlags:\t\t0x%016I64x\n\n\n", ReadField (InternalFlags));
dprintf("\tSetupData.SetupMode :\t\t0x%016I64x\n", ReadField (SetupData.SetupMode));
dprintf("\tSetupData.ProductType :\t\t0x%016I64x\n", ReadField (SetupData.ProductType));
dprintf("\tSetupData.OperationFlags :\t0x%016I64x\n", ReadField (SetupData.OperationFlags));
UtilGetWStringField (pocm, "OCMANAGE!OC_MANAGER", "SetupData.SourcePath", Buffer, sizeof (Buffer));
dprintf("\tSetupData.SourcePath :\t\t%ws\n", Buffer);
UtilGetWStringField (pocm, "OCMANAGE!OC_MANAGER", "SetupData.UnattendFile", Buffer, sizeof (Buffer));
dprintf("\tSetupData.UnattendFile :\t\t%ws\n", Buffer);
//
// Verbose print
//
if ((Mask&1) && ReadField (InfListStringTable)) {
ULONG64 pinfdata = 0;
dprintf("\t\t***InfListStringTable***\n");
pinfdata = GetStringTableData( ReadField (InfListStringTable));
if (!pinfdata) {
dprintf("error retrieving string table data!\n");
return;
}
// now, dump each node with data in the string table
for (i = 0; i<HASH_BUCKET_COUNT; i++ ) {
node = GetFirstNode(pinfdata, (pinfdata + (GetTypeSize ("SETUPAPI!ULONG_PTR") * i)), &offset);
if (!node) {
// dprintf("No data at hash bucket %d\n", i);
} else {
//dprintf("Data at hash bucket %d\n", i);
while (node) {
ULONG64 pocinf = 0;
//dprintf("\tNode Name:%ws\n", node->String);
UtilReadWString (node + GetTypeSize ("SETUPAPI!ULONG_PTR"),
Buffer,
sizeof (Buffer)
);
boffset = wcslen (Buffer) * sizeof (WCHAR);
ReadPtr (node + GetTypeSize ("SETUPAPI!ULONG_PTR") + boffset + 1,
&pocinf);
pocinf = node + GetTypeSize ("SETUPAPI!ULONG_PTR") + boffset + 2;
if (pocinf) {
InitTypeRead (pocinf, OCMANAGE!OC_INF);
dprintf("\tNode Data for %ws\t (0x%08x): 0x%016I64x\n",
Buffer,
offset,
ReadField (Handle)
);
} else {
dprintf("\tNo Node Data for %ws\n",
Buffer
);
}
node = GetNextNode(pinfdata, node, &offset );
if (CheckInterupted()) {
return;
}
}
}
}
dprintf("\n\n");
}
InitTypeRead (pocm, OCMANAGE!OC_MANAGER);
if ((Mask&1) && ReadField (ComponentStringTable)) {
ULONG64 compdata = 0;
dprintf("\t\t***ComponentStringTable***\n");
compdata = GetStringTableData(ReadField (ComponentStringTable));
if (!compdata) {
dprintf("error retrieving string table data!\n");
return;
}
//
// dump each node with data in the string table
//
for (i = 0; i<HASH_BUCKET_COUNT; i++ ) {
node = GetFirstNode(compdata, (compdata + (GetTypeSize ("SETUPAPI!ULONG_PTR") * i)), &offset);
if (!node) {
// dprintf("No data at hash bucket %d\n", i);
} else {
//dprintf("Data at hash bucket %d\n", i);
while (node) {
ULONG64 pcomp = 0;
//dprintf("\tNode Name:%ws\n", node->String);
UtilReadWString (node + GetTypeSize ("SETUPAPI!ULONG_PTR"),
Buffer,
sizeof (Buffer)
);
boffset = wcslen (Buffer) * sizeof (WCHAR);
pcomp = node + GetTypeSize ("SETUPAPI!ULONG_PTR") + boffset + 2;
if (pcomp) {
DumpOcComponent( offset , node, pcomp );
} else {
dprintf("\tNo Node Data for %ws\n",
Buffer
);
}
if (CheckInterupted()) {
return;
}
node = GetNextNode( compdata, node, &offset );
}
}
}
}
return;
}
DECLARE_API( infdump )
/*++
Routine Description:
This debugger extension dumps the data related to an HINF structure
Arguments:
Return Value:
--*/
{
DWORD ReturnLength;
ULONG64 pinf;
//LOADED_INF inf;
//INF_SECTION InfSection;
//INF_LINE InfLine;
DWORD i;
ULONG64 offset = 0, count = 0;
ULONG64 stdata,pextradata;
//STRING_TABLE st;
//PSTRING_NODEW node;//, prev;
PUCHAR argptr = (PUCHAR) args;
UCHAR arg[2][100];
WCHAR Buffer[200];
ULONG argcount = 0;
ULONG64 node = 0, boffset = 0, pst = 0;
ULONG64 Mask = 0;
ZeroMemory (&arg, sizeof (arg));
while (*argptr != 0) {
if (*argptr == ' ') {
argcount++;
count = 0;
argptr++;
}
if (argcount > 1) {
break;
}
arg[argcount][count] = *argptr;
count++;
argptr++;
}
if (!arg[0][0]) {
dprintf ("infdump: missing one or more parameters\nusage:!infdump [address] [verbosity]\n");
return;
}
pinf = UtilStringToUlong64 (arg[0]);
Mask = UtilStringToUlong64 (arg[1]);
InitTypeRead (pinf, SETUPAPI!LOADED_INF);
count = ReadField (Signature);
dprintf("LOADED_INF at :\t0x%016I64x\n", pinf);
dprintf("\t Signature : 0x%08x (%s)\n", (ULONG) count, ((count == LOADED_INF_SIG) ? "Valid" : "Invalid"));
if (ReadField (Signature) != LOADED_INF_SIG) {
return;
}
dprintf("\t FileHandle:\t0x%016I64x\n", ReadField (FileHandle));
dprintf("\t MappingHandle:\t0x%016I64x\n", ReadField (MappingHandle));
dprintf("\t ViewAddress:\t0x%016I64x\n", ReadField (ViewAddress));
if (ReadField (FileHandle) == (ULONG64) INVALID_HANDLE_VALUE) {
dprintf(" *** In memory INF ***\n" );
} else {
dprintf(" *** PNF ***\n" );
}
dprintf("\t StringTable:\t0x%016I64x\n", ReadField (StringTable));
dprintf("\t SectionCount:\t0x%016I64x\n", ReadField (SectionCount));
dprintf("\tSectionBlock:\t0x%016I64x\n", ReadField (SectionBlock));
for (i = 0; i < ReadField (SectionCount); i++) {
dprintf("***INF_SECTION [%d] at 0x%016I64x***\n",i, ReadField (SectionBlock) + (GetTypeSize ("SETUPAPI!INF_SECTION") * i));
DumpInfSection( ReadField (SectionBlock) + (GetTypeSize ("SETUPAPI!INF_SECTION") * i), ReadField (LineBlock), ReadField (ValueBlock));
//
// Need to reinit type read because previous functions change the
// default read structure type
//
InitTypeRead (pinf, SETUPAPI!LOADED_INF);
if (CheckInterupted()) {
return;
}
}
dprintf("\tLineBlock : 0x%I64x\n", ReadField (LineBlock));
dprintf("\t ValueBlock : 0x%I64x\n", ReadField (ValueBlock));
DumpInfVersionNode(ReadField (VersionBlock));
InitTypeRead (pinf, SETUPAPI!LOADED_INF);
dprintf("\t HasStrings : 0x%I64x\n", ReadField (HasStrings));
UtilGetWStringField (pinf, "SETUPAPI!LOADED_INF", "OsLoaderPath", Buffer, sizeof (Buffer));
dprintf("\t OsLoaderPath : %ws\n", Buffer);
dprintf("\t InfSourceMediaType : 0x%I64x ( ", ReadField (InfSourceMediaType));
if (ReadField (InfSourceMediaType)) {
if (ReadField (InfSourceMediaType) & SPOST_PATH ) {
dprintf("SPOST_PATH ");
}
if (ReadField (InfSourceMediaType) & SPOST_URL) {
dprintf("SPOST_URL ");
}
} else {
dprintf("SPOST_NONE ");
}
dprintf(")\n");
UtilGetWStringField (pinf, "SETUPAPI!LOADED_INF", "InfSourcePath", Buffer, sizeof (Buffer));
dprintf("\t InfSourcePath : %ws\n", Buffer);
UtilGetWStringField (pinf, "SETUPAPI!LOADED_INF", "OriginalInfName", Buffer, sizeof (Buffer));
dprintf("\t OriginalInfName : %ws\n", Buffer);
dprintf("\t SubstValueList : 0x%I64x\n", ReadField (SubstValueList));
dprintf("\t SubstValueCount : 0x%I64x\n", ReadField (SubstValueCount));
dprintf("\t Style : 0x%x ( ", ReadField (Style));
if (ReadField (Style) & INF_STYLE_OLDNT) {
dprintf("INF_STYLE_OLDNT ");
}
if (ReadField (Style) & INF_STYLE_WIN4) {
dprintf("INF_STYLE_WIN4 ");
}
dprintf(")\n");
dprintf("\t SectionBlockSizeBytes : 0x%x\n", ReadField (SectionBlockSizeBytes));
dprintf("\t LineBlockSizeBytes : 0x%x\n", ReadField (LineBlockSizeBytes));
dprintf("\t ValueBlockSizeBytes : 0x%x\n", ReadField (ValueBlockSizeBytes));
dprintf("\t LanguageId : 0x%x\n", ReadField (LanguageId));
dprintf("\t UserDirIdList : 0x%x\n", ReadField (UserDirIdList));
dprintf("\tLock[0] : 0x%x\n", ReadField (Lock.handles[0]));
dprintf("\tLock[1] : 0x%x\n", ReadField (Lock.handles[1]));
dprintf("\tPrev : 0x%x\n", ReadField (Prev));
dprintf("\tNext : 0x%x\n", ReadField (Next));
pst = ReadField (StringTable);
DumpStringTableHeader (pst);
stdata = GetStringTableData (pst);
//
// now, dump each node in the string table
//
for (i = 0; i<HASH_BUCKET_COUNT; i++ ) {
node = GetFirstNode(stdata, (stdata + (GetTypeSize ("SETUPAPI!ULONG_PTR") * i)), &offset );
if (!node) {
// dprintf("No data at hash bucket %d\n", i);
} else {
dprintf("Data at hash bucket %d\n", i);
while (node) {
//
// BUG BUG: Hack for offset - STRING_NODEW is not built into any file
// so I will cheat because I know that the offset is after a ptr
//
boffset = GetTypeSize ("SETUPAPI!ULONG_PTR");
count = 0;
while (1)
{
if (count == sizeof (Buffer)) {
break;
}
ReadMemory (node + boffset + count,
(PWCHAR) &Buffer + count/2,
sizeof (WCHAR),
NULL);
if (!Buffer[count/2]) {
break;
}
count +=2;
}
dprintf("\tEntry Name:\t%ws (0x%08x)\n", Buffer, offset);
InitTypeRead (pst, SETUPAPI!STRING_TABLE);
pextradata = ReadField (Data) + offset + (wcslen(Buffer) + 1)*sizeof(WCHAR) + sizeof(DWORD);
dprintf("\tExtra Data:\t0x%016I64x\n", pextradata );
node = GetNextNode(stdata, node, &offset );
if (CheckInterupted()) {
return;
}
}
}
}
return;
}
DECLARE_API( space )
/*++
Routine Description:
This debugger extension dumps the data related to a HDSKSPC structure
Arguments:
Return Value:
--*/
{
DWORD ReturnLength;
ULONG64 pst = 0;
ULONG64 dsl = 0;
DWORD i;
ULONG64 offset = 0, count = 0, boffset = 0;
ULONG64 stdata = 0,pextradata = 0;
ULONG64 Mask = 0;
ULONG64 node = 0, pxd = 0, pte = 0;
PUCHAR argptr = (PUCHAR) args;
UCHAR arg[2][100];
WCHAR Buffer[200];
ULONG argcount = 0;
while (*argptr != 0) {
if (*argptr == ' ') {
argcount++;
count = 0;
argptr++;
}
if (argcount > 1) {
break;
}
arg[argcount][count] = *argptr;
count++;
argptr++;
}
if (!arg[0][0]) {
dprintf ("space: missing one or more parameters\nusage:!space [address] [verbosity]\n");
return;
}
dsl = UtilStringToUlong64 (arg[0]);
Mask = UtilStringToUlong64 (arg[1]);
InitTypeRead (dsl, SETUPAPI!DISK_SPACE_LIST);
dprintf("DISK_SPACE_LIST at :\t0x%016I64x\n", dsl);
GetFieldOffset ("SETUPAPI!DISK_SPACE_LIST", "Lock", (ULONG *) &offset);
boffset = GetTypeSize ("SETUPAPI!HANDLE");
ReadMemory (dsl + offset, &count, (ULONG) boffset, NULL);
dprintf("\tLock[0] : 0x%016I64x\n", count);
ReadMemory (dsl + offset + boffset, &count, (ULONG) boffset, NULL);
dprintf("\tLock[1] : 0x%016I64x\n", count);
dprintf("\tDrivesTable : 0x%016I64x\n", ReadField (DrivesTable));
dprintf("\tFlags : 0x%016I64x\n", ReadField (Flags));
pst = ReadField (DrivesTable);
dprintf("\t ***DrivesTable***\n");
DumpStringTableHeader(pst);
stdata = GetStringTableData(pst);
if (!stdata) {
dprintf("error retrieving string table data!\n");
return;
}
//
// now, dump each node in the string table
//
for (i = 0; i<HASH_BUCKET_COUNT; i++ ) {
node = GetFirstNode(stdata, (stdata + (GetTypeSize ("SETUPAPI!ULONG_PTR") * i)), &offset );
if (!node) {
// dprintf("No data at hash bucket %d\n", i);
} else {
dprintf("Data at hash bucket %d\n", i);
while (node) {
boffset = GetTypeSize ("SETUPAPI!ULONG_PTR");
count = 0;
while (1)
{
if (count == sizeof (Buffer)) {
break;
}
ReadMemory (node + boffset + count,
(PWCHAR) &Buffer + count/2,
sizeof (WCHAR),
NULL);
if (!Buffer[count/2]) {
break;
}
count +=2;
}
dprintf("\tEntry Name:\t%ws (0x%08x)\n", Buffer, offset);
InitTypeRead (pst, SETUPAPI!STRING_TABLE);
pxd = ReadField (Data) + offset + (wcslen(Buffer) + 1)*sizeof(WCHAR) + sizeof(DWORD);
DumpXDrive( pxd, Mask );
node = GetNextNode( stdata, node, &offset );
if (CheckInterupted()) {
return;
}
}
}
if (CheckInterupted()) {
return;
}
}
}
DECLARE_API( queue )
/*++
Routine Description:
This debugger extension dumps the data related to a HSPFILEQ
Arguments:
Return Value:
--*/
{
ULONG64 ReturnLength;
ULONG64 pfq = 0,pst = 0, pte = 0;
//SP_FILE_QUEUE fq;
//PSP_TARGET_ENT pte;
DWORD i;
ULONG64 offset = 0, count = 0, boffset = 0;
ULONG64 stdata = 0, pextradata = 0, node = 0;
//STRING_TABLE st;
//PSTRING_NODEW node;//, prev;
ULONG64 Mask = 0;
PUCHAR argptr = (PUCHAR) args;
UCHAR arg[2][100];
WCHAR Buffer[200];
ULONG argcount = 0;
while (*argptr != 0) {
if (*argptr == ' ') {
argcount++;
count = 0;
argptr++;
}
if (argcount > 1) {
break;
}
arg[argcount][count] = *argptr;
count++;
argptr++;
}
if (!arg[0][0]) {
dprintf ("queue: missing one or more parameters\nusage:!queue [address] [verbosity]\n");
return;
}
pfq = UtilStringToUlong64 (arg[0]);
Mask = UtilStringToUlong64 (arg[1]);
InitTypeRead (pfq, SETUPAPI!SP_FILE_QUEUE);
dprintf("SP_FILE_QUEUE at :\t0x%016I64x\n", pfq);
dprintf("\t BackupQueue : 0x%016I64x\n", ReadField (BackupQueue));
dprintf("\t DeleteQueue : 0x%016I64x\n", ReadField (DeleteQueue));
dprintf("\t RenameQueue : 0x%016I64x\n", ReadField (RenameQueue));
dprintf("\t CopyNodeCount : 0x%016I64x\n", ReadField (CopyNodeCount));
dprintf("\t DeleteNodeCount : 0x%016I64x\n", ReadField (DeleteNodeCount));
dprintf("\t RenameNodeCount : 0x%016I64x\n", ReadField (RenameNodeCount));
dprintf("\t BackupNodeCount : 0x%016I64x\n", ReadField (BackupNodeCount));
dprintf("\t SourceMediaList : 0x%016I64x\n", ReadField (SourceMediaList));
dprintf("\t SourceMediaCount : 0x%016I64x\n", ReadField (SourceMediaCount));
dprintf("\t CatalogList : 0x%016I64x\n", ReadField (CatalogList));
dprintf("\t DriverSigningPolicy : 0x%016I64x (%s)\n",
ReadField (DriverSigningPolicy),
(ReadField (DriverSigningPolicy) == DRIVERSIGN_BLOCKING) ? "DRIVERSIGN_BLOCKING" :
(ReadField (DriverSigningPolicy) == DRIVERSIGN_WARNING) ? "DRIVERSIGN_WARNING" :
"DRIVERSIGN_NONE" );
dprintf("\t hWndDriverSigningUi : 0x%016I64x\n", ReadField (hWndDriverSigningUi));
dprintf("\t DeviceDescStringId : 0x%016I64x\n", ReadField (DeviceDescStringId));
dprintf("\t AltPlatformInfo : 0x%016I64x\n", ReadField (AltPlatformInfo));
GetFieldOffset ("SETUPAPI!SP_FILE_QUEUE", "AltPlatformInfo", (ULONG *) &offset);
DumpAltPlatformInfo(pfq + offset);
InitTypeRead (pfq, SETUPAPI!SP_FILE_QUEUE);
dprintf("\t AltCatalogFile : 0x%016I64x\n", ReadField (AltCatalogFile));
dprintf("\t StringTable : 0x%016I64x\n", ReadField (StringTable));
dprintf("\t LockRefCount : 0x%016I64x\n", ReadField (LockRefCount));
dprintf("\t Flags : 0x%016I64x\n", ReadField (Flags));
dprintf("\t SisSourceHandle : 0x%016I64x\n", ReadField (SisSourceHandle));
dprintf("\t SisSourceDirectory : 0x%016I64x\n", ReadField (SisSourceDirectory));
dprintf("\t BackupInfID : 0x%016I64x\n", ReadField (BackupInfID));
dprintf("\t TargetLookupTable : 0x%016I64x\n", ReadField (TargetLookupTable));
dprintf("\t UnwindQueue : 0x%016I64x\n", ReadField (UnwindQueue));
dprintf("\t DelayMoveQueue : 0x%016I64x\n", ReadField (DelayMoveQueue));
dprintf("\t DelayMoveQueueTail : 0x%016I64x\n", ReadField (DelayMoveQueueTail));
dprintf("\t Signature : 0x%016I64x (%s)\n",
ReadField (Signature),
(ReadField (Signature) == SP_FILE_QUEUE_SIG) ? "VALID" : "INVALID" );
//
// dump the queue nodes
//
if (Mask & 1) {
if (ReadField (BackupQueue)) {
dprintf("\t ***BackupQueue***\n");
DumpFileQueueNodeList(ReadField (BackupQueue), Mask, TRUE );
InitTypeRead (pfq, SETUPAPI!SP_FILE_QUEUE);
}
if (ReadField (DeleteQueue)) {
dprintf("\t ***DeleteQueue***\n");
DumpFileQueueNodeList(ReadField (DeleteQueue), Mask, TRUE );
InitTypeRead (pfq, SETUPAPI!SP_FILE_QUEUE);
}
if (ReadField (RenameQueue)) {
dprintf("\t ***RenameQueue***\n");
DumpFileQueueNodeList( ReadField (RenameQueue), Mask, TRUE );
InitTypeRead (pfq, SETUPAPI!SP_FILE_QUEUE);
}
if (ReadField (SourceMediaList)) {
dprintf("\t ***source media list***\n");
DumpSourceMediaInfoList( ReadField (SourceMediaList), Mask, TRUE );
InitTypeRead (pfq, SETUPAPI!SP_FILE_QUEUE);
}
}
//
// dump the catalog info
//
if (Mask & 2) {
if (ReadField (CatalogList)) {
dprintf("\t ***CatalogList***\n");
DumpCatalogInfoList( ReadField (CatalogList), Mask, TRUE );
}
}
//
// dump the string table
//
if (Mask & 4) {
dprintf("\t ***StringTable***\n");
pst = ReadField (StringTable);
DumpStringTableHeader (pst);
stdata = GetStringTableData (pst);
if (!stdata) {
dprintf("error retrieving string table data!\n");
return;
}
}
//
// now, dump each node in the string table
//
for (i = 0; i<HASH_BUCKET_COUNT; i++ ) {
node = GetFirstNode(stdata, (stdata + (GetTypeSize ("SETUPAPI!ULONG_PTR") * i)), &offset );
if (!node) {
// dprintf("No data at hash bucket %d\n", i);
} else {
dprintf("Data at hash bucket %d\n", i);
while (node) {
boffset = GetTypeSize ("SETUPAPI!ULONG_PTR");
count = 0;
while (1)
{
if (count == sizeof (Buffer)) {
break;
}
ReadMemory (node + boffset + count,
(PWCHAR) &Buffer + count/2,
sizeof (WCHAR),
NULL);
if (!Buffer[count/2]) {
break;
}
count +=2;
}
dprintf("\tEntry Name:\t%ws (0x%08x)\n", Buffer, offset);
InitTypeRead (pst, SETUPAPI!STRING_TABLE);
pextradata = ReadField (Data) + offset + (wcslen(Buffer) + 1)*sizeof(WCHAR) + sizeof(DWORD);
dprintf("\tExtra Data:\t0x%016I64x\n", pextradata );
node = GetNextNode( stdata, node, &offset );
if (CheckInterupted()) {
return;
}
}
}
if (CheckInterupted()) {
return;
}
}
dprintf("\t ***TargetLookupTable***\n");
InitTypeRead (pfq, SETUPAPI!SP_FILE_QUEUE);
pst = ReadField (TargetLookupTable);
DumpStringTableHeader (pst);
stdata = GetStringTableData (pst);
if (!stdata) {
dprintf("error retrieving string table data!\n");
return;
}
//
// now, dump each node in the string table
//
for (i = 0; i<HASH_BUCKET_COUNT; i++ ) {
node = GetFirstNode(stdata, (stdata + (GetTypeSize ("SETUPAPI!ULONG_PTR") * i)), &offset );
if (!node) {
// dprintf("No data at hash bucket %d\n", i);
} else {
dprintf("Data at hash bucket %d\n", i);
while (node) {
boffset = GetTypeSize ("SETUPAPI!ULONG_PTR");
count = 0;
while (1)
{
if (count == sizeof (Buffer)) {
break;
}
ReadMemory (node + boffset + count,
(PWCHAR) &Buffer + count/2,
sizeof (WCHAR),
NULL);
if (!Buffer[count/2]) {
break;
}
count +=2;
}
dprintf("\tEntry Name:\t%ws (0x%08x)\n", Buffer, offset);
InitTypeRead (pst, SETUPAPI!STRING_TABLE);
pte = ReadField (Data) + offset + (wcslen(Buffer) + 1)*sizeof(WCHAR) + sizeof(DWORD);
DumpTargetEnt(pte);
node = GetNextNode( stdata, node, &offset );
if (CheckInterupted()) {
return;
}
}
}
if (CheckInterupted()) {
return;
}
}
//
// backup stuff
//
InitTypeRead (pfq, SETUPAPI!SP_FILE_QUEUE);
if (Mask & 8) {
if (ReadField (UnwindQueue)) {
dprintf("\t ***UnwindQueue***\n");
DumpUnwindList( ReadField (UnwindQueue), TRUE );
InitTypeRead (pfq, SETUPAPI!SP_FILE_QUEUE);
}
if (ReadField (DelayMoveQueue)) {
dprintf("\t ***DelayMoveQueue***\n");
DumpDelayMoveList(ReadField (DelayMoveQueue), TRUE );
InitTypeRead (pfq, SETUPAPI!SP_FILE_QUEUE);
}
if (ReadField (DelayMoveQueueTail)) {
dprintf("\t ***DelayMoveQueueTail***\n");
DumpDelayMoveList( ReadField (DelayMoveQueueTail), TRUE );
InitTypeRead (pfq, SETUPAPI!SP_FILE_QUEUE);
}
}
return;
}
DECLARE_API( qcontext )
/*++
Routine Description:
This debugger extension dumps the data related to a queue context structure
Arguments:
Return Value:
--*/
{
ULONG64 pqc = 0, count = 0;
PUCHAR argptr = (PUCHAR) args;
UCHAR arg[2][100];
WCHAR Buffer[200];
ULONG argcount = 0;
while (*argptr != 0) {
if (*argptr == ' ') {
argcount++;
count = 0;
argptr++;
}
if (argcount > 1) {
break;
}
arg[argcount][count] = *argptr;
count++;
argptr++;
}
if (!arg[0][0]) {
dprintf ("qcontext: missing one or more parameters\nusage:!qcontext [address]\n");
return;
}
pqc = UtilStringToUlong64 (arg[0]);
InitTypeRead (pqc, SETUPAPI!QUEUECONTEXT);
dprintf("QUEUECONTEXT at :\t0x%016I64x\n", pqc);
dprintf("\t OwnerWindow : 0x%016I64x\n", ReadField (OwnerWindow));
dprintf("\t MainThreadId : 0x%016I64x\n", ReadField (MainThreadId));
dprintf("\t ProgressDialog : 0x%016I64x\n", ReadField (ProgressDialog));
dprintf("\t ProgressBar : 0x%016I64x\n", ReadField (ProgressBar));
dprintf("\t Cancelled : 0x%016I64x\n", ReadField (Cancelled));
UtilGetWStringField (pqc, "SETUPAPI!QUEUECONTEXT", "CurrentSourceName", Buffer, sizeof (Buffer));
dprintf("\t CurrentSourceName : %ws\n", Buffer);
dprintf("\t ScreenReader : 0x%016I64x\n", ReadField (ScreenReader));
dprintf("\t MessageBoxUp : 0x%016I64x\n", ReadField (MessageBoxUp));
dprintf("\t PendingUiType : 0x%016I64x\n", ReadField (PendingUiType));
dprintf("\t PendingUiParameters : 0x%016I64x\n", ReadField (PendingUiParameters));
dprintf("\t CancelReturnCode : 0x%016I64x\n", ReadField (CancelReturnCode));
dprintf("\t DialogKilled : 0x%016I64x\n", ReadField (DialogKilled));
dprintf("\t AlternateProgressWindow : 0x%016I64x\n", ReadField (AlternateProgressWindow));
dprintf("\t ProgressMsg : 0x%016I64x\n", ReadField (ProgressMsg));
dprintf("\t NoToAllMask : 0x%016I64x\n", ReadField (NoToAllMask));
dprintf("\t UiThreadHandle : 0x%016I64x\n", ReadField (UiThreadHandle));
}