Leaked source code of windows server 2003
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

  1. /*--
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. dumpsdb.c
  5. Abstract:
  6. code for a dump tool for shim db files
  7. Author:
  8. dmunsil 02/02/2000
  9. Revision History:
  10. Notes:
  11. This program dumps a text representation of all of the data in a shim db file.
  12. --*/
  13. #define _UNICODE
  14. #define WIN
  15. #define FLAT_32
  16. #define TRUE_IF_WIN32 1
  17. #include <nt.h>
  18. #include <ntrtl.h>
  19. #include <nturtl.h>
  20. #define _WINDOWS
  21. #include <windows.h>
  22. #include <stdio.h>
  23. extern "C" {
  24. #include "shimdb.h"
  25. }
  26. BOOL bDumpDB(PDB pdb, TAGID tiParent, WCHAR *szIndent, BOOL bWithTagIDs);
  27. BOOL bGetTypeName(TAG tWhich, WCHAR *szName);
  28. HANDLE g_hOutputFile = INVALID_HANDLE_VALUE;
  29. WCHAR* g_pszOutputBuffer = NULL;
  30. int g_cbOutputBufferSize = 0;
  31. int _cdecl Output(const WCHAR * fmt, ...)
  32. {
  33. int cch = 0;
  34. va_list arglist;
  35. DWORD dwBytesWritten = 0;
  36. WCHAR* psz;
  37. WCHAR CRLF[2] = { 0x000D, 0x000A };
  38. if (g_hOutputFile != INVALID_HANDLE_VALUE) {
  39. va_start(arglist, fmt);
  40. cch = _vscwprintf(fmt, arglist);
  41. if ((cch + 1) * 2 > g_cbOutputBufferSize) {
  42. if (g_pszOutputBuffer) {
  43. LocalFree(g_pszOutputBuffer);
  44. }
  45. g_pszOutputBuffer = (WCHAR *) LocalAlloc(0, (cch + 1) * sizeof(WCHAR) * 2);
  46. if (g_pszOutputBuffer == NULL) {
  47. return 0;
  48. }
  49. g_cbOutputBufferSize = (cch + 1) * sizeof(WCHAR) * 2;
  50. }
  51. cch = _vsnwprintf(g_pszOutputBuffer, g_cbOutputBufferSize / sizeof(WCHAR), fmt, arglist);
  52. psz = g_pszOutputBuffer;
  53. while (*psz) {
  54. if (*psz == L'\n') {
  55. if (!WriteFile(g_hOutputFile, CRLF, 4, &dwBytesWritten, NULL)) {
  56. return 0;
  57. }
  58. } else {
  59. if (!WriteFile(g_hOutputFile, psz, 2, &dwBytesWritten, NULL)) {
  60. return 0;
  61. }
  62. }
  63. psz++;
  64. }
  65. va_end(arglist);
  66. } else {
  67. va_start(arglist, fmt);
  68. cch = vwprintf(fmt, arglist);
  69. va_end(arglist);
  70. }
  71. return cch;
  72. }
  73. extern "C" int __cdecl wmain(int argc, wchar_t *argv[])
  74. {
  75. PDB pdb = NULL;
  76. int nReturn = 1;
  77. DWORD dwMajor = 0, dwMinor = 0;
  78. LPWSTR szDB = NULL;
  79. LPWSTR szOutputFileName = NULL;
  80. BOOL bSuccess;
  81. BOOL bWithTagIDs = TRUE;
  82. WCHAR szIndent[500];
  83. WCHAR szArg[500];
  84. if (argc < 2 || (argv[1][1] == '?')) {
  85. Output(L"Usage:\n\n");
  86. Output(L" dumpsdb [-d] foo.sdb > foo.txt (dumps to console)\n\n");
  87. Output(L"or dumpsdb [-d] foo.sdb -o foo.txt (dumps to unicode file)\n\n");
  88. Output(L" -d switch formats output to faciliate differencing of two output files.\n");
  89. return 1;
  90. }
  91. for (int i = 1; i < argc; i++) {
  92. if (argv[i][0] == '/' || argv[i][0] == '-') {
  93. if (argv[i][1] == 'd' || argv[i][1] == 'D') {
  94. bWithTagIDs = FALSE;
  95. } else if (argv[i][1] == 'o' || argv[i][1] == 'O') {
  96. szOutputFileName = argv[++i];
  97. }
  98. } else {
  99. szDB = argv[i];
  100. }
  101. }
  102. if (szOutputFileName) {
  103. g_hOutputFile = CreateFileW(
  104. szOutputFileName,
  105. GENERIC_READ | GENERIC_WRITE,
  106. 0,
  107. NULL,
  108. CREATE_ALWAYS,
  109. FILE_ATTRIBUTE_NORMAL,
  110. NULL);
  111. if (g_hOutputFile == INVALID_HANDLE_VALUE) {
  112. LPVOID lpMsgBuf;
  113. FormatMessageW(
  114. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  115. FORMAT_MESSAGE_FROM_SYSTEM |
  116. FORMAT_MESSAGE_IGNORE_INSERTS,
  117. NULL,
  118. GetLastError(),
  119. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  120. (LPWSTR) &lpMsgBuf,
  121. 0,
  122. NULL
  123. );
  124. wprintf(L"\n\nError creating output file:\n\n%s\n", lpMsgBuf);
  125. LocalFree(lpMsgBuf);
  126. goto eh;
  127. }
  128. BYTE BOM[2] = {0xFF, 0xFE};
  129. DWORD dwBytesWritten;
  130. if (!WriteFile(g_hOutputFile, BOM, 2, &dwBytesWritten, NULL)) {
  131. LPVOID lpMsgBuf;
  132. FormatMessage(
  133. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  134. FORMAT_MESSAGE_FROM_SYSTEM |
  135. FORMAT_MESSAGE_IGNORE_INSERTS,
  136. NULL,
  137. GetLastError(),
  138. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  139. (LPTSTR) &lpMsgBuf,
  140. 0,
  141. NULL
  142. );
  143. wprintf(L"\n\nError writing byte-order-marker:\n\n%s\n", lpMsgBuf);
  144. LocalFree(lpMsgBuf);
  145. goto eh;
  146. }
  147. }
  148. // Open the DB.
  149. pdb = SdbOpenDatabase(szDB, DOS_PATH);
  150. if (pdb == NULL) {
  151. nReturn = 1;
  152. wprintf(L"Error: can't open DB \"%s\"\n", szDB);
  153. goto eh;
  154. }
  155. SdbGetDatabaseVersion(szDB, &dwMajor, &dwMinor);
  156. Output(L"Dumping DB \"%s. Version %d.%d.\"\n",
  157. szDB,
  158. dwMajor,
  159. dwMinor);
  160. wcscpy(szIndent, L"");
  161. bSuccess = bDumpDB(pdb, TAGID_ROOT, szIndent, bWithTagIDs);
  162. nReturn = 0;
  163. eh:
  164. if (pdb) {
  165. Output(L"Closing DB.\n");
  166. SdbCloseDatabase(pdb);
  167. }
  168. if (g_hOutputFile != INVALID_HANDLE_VALUE) {
  169. CloseHandle(g_hOutputFile);
  170. }
  171. return nReturn;
  172. }
  173. BOOL bGetTypeName(TAG tWhich, WCHAR *szName)
  174. {
  175. DWORD i;
  176. LPCWSTR pName = SdbTagToString(tWhich);
  177. if (NULL != pName) {
  178. wcscpy(szName, pName);
  179. return TRUE;
  180. }
  181. swprintf(szName, L"!unknown_tag!");
  182. return TRUE;
  183. }
  184. BOOL bDumpDB(PDB pdb, TAGID tiParent, WCHAR *szIndent, BOOL bWithTagIDs)
  185. {
  186. TAGID tiTemp;
  187. WCHAR szTemp[200];
  188. WCHAR szNewIndent[200];
  189. tiTemp = SdbGetFirstChild(pdb, tiParent);
  190. while (tiTemp) {
  191. TAG tWhich;
  192. TAG_TYPE ttType;
  193. DWORD dwData;
  194. LARGE_INTEGER liData;
  195. WCHAR szData[1000];
  196. tWhich = SdbGetTagFromTagID(pdb, tiTemp);
  197. if (!tWhich) {
  198. //
  199. // error
  200. //
  201. Output(L"Error: Can't get tag for TagID 0x%8.8X. Corrupt file.\n", tiTemp);
  202. break;
  203. }
  204. ttType = GETTAGTYPE(tWhich);
  205. if (!bGetTypeName(tWhich, szTemp)) {
  206. Output(L"Error getting Tag name. Tag: 0x%4.4X\n", (DWORD)tWhich);
  207. return FALSE;
  208. }
  209. if (bWithTagIDs) {
  210. Output(L"%s0x%8.8X | 0x%4.4X | %-13s ", szIndent, tiTemp, tWhich, szTemp);
  211. } else {
  212. Output(L"%s%-13s ", szIndent, szTemp);
  213. if (wcsstr(szTemp, L"_TAGID")) {
  214. Output(L"\n");
  215. tiTemp = SdbGetNextChild(pdb, tiParent, tiTemp);
  216. continue;
  217. }
  218. }
  219. switch (ttType) {
  220. case TAG_TYPE_NULL:
  221. Output(L" | NULL |\n");
  222. break;
  223. case TAG_TYPE_BYTE:
  224. dwData = SdbReadBYTETag(pdb, tiTemp, 0);
  225. Output(L" | BYTE | 0x%2.2X\n", dwData);
  226. break;
  227. case TAG_TYPE_WORD:
  228. dwData = SdbReadWORDTag(pdb, tiTemp, 0);
  229. if (tWhich == TAG_INDEX_KEY || tWhich == TAG_INDEX_TAG) {
  230. // for index tags and keys, we'd like to see what the names are
  231. if (!bGetTypeName((TAG)dwData, szTemp)) {
  232. Output(L"Error getting Tag name. Tag: 0x%4.4X\n", dwData);
  233. return FALSE;
  234. }
  235. Output(L" | WORD | 0x%4.4X (%s)\n", dwData, szTemp);
  236. } else {
  237. Output(L" | WORD | 0x%4.4X\n", dwData);
  238. }
  239. break;
  240. case TAG_TYPE_DWORD:
  241. dwData = SdbReadDWORDTag(pdb, tiTemp, 0);
  242. Output(L" | DWORD | 0x%8.8X\n", dwData);
  243. break;
  244. case TAG_TYPE_QWORD:
  245. liData.QuadPart = SdbReadQWORDTag(pdb, tiTemp, 0);
  246. Output(L" | QWORD | 0x%8.8X%8.8X\n", liData.HighPart, liData.LowPart);
  247. break;
  248. case TAG_TYPE_STRINGREF:
  249. if (!SdbReadStringTag(pdb, tiTemp, szData, ARRAYSIZE(szData))) {
  250. wcscpy(szData, L"(error)");
  251. }
  252. Output(L" | STRINGREF | %s\n", szData);
  253. break;
  254. case TAG_TYPE_STRING:
  255. dwData = SdbGetTagDataSize(pdb, tiTemp);
  256. if (!SdbReadStringTag(pdb, tiTemp, szData, ARRAYSIZE(szData))) {
  257. wcscpy(szData, L"(error)");
  258. }
  259. Output(L" | STRING | Size 0x%8.8X | %s\n", dwData, szData);
  260. break;
  261. case TAG_TYPE_BINARY:
  262. dwData = SdbGetTagDataSize(pdb, tiTemp);
  263. Output(L" | BINARY | Size 0x%8.8X", dwData);
  264. switch(tWhich) {
  265. case TAG_INDEX_BITS:
  266. {
  267. char szKey[9];
  268. DWORD dwRecords;
  269. INDEX_RECORD *pRecords;
  270. DWORD i;
  271. Output(L"\n");
  272. ZeroMemory(szKey, 9);
  273. dwRecords = dwData / sizeof(INDEX_RECORD);
  274. pRecords = (INDEX_RECORD *)SdbGetBinaryTagData(pdb, tiTemp);
  275. for (i = 0; i < dwRecords; ++i) {
  276. char *szRevKey;
  277. int j;
  278. szRevKey = (char *)&pRecords[i].ullKey;
  279. for (j = 0; j < 8; ++j) {
  280. szKey[j] = isprint(szRevKey[7-j]) ? szRevKey[7-j] : '.';
  281. }
  282. if (bWithTagIDs) {
  283. Output(L"%s Key: 0x%I64X (\"%-8S\"), TAGID: 0x%08X\n",
  284. szIndent, pRecords[i].ullKey, szKey, pRecords[i].tiRef);
  285. } else {
  286. Output(L"%s Key: 0x%I64X (\"%-8S\")\n",
  287. szIndent, pRecords[i].ullKey, szKey);
  288. }
  289. }
  290. }
  291. break;
  292. case TAG_EXE_ID:
  293. case TAG_MSI_PACKAGE_ID:
  294. case TAG_DATABASE_ID:
  295. // this is exe id -- which happens to be GUID which we do understand
  296. {
  297. GUID *pGuid;
  298. UNICODE_STRING sGuid;
  299. pGuid = (GUID*)SdbGetBinaryTagData(pdb, tiTemp);
  300. // convert this thing to string
  301. if (pGuid && NT_SUCCESS(RtlStringFromGUID(*pGuid, &sGuid))) {
  302. Output(L" | %s", sGuid.Buffer);
  303. RtlFreeUnicodeString(&sGuid);
  304. }
  305. Output(L"\n");
  306. }
  307. break;
  308. default:
  309. Output(L"\n");
  310. break;
  311. }
  312. break;
  313. case TAG_TYPE_LIST:
  314. dwData = SdbGetTagDataSize(pdb, tiTemp);
  315. Output(L" | LIST | Size 0x%8.8X\n", dwData);
  316. wcscpy(szNewIndent, szIndent);
  317. wcscat(szNewIndent, L" ");
  318. bDumpDB(pdb, tiTemp, szNewIndent, bWithTagIDs);
  319. Output(L"%s-end- %s\n", szIndent, szTemp);
  320. break;
  321. default:
  322. dwData = SdbGetTagDataSize(pdb, tiTemp);
  323. Output(L" | UNKNOWN | Size 0x%8.8X\n", dwData);
  324. break;
  325. }
  326. tiTemp = SdbGetNextChild(pdb, tiParent, tiTemp);
  327. }
  328. return TRUE;
  329. }