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.

482 lines
12 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // AutoDump Plus support extension DLL.
  4. //
  5. // Copyright (C) Microsoft Corporation, 2000-2001.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "dbgexts.h"
  9. #define STATUS_CPP_EH_EXCEPTION 0xe06d7363
  10. #define MAX_NAME 64
  11. #define MAX_MACHINE 64
  12. #define MAX_COMMENT 256
  13. char g_BaseDir[MAX_PATH - 1];
  14. char g_Machine[MAX_MACHINE];
  15. struct PARAM
  16. {
  17. ULONG Len;
  18. PSTR Buf;
  19. };
  20. PARAM g_DirMachParams[2] =
  21. {
  22. sizeof(g_BaseDir), g_BaseDir,
  23. sizeof(g_Machine), g_Machine,
  24. };
  25. union LAST_EVENT_INFO_ALL
  26. {
  27. DEBUG_LAST_EVENT_INFO_BREAKPOINT Breakpoint;
  28. DEBUG_LAST_EVENT_INFO_EXCEPTION Exception;
  29. DEBUG_LAST_EVENT_INFO_EXIT_THREAD ExitThread;
  30. DEBUG_LAST_EVENT_INFO_EXIT_PROCESS ExitProcess;
  31. DEBUG_LAST_EVENT_INFO_LOAD_MODULE LoadModule;
  32. DEBUG_LAST_EVENT_INFO_UNLOAD_MODULE UnloadModule;
  33. DEBUG_LAST_EVENT_INFO_SYSTEM_ERROR SystemError;
  34. };
  35. ULONG g_LastEventType;
  36. LAST_EVENT_INFO_ALL g_LastEventInfo;
  37. PSTR g_LastExName;
  38. char g_UnknownExceptionName[64];
  39. PSTR g_LastExChanceStr;
  40. ULONG g_ProcessId;
  41. char g_ProcessName[MAX_NAME];
  42. struct EXCEPTION_NAME
  43. {
  44. PSTR Name;
  45. ULONG Code;
  46. };
  47. EXCEPTION_NAME g_ExceptionNames[] =
  48. {
  49. "Access Violation", STATUS_ACCESS_VIOLATION,
  50. "C++ EH Exception", STATUS_CPP_EH_EXCEPTION,
  51. "Invalid Handle Exception", STATUS_INVALID_HANDLE,
  52. "Stack Overflow", STATUS_STACK_OVERFLOW,
  53. NULL, 0,
  54. };
  55. PCSTR
  56. GetParams(PCSTR Args, ULONG Count, PARAM* Params)
  57. {
  58. PCSTR Start;
  59. ULONG Len;
  60. ULONG Index = 0;
  61. while (Count-- > 0)
  62. {
  63. while (*Args == ' ' || *Args == '\t')
  64. {
  65. Args++;
  66. }
  67. Start = Args;
  68. while (*Args && *Args != ' ' && *Args != '\t')
  69. {
  70. Args++;
  71. }
  72. Len = (ULONG)(Args - Start);
  73. if ((Count > 0 && !*Args) || Len >= Params[Index].Len)
  74. {
  75. ExtErr("Invalid extension command arguments\n");
  76. return NULL;
  77. }
  78. memcpy(Params[Index].Buf, Start, Len);
  79. Params[Index].Buf[Len] = 0;
  80. Index++;
  81. }
  82. return Args;
  83. }
  84. HRESULT
  85. GetProcessInfo(void)
  86. {
  87. HRESULT Status;
  88. if ((Status = g_ExtSystem->
  89. GetCurrentProcessSystemId(&g_ProcessId)) != S_OK)
  90. {
  91. ExtErr("Unable to get current process ID\n");
  92. return Status;
  93. }
  94. if (FAILED(g_ExtClient->
  95. GetRunningProcessDescription(0, g_ProcessId,
  96. DEBUG_PROC_DESC_NO_PATHS,
  97. NULL, 0, NULL,
  98. g_ProcessName, MAX_NAME,
  99. NULL)))
  100. {
  101. g_ProcessName[0] = 0;
  102. }
  103. else
  104. {
  105. PSTR Scan;
  106. // Use the MTS package name as the name if it exists.
  107. Scan = strstr(g_ProcessName, "MTS Packages: ");
  108. if (Scan)
  109. {
  110. PSTR Start;
  111. ULONG Len;
  112. Scan += 14;
  113. Start = Scan;
  114. Scan = strchr(Start, ',');
  115. if (!Scan)
  116. {
  117. Scan = strchr(Start, ' ');
  118. }
  119. if (Scan)
  120. {
  121. *Scan = 0;
  122. }
  123. Len = strlen(Start) + 1;
  124. if (Len > 2)
  125. {
  126. memmove(g_ProcessName, Start, Len);
  127. }
  128. else
  129. {
  130. g_ProcessName[0] = 0;
  131. }
  132. }
  133. else
  134. {
  135. g_ProcessName[0] = 0;
  136. }
  137. }
  138. if (!g_ProcessName[0])
  139. {
  140. if (FAILED(g_ExtSystem->
  141. GetCurrentProcessExecutableName(g_ProcessName, MAX_NAME,
  142. NULL)))
  143. {
  144. // This can happen in some situations so handle it
  145. // rather than exiting.
  146. ExtErr("Unable to get current process name\n");
  147. strcpy(g_ProcessName, "UnknownProcess");
  148. }
  149. }
  150. return S_OK;
  151. }
  152. HRESULT
  153. GetEventInfo(void)
  154. {
  155. HRESULT Status;
  156. ULONG ProcessId, ThreadId;
  157. if ((Status = g_ExtControl->
  158. GetLastEventInformation(&g_LastEventType, &ProcessId, &ThreadId,
  159. &g_LastEventInfo, sizeof(g_LastEventInfo),
  160. NULL, NULL, 0, NULL)) != S_OK)
  161. {
  162. ExtErr("Unable to get event information\n");
  163. return Status;
  164. }
  165. if ((Status = GetProcessInfo()) != S_OK)
  166. {
  167. return Status;
  168. }
  169. switch(g_LastEventType)
  170. {
  171. case DEBUG_EVENT_EXCEPTION:
  172. {
  173. EXCEPTION_NAME* ExName = g_ExceptionNames;
  174. while (ExName->Name != NULL)
  175. {
  176. if (ExName->Code == g_LastEventInfo.Exception.
  177. ExceptionRecord.ExceptionCode)
  178. {
  179. break;
  180. }
  181. ExName++;
  182. }
  183. if (ExName->Name != NULL)
  184. {
  185. g_LastExName = ExName->Name;
  186. }
  187. else
  188. {
  189. sprintf(g_UnknownExceptionName, "Unknown Exception (%08X)",
  190. g_LastEventInfo.Exception.
  191. ExceptionRecord.ExceptionCode);
  192. g_LastExName = g_UnknownExceptionName;
  193. }
  194. if (g_LastEventInfo.Exception.FirstChance)
  195. {
  196. g_LastExChanceStr = "First";
  197. }
  198. else
  199. {
  200. g_LastExChanceStr = "Second";
  201. }
  202. }
  203. break;
  204. }
  205. return S_OK;
  206. }
  207. void
  208. SanitizeFileName(PSTR FileName)
  209. {
  210. while (*FileName)
  211. {
  212. switch(*FileName)
  213. {
  214. case ' ':
  215. case '\t':
  216. case '\n':
  217. case '\r':
  218. *FileName = '_';
  219. break;
  220. case '\\':
  221. case '/':
  222. case ':':
  223. *FileName = '-';
  224. break;
  225. }
  226. FileName++;
  227. }
  228. }
  229. void
  230. GetDumpPath(PSTR NameQual, PSTR TypeStr, PSTR Path)
  231. {
  232. SYSTEMTIME Time;
  233. PSTR FilePart;
  234. GetLocalTime(&Time);
  235. strcpy(Path, g_BaseDir);
  236. FilePart = Path + strlen(Path) - 1;
  237. if (*FilePart != '/' && *FilePart != '\\')
  238. {
  239. *++FilePart = '\\';
  240. }
  241. FilePart++;
  242. _snprintf(FilePart,
  243. MAX_PATH - (FilePart - Path),
  244. "PID-%d__%s__Date_%02d-%02d-%04d__Time_%02d-%02d-%02d__%s__%s.dmp",
  245. g_ProcessId,
  246. g_ProcessName,
  247. Time.wMonth,
  248. Time.wDay,
  249. Time.wYear,
  250. Time.wHour,
  251. Time.wMinute,
  252. Time.wSecond,
  253. NameQual,
  254. TypeStr);
  255. Path[MAX_PATH - 1] = 0;
  256. SanitizeFileName(FilePart);
  257. }
  258. void
  259. WriteDump(PSTR NameQual, PSTR Comment,
  260. ULONG DumpQual, ULONG DumpFormat, PSTR TypeStr)
  261. {
  262. char Path[MAX_PATH];
  263. ULONG Len;
  264. Len = strlen(Comment);
  265. _snprintf(Comment + Len, MAX_COMMENT - Len,
  266. " - %s dump from %s",
  267. TypeStr, g_Machine);
  268. Comment[MAX_COMMENT - 1] = 0;
  269. GetDumpPath(NameQual, TypeStr, Path);
  270. g_ExtClient->WriteDumpFile2(Path, DumpQual, DumpFormat, Comment);
  271. }
  272. extern "C" HRESULT
  273. AdpEventControlC(PDEBUG_CLIENT Client, PCSTR Args)
  274. {
  275. char Comment[MAX_COMMENT];
  276. INIT_API();
  277. //
  278. // Parameters: directory, machine name.
  279. //
  280. Args = GetParams(Args, 2, g_DirMachParams);
  281. if (Args == NULL)
  282. {
  283. goto Exit;
  284. }
  285. //
  286. // Retrieve standard information.
  287. //
  288. if ((Status = GetEventInfo()) != S_OK)
  289. {
  290. goto Exit;
  291. }
  292. //
  293. // Log information.
  294. //
  295. ExtOut("\n\n----------------------------------------------------------------------\n");
  296. ExtOut("CTRL-C was pressed to stop debugging this process!\n");
  297. ExtOut("----------------------------------------------------------------------\n");
  298. ExtOut("Exiting the debugger at:\n");
  299. ExtExec(".time");
  300. ExtOut("\n\n--- Listing all thread stacks: ---\n");
  301. ExtExec("~*kb250");
  302. ExtOut("\n--- Listing loaded modules: ---\n");
  303. ExtExec("lmv");
  304. ExtOut("\n--- Modules with matching symbols:\n");
  305. ExtExec("lml");
  306. ExtOut("\n--- Listing all locks: ---\n");
  307. ExtExec("!locks");
  308. //
  309. // Create a dump file.
  310. //
  311. strcpy(Comment, "CTRL-C was pressed to stop the debugger while running in crash mode");
  312. WriteDump("CTRL-C", Comment,
  313. DEBUG_DUMP_SMALL, DEBUG_FORMAT_DEFAULT, "mini");
  314. Exit:
  315. EXIT_API();
  316. return Status;
  317. }
  318. extern "C" HRESULT
  319. AdpEventException(PDEBUG_CLIENT Client, PCSTR Args)
  320. {
  321. char Comment[MAX_COMMENT];
  322. char Qual[MAX_COMMENT];
  323. ULONG Format;
  324. PSTR TypeStr;
  325. INIT_API();
  326. //
  327. // Parameters: directory, machine name.
  328. //
  329. Args = GetParams(Args, 2, g_DirMachParams);
  330. if (Args == NULL)
  331. {
  332. goto Exit;
  333. }
  334. //
  335. // Retrieve standard information.
  336. //
  337. if ((Status = GetEventInfo()) != S_OK)
  338. {
  339. goto Exit;
  340. }
  341. if (g_LastEventType != DEBUG_EVENT_EXCEPTION)
  342. {
  343. ExtErr("Last event was not an exception\n");
  344. goto Exit;
  345. }
  346. if (g_LastEventInfo.Exception.FirstChance)
  347. {
  348. Format = DEBUG_FORMAT_DEFAULT;
  349. TypeStr = "mini";
  350. }
  351. else
  352. {
  353. Format = DEBUG_FORMAT_USER_SMALL_FULL_MEMORY |
  354. DEBUG_FORMAT_USER_SMALL_HANDLE_DATA;
  355. TypeStr = "mini full handle";
  356. }
  357. //
  358. // Log information.
  359. //
  360. ExtOut("\n---- %s-chance %s - Exception stack below ----\n",
  361. g_LastExChanceStr, g_LastExName);
  362. ExtExec(".time");
  363. ExtOut("\n");
  364. ExtExec("kvn250");
  365. ExtOut("-----------------------------------\n");
  366. //
  367. // Create a dump file.
  368. //
  369. _snprintf(Comment, sizeof(Comment), "%s-chance %s in %s",
  370. g_LastExChanceStr, g_LastExName, g_ProcessName);
  371. Comment[sizeof(Comment) - 1] = 0;
  372. _snprintf(Qual, sizeof(Qual), "%s-chance %s",
  373. g_LastExChanceStr, g_LastExName);
  374. Qual[sizeof(Qual) - 1] = 0;
  375. WriteDump(Qual, Comment, DEBUG_DUMP_SMALL, Format, TypeStr);
  376. ExtOut("\n\n");
  377. Exit:
  378. EXIT_API();
  379. return Status;
  380. }
  381. extern "C" HRESULT
  382. AdpEventExitProcess(PDEBUG_CLIENT Client, PCSTR Args)
  383. {
  384. INIT_API();
  385. UNREFERENCED_PARAMETER(Args);
  386. //
  387. // Log information.
  388. //
  389. ExtOut("\n\n----------------------------------------------------------------------\n");
  390. ExtOut("This process is shutting down!\n");
  391. ExtOut("\nThis can happen for the following reasons:\n");
  392. ExtOut("1.) Someone killed the process with Task Manager or the kill command.\n");
  393. ExtOut("\n2.) If this process is an MTS or COM+ server package, it could be\n");
  394. ExtOut("* exiting because an MTS/COM+ server package idle limit was reached.\n");
  395. ExtOut("\n3.) If this process is an MTS or COM+ server package,\n");
  396. ExtOut("* someone may have shutdown the package via the MTS Explorer or\n");
  397. ExtOut("* Component Services MMC snap-in.\n");
  398. ExtOut("\n4.) If this process is an MTS or COM+ server package,\n");
  399. ExtOut("* MTS or COM+ could be shutting down the process because an internal\n");
  400. ExtOut("* error was detected in the process (MTS/COM+ fail fast condition).\n");
  401. ExtOut("----------------------------------------------------------------------\n");
  402. ExtOut("\nThe process was shut down at:\n");
  403. ExtExec(".time");
  404. ExtOut("\n\n");
  405. EXIT_API();
  406. return Status;
  407. }