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.

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