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.
415 lines
12 KiB
415 lines
12 KiB
/*--
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
dumpsdb.c
|
|
|
|
Abstract:
|
|
|
|
code for a dump tool for shim db files
|
|
|
|
Author:
|
|
|
|
dmunsil 02/02/2000
|
|
|
|
Revision History:
|
|
|
|
Notes:
|
|
|
|
This program dumps a text representation of all of the data in a shim db file.
|
|
|
|
--*/
|
|
|
|
#define _UNICODE
|
|
|
|
#define WIN
|
|
#define FLAT_32
|
|
#define TRUE_IF_WIN32 1
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#define _WINDOWS
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
|
|
extern "C" {
|
|
#include "shimdb.h"
|
|
}
|
|
|
|
|
|
BOOL bDumpDB(PDB pdb, TAGID tiParent, WCHAR *szIndent, BOOL bWithTagIDs);
|
|
BOOL bGetTypeName(TAG tWhich, WCHAR *szName);
|
|
|
|
HANDLE g_hOutputFile = INVALID_HANDLE_VALUE;
|
|
WCHAR* g_pszOutputBuffer = NULL;
|
|
int g_cbOutputBufferSize = 0;
|
|
|
|
int _cdecl Output(const WCHAR * fmt, ...)
|
|
{
|
|
int cch = 0;
|
|
va_list arglist;
|
|
DWORD dwBytesWritten = 0;
|
|
WCHAR* psz;
|
|
WCHAR CRLF[2] = { 0x000D, 0x000A };
|
|
|
|
if (g_hOutputFile != INVALID_HANDLE_VALUE) {
|
|
va_start(arglist, fmt);
|
|
cch = _vscwprintf(fmt, arglist);
|
|
|
|
if ((cch + 1) * 2 > g_cbOutputBufferSize) {
|
|
if (g_pszOutputBuffer) {
|
|
LocalFree(g_pszOutputBuffer);
|
|
}
|
|
|
|
g_pszOutputBuffer = (WCHAR *) LocalAlloc(0, (cch + 1) * sizeof(WCHAR) * 2);
|
|
|
|
if (g_pszOutputBuffer == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
g_cbOutputBufferSize = (cch + 1) * sizeof(WCHAR) * 2;
|
|
}
|
|
|
|
cch = _vsnwprintf(g_pszOutputBuffer, g_cbOutputBufferSize / sizeof(WCHAR), fmt, arglist);
|
|
|
|
psz = g_pszOutputBuffer;
|
|
while (*psz) {
|
|
if (*psz == L'\n') {
|
|
if (!WriteFile(g_hOutputFile, CRLF, 4, &dwBytesWritten, NULL)) {
|
|
return 0;
|
|
}
|
|
} else {
|
|
if (!WriteFile(g_hOutputFile, psz, 2, &dwBytesWritten, NULL)) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
psz++;
|
|
}
|
|
|
|
va_end(arglist);
|
|
} else {
|
|
va_start(arglist, fmt);
|
|
cch = vwprintf(fmt, arglist);
|
|
va_end(arglist);
|
|
}
|
|
|
|
return cch;
|
|
}
|
|
|
|
extern "C" int __cdecl wmain(int argc, wchar_t *argv[])
|
|
{
|
|
PDB pdb = NULL;
|
|
int nReturn = 1;
|
|
DWORD dwMajor = 0, dwMinor = 0;
|
|
LPWSTR szDB = NULL;
|
|
LPWSTR szOutputFileName = NULL;
|
|
|
|
BOOL bSuccess;
|
|
BOOL bWithTagIDs = TRUE;
|
|
|
|
WCHAR szIndent[500];
|
|
WCHAR szArg[500];
|
|
|
|
if (argc < 2 || (argv[1][1] == '?')) {
|
|
Output(L"Usage:\n\n");
|
|
Output(L" dumpsdb [-d] foo.sdb > foo.txt (dumps to console)\n\n");
|
|
Output(L"or dumpsdb [-d] foo.sdb -o foo.txt (dumps to unicode file)\n\n");
|
|
Output(L" -d switch formats output to faciliate differencing of two output files.\n");
|
|
return 1;
|
|
}
|
|
|
|
for (int i = 1; i < argc; i++) {
|
|
if (argv[i][0] == '/' || argv[i][0] == '-') {
|
|
if (argv[i][1] == 'd' || argv[i][1] == 'D') {
|
|
bWithTagIDs = FALSE;
|
|
} else if (argv[i][1] == 'o' || argv[i][1] == 'O') {
|
|
szOutputFileName = argv[++i];
|
|
}
|
|
} else {
|
|
szDB = argv[i];
|
|
}
|
|
}
|
|
|
|
if (szOutputFileName) {
|
|
g_hOutputFile = CreateFileW(
|
|
szOutputFileName,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
0,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
|
|
if (g_hOutputFile == INVALID_HANDLE_VALUE) {
|
|
LPVOID lpMsgBuf;
|
|
FormatMessageW(
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL,
|
|
GetLastError(),
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
|
(LPWSTR) &lpMsgBuf,
|
|
0,
|
|
NULL
|
|
);
|
|
wprintf(L"\n\nError creating output file:\n\n%s\n", lpMsgBuf);
|
|
LocalFree(lpMsgBuf);
|
|
goto eh;
|
|
}
|
|
|
|
BYTE BOM[2] = {0xFF, 0xFE};
|
|
DWORD dwBytesWritten;
|
|
if (!WriteFile(g_hOutputFile, BOM, 2, &dwBytesWritten, NULL)) {
|
|
LPVOID lpMsgBuf;
|
|
FormatMessage(
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL,
|
|
GetLastError(),
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
|
(LPTSTR) &lpMsgBuf,
|
|
0,
|
|
NULL
|
|
);
|
|
wprintf(L"\n\nError writing byte-order-marker:\n\n%s\n", lpMsgBuf);
|
|
LocalFree(lpMsgBuf);
|
|
goto eh;
|
|
}
|
|
}
|
|
|
|
// Open the DB.
|
|
pdb = SdbOpenDatabase(szDB, DOS_PATH);
|
|
|
|
if (pdb == NULL) {
|
|
nReturn = 1;
|
|
wprintf(L"Error: can't open DB \"%s\"\n", szDB);
|
|
goto eh;
|
|
}
|
|
|
|
SdbGetDatabaseVersion(szDB, &dwMajor, &dwMinor);
|
|
|
|
Output(L"Dumping DB \"%s. Version %d.%d.\"\n",
|
|
szDB,
|
|
dwMajor,
|
|
dwMinor);
|
|
|
|
wcscpy(szIndent, L"");
|
|
|
|
bSuccess = bDumpDB(pdb, TAGID_ROOT, szIndent, bWithTagIDs);
|
|
|
|
nReturn = 0;
|
|
eh:
|
|
|
|
if (pdb) {
|
|
Output(L"Closing DB.\n");
|
|
SdbCloseDatabase(pdb);
|
|
}
|
|
|
|
if (g_hOutputFile != INVALID_HANDLE_VALUE) {
|
|
CloseHandle(g_hOutputFile);
|
|
}
|
|
|
|
return nReturn;
|
|
}
|
|
|
|
BOOL bGetTypeName(TAG tWhich, WCHAR *szName)
|
|
{
|
|
DWORD i;
|
|
|
|
LPCWSTR pName = SdbTagToString(tWhich);
|
|
if (NULL != pName) {
|
|
wcscpy(szName, pName);
|
|
return TRUE;
|
|
}
|
|
|
|
swprintf(szName, L"!unknown_tag!");
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL bDumpDB(PDB pdb, TAGID tiParent, WCHAR *szIndent, BOOL bWithTagIDs)
|
|
{
|
|
TAGID tiTemp;
|
|
WCHAR szTemp[200];
|
|
WCHAR szNewIndent[200];
|
|
|
|
|
|
tiTemp = SdbGetFirstChild(pdb, tiParent);
|
|
while (tiTemp) {
|
|
TAG tWhich;
|
|
TAG_TYPE ttType;
|
|
DWORD dwData;
|
|
LARGE_INTEGER liData;
|
|
WCHAR szData[1000];
|
|
|
|
tWhich = SdbGetTagFromTagID(pdb, tiTemp);
|
|
if (!tWhich) {
|
|
//
|
|
// error
|
|
//
|
|
Output(L"Error: Can't get tag for TagID 0x%8.8X. Corrupt file.\n", tiTemp);
|
|
break;
|
|
}
|
|
|
|
ttType = GETTAGTYPE(tWhich);
|
|
|
|
if (!bGetTypeName(tWhich, szTemp)) {
|
|
Output(L"Error getting Tag name. Tag: 0x%4.4X\n", (DWORD)tWhich);
|
|
return FALSE;
|
|
}
|
|
|
|
if (bWithTagIDs) {
|
|
Output(L"%s0x%8.8X | 0x%4.4X | %-13s ", szIndent, tiTemp, tWhich, szTemp);
|
|
} else {
|
|
Output(L"%s%-13s ", szIndent, szTemp);
|
|
|
|
if (wcsstr(szTemp, L"_TAGID")) {
|
|
Output(L"\n");
|
|
tiTemp = SdbGetNextChild(pdb, tiParent, tiTemp);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
switch (ttType) {
|
|
case TAG_TYPE_NULL:
|
|
Output(L" | NULL |\n");
|
|
break;
|
|
|
|
case TAG_TYPE_BYTE:
|
|
dwData = SdbReadBYTETag(pdb, tiTemp, 0);
|
|
Output(L" | BYTE | 0x%2.2X\n", dwData);
|
|
break;
|
|
|
|
case TAG_TYPE_WORD:
|
|
dwData = SdbReadWORDTag(pdb, tiTemp, 0);
|
|
if (tWhich == TAG_INDEX_KEY || tWhich == TAG_INDEX_TAG) {
|
|
|
|
// for index tags and keys, we'd like to see what the names are
|
|
if (!bGetTypeName((TAG)dwData, szTemp)) {
|
|
Output(L"Error getting Tag name. Tag: 0x%4.4X\n", dwData);
|
|
return FALSE;
|
|
}
|
|
Output(L" | WORD | 0x%4.4X (%s)\n", dwData, szTemp);
|
|
} else {
|
|
Output(L" | WORD | 0x%4.4X\n", dwData);
|
|
}
|
|
break;
|
|
|
|
case TAG_TYPE_DWORD:
|
|
dwData = SdbReadDWORDTag(pdb, tiTemp, 0);
|
|
Output(L" | DWORD | 0x%8.8X\n", dwData);
|
|
break;
|
|
|
|
case TAG_TYPE_QWORD:
|
|
liData.QuadPart = SdbReadQWORDTag(pdb, tiTemp, 0);
|
|
Output(L" | QWORD | 0x%8.8X%8.8X\n", liData.HighPart, liData.LowPart);
|
|
break;
|
|
|
|
case TAG_TYPE_STRINGREF:
|
|
if (!SdbReadStringTag(pdb, tiTemp, szData, ARRAYSIZE(szData))) {
|
|
wcscpy(szData, L"(error)");
|
|
}
|
|
Output(L" | STRINGREF | %s\n", szData);
|
|
break;
|
|
|
|
case TAG_TYPE_STRING:
|
|
dwData = SdbGetTagDataSize(pdb, tiTemp);
|
|
if (!SdbReadStringTag(pdb, tiTemp, szData, ARRAYSIZE(szData))) {
|
|
wcscpy(szData, L"(error)");
|
|
}
|
|
Output(L" | STRING | Size 0x%8.8X | %s\n", dwData, szData);
|
|
break;
|
|
|
|
case TAG_TYPE_BINARY:
|
|
dwData = SdbGetTagDataSize(pdb, tiTemp);
|
|
Output(L" | BINARY | Size 0x%8.8X", dwData);
|
|
switch(tWhich) {
|
|
case TAG_INDEX_BITS:
|
|
{
|
|
char szKey[9];
|
|
DWORD dwRecords;
|
|
INDEX_RECORD *pRecords;
|
|
DWORD i;
|
|
|
|
Output(L"\n");
|
|
ZeroMemory(szKey, 9);
|
|
dwRecords = dwData / sizeof(INDEX_RECORD);
|
|
pRecords = (INDEX_RECORD *)SdbGetBinaryTagData(pdb, tiTemp);
|
|
for (i = 0; i < dwRecords; ++i) {
|
|
char *szRevKey;
|
|
int j;
|
|
|
|
szRevKey = (char *)&pRecords[i].ullKey;
|
|
for (j = 0; j < 8; ++j) {
|
|
szKey[j] = isprint(szRevKey[7-j]) ? szRevKey[7-j] : '.';
|
|
}
|
|
if (bWithTagIDs) {
|
|
Output(L"%s Key: 0x%I64X (\"%-8S\"), TAGID: 0x%08X\n",
|
|
szIndent, pRecords[i].ullKey, szKey, pRecords[i].tiRef);
|
|
} else {
|
|
Output(L"%s Key: 0x%I64X (\"%-8S\")\n",
|
|
szIndent, pRecords[i].ullKey, szKey);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case TAG_EXE_ID:
|
|
case TAG_MSI_PACKAGE_ID:
|
|
case TAG_DATABASE_ID:
|
|
// this is exe id -- which happens to be GUID which we do understand
|
|
{
|
|
GUID *pGuid;
|
|
UNICODE_STRING sGuid;
|
|
|
|
pGuid = (GUID*)SdbGetBinaryTagData(pdb, tiTemp);
|
|
|
|
// convert this thing to string
|
|
if (pGuid && NT_SUCCESS(RtlStringFromGUID(*pGuid, &sGuid))) {
|
|
Output(L" | %s", sGuid.Buffer);
|
|
RtlFreeUnicodeString(&sGuid);
|
|
}
|
|
|
|
Output(L"\n");
|
|
}
|
|
break;
|
|
|
|
default:
|
|
Output(L"\n");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case TAG_TYPE_LIST:
|
|
dwData = SdbGetTagDataSize(pdb, tiTemp);
|
|
Output(L" | LIST | Size 0x%8.8X\n", dwData);
|
|
wcscpy(szNewIndent, szIndent);
|
|
wcscat(szNewIndent, L" ");
|
|
bDumpDB(pdb, tiTemp, szNewIndent, bWithTagIDs);
|
|
Output(L"%s-end- %s\n", szIndent, szTemp);
|
|
break;
|
|
|
|
default:
|
|
dwData = SdbGetTagDataSize(pdb, tiTemp);
|
|
Output(L" | UNKNOWN | Size 0x%8.8X\n", dwData);
|
|
break;
|
|
}
|
|
|
|
tiTemp = SdbGetNextChild(pdb, tiParent, tiTemp);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|