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.

462 lines
13 KiB

  1. #include <windows.h>
  2. #include <malloc.h>
  3. #include <stddef.h>
  4. #include <process.h>
  5. #define _DBDBG32_
  6. #include "dbwin32.h"
  7. ProcessList::ProcessList() : GrowableList(sizeof(ProcessInfo))
  8. {
  9. }
  10. ProcessList::~ProcessList()
  11. {
  12. }
  13. BOOL ProcessList::IsEqual(void *pv1, void *pv2)
  14. {
  15. return(!memcmp(pv1, pv2, sizeof(DWORD)));
  16. }
  17. ThreadList::ThreadList() : GrowableList(sizeof(ThreadInfo))
  18. {
  19. }
  20. ThreadList::~ThreadList()
  21. {
  22. }
  23. BOOL ThreadList::IsEqual(void *pv1, void *pv2)
  24. {
  25. return(!memcmp(pv1, pv2, sizeof(ThreadInfo)));
  26. }
  27. DllList::DllList() : GrowableList(sizeof(DllInfo))
  28. {
  29. }
  30. DllList::~DllList()
  31. {
  32. }
  33. BOOL DllList::IsEqual(void *pv1, void *pv2)
  34. {
  35. return(!memcmp(pv1, pv2, (sizeof(DWORD) + sizeof(LPVOID))));
  36. }
  37. void __cdecl AttachThread(void *pv)
  38. {
  39. AttachInfo *pai = (AttachInfo *)pv;
  40. if (DebugActiveProcess(pai->dwProcess))
  41. DebugThread(pai->hwndFrame, pai->dwProcess);
  42. else
  43. {
  44. MessageBeep(MB_ICONEXCLAMATION);
  45. MessageBox(pai->hwndFrame, "Unable to attach to process.", "DbWin32",
  46. MB_ICONEXCLAMATION | MB_OK);
  47. }
  48. delete pai;
  49. }
  50. void __cdecl ExecThread(void *pv)
  51. {
  52. ExecInfo *pei = (ExecInfo *)pv;
  53. STARTUPINFO si;
  54. PROCESS_INFORMATION pi;
  55. memset(&si, 0, sizeof(STARTUPINFO));
  56. si.cb = sizeof(STARTUPINFO);
  57. si.wShowWindow = SW_SHOWDEFAULT;
  58. pi.hProcess = NULL;
  59. if (CreateProcess(NULL, pei->lpszCommandLine, NULL, NULL, TRUE,
  60. DEBUG_PROCESS | CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi))
  61. {
  62. CloseHandle(pi.hProcess);
  63. CloseHandle(pi.hThread);
  64. DebugThread(pei->hwndFrame, pi.dwProcessId);
  65. }
  66. else
  67. {
  68. MessageBeep(MB_ICONEXCLAMATION);
  69. MessageBox(pei->hwndFrame, "Unable to execute process.", "DbWin32",
  70. MB_ICONEXCLAMATION | MB_OK);
  71. }
  72. free((void *)(pei->lpszCommandLine));
  73. delete pei;
  74. }
  75. void __cdecl SystemThread(void *pv)
  76. {
  77. BOOL fFailed = TRUE;
  78. DWORD dwRet;
  79. HANDLE hevtBuffer = NULL, hevtData = NULL;
  80. HANDLE hfileShared = NULL;
  81. HWND hwndFrame = (HWND)pv;
  82. LPVOID lpvBuffer = NULL;
  83. LPSTR lpszText = NULL;
  84. DEBUG_EVENT DebugEvent;
  85. hevtBuffer = CreateEvent(NULL, FALSE, FALSE, "DBWIN_BUFFER_READY");
  86. if (hevtBuffer)
  87. hevtData = CreateEvent(NULL, FALSE, FALSE, "DBWIN_DATA_READY");
  88. if (hevtBuffer && hevtData)
  89. hfileShared = CreateFileMapping((HANDLE)-1, NULL, PAGE_READWRITE, 0,
  90. 4096, "DBWIN_BUFFER");
  91. if (hevtBuffer && hevtData && hfileShared)
  92. lpvBuffer = MapViewOfFile(hfileShared, FILE_MAP_READ, 0, 0, 512);
  93. if (hevtBuffer && hevtData && hfileShared && lpvBuffer)
  94. {
  95. fFailed = FALSE;
  96. lpszText = (LPSTR)lpvBuffer + sizeof(DWORD);
  97. DebugEvent.dwDebugEventCode = OUTPUT_DEBUG_STRING_EVENT;
  98. DebugEvent.dwProcessId = DebugEvent.dwThreadId = 0;
  99. SetEvent(hevtBuffer);
  100. }
  101. else
  102. {
  103. MessageBeep(MB_ICONEXCLAMATION);
  104. MessageBox(hwndFrame, "Unable to open System Window.", "DbWin32",
  105. MB_ICONEXCLAMATION | MB_OK);
  106. }
  107. while (!fFailed)
  108. {
  109. dwRet = WaitForSingleObject(hevtData, INFINITE);
  110. if (dwRet != WAIT_OBJECT_0)
  111. {
  112. SendText(hwndFrame, &DebugEvent, 0,
  113. "-------- DbWin32 ERROR! --------\r\n",
  114. DBO_OUTPUTDEBUGSTRING);
  115. SendText(hwndFrame, &DebugEvent, 0,
  116. "-------- Shutting down System Window --------\r\n",
  117. DBO_OUTPUTDEBUGSTRING);
  118. fFailed = TRUE;
  119. }
  120. else
  121. {
  122. SendText(hwndFrame, &DebugEvent, 0, lpszText,
  123. DBO_OUTPUTDEBUGSTRING);
  124. SetEvent(hevtBuffer);
  125. }
  126. }
  127. if (hfileShared)
  128. CloseHandle(hfileShared);
  129. if (hevtData)
  130. CloseHandle(hevtData);
  131. if (hevtBuffer)
  132. CloseHandle(hevtBuffer);
  133. }
  134. void __cdecl DebugThread(HWND hwndFrame, DWORD dwProcess)
  135. {
  136. char DisplayBuffer[BUF_SIZE];
  137. WORD wEvent;
  138. DWORD dwContinue;
  139. SIZE_T dwRead;
  140. ProcessList pl;
  141. ProcessInfo pi;
  142. ThreadList tl;
  143. ThreadInfo ti;
  144. DllList dl;
  145. DllInfo di;
  146. int iItem;
  147. BOOL fDone = FALSE;
  148. DEBUG_EVENT DebugEvent;
  149. EXCEPTION_DEBUG_INFO *pException = &DebugEvent.u.Exception;
  150. CREATE_THREAD_DEBUG_INFO *pCreateThread = &DebugEvent.u.CreateThread;
  151. CREATE_PROCESS_DEBUG_INFO *pCreateProcessInfo = &DebugEvent.u.CreateProcessInfo;
  152. EXIT_THREAD_DEBUG_INFO *pExitThread = &DebugEvent.u.ExitThread;
  153. EXIT_PROCESS_DEBUG_INFO *pExitProcess = &DebugEvent.u.ExitProcess;
  154. LOAD_DLL_DEBUG_INFO *pLoadDll = &DebugEvent.u.LoadDll;
  155. UNLOAD_DLL_DEBUG_INFO *pUnloadDll = &DebugEvent.u.UnloadDll;
  156. OUTPUT_DEBUG_STRING_INFO *pDebugString = &DebugEvent.u.DebugString;
  157. RIP_INFO *pRipInfo = &DebugEvent.u.RipInfo;
  158. while (!fDone && WaitForDebugEvent(&DebugEvent, INFINITE))
  159. {
  160. *DisplayBuffer = '\0';
  161. dwContinue = DBG_CONTINUE;
  162. switch (DebugEvent.dwDebugEventCode)
  163. {
  164. case EXCEPTION_DEBUG_EVENT:
  165. ProcessExceptionEvent(pException, DisplayBuffer);
  166. if (pException->ExceptionRecord.ExceptionCode != EXCEPTION_BREAKPOINT)
  167. dwContinue = DBG_EXCEPTION_NOT_HANDLED;
  168. wEvent = DBO_EXCEPTIONS;
  169. break;
  170. case CREATE_THREAD_DEBUG_EVENT:
  171. ti.dwProcess = DebugEvent.dwProcessId;
  172. ti.dwThread = DebugEvent.dwThreadId;
  173. tl.InsertItem(&ti);
  174. wsprintf(DisplayBuffer, "Create Thread: PID 0x%X - TID 0x%X\r\n",
  175. ti.dwProcess, ti.dwThread);
  176. wEvent = DBO_THREADCREATE;
  177. break;
  178. case CREATE_PROCESS_DEBUG_EVENT:
  179. ti.dwProcess = pi.dwProcess = DebugEvent.dwProcessId;
  180. ti.dwThread = DebugEvent.dwThreadId;
  181. tl.InsertItem(&ti);
  182. pi.hProcess = pCreateProcessInfo->hProcess;
  183. GetModuleName(pCreateProcessInfo->hFile, pi.hProcess,
  184. (DWORD_PTR)pCreateProcessInfo->lpBaseOfImage, pi.rgchModule);
  185. pl.InsertItem(&pi);
  186. wsprintf(DisplayBuffer, "Create Process: PID 0x%X - %s\r\n",
  187. pi.dwProcess, pi.rgchModule);
  188. wEvent = DBO_PROCESSCREATE;
  189. break;
  190. case EXIT_THREAD_DEBUG_EVENT:
  191. ti.dwProcess = DebugEvent.dwProcessId;
  192. ti.dwThread = DebugEvent.dwThreadId;
  193. tl.RemoveItem(&ti);
  194. wsprintf(DisplayBuffer, "Exit Thread: PID 0x%X - TID 0x%X - dwReturnCode %d\r\n",
  195. ti.dwProcess, ti.dwThread, pExitThread->dwExitCode);
  196. wEvent = DBO_THREADEXIT;
  197. break;
  198. case EXIT_PROCESS_DEBUG_EVENT:
  199. pi.dwProcess = DebugEvent.dwProcessId;
  200. if (pl.FindItem(&pi, &iItem))
  201. {
  202. pl.RemoveItem(iItem);
  203. }
  204. wsprintf(DisplayBuffer, "Exit Process: PID 0x%X - %s - dwReturnCode %d\r\n",
  205. pi.dwProcess, pi.rgchModule, pExitProcess->dwExitCode);
  206. if (pi.dwProcess == dwProcess)
  207. fDone = TRUE;
  208. wEvent = DBO_PROCESSEXIT;
  209. break;
  210. case LOAD_DLL_DEBUG_EVENT:
  211. di.dwProcess = pi.dwProcess = DebugEvent.dwProcessId;
  212. pl.FindItem(&pi);
  213. di.lpBaseOfDll = pLoadDll->lpBaseOfDll;
  214. GetModuleName(pLoadDll->hFile, pi.hProcess, (DWORD_PTR)di.lpBaseOfDll,
  215. di.rgchModule);
  216. dl.InsertItem(&di);
  217. wsprintf(DisplayBuffer, "DLL Load: %s\r\n", di.rgchModule);
  218. wEvent = DBO_DLLLOAD;
  219. break;
  220. case UNLOAD_DLL_DEBUG_EVENT:
  221. di.dwProcess = DebugEvent.dwProcessId;
  222. di.lpBaseOfDll = pUnloadDll->lpBaseOfDll;
  223. if (dl.FindItem(&di, &iItem))
  224. {
  225. dl.RemoveItem(iItem);
  226. }
  227. wsprintf(DisplayBuffer, "Dll Unload: %s\r\n", di.rgchModule);
  228. wEvent = DBO_DLLUNLOAD;
  229. break;
  230. case OUTPUT_DEBUG_STRING_EVENT:
  231. pi.dwProcess = DebugEvent.dwProcessId;
  232. pl.FindItem(&pi);
  233. if (!ReadProcessMemory(pi.hProcess,
  234. pDebugString->lpDebugStringData, DisplayBuffer,
  235. pDebugString->nDebugStringLength, &dwRead))
  236. dwRead = 0;
  237. DisplayBuffer[dwRead] = '\0';
  238. wEvent = DBO_OUTPUTDEBUGSTRING;
  239. break;
  240. case RIP_EVENT:
  241. wsprintf(DisplayBuffer, "RIP: dwError %d - dwType %d\r\n",
  242. pRipInfo->dwError, pRipInfo->dwType);
  243. wEvent = DBO_RIP;
  244. break;
  245. // No events should reach here.
  246. default:
  247. wsprintf(DisplayBuffer, "Unknown Event: 0x%X\r\n",
  248. DebugEvent.dwDebugEventCode);
  249. wEvent = DBO_ALL;
  250. break;
  251. }
  252. if (*DisplayBuffer)
  253. SendText(hwndFrame, &DebugEvent, dwProcess, DisplayBuffer, wEvent);
  254. if (DebugEvent.dwDebugEventCode == EXIT_THREAD_DEBUG_EVENT)
  255. PostMessage(hwndFrame, WM_ENDTHREAD, (WPARAM)ti.dwThread,
  256. ti.dwProcess);
  257. if (DebugEvent.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
  258. {
  259. if (fDone)
  260. {
  261. for (iItem = tl.Count(); iItem > 0; iItem--)
  262. {
  263. tl.GetItem(iItem - 1, &ti);
  264. PostMessage(hwndFrame, WM_ENDTHREAD, (WPARAM)ti.dwThread, ti.dwProcess);
  265. }
  266. for (iItem = pl.Count(); iItem > 0; iItem--)
  267. {
  268. pl.GetItem(iItem - 1, &pi);
  269. PostMessage(hwndFrame, WM_ENDTHREAD, 0, pi.dwProcess);
  270. }
  271. }
  272. PostMessage(hwndFrame, WM_ENDTHREAD, 0, DebugEvent.dwProcessId);
  273. }
  274. ContinueDebugEvent(DebugEvent.dwProcessId, DebugEvent.dwThreadId, dwContinue);
  275. }
  276. }
  277. void SendText(HWND hwndFrame, DEBUG_EVENT *pDebugEvent, DWORD dwParentProcess,
  278. LPCSTR lpszText, WORD wEvent)
  279. {
  280. char rgchText[BUF_SIZE], *pch = rgchText;
  281. StringInfo *psi;
  282. psi = new StringInfo;
  283. // Niceify the text
  284. if (pDebugEvent->dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT)
  285. {
  286. psi->cLines = 0;
  287. while (*lpszText != '\0')
  288. {
  289. if ((*lpszText == 0x0d) || (*lpszText == 0x0a))
  290. {
  291. *pch++ = 0x0d;
  292. *pch++ = 0x0a;
  293. while ((*lpszText == 0x0d) || (*lpszText == 0x0a))
  294. lpszText++;
  295. psi->cLines++;
  296. }
  297. else
  298. {
  299. *pch++ = *lpszText++;
  300. }
  301. }
  302. *pch = '\0';
  303. psi->lpszText = _strdup(rgchText);
  304. }
  305. else
  306. {
  307. psi->cLines = 1;
  308. psi->lpszText = _strdup(lpszText);
  309. }
  310. psi->dwProcess = pDebugEvent->dwProcessId;
  311. psi->dwThread = pDebugEvent->dwThreadId;
  312. psi->dwParentProcess = dwParentProcess;
  313. PostMessage(hwndFrame, WM_SENDTEXT, wEvent, (LPARAM)psi);
  314. }
  315. void ProcessExceptionEvent(EXCEPTION_DEBUG_INFO *pException, LPSTR lpszBuf)
  316. {
  317. if (pException->dwFirstChance)
  318. strcpy(lpszBuf, "First");
  319. else
  320. strcpy(lpszBuf, "Second");
  321. strcat(lpszBuf, " chance exception: ");
  322. switch (pException->ExceptionRecord.ExceptionCode)
  323. {
  324. //--standard exceptions
  325. case EXCEPTION_ACCESS_VIOLATION:
  326. strcat(lpszBuf, "Access Violation");
  327. break;
  328. case EXCEPTION_DATATYPE_MISALIGNMENT:
  329. strcat(lpszBuf, "Datatype Misalignment");
  330. break;
  331. case EXCEPTION_BREAKPOINT:
  332. strcat(lpszBuf, "Breakpoint");
  333. break;
  334. case EXCEPTION_SINGLE_STEP:
  335. strcat(lpszBuf, "Single Step");
  336. break;
  337. case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
  338. strcat(lpszBuf, "Array Bound Exceeded");
  339. break;
  340. case EXCEPTION_FLT_DENORMAL_OPERAND:
  341. strcat(lpszBuf, "FP-Denormal Operand");
  342. break;
  343. case EXCEPTION_FLT_DIVIDE_BY_ZERO:
  344. strcat(lpszBuf, "FP-Divide By Zero");
  345. break;
  346. case EXCEPTION_FLT_INEXACT_RESULT:
  347. strcat(lpszBuf, "FP-Inexact Result");
  348. break;
  349. case EXCEPTION_FLT_INVALID_OPERATION:
  350. strcat(lpszBuf, "FP-Invalid Operation");
  351. break;
  352. case EXCEPTION_FLT_OVERFLOW:
  353. strcat(lpszBuf, "FP-Overflow");
  354. break;
  355. case EXCEPTION_FLT_STACK_CHECK:
  356. strcat(lpszBuf, "FP-Stack Check");
  357. break;
  358. case EXCEPTION_FLT_UNDERFLOW:
  359. strcat(lpszBuf, "FP-Underflow");
  360. break;
  361. case EXCEPTION_INT_DIVIDE_BY_ZERO:
  362. strcat(lpszBuf, "INT-Divide By Zero");
  363. break;
  364. case EXCEPTION_INT_OVERFLOW:
  365. strcat(lpszBuf, "INT-Overflow");
  366. break;
  367. case EXCEPTION_PRIV_INSTRUCTION:
  368. strcat(lpszBuf, "Privileged Instruction");
  369. break;
  370. case EXCEPTION_IN_PAGE_ERROR:
  371. strcat(lpszBuf, "In Page Error");
  372. break;
  373. //-- Debug exceptions
  374. case DBG_TERMINATE_THREAD:
  375. strcat(lpszBuf, "DBG-Terminate Thread");
  376. break;
  377. case DBG_TERMINATE_PROCESS:
  378. strcat(lpszBuf, "DBG-Terminate Process");
  379. break;
  380. case DBG_CONTROL_C:
  381. strcat(lpszBuf, "DBG-Control+C");
  382. break;
  383. case DBG_CONTROL_BREAK:
  384. strcat(lpszBuf, "DBG-Control+Break");
  385. break;
  386. //-- RPC exceptions (some)
  387. case RPC_S_UNKNOWN_IF:
  388. strcat(lpszBuf, "RPC-Unknown Interface");
  389. break;
  390. case RPC_S_SERVER_UNAVAILABLE:
  391. strcat(lpszBuf, "RPC-Server Unavailable");
  392. break;
  393. //-- VDM exceptions (minimal information)
  394. case EXCEPTION_VDM_EVENT: // see dbwin32.h for definition
  395. strcat(lpszBuf, "VDM");
  396. break;
  397. default:
  398. char rgchTmp[25];
  399. wsprintf(rgchTmp, "Unknown-[0x%X]", pException->ExceptionRecord.ExceptionCode);
  400. strcat(lpszBuf, rgchTmp);
  401. break;
  402. }
  403. strcat(lpszBuf, "\r\n");
  404. }
  405. #define IMAGE_SECOND_HEADER_OFFSET (15 * sizeof(ULONG))
  406. #define IMAGE_EXPORT_TABLE_RVA_OFFSET (30 * sizeof(DWORD))
  407. #define IMAGE_NAME_RVA_OFFSET offsetof(IMAGE_EXPORT_DIRECTORY, Name)
  408. void GetModuleName(HANDLE hFile, HANDLE hProcess, DWORD_PTR BaseOfImage, LPSTR lpszBuf)
  409. {
  410. DWORD dwRead = 0;
  411. WORD DosSignature;
  412. DWORD NtSignature, PeHeader, ExportTableRVA, NameRVA;
  413. strcpy(lpszBuf, "<unknown>");
  414. if (!hFile)
  415. return;
  416. if (GetFileType(hFile) != FILE_TYPE_DISK)
  417. return;
  418. SetFilePointer(hFile, 0L, NULL, FILE_BEGIN);
  419. if (!ReadFile(hFile, &DosSignature, sizeof(DosSignature), &dwRead, NULL))
  420. return;
  421. if (DosSignature != IMAGE_DOS_SIGNATURE)
  422. return;
  423. SetFilePointer(hFile, IMAGE_SECOND_HEADER_OFFSET, NULL, FILE_BEGIN);
  424. if (!ReadFile(hFile, &PeHeader, sizeof(PeHeader), &dwRead, NULL))
  425. return;
  426. SetFilePointer(hFile, PeHeader, NULL, FILE_BEGIN);
  427. if (!ReadFile(hFile, &NtSignature, sizeof(NtSignature), &dwRead, NULL))
  428. return;
  429. if (NtSignature != IMAGE_NT_SIGNATURE)
  430. return;
  431. SetFilePointer(hFile, PeHeader + IMAGE_EXPORT_TABLE_RVA_OFFSET, NULL, FILE_BEGIN);
  432. if (!ReadFile(hFile, &ExportTableRVA, sizeof(ExportTableRVA), &dwRead, NULL))
  433. return;
  434. if (!ExportTableRVA)
  435. return;
  436. ReadProcessMemory(hProcess, (LPVOID)(BaseOfImage + ExportTableRVA +
  437. IMAGE_NAME_RVA_OFFSET), &NameRVA, sizeof(NameRVA), NULL);
  438. ReadProcessMemory(hProcess, (LPVOID)(BaseOfImage + NameRVA), lpszBuf, MODULE_SIZE, NULL);
  439. }