Source code of Windows XP (NT5)
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.

268 lines
6.1 KiB

  1. #include <nt.h>
  2. #include <ntrtl.h>
  3. #include <nturtl.h>
  4. #include <stdio.h>
  5. #include <windows.h>
  6. #include <lmcons.h>
  7. #include <lmalert.h>
  8. #include <ntiodump.h>
  9. #define INITGUID
  10. #include <dbgeng.h>
  11. #include <guiddef.h>
  12. //
  13. // Outputcallbacks for dumpcheck
  14. //
  15. class DumpChkOutputCallbacks : public IDebugOutputCallbacks
  16. {
  17. public:
  18. // IUnknown.
  19. STDMETHOD(QueryInterface)(
  20. THIS_
  21. IN REFIID InterfaceId,
  22. OUT PVOID* Interface
  23. );
  24. STDMETHOD_(ULONG, AddRef)(
  25. THIS
  26. );
  27. STDMETHOD_(ULONG, Release)(
  28. THIS
  29. );
  30. // IDebugOutputCallbacks.
  31. STDMETHOD(Output)(
  32. THIS_
  33. IN ULONG Mask,
  34. IN PCSTR Text
  35. );
  36. };
  37. STDMETHODIMP
  38. DumpChkOutputCallbacks::QueryInterface(
  39. THIS_
  40. IN REFIID InterfaceId,
  41. OUT PVOID* Interface
  42. )
  43. {
  44. *Interface = NULL;
  45. if (IsEqualIID(InterfaceId, IID_IUnknown) ||
  46. IsEqualIID(InterfaceId, IID_IDebugOutputCallbacks))
  47. {
  48. *Interface = (IDebugOutputCallbacks *)this;
  49. AddRef();
  50. return S_OK;
  51. }
  52. else
  53. {
  54. return E_NOINTERFACE;
  55. }
  56. }
  57. STDMETHODIMP_(ULONG)
  58. DumpChkOutputCallbacks::AddRef(
  59. THIS
  60. )
  61. {
  62. // This class is designed to be static so
  63. // there's no true refcount.
  64. return 1;
  65. }
  66. STDMETHODIMP_(ULONG)
  67. DumpChkOutputCallbacks::Release(
  68. THIS
  69. )
  70. {
  71. // This class is designed to be static so
  72. // there's no true refcount.
  73. return 0;
  74. }
  75. STDMETHODIMP
  76. DumpChkOutputCallbacks::Output(
  77. THIS_
  78. IN ULONG Mask,
  79. IN PCSTR Text
  80. )
  81. {
  82. printf(Text);
  83. return S_OK;
  84. }
  85. DumpChkOutputCallbacks g_OutputCallback;
  86. void Usage()
  87. {
  88. fprintf(stderr, "Usage: DumpCheck [y <sympath>] <Dumpfile>\n");
  89. }
  90. BOOL
  91. CheckDumpHeader(
  92. IN PTSTR DumpFileName
  93. )
  94. {
  95. HANDLE File;
  96. ULONG Bytes;
  97. BOOL Succ;
  98. DUMP_HEADER Header;
  99. File = CreateFile (DumpFileName,
  100. GENERIC_READ,
  101. FILE_SHARE_READ,
  102. NULL,
  103. OPEN_EXISTING,
  104. 0,
  105. NULL
  106. );
  107. if (File == INVALID_HANDLE_VALUE) {
  108. fprintf(stderr, "Unable to open dumpfile %s\n", DumpFileName);
  109. return FALSE;
  110. }
  111. Succ = ReadFile (File,
  112. &Header,
  113. sizeof (Header),
  114. &Bytes,
  115. NULL);
  116. CloseHandle (File);
  117. if (Succ &&
  118. Header.Signature == DUMP_SIGNATURE &&
  119. Header.ValidDump == DUMP_VALID_DUMP) {
  120. fprintf(stderr, "Invalid dump header\n");
  121. return TRUE;
  122. }
  123. else
  124. {
  125. return FALSE;
  126. }
  127. }
  128. HRESULT
  129. DoDumpCheck(
  130. PTSTR szDumpFile,
  131. PTSTR szSymbolPath
  132. )
  133. {
  134. HRESULT Hr = E_FAIL;
  135. IDebugClient2 *DebugClient;
  136. IDebugControl2 *DebugControl;
  137. IDebugSymbols2 *DebugSymbols;
  138. IDebugSystemObjects2 *DebugSysObjects;
  139. if ((Hr = DebugCreate(__uuidof(IDebugClient),
  140. (void **)&DebugClient)) != S_OK) {
  141. fprintf(stderr, "Cannot initialize DebugClient\n");
  142. return Hr;
  143. }
  144. if ((DebugClient->QueryInterface(__uuidof(IDebugControl2),
  145. (void **)&DebugControl) != S_OK) ||
  146. (DebugClient->QueryInterface(__uuidof(IDebugSymbols2),
  147. (void **)&DebugSymbols) != S_OK) ||
  148. (DebugClient->QueryInterface(__uuidof(IDebugSystemObjects2),
  149. (void **)&DebugSysObjects) != S_OK)) {
  150. fprintf(stderr, "QueryInterface failed for DebugClient\n");
  151. return Hr;
  152. }
  153. fprintf(stderr,"Loading dump file %s\n", szDumpFile);
  154. if ((Hr = DebugClient->OpenDumpFile(szDumpFile)) != S_OK) {
  155. fprintf(stderr, "**** DebugClient cannot open DumpFile - error %lx\n", Hr);
  156. if (Hr == HRESULT_FROM_WIN32(ERROR_FILE_CORRUPT)) {
  157. fprintf(stderr, "DumpFile is corrupt\n", Hr);
  158. }
  159. return Hr;
  160. }
  161. if (szSymbolPath) {
  162. DebugSymbols->SetSymbolPath(szSymbolPath);
  163. }
  164. DebugControl->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE);
  165. DebugClient->SetOutputCallbacks(&g_OutputCallback);
  166. DebugControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS, ".dumpdebug", DEBUG_EXECUTE_DEFAULT);
  167. g_OutputCallback.Output(0,"\n\n");
  168. DebugControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS, "vertarget", DEBUG_EXECUTE_DEFAULT);
  169. ULONG Class, Qual;
  170. if ((Hr = DebugControl->GetDebuggeeType(&Class, &Qual)) != S_OK) {
  171. Class = Qual = 0;
  172. }
  173. if (Class == DEBUG_CLASS_USER_WINDOWS) {
  174. //
  175. // User Mode dump
  176. //
  177. DebugControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS, "!peb", DEBUG_EXECUTE_DEFAULT);
  178. } else {
  179. //
  180. // Kernel Mode dump
  181. //
  182. ULONG64 NtModBase = 0;
  183. Hr = DebugSymbols->GetModuleByModuleName("nt", 0, NULL, &NtModBase);
  184. if (Hr != S_OK || !NtModBase) {
  185. fprintf(stderr, "***** NT module not found - module list may be corrupt\n");
  186. } else {
  187. DebugControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS, "lmt", DEBUG_EXECUTE_DEFAULT);
  188. }
  189. ULONG ThreadId;
  190. Hr = DebugSysObjects->GetCurrentThreadId(&ThreadId);
  191. if (Hr != S_OK) {
  192. fprintf(stderr, "***** Cannot get current thread ID, dump may be corrupt\n");
  193. }
  194. }
  195. g_OutputCallback.Output(0,"Finished dump check\n");
  196. DebugSysObjects->Release();
  197. DebugControl->Release();
  198. DebugSymbols->Release();
  199. DebugClient->Release();
  200. return S_OK;
  201. }
  202. void
  203. __cdecl
  204. main (
  205. int Argc,
  206. PCHAR *Argv
  207. )
  208. {
  209. LONG arg;
  210. PCHAR DumpFileName = NULL;
  211. PCHAR SymbolPath = NULL;
  212. for (arg = 1; arg < Argc; arg++) {
  213. if (Argv[arg][0] == '-' || Argv[arg][0] == '/') {
  214. switch (Argv[arg][1]) {
  215. case 'y':
  216. case 'Y':
  217. if (++arg < Argc) {
  218. SymbolPath = Argv[arg];
  219. }
  220. break;
  221. default:
  222. break;
  223. }
  224. } else {
  225. // Its a dumpfile name
  226. DumpFileName = Argv[arg];
  227. }
  228. }
  229. if (!DumpFileName) {
  230. Usage();
  231. return;
  232. }
  233. DoDumpCheck(DumpFileName, SymbolPath);
  234. return;
  235. }