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.

1935 lines
56 KiB

  1. /*++
  2. Copyright (c) 1999-2002 Microsoft Corporation
  3. Module Name:
  4. windbg.cpp
  5. Abstract:
  6. This module contains the main program, main window proc and MDICLIENT
  7. window proc for Windbg.
  8. --*/
  9. #include "precomp.hxx"
  10. #pragma hdrstop
  11. #include <dbghelp.h>
  12. ULONG g_CodeDisplaySequence;
  13. PTSTR g_ProgramName;
  14. ULONG g_CommandLineStart;
  15. PSTR g_RemoteOptions;
  16. QUIET_MODES g_QuietMode = QMODE_DISABLED;
  17. QUIET_MODES g_QuietSourceMode = QMODE_DISABLED;
  18. ULONG g_DefPriority;
  19. char g_TitleServerText[MAX_PATH];
  20. char g_TitleExtraText[MAX_PATH];
  21. BOOL g_ExplicitTitle;
  22. PFN_FlashWindowEx g_FlashWindowEx;
  23. BOOL g_AllowJournaling;
  24. BOOL g_Exit;
  25. // Handle to main window
  26. HWND g_hwndFrame = NULL;
  27. // Handle to MDI client
  28. HWND g_hwndMDIClient = NULL;
  29. // Width and height of MDI client.
  30. ULONG g_MdiWidth, g_MdiHeight;
  31. //Handle to instance data
  32. HINSTANCE g_hInst;
  33. //Handle to accelerator table
  34. HACCEL g_hMainAccTable;
  35. //Keyboard Hooks functions
  36. HHOOK hKeyHook;
  37. // WinDBG title text
  38. TCHAR g_MainTitleText[MAX_MSG_TXT];
  39. // menu that belongs to g_hwndFrame
  40. HMENU g_hmenuMain;
  41. HMENU g_hmenuMainSave;
  42. // Window submenu
  43. HMENU g_hmenuWindowSub;
  44. #ifdef DBG
  45. // Used to define debugger output
  46. DWORD dwVerboseLevel = MIN_VERBOSITY_LEVEL;
  47. #endif
  48. INDEXED_COLOR g_Colors[COL_COUNT] =
  49. {
  50. // Set from GetSysColor(COLOR_WINDOW).
  51. "Background", 0, 0, NULL,
  52. // Set from GetSysColor(COLOR_WINDOWTEXT).
  53. "Text", 0, 0, NULL,
  54. // Set from GetSysColor(COLOR_HIGHLIGHT).
  55. "Current line background", 0, 0, NULL,
  56. // Set from GetSysColor(COLOR_HIGHLIGHTTEXT).
  57. "Current line text", 0, 0, NULL,
  58. // Purple.
  59. "Breakpoint current line background", 0, RGB(255, 0, 255), NULL,
  60. // Set from GetSysColor(COLOR_HIGHLIGHTTEXT).
  61. "Breakpoint current line text", 0, 0, NULL,
  62. // Red.
  63. "Enabled breakpoint background", 0, RGB(255, 0, 0), NULL,
  64. // Set from GetSysColor(COLOR_HIGHLIGHTTEXT).
  65. "Enabled breakpoint text", 0, 0, NULL,
  66. // Yellow.
  67. "Disabled breakpoint background", 0, RGB(255, 255, 0), NULL,
  68. // Set from GetSysColor(COLOR_HIGHLIGHTTEXT).
  69. "Disabled breakpoint text", 0, 0, NULL,
  70. // Red.
  71. "Changed data text", 0, RGB(255, 0, 0), NULL,
  72. // Set from GetSysColor(COLOR_3DFACE).
  73. "Disabled window", 0, 0, NULL,
  74. };
  75. // There is a foreground and background color for each
  76. // possible bit in the output mask. The default foreground
  77. // color is normal window text and the background is
  78. // the normal window background.
  79. //
  80. // There are also some extra colors for user-added output.
  81. //
  82. // Some mask bits have no assigned meaning right now and
  83. // are given NULL names to mark them as skip entries. Their
  84. // indices are allocated now for future use.
  85. INDEXED_COLOR g_OutMaskColors[OUT_MASK_COL_COUNT] =
  86. {
  87. // 0x00000001 - 0x00000008.
  88. "Normal level command window text", 0, 0, NULL,
  89. "Normal level command window text background", 0, 0, NULL,
  90. "Error level command window text", 0, 0, NULL,
  91. "Error level command window text background", 0, 0, NULL,
  92. "Warning level command window text", 0, 0, NULL,
  93. "Warning level command window text background", 0, 0, NULL,
  94. "Verbose level command window text", 0, 0, NULL,
  95. "Verbose level command window text background", 0, 0, NULL,
  96. // 0x00000010 - 0x00000080.
  97. "Prompt level command window text", 0, 0, NULL,
  98. "Prompt level command window text background", 0, 0, NULL,
  99. "Prompt registers level command window text", 0, 0, NULL,
  100. "Prompt registers level command window text background", 0, 0, NULL,
  101. "Extension warning level command window text", 0, 0, NULL,
  102. "Extension warning level command window text background", 0, 0, NULL,
  103. "Debuggee level command window text", 0, 0, NULL,
  104. "Debuggee level command window text background", 0, 0, NULL,
  105. // 0x00000100 - 0x00000800.
  106. "Debuggee prompt level command window text", 0, 0, NULL,
  107. "Debuggee prompt level command window text background", 0, 0, NULL,
  108. "Symbol message level command window text", 0, 0, NULL,
  109. "Symbol message level command window text background", 0, 0, NULL,
  110. NULL, 0, 0, NULL,
  111. NULL, 0, 0, NULL,
  112. NULL, 0, 0, NULL,
  113. NULL, 0, 0, NULL,
  114. // 0x00001000 - 0x00008000.
  115. NULL, 0, 0, NULL,
  116. NULL, 0, 0, NULL,
  117. NULL, 0, 0, NULL,
  118. NULL, 0, 0, NULL,
  119. NULL, 0, 0, NULL,
  120. NULL, 0, 0, NULL,
  121. NULL, 0, 0, NULL,
  122. NULL, 0, 0, NULL,
  123. // 0x00010000 - 0x00080000.
  124. NULL, 0, 0, NULL,
  125. NULL, 0, 0, NULL,
  126. NULL, 0, 0, NULL,
  127. NULL, 0, 0, NULL,
  128. NULL, 0, 0, NULL,
  129. NULL, 0, 0, NULL,
  130. NULL, 0, 0, NULL,
  131. NULL, 0, 0, NULL,
  132. // 0x00100000 - 0x00800000.
  133. NULL, 0, 0, NULL,
  134. NULL, 0, 0, NULL,
  135. NULL, 0, 0, NULL,
  136. NULL, 0, 0, NULL,
  137. NULL, 0, 0, NULL,
  138. NULL, 0, 0, NULL,
  139. NULL, 0, 0, NULL,
  140. NULL, 0, 0, NULL,
  141. // 0x01000000 - 0x08000000.
  142. NULL, 0, 0, NULL,
  143. NULL, 0, 0, NULL,
  144. NULL, 0, 0, NULL,
  145. NULL, 0, 0, NULL,
  146. NULL, 0, 0, NULL,
  147. NULL, 0, 0, NULL,
  148. NULL, 0, 0, NULL,
  149. NULL, 0, 0, NULL,
  150. // 0x10000000 - 0x80000000.
  151. "Internal event level command window text", 0, 0, NULL,
  152. "Internal event level command window text background", 0, 0, NULL,
  153. "Internal breakpoint level command window text", 0, 0, NULL,
  154. "Internal breakpoint level command window text background", 0, 0, NULL,
  155. "Internal remoting level command window text", 0, 0, NULL,
  156. "Internal remoting level command window text background", 0, 0, NULL,
  157. "Internal KD protocol level command window text", 0, 0, NULL,
  158. "Internal KD protocol level command window text background", 0, 0, NULL,
  159. // User-added text.
  160. "User-added command window text", 0, 0, NULL,
  161. "User-added command window text background", 0, 0, NULL,
  162. };
  163. COLORREF g_CustomColors[CUSTCOL_COUNT];
  164. void
  165. UpdateFrameTitle(void)
  166. {
  167. char Title[MAX_MSG_TXT + 2 * MAX_PATH + 32];
  168. Title[0] = 0;
  169. if (g_ExplicitTitle)
  170. {
  171. CatString(Title, g_TitleExtraText, DIMA(Title));
  172. CatString(Title, " - ", DIMA(Title));
  173. }
  174. else
  175. {
  176. if (g_TitleServerText[0])
  177. {
  178. CatString(Title, g_TitleServerText, DIMA(Title));
  179. CatString(Title, " - ", DIMA(Title));
  180. }
  181. if (g_TitleExtraText[0])
  182. {
  183. CatString(Title, g_TitleExtraText, DIMA(Title));
  184. CatString(Title, " - ", DIMA(Title));
  185. }
  186. }
  187. CatString(Title, g_MainTitleText, DIMA(Title));
  188. SetWindowText(g_hwndFrame, Title);
  189. }
  190. void
  191. SetTitleServerText(PCSTR Format, ...)
  192. {
  193. va_list Args;
  194. va_start(Args, Format);
  195. _vsnprintf(g_TitleServerText, sizeof(g_TitleServerText), Format, Args);
  196. g_TitleServerText[sizeof(g_TitleServerText) - 1] = 0;
  197. va_end(Args);
  198. UpdateFrameTitle();
  199. }
  200. void
  201. SetTitleSessionText(PCSTR Format, ...)
  202. {
  203. // Don't override an explicit title.
  204. if (g_ExplicitTitle)
  205. {
  206. return;
  207. }
  208. if (Format == NULL)
  209. {
  210. g_TitleExtraText[0] = 0;
  211. }
  212. else
  213. {
  214. va_list Args;
  215. va_start(Args, Format);
  216. _vsnprintf(g_TitleExtraText, sizeof(g_TitleExtraText), Format, Args);
  217. g_TitleExtraText[sizeof(g_TitleExtraText) - 1] = 0;
  218. va_end(Args);
  219. }
  220. UpdateFrameTitle();
  221. }
  222. void
  223. SetTitleExplicitText(PCSTR Text)
  224. {
  225. CopyString(g_TitleExtraText, Text, DIMA(g_TitleExtraText));
  226. g_ExplicitTitle = TRUE;
  227. UpdateFrameTitle();
  228. if (g_ExplicitWorkspace && g_Workspace != NULL)
  229. {
  230. g_Workspace->SetString(WSP_WINDOW_FRAME_TITLE, Text);
  231. }
  232. }
  233. void
  234. UpdateTitleSessionText(void)
  235. {
  236. if (!g_RemoteClient)
  237. {
  238. char ProcServer[MAX_CMDLINE_TXT];
  239. if (g_ProcessServer != NULL)
  240. {
  241. PrintString(ProcServer, DIMA(ProcServer),
  242. "[%s] ", g_ProcessServer);
  243. }
  244. else
  245. {
  246. ProcServer[0] = 0;
  247. }
  248. if (g_NumDumpFiles)
  249. {
  250. SetTitleSessionText("Dump %s", g_DumpFiles[0]);
  251. }
  252. else if (g_DebugCommandLine != NULL)
  253. {
  254. SetTitleSessionText("%s%s", ProcServer, g_DebugCommandLine);
  255. }
  256. else if (g_PidToDebug != 0)
  257. {
  258. SetTitleSessionText("%sPid %d", ProcServer, g_PidToDebug);
  259. }
  260. else if (g_ProcNameToDebug != NULL)
  261. {
  262. SetTitleSessionText("%sProcess %s", ProcServer, g_ProcNameToDebug);
  263. }
  264. else if (g_AttachKernelFlags == DEBUG_ATTACH_LOCAL_KERNEL)
  265. {
  266. SetTitleSessionText("Local kernel");
  267. }
  268. else if (g_AttachKernelFlags == DEBUG_ATTACH_EXDI_DRIVER)
  269. {
  270. SetTitleSessionText("eXDI '%s'",
  271. g_KernelConnectOptions);
  272. }
  273. else
  274. {
  275. SetTitleSessionText("Kernel '%s'",
  276. g_KernelConnectOptions);
  277. }
  278. }
  279. else
  280. {
  281. SetTitleSessionText("Remote '%s'", g_RemoteOptions);
  282. }
  283. }
  284. BOOL
  285. CreateUiInterfaces(
  286. BOOL Remote,
  287. LPTSTR CreateOptions
  288. )
  289. {
  290. HRESULT Status;
  291. //
  292. // Destroy the old interfaces if they existed.
  293. //
  294. ReleaseUiInterfaces();
  295. //
  296. // Create the new debugger interfaces the UI will use.
  297. //
  298. if (Remote)
  299. {
  300. if ((Status = DebugConnect(CreateOptions, IID_IDebugClient,
  301. (void **)&g_pUiClient)) != S_OK)
  302. {
  303. if (Status == E_INVALIDARG)
  304. {
  305. InformationBox(ERR_Invalid_Remote_Param);
  306. }
  307. else if (Status == RPC_E_VERSION_MISMATCH)
  308. {
  309. InformationBox(ERR_Remoting_Version_Mismatch);
  310. }
  311. else if (Status == RPC_E_SERVER_DIED ||
  312. Status == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) ||
  313. Status == HRESULT_FROM_WIN32(ERROR_BAD_NETPATH))
  314. {
  315. InformationBox(ERR_No_Remote_Server, CreateOptions);
  316. }
  317. else
  318. {
  319. InformationBox(ERR_Unable_To_Connect, CreateOptions,
  320. FormatStatusCode(Status), FormatStatus(Status));
  321. }
  322. return FALSE;
  323. }
  324. g_RemoteClient = TRUE;
  325. g_RemoteOptions = _tcsdup(CreateOptions);
  326. }
  327. else
  328. {
  329. if ((Status = DebugCreate(IID_IDebugClient,
  330. (void **)&g_pUiClient)) != S_OK)
  331. {
  332. InternalError(Status, "UI DebugCreate");
  333. return FALSE;
  334. }
  335. if (CreateOptions != NULL &&
  336. (Status = g_pUiClient->StartServer(CreateOptions)) != S_OK)
  337. {
  338. if (Status == E_INVALIDARG)
  339. {
  340. InformationBox(ERR_Invalid_Server_Param);
  341. }
  342. else if (Status == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) ||
  343. Status == HRESULT_FROM_WIN32(WSAEADDRINUSE))
  344. {
  345. InformationBox(ERR_Connection_In_Use);
  346. }
  347. else
  348. {
  349. InternalError(Status, "UI StartServer");
  350. }
  351. return FALSE;
  352. }
  353. }
  354. if ((Status = g_pUiClient->QueryInterface(IID_IDebugControl,
  355. (void **)&g_pUiControl)) != S_OK)
  356. {
  357. if (Status == RPC_E_VERSION_MISMATCH)
  358. {
  359. InformationBox(ERR_Remoting_Version_Mismatch);
  360. }
  361. else
  362. {
  363. InternalError(Status, "UI QueryControl");
  364. }
  365. return FALSE;
  366. }
  367. if ((Status = g_pUiClient->QueryInterface(IID_IDebugSymbols,
  368. (void **)&g_pUiSymbols)) != S_OK)
  369. {
  370. if (Status == RPC_E_VERSION_MISMATCH)
  371. {
  372. InformationBox(ERR_Remoting_Version_Mismatch);
  373. }
  374. else
  375. {
  376. InternalError(Status, "UI QuerySymbols");
  377. }
  378. return FALSE;
  379. }
  380. if ((Status = g_pUiClient->QueryInterface(IID_IDebugSystemObjects,
  381. (void **)&g_pUiSystem)) != S_OK)
  382. {
  383. if (Status == RPC_E_VERSION_MISMATCH)
  384. {
  385. InformationBox(ERR_Remoting_Version_Mismatch);
  386. }
  387. else
  388. {
  389. InternalError(Status, "UI QuerySystem");
  390. }
  391. return FALSE;
  392. }
  393. //
  394. // Optional interfaces.
  395. //
  396. if ((Status = g_pUiClient->
  397. QueryInterface(IID_IDebugSymbols2, (void **)&g_pUiSymbols2)) != S_OK)
  398. {
  399. g_pUiSymbols2 = NULL;
  400. }
  401. if ((Status = g_pUiClient->
  402. QueryInterface(IID_IDebugControl3, (void **)&g_pUiControl3)) != S_OK)
  403. {
  404. g_pUiControl3 = NULL;
  405. }
  406. if (g_RemoteClient)
  407. {
  408. // Create a local client to do local source file lookups.
  409. if ((Status = DebugCreate(IID_IDebugClient,
  410. (void **)&g_pUiLocClient)) != S_OK ||
  411. (Status = g_pUiLocClient->
  412. QueryInterface(IID_IDebugControl,
  413. (void **)&g_pUiLocControl)) != S_OK ||
  414. (Status = g_pUiLocClient->
  415. QueryInterface(IID_IDebugSymbols,
  416. (void **)&g_pUiLocSymbols)) != S_OK)
  417. {
  418. InternalError(Status, "UI local symbol object");
  419. return FALSE;
  420. }
  421. }
  422. else
  423. {
  424. g_pUiLocClient = g_pUiClient;
  425. g_pUiLocClient->AddRef();
  426. g_pUiLocControl = g_pUiControl;
  427. g_pUiLocControl->AddRef();
  428. g_pUiLocSymbols = g_pUiSymbols;
  429. g_pUiLocSymbols->AddRef();
  430. }
  431. return TRUE;
  432. }
  433. void
  434. ReleaseUiInterfaces(void)
  435. {
  436. RELEASE(g_pUiClient);
  437. RELEASE(g_pUiControl);
  438. RELEASE(g_pUiControl3);
  439. RELEASE(g_pUiSymbols);
  440. RELEASE(g_pUiSymbols2);
  441. RELEASE(g_pUiSystem);
  442. RELEASE(g_pUiLocClient);
  443. RELEASE(g_pUiLocControl);
  444. RELEASE(g_pUiLocSymbols);
  445. }
  446. PTSTR
  447. GetArg(
  448. PTSTR *lpp
  449. )
  450. {
  451. static PTSTR pszBuffer = NULL;
  452. int r;
  453. PTSTR p1 = *lpp;
  454. while (*p1 == _T(' ') || *p1 == _T('\t'))
  455. {
  456. p1++;
  457. }
  458. if (pszBuffer)
  459. {
  460. free(pszBuffer);
  461. }
  462. pszBuffer = (PTSTR) calloc(_tcslen(p1) + 1, sizeof(TCHAR));
  463. if (pszBuffer == NULL)
  464. {
  465. ErrorExit(NULL, "Unable to allocate command line argument\n");
  466. }
  467. r = CPCopyString(&p1, pszBuffer, 0, (*p1 == _T('\'') || *p1 == _T('"') ));
  468. if (r >= 0)
  469. {
  470. *lpp = p1;
  471. }
  472. return pszBuffer;
  473. }
  474. BOOL
  475. ParseCommandLine(BOOL FirstParse)
  476. {
  477. PTSTR lp1 = GetCommandLine();
  478. PTSTR lp2 = NULL;
  479. int Starts;
  480. HRESULT Status;
  481. g_CommandLineStart = 0;
  482. g_EngOptModified = 0;
  483. // skip whitespace
  484. while (*lp1 == _T(' ') || *lp1 == _T('\t'))
  485. {
  486. lp1++;
  487. }
  488. // skip over our program name
  489. if (_T('"') != *lp1)
  490. {
  491. lp1 += _tcslen(g_ProgramName);
  492. }
  493. else
  494. {
  495. // The program name is quoted. This is a tough thing
  496. // to parse through as the system allows a lot of weird
  497. // quote placement and no trailing quote is required.
  498. // Once we skip ahead by the program name we continue
  499. // to whitespace on the theory that the program
  500. // name and the first argument must be separated by whitespace
  501. // at some point.
  502. lp1 += _tcslen(g_ProgramName) + 1;
  503. while (*lp1 && *lp1 != _T(' ') && *lp1 != _T('\t'))
  504. {
  505. lp1++;
  506. }
  507. }
  508. while (*lp1)
  509. {
  510. if (*lp1 == _T(' ') || *lp1 == _T('\t'))
  511. {
  512. lp1++;
  513. continue;
  514. }
  515. if (*lp1 == _T('-') || *lp1 == _T('/'))
  516. {
  517. ++lp1;
  518. switch (*lp1++)
  519. {
  520. case _T('?'):
  521. usage:
  522. SpawnHelp(HELP_TOPIC_COMMAND_LINE_WINDBG);
  523. exit(1);
  524. case _T(' '):
  525. case _T('\t'):
  526. break;
  527. case 'a':
  528. ULONG64 ExtHandle;
  529. lp2 = GetArg(&lp1);
  530. g_pUiControl->AddExtension(lp2, DEBUG_EXTENSION_AT_ENGINE,
  531. &ExtHandle);
  532. break;
  533. case _T('b'):
  534. g_pUiControl->AddEngineOptions(DEBUG_ENGOPT_INITIAL_BREAK);
  535. if (g_RemoteClient)
  536. {
  537. // The engine may already be waiting so just ask
  538. // for a breakin immediately.
  539. g_pUiControl->SetInterrupt(DEBUG_INTERRUPT_ACTIVE);
  540. }
  541. g_EngOptModified |= DEBUG_ENGOPT_INITIAL_BREAK;
  542. break;
  543. case _T('c'):
  544. lp2 = lp1;
  545. while (*lp2 && *lp2 != ' ' && *lp2 != '\t')
  546. {
  547. lp2++;
  548. }
  549. if (lp2 == lp1 + 5 &&
  550. !memcmp(lp1, "lines", 5))
  551. {
  552. lp1 = lp2;
  553. g_HistoryLines = atoi(GetArg(&lp1));
  554. }
  555. else
  556. {
  557. g_InitialCommand = _tcsdup(GetArg(&lp1));
  558. }
  559. break;
  560. case _T('d'):
  561. g_pUiControl->
  562. AddEngineOptions(DEBUG_ENGOPT_INITIAL_MODULE_BREAK);
  563. g_EngOptModified |= DEBUG_ENGOPT_INITIAL_MODULE_BREAK;
  564. break;
  565. case _T('e'):
  566. lp2 = lp1;
  567. while (*lp2 && *lp2 != ' ' && *lp2 != '\t')
  568. {
  569. lp2++;
  570. }
  571. if (lp2 == lp1 + 1 &&
  572. *lp1 == _T('e'))
  573. {
  574. if (!g_pUiControl3)
  575. {
  576. goto usage;
  577. }
  578. lp1 = lp2;
  579. if (g_pUiControl3->
  580. SetExpressionSyntaxByName(GetArg(&lp1)) != S_OK)
  581. {
  582. goto usage;
  583. }
  584. }
  585. else
  586. {
  587. // Signal an event after process is attached.
  588. g_pUiControl->SetNotifyEventHandle(_atoi64(GetArg(&lp1)));
  589. }
  590. break;
  591. case _T('f'):
  592. lp2 = lp1;
  593. while (*lp2 && *lp2 != ' ' && *lp2 != '\t')
  594. {
  595. lp2++;
  596. }
  597. if (lp2 != lp1 + 6 ||
  598. memcmp(lp1, "ailinc", 6))
  599. {
  600. goto usage;
  601. }
  602. lp1 = lp2;
  603. g_pUiControl->
  604. AddEngineOptions(DEBUG_ENGOPT_FAIL_INCOMPLETE_INFORMATION);
  605. g_pUiSymbols->
  606. AddSymbolOptions(SYMOPT_EXACT_SYMBOLS);
  607. break;
  608. case _T('g'):
  609. g_pUiControl->
  610. RemoveEngineOptions(DEBUG_ENGOPT_INITIAL_BREAK);
  611. g_EngOptModified |= DEBUG_ENGOPT_INITIAL_BREAK;
  612. break;
  613. case _T('G'):
  614. g_pUiControl->
  615. RemoveEngineOptions(DEBUG_ENGOPT_FINAL_BREAK);
  616. g_EngOptModified |= DEBUG_ENGOPT_FINAL_BREAK;
  617. break;
  618. case _T('h'):
  619. if (*lp1 == _T('d'))
  620. {
  621. lp1++;
  622. g_DebugCreateFlags |=
  623. DEBUG_CREATE_PROCESS_NO_DEBUG_HEAP;
  624. }
  625. else
  626. {
  627. goto usage;
  628. }
  629. break;
  630. case _T('i'):
  631. g_pUiSymbols->SetImagePath(GetArg(&lp1));
  632. break;
  633. case _T('I'):
  634. if (!InstallAsAeDebug(NULL))
  635. {
  636. InformationBox(ERR_Fail_Inst_Postmortem_Dbg);
  637. }
  638. else
  639. {
  640. InformationBox(ERR_Success_Inst_Postmortem_Dbg);
  641. exit(1);
  642. }
  643. break;
  644. // XXX AndreVa - This needs to be checked before we start
  645. // the GUI.
  646. case _T('J'):
  647. case _T('j'):
  648. g_AllowJournaling = TRUE;
  649. break;
  650. case _T('k'):
  651. if (*lp1 == _T('l'))
  652. {
  653. g_AttachKernelFlags = DEBUG_ATTACH_LOCAL_KERNEL;
  654. lp1++;
  655. }
  656. else if (*lp1 == _T('x'))
  657. {
  658. g_AttachKernelFlags = DEBUG_ATTACH_EXDI_DRIVER;
  659. lp1++;
  660. g_KernelConnectOptions = _tcsdup(GetArg(&lp1));
  661. }
  662. else
  663. {
  664. g_KernelConnectOptions = _tcsdup(GetArg(&lp1));
  665. }
  666. g_CommandLineStart++;
  667. break;
  668. case _T('l'):
  669. lp2 = lp1;
  670. while (*lp2 && *lp2 != ' ' && *lp2 != '\t')
  671. {
  672. lp2++;
  673. }
  674. if (lp2 == lp1 + 3 &&
  675. (!memcmp(lp1, "oga", 3) ||
  676. !memcmp(lp1, "ogo", 3)))
  677. {
  678. lp1 = lp2;
  679. g_pUiControl->OpenLogFile(GetArg(&lp1), *(lp2 - 1) == 'a');
  680. break;
  681. }
  682. else
  683. {
  684. goto usage;
  685. }
  686. break;
  687. case _T('n'):
  688. lp2 = lp1;
  689. while (*lp2 && *lp2 != ' ' && *lp2 != '\t')
  690. {
  691. lp2++;
  692. }
  693. if (lp2 == lp1 + 6 &&
  694. !memcmp(lp1, "oshell", 6))
  695. {
  696. lp1 = lp2;
  697. g_pUiControl->AddEngineOptions
  698. (DEBUG_ENGOPT_DISALLOW_SHELL_COMMANDS);
  699. break;
  700. }
  701. else
  702. {
  703. g_pUiSymbols->AddSymbolOptions(SYMOPT_DEBUG);
  704. }
  705. break;
  706. case _T('o'):
  707. if (g_RemoteClient)
  708. {
  709. goto usage;
  710. }
  711. g_DebugCreateFlags |= DEBUG_PROCESS;
  712. g_DebugCreateFlags &= ~DEBUG_ONLY_THIS_PROCESS;
  713. break;
  714. case _T('p'):
  715. // attach to an active process
  716. // p specifies a process id
  717. // pn specifies a process by name
  718. // ie: -p 360
  719. // -pn _T("foo bar")
  720. if (!isspace(*lp1) && !isdigit(*lp1))
  721. {
  722. // They may have specified a -p flag with
  723. // a tail such as -premote.
  724. lp2 = lp1;
  725. while (*lp2 && *lp2 != ' ' && *lp2 != '\t')
  726. {
  727. lp2++;
  728. }
  729. if (lp2 == lp1 + 6 &&
  730. !memcmp(lp1, "remote", 6))
  731. {
  732. lp1 = lp2;
  733. g_ProcessServer = _tcsdup(GetArg(&lp1));
  734. break;
  735. }
  736. else if (_T('b') == *lp1)
  737. {
  738. lp1++;
  739. g_AttachProcessFlags |=
  740. DEBUG_ATTACH_INVASIVE_NO_INITIAL_BREAK;
  741. break;
  742. }
  743. else if (_T('d') == *lp1)
  744. {
  745. lp1++;
  746. g_DetachOnExit = TRUE;
  747. break;
  748. }
  749. else if (_T('e') == *lp1)
  750. {
  751. lp1++;
  752. g_AttachProcessFlags = DEBUG_ATTACH_EXISTING;
  753. break;
  754. }
  755. else if (_T('r') == *lp1)
  756. {
  757. lp1++;
  758. g_AttachProcessFlags |=
  759. DEBUG_ATTACH_INVASIVE_RESUME_PROCESS;
  760. break;
  761. }
  762. else if (_T('t') == *lp1)
  763. {
  764. lp1++;
  765. g_pUiControl->
  766. SetInterruptTimeout(atoi(GetArg(&lp1)));
  767. break;
  768. }
  769. else if (_T('v') == *lp1)
  770. {
  771. lp1++;
  772. g_AttachProcessFlags = DEBUG_ATTACH_NONINVASIVE;
  773. if (_T('r') == *lp1)
  774. {
  775. lp1++;
  776. g_AttachProcessFlags |=
  777. DEBUG_ATTACH_NONINVASIVE_NO_SUSPEND;
  778. }
  779. break;
  780. }
  781. else if (_T('n') != *lp1)
  782. {
  783. goto usage;
  784. }
  785. else
  786. {
  787. // Skip the _T('n')
  788. lp1++;
  789. g_ProcNameToDebug = _tcsdup(GetArg(&lp1));
  790. }
  791. }
  792. else
  793. {
  794. // They specified -p 360
  795. g_PidToDebug = strtoul(GetArg(&lp1), NULL, 0);
  796. if (g_PidToDebug <= 0)
  797. {
  798. g_PidToDebug = -2;
  799. ErrorBox(NULL, 0, ERR_Invalid_Process_Id,
  800. g_PidToDebug);
  801. }
  802. }
  803. g_CommandLineStart++;
  804. break;
  805. case _T('Q'):
  806. if (*lp1 == 'S')
  807. {
  808. lp1++;
  809. if (*lp1 == 'Y')
  810. {
  811. lp1++;
  812. g_QuietSourceMode = QMODE_ALWAYS_YES;
  813. }
  814. else if (!*lp1 || isspace(*lp1))
  815. {
  816. g_QuietSourceMode = QMODE_ALWAYS_NO;
  817. }
  818. else
  819. {
  820. goto usage;
  821. }
  822. }
  823. else if (*lp1 == 'Y')
  824. {
  825. lp1++;
  826. g_QuietMode = QMODE_ALWAYS_YES;
  827. }
  828. else if (!*lp1 || isspace(*lp1))
  829. {
  830. g_QuietMode = QMODE_ALWAYS_NO;
  831. }
  832. else
  833. {
  834. goto usage;
  835. }
  836. break;
  837. case _T('r'):
  838. lp2 = lp1;
  839. while (*lp2 && *lp2 != ' ' && *lp2 != '\t')
  840. {
  841. lp2++;
  842. }
  843. if (lp2 == lp1 + 3 &&
  844. !memcmp(lp1, "obp", 3))
  845. {
  846. lp1 = lp2;
  847. g_pUiControl->AddEngineOptions
  848. (DEBUG_ENGOPT_ALLOW_READ_ONLY_BREAKPOINTS);
  849. break;
  850. }
  851. else if (lp2 != lp1 + 5 ||
  852. memcmp(lp1, "emote", 5))
  853. {
  854. goto usage;
  855. }
  856. lp1 = lp2;
  857. lp2 = GetArg(&lp1);
  858. if (!CreateUiInterfaces(TRUE, lp2))
  859. {
  860. return FALSE;
  861. }
  862. g_CommandLineStart++;
  863. break;
  864. case _T('s'):
  865. lp2 = lp1;
  866. while (*lp2 && *lp2 != ' ' && *lp2 != '\t')
  867. {
  868. lp2++;
  869. }
  870. if (lp2 == lp1 + 5 &&
  871. !memcmp(lp1, "erver", 5))
  872. {
  873. lp1 = lp2;
  874. lp2 = GetArg(&lp1);
  875. if (!CreateUiInterfaces(FALSE, lp2))
  876. {
  877. return FALSE;
  878. }
  879. SetTitleServerText("Server '%s'", lp2);
  880. }
  881. else if (lp2 == lp1 + 3 &&
  882. !memcmp(lp1, "dce", 3))
  883. {
  884. lp1 = lp2;
  885. g_pUiSymbols->
  886. RemoveSymbolOptions(SYMOPT_FAIL_CRITICAL_ERRORS);
  887. }
  888. else if (lp2 == lp1 + 5 &&
  889. !memcmp(lp1, "ecure", 5))
  890. {
  891. lp1 = lp2;
  892. if (g_pUiSymbols->
  893. AddSymbolOptions(SYMOPT_SECURE) != S_OK)
  894. {
  895. ErrorBox(NULL, 0, ERR_Cant_Secure);
  896. return FALSE;
  897. }
  898. }
  899. else if (lp2 == lp1 + 2 &&
  900. !memcmp(lp1, "es", 2))
  901. {
  902. lp1 = lp2;
  903. g_pUiSymbols->
  904. AddSymbolOptions(SYMOPT_EXACT_SYMBOLS);
  905. }
  906. else if (lp2 == lp1 + 3 &&
  907. !memcmp(lp1, "fce", 3))
  908. {
  909. lp1 = lp2;
  910. g_pUiSymbols->
  911. AddSymbolOptions(SYMOPT_FAIL_CRITICAL_ERRORS);
  912. }
  913. else if (lp2 == lp1 + 5 &&
  914. !memcmp(lp1, "flags", 5))
  915. {
  916. lp1 = lp2;
  917. lp2 = GetArg(&lp1);
  918. g_pUiSymbols->
  919. SetSymbolOptions(strtoul(lp2, NULL, 0));
  920. }
  921. else if (lp2 == lp1 + 3 &&
  922. !memcmp(lp1, "icv", 3))
  923. {
  924. lp1 = lp2;
  925. g_pUiSymbols->AddSymbolOptions(SYMOPT_IGNORE_CVREC);
  926. }
  927. else if (lp2 == lp1 + 3 &&
  928. !memcmp(lp1, "ins", 3))
  929. {
  930. lp1 = lp2;
  931. g_pUiSymbols->AddSymbolOptions(SYMOPT_IGNORE_NT_SYMPATH);
  932. }
  933. else if (lp2 == lp1 + 2 &&
  934. !memcmp(lp1, "nc", 2))
  935. {
  936. lp1 = lp2;
  937. g_pUiSymbols->
  938. AddSymbolOptions(SYMOPT_NO_CPP);
  939. }
  940. else if (lp2 == lp1 + 3 &&
  941. !memcmp(lp1, "nul", 3))
  942. {
  943. lp1 = lp2;
  944. g_pUiSymbols->
  945. AddSymbolOptions(SYMOPT_NO_UNQUALIFIED_LOADS);
  946. }
  947. else if (lp2 == lp1 + 2 &&
  948. !memcmp(lp1, "up", 2))
  949. {
  950. lp1 = lp2;
  951. g_pUiSymbols->
  952. RemoveSymbolOptions(SYMOPT_AUTO_PUBLICS |
  953. SYMOPT_NO_PUBLICS);
  954. }
  955. else if (lp2 == lp1 + 6 &&
  956. !memcmp(lp1, "rcpath", 6))
  957. {
  958. lp1 = lp2;
  959. g_pUiSymbols->SetSourcePath(GetArg(&lp1));
  960. }
  961. else
  962. {
  963. goto usage;
  964. }
  965. break;
  966. case _T('T'):
  967. lp2 = GetArg(&lp1);
  968. SetTitleExplicitText(lp2);
  969. break;
  970. case _T('v'):
  971. g_Verbose = TRUE;
  972. break;
  973. case _T('w'):
  974. lp2 = lp1;
  975. while (*lp2 && *lp2 != ' ' && *lp2 != '\t')
  976. {
  977. lp2++;
  978. }
  979. if (lp2 == lp1 + 3 &&
  980. !memcmp(lp1, "ake", 3))
  981. {
  982. ULONG Pid;
  983. lp1 = lp2;
  984. Pid = strtoul(GetArg(&lp1), NULL, 0);
  985. if (!SetPidEvent(Pid, OPEN_EXISTING))
  986. {
  987. InformationBox(ERR_Wake_Failed, Pid);
  988. ErrorExit(NULL,
  989. "Process %d is not a sleeping debugger\n",
  990. Pid);
  991. }
  992. else
  993. {
  994. ExitDebugger(NULL, 0);
  995. }
  996. }
  997. break;
  998. case _T('W'):
  999. if (*lp1 == _T('F'))
  1000. {
  1001. lp1++;
  1002. lp2 = GetArg(&lp1);
  1003. if ((Status =
  1004. UiSwitchWorkspace(WSP_NAME_FILE, lp2,
  1005. WSP_CREATE_QUERY,
  1006. WSP_APPLY_EXPLICIT,
  1007. &Starts)) != S_OK)
  1008. {
  1009. InformationBox(ERR_Cant_Open_Workspace,
  1010. FormatStatusCode(Status),
  1011. FormatStatus(Status));
  1012. ExitDebugger(NULL, 0);
  1013. }
  1014. g_CommandLineStart += Starts;
  1015. }
  1016. else if (*lp1 != _T('X'))
  1017. {
  1018. lp2 = GetArg(&lp1);
  1019. if ((Status =
  1020. UiSwitchWorkspace(WSP_NAME_EXPLICIT, lp2,
  1021. WSP_CREATE_QUERY,
  1022. WSP_APPLY_EXPLICIT,
  1023. &Starts)) != S_OK)
  1024. {
  1025. InformationBox(ERR_Cant_Open_Workspace,
  1026. FormatStatusCode(Status),
  1027. FormatStatus(Status));
  1028. ExitDebugger(NULL, 0);
  1029. }
  1030. g_CommandLineStart += Starts;
  1031. }
  1032. else
  1033. {
  1034. // Skip X.
  1035. lp1++;
  1036. if (g_Workspace != NULL)
  1037. {
  1038. g_Workspace->Flush(FALSE, FALSE);
  1039. delete g_Workspace;
  1040. }
  1041. g_Workspace = NULL;
  1042. }
  1043. g_ExplicitWorkspace = TRUE;
  1044. break;
  1045. case _T('y'):
  1046. g_pUiSymbols->SetSymbolPath(GetArg(&lp1));
  1047. break;
  1048. case _T('z'):
  1049. if (*lp1 == _T('p'))
  1050. {
  1051. lp1++;
  1052. lp2 = GetArg(&lp1);
  1053. if (g_NumDumpInfoFiles == MAX_DUMP_FILES)
  1054. {
  1055. InformationBox(ERR_Too_Many_Dump_Files, lp2);
  1056. }
  1057. else
  1058. {
  1059. g_DumpInfoFiles[g_NumDumpInfoFiles] = _tcsdup(lp2);
  1060. g_DumpInfoTypes[g_NumDumpInfoFiles] =
  1061. DEBUG_DUMP_FILE_PAGE_FILE_DUMP;
  1062. g_NumDumpInfoFiles++;
  1063. }
  1064. }
  1065. else if (*lp1 && *lp1 != _T(' ') && *lp1 != _T('\t'))
  1066. {
  1067. goto usage;
  1068. }
  1069. else
  1070. {
  1071. lp2 = GetArg(&lp1);
  1072. if (g_NumDumpFiles == MAX_DUMP_FILES)
  1073. {
  1074. InformationBox(ERR_Too_Many_Dump_Files, lp2);
  1075. }
  1076. else
  1077. {
  1078. g_DumpFiles[g_NumDumpFiles] = _tcsdup(lp2);
  1079. if (++g_NumDumpFiles == 1)
  1080. {
  1081. g_CommandLineStart++;
  1082. }
  1083. }
  1084. }
  1085. break;
  1086. default:
  1087. --lp1;
  1088. goto usage;
  1089. }
  1090. }
  1091. else
  1092. {
  1093. // pick up file args. If it is a program name,
  1094. // keep the tail of the cmd line intact.
  1095. g_DebugCommandLine = _tcsdup(lp1);
  1096. g_CommandLineStart++;
  1097. break;
  1098. }
  1099. }
  1100. //
  1101. // If a command line start option was set, we can just start the engine
  1102. // right away. Otherwise, we have to wait for user input.
  1103. //
  1104. // If multiple command line option were set, print an error.
  1105. //
  1106. if (g_CommandLineStart == 1)
  1107. {
  1108. PostMessage(g_hwndFrame, WU_START_ENGINE, 0, 0);
  1109. }
  1110. else if (g_CommandLineStart > 1)
  1111. {
  1112. ErrorBox(NULL, 0, ERR_Invalid_Command_Line);
  1113. return FALSE;
  1114. }
  1115. return TRUE;
  1116. }
  1117. void
  1118. StopDebugging(BOOL UserRequest)
  1119. {
  1120. // Flush the current workspace first so
  1121. // the engine thread doesn't.
  1122. if (g_Workspace != NULL &&
  1123. g_Workspace->Flush(FALSE, FALSE) == S_FALSE)
  1124. {
  1125. // User cancelled things so don't terminate. We
  1126. // don't offer that option right now so this
  1127. // should never happen.
  1128. return;
  1129. }
  1130. if (g_EngineThreadId)
  1131. {
  1132. DWORD WaitStatus;
  1133. if (UserRequest)
  1134. {
  1135. if (!g_RemoteClient)
  1136. {
  1137. // Try to get the current engine operation stopped.
  1138. g_pUiControl->SetInterrupt(DEBUG_INTERRUPT_EXIT);
  1139. }
  1140. // If this stop is coming from the UI thread
  1141. // clean up the current session.
  1142. AddEnumCommand(UIC_END_SESSION);
  1143. }
  1144. for (;;)
  1145. {
  1146. // Wait for the engine thread to finish.
  1147. WaitStatus = WaitForSingleObject(g_EngineThread, 30000);
  1148. if (WaitStatus != WAIT_TIMEOUT)
  1149. {
  1150. break;
  1151. }
  1152. else
  1153. {
  1154. // Engine is still busy. If the user requested
  1155. // the stop, ask the user whether they want to keep
  1156. // waiting. If they don't they'll have to exit
  1157. // windbg as the engine must be available in
  1158. // order to restart anything. If this is a stop
  1159. // from the engine thread itself it should have
  1160. // finished up by now, so something is wrong.
  1161. // For now give the user the same option but
  1162. // in the future we might want to have special
  1163. // behavior.
  1164. if (QuestionBox(STR_Engine_Still_Busy, MB_YESNO) == IDNO)
  1165. {
  1166. ExitDebugger(g_pUiClient, 0);
  1167. }
  1168. if (UserRequest)
  1169. {
  1170. // Try again to get the engine to stop.
  1171. g_pUiControl->SetInterrupt(DEBUG_INTERRUPT_EXIT);
  1172. }
  1173. }
  1174. }
  1175. }
  1176. if (g_EngineThread != NULL)
  1177. {
  1178. CloseHandle(g_EngineThread);
  1179. g_EngineThread = NULL;
  1180. }
  1181. CloseAllWindows(ALL_WINDOWS);
  1182. if (!CreateUiInterfaces(FALSE, NULL))
  1183. {
  1184. InternalError(E_OUTOFMEMORY, "CreateUiInterfaces");
  1185. ErrorExit(NULL, "Unable to recreate UI interfaces\n");
  1186. }
  1187. ClearDebuggingParams();
  1188. SetTitleSessionText(NULL);
  1189. // Any changes caused by shutting things down
  1190. // are not user changes and can be ignored.
  1191. if (g_Workspace != NULL)
  1192. {
  1193. g_Workspace->ClearDirty();
  1194. }
  1195. if (!g_ExplicitWorkspace)
  1196. {
  1197. UiSwitchWorkspace(WSP_NAME_BASE, g_WorkspaceDefaultName,
  1198. WSP_CREATE_ALWAYS, WSP_APPLY_DEFAULT, NULL);
  1199. }
  1200. SetLineColumn_StatusBar(0, 0);
  1201. SetSysPidTid_StatusBar(0, "<None>", 0, 0, 0, 0);
  1202. EnableToolbarControls();
  1203. }
  1204. void
  1205. ClearDebuggingParams(void)
  1206. {
  1207. ULONG i;
  1208. //
  1209. // Reset all session starting values.
  1210. //
  1211. // Do not clear the process server value here
  1212. // as the UI doesn't offer any way to set it
  1213. // so just let the command line setting persist
  1214. // for the entire run of the process.
  1215. //
  1216. g_AttachKernelFlags = 0;
  1217. free(g_KernelConnectOptions);
  1218. g_KernelConnectOptions = NULL;
  1219. g_PidToDebug = 0;
  1220. free(g_ProcNameToDebug);
  1221. g_ProcNameToDebug = NULL;
  1222. for (i = 0; i < g_NumDumpFiles; i++)
  1223. {
  1224. free(g_DumpFiles[i]);
  1225. g_DumpFiles[i] = NULL;
  1226. }
  1227. g_NumDumpFiles = 0;
  1228. for (i = 0; i < g_NumDumpInfoFiles; i++)
  1229. {
  1230. free(g_DumpInfoFiles[i]);
  1231. g_DumpInfoFiles[i] = NULL;
  1232. }
  1233. g_NumDumpInfoFiles = 0;
  1234. free(g_DebugCommandLine);
  1235. g_DebugCommandLine = NULL;
  1236. free(g_ProcessStartDir);
  1237. g_ProcessStartDir = NULL;
  1238. g_DebugCreateFlags = DEBUG_ONLY_THIS_PROCESS;
  1239. g_RemoteClient = FALSE;
  1240. free(g_RemoteOptions);
  1241. g_RemoteOptions = NULL;
  1242. g_DetachOnExit = FALSE;
  1243. g_AttachProcessFlags = DEBUG_ATTACH_DEFAULT;
  1244. }
  1245. void
  1246. InitDefaults(
  1247. void
  1248. )
  1249. {
  1250. SetSrcMode_StatusBar(TRUE);
  1251. }
  1252. INDEXED_COLOR*
  1253. GetIndexedColor(ULONG Index)
  1254. {
  1255. if (Index < OUT_MASK_COL_BASE)
  1256. {
  1257. if (Index >= COL_COUNT)
  1258. {
  1259. return NULL;
  1260. }
  1261. return g_Colors + Index;
  1262. }
  1263. else
  1264. {
  1265. Index -= OUT_MASK_COL_BASE;
  1266. if (Index >= OUT_MASK_COL_COUNT ||
  1267. g_OutMaskColors[Index].Name == NULL)
  1268. {
  1269. return NULL;
  1270. }
  1271. return g_OutMaskColors + Index;
  1272. }
  1273. }
  1274. BOOL
  1275. SetColor(ULONG Index, COLORREF Color)
  1276. {
  1277. INDEXED_COLOR* IdxCol = GetIndexedColor(Index);
  1278. if (IdxCol == NULL)
  1279. {
  1280. return FALSE;
  1281. }
  1282. if (IdxCol->Brush != NULL)
  1283. {
  1284. DeleteObject(IdxCol->Brush);
  1285. }
  1286. IdxCol->Color = Color;
  1287. IdxCol->Brush = CreateSolidBrush(IdxCol->Color);
  1288. // A UI color selection changing means the UI needs to refresh.
  1289. // Out mask color changes only apply to new text and do
  1290. // not need a refresh.
  1291. return Index < COL_COUNT ? TRUE : FALSE;
  1292. }
  1293. BOOL
  1294. GetOutMaskColors(ULONG Mask, COLORREF* Fg, COLORREF* Bg)
  1295. {
  1296. if (Mask == 0)
  1297. {
  1298. return FALSE;
  1299. }
  1300. ULONG Idx = 0;
  1301. while ((Mask & 1) == 0)
  1302. {
  1303. Idx++;
  1304. Mask >>= 1;
  1305. }
  1306. Idx *= 2;
  1307. if (g_OutMaskColors[Idx].Name == NULL)
  1308. {
  1309. return FALSE;
  1310. }
  1311. *Fg = g_OutMaskColors[Idx].Color;
  1312. *Bg = g_OutMaskColors[Idx + 1].Color;
  1313. return TRUE;
  1314. }
  1315. void
  1316. InitColors(void)
  1317. {
  1318. g_Colors[COL_PLAIN].Default =
  1319. GetSysColor(COLOR_WINDOW);
  1320. g_Colors[COL_PLAIN_TEXT].Default =
  1321. GetSysColor(COLOR_WINDOWTEXT);
  1322. g_Colors[COL_CURRENT_LINE].Default =
  1323. GetSysColor(COLOR_HIGHLIGHT);
  1324. g_Colors[COL_CURRENT_LINE_TEXT].Default =
  1325. GetSysColor(COLOR_HIGHLIGHTTEXT);
  1326. g_Colors[COL_BP_CURRENT_LINE_TEXT].Default =
  1327. GetSysColor(COLOR_HIGHLIGHTTEXT);
  1328. g_Colors[COL_ENABLED_BP_TEXT].Default =
  1329. GetSysColor(COLOR_HIGHLIGHTTEXT);
  1330. g_Colors[COL_DISABLED_BP_TEXT].Default =
  1331. GetSysColor(COLOR_HIGHLIGHTTEXT);
  1332. g_Colors[COL_DISABLED_WINDOW].Default =
  1333. GetSysColor(COLOR_3DFACE);
  1334. ULONG i;
  1335. for (i = 0; i < COL_COUNT; i++)
  1336. {
  1337. SetColor(i, g_Colors[i].Default);
  1338. }
  1339. for (i = 0; i < OUT_MASK_COL_COUNT; i++)
  1340. {
  1341. if (g_OutMaskColors[i].Name != NULL)
  1342. {
  1343. g_OutMaskColors[i].Default =
  1344. GetSysColor((i & 1) ? COLOR_WINDOW : COLOR_WINDOWTEXT);
  1345. SetColor(i + OUT_MASK_COL_BASE, g_OutMaskColors[i].Default);
  1346. }
  1347. }
  1348. for (i = 0; i < CUSTCOL_COUNT; i++)
  1349. {
  1350. g_CustomColors[i] = GetSysColor(i + 1);
  1351. }
  1352. }
  1353. BOOL
  1354. InitGUI(
  1355. VOID
  1356. )
  1357. /*++
  1358. Routine Description:
  1359. Initialize the GUI components of WinDBG so we can bring up
  1360. the parent MDI window with the top level menus.
  1361. Arguments:
  1362. Return Value:
  1363. TRUE if everything is OK, FALSE if something fails
  1364. --*/
  1365. {
  1366. WNDCLASSEX wcex = {0};
  1367. TCHAR szClassName[MAX_MSG_TXT];
  1368. INITCOMMONCONTROLSEX InitCtrls =
  1369. {
  1370. sizeof(InitCtrls), ICC_WIN95_CLASSES | ICC_COOL_CLASSES |
  1371. ICC_USEREX_CLASSES
  1372. };
  1373. // Journaling is a feature that applications, such as Visual Test, can
  1374. // enable to synchronize all message queues.
  1375. // In order to allow WinDBG to debug an app such as Visual Test, we
  1376. // provide the option to disable journaling, which ensures WinDBG
  1377. // has its own message queue at all times.
  1378. //
  1379. // Should journaling be allowed or disabled?
  1380. //
  1381. if (g_AllowJournaling == FALSE)
  1382. {
  1383. #define RST_DONTJOURNALATTACH 0x00000002
  1384. typedef VOID (WINAPI * RST)(DWORD,DWORD);
  1385. RST Rst = (RST) GetProcAddress( GetModuleHandle( _T("user32.dll") ),
  1386. "RegisterSystemThread" );
  1387. if (Rst)
  1388. {
  1389. (Rst) (RST_DONTJOURNALATTACH, 0);
  1390. }
  1391. }
  1392. // Load the richedit 2.0 dll so that it can register the window class.
  1393. // We require RichEdit 2 and cannot use RichEdit 1.
  1394. // Since we intentionally need this library the entire duration, we
  1395. // simply load it and lose the handle to it. We are in win32 and running
  1396. // separate address spaces, and don't have to worry about freeing the
  1397. // library.
  1398. if (!LoadLibrary(_T("RICHED20.DLL")))
  1399. {
  1400. return FALSE;
  1401. }
  1402. if ( !InitCommonControlsEx( &InitCtrls ))
  1403. {
  1404. return FALSE;
  1405. }
  1406. //We use tmp strings as edit buffers
  1407. Assert(MAX_LINE_SIZE < TMP_STRING_SIZE);
  1408. Dbg(LoadString(g_hInst, SYS_Main_wTitle,
  1409. g_MainTitleText, _tsizeof(g_MainTitleText)));
  1410. Dbg(LoadString(g_hInst, SYS_Main_wClass,
  1411. szClassName, _tsizeof(szClassName) ));
  1412. //Register the main window szClassName
  1413. wcex.cbSize = sizeof(wcex);
  1414. wcex.style = 0;
  1415. wcex.lpfnWndProc = MainWndProc;
  1416. wcex.cbClsExtra = 0;
  1417. wcex.cbWndExtra = 0;
  1418. wcex.hInstance = g_hInst;
  1419. wcex.hIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(WINDBGICON) );
  1420. wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
  1421. wcex.hbrBackground = (HBRUSH) (COLOR_ACTIVEBORDER + 1);
  1422. wcex.lpszMenuName = MAKEINTRESOURCE(MAIN_MENU);
  1423. wcex.lpszClassName = szClassName;
  1424. wcex.hIconSm = LoadIcon(g_hInst, MAKEINTRESOURCE(WINDBGICON) );
  1425. if (!RegisterClassEx (&wcex) )
  1426. {
  1427. return FALSE;
  1428. }
  1429. //
  1430. // Generic MDI child window. Channels all processing
  1431. // through the COMMONWIN abstraction.
  1432. //
  1433. Dbg(LoadString(g_hInst, SYS_CommonWin_wClass,
  1434. szClassName, _tsizeof(szClassName)));
  1435. wcex.cbSize = sizeof(wcex);
  1436. wcex.style = 0;
  1437. wcex.lpfnWndProc = COMMONWIN_DATA::WindowProc;
  1438. wcex.cbClsExtra = 0;
  1439. wcex.cbWndExtra = 0;
  1440. wcex.hInstance = g_hInst;
  1441. wcex.hIcon = NULL;
  1442. // The cursor is set to SIZENS so that the proper
  1443. // cursor appears in the command window splitter area.
  1444. // All other areas are covered by child windows with
  1445. // their own cursors.
  1446. wcex.hCursor = LoadCursor(NULL, IDC_SIZENS);
  1447. wcex.hbrBackground = (HBRUSH) (COLOR_ACTIVEBORDER + 1);
  1448. wcex.lpszMenuName = NULL;
  1449. wcex.lpszClassName = szClassName;
  1450. wcex.hIconSm = NULL;
  1451. if (!RegisterClassEx(&wcex))
  1452. {
  1453. return FALSE ;
  1454. }
  1455. HDC Dc = GetDC(NULL);
  1456. if (Dc == NULL)
  1457. {
  1458. return FALSE;
  1459. }
  1460. g_Fonts[FONT_FIXED].Font = (HFONT)GetStockObject(ANSI_FIXED_FONT);
  1461. g_Fonts[FONT_VARIABLE].Font = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
  1462. for (ULONG FontIndex = 0; FontIndex < FONT_COUNT; FontIndex++)
  1463. {
  1464. SelectObject(Dc, g_Fonts[FontIndex].Font);
  1465. if (!GetTextMetrics(Dc, &g_Fonts[FontIndex].Metrics))
  1466. {
  1467. return FALSE;
  1468. }
  1469. }
  1470. ReleaseDC(NULL, Dc);
  1471. InitColors();
  1472. // Register message for FINDMSGSTRING.
  1473. g_FindMsgString = RegisterWindowMessage(FINDMSGSTRING);
  1474. // Look up FindWindowEx.
  1475. HMODULE User32 = GetModuleHandle("user32.dll");
  1476. if (User32 != NULL)
  1477. {
  1478. g_FlashWindowEx = (PFN_FlashWindowEx)
  1479. GetProcAddress(User32, "FlashWindowEx");
  1480. }
  1481. //
  1482. // Initialize window lists
  1483. //
  1484. InitializeListHead(&g_ActiveWin);
  1485. Dbg(g_hMainAccTable = LoadAccelerators(g_hInst, MAKEINTRESOURCE(MAIN_ACC)));
  1486. Dbg(LoadString(g_hInst, SYS_Main_wClass, szClassName, MAX_MSG_TXT));
  1487. InitializeListHead(&g_StateList);
  1488. __try
  1489. {
  1490. Dbg_InitializeCriticalSection( &g_QuickLock );
  1491. }
  1492. __except(EXCEPTION_EXECUTE_HANDLER)
  1493. {
  1494. return FALSE;
  1495. }
  1496. RECT WorkRect;
  1497. RECT FrameRect;
  1498. //
  1499. // Try and create an initial window that's ready to work
  1500. // without resizing. Our goal here is to grab enough
  1501. // screen space to given plenty of room for MDI windows
  1502. // but not so much we might as well be maximized.
  1503. //
  1504. Dbg(SystemParametersInfo(SPI_GETWORKAREA, 0, &WorkRect, FALSE));
  1505. // We don't want to take up more than 80% of either dimension.
  1506. FrameRect.right = (WorkRect.right - WorkRect.left) * 4 / 5;
  1507. FrameRect.bottom = (WorkRect.bottom - WorkRect.top) * 4 / 5;
  1508. // We want width for an 80-character window plus space for
  1509. // another narrow window like the CPU window. We want
  1510. // height for a forty row window plus space for a short
  1511. // window like the stack.
  1512. // If we can't get that much room just let the system
  1513. // take charge.
  1514. if (FrameRect.right < (CMD_WIDTH + CPU_WIDTH_32) ||
  1515. FrameRect.bottom < (CMD_HEIGHT + CALLS_HEIGHT))
  1516. {
  1517. SetRect(&FrameRect, CW_USEDEFAULT, CW_USEDEFAULT,
  1518. CW_USEDEFAULT, CW_USEDEFAULT);
  1519. }
  1520. else
  1521. {
  1522. // Hug the bottom left corner of the screen to
  1523. // try and keep out of the way as much as possible
  1524. // while still allowing the first bits of the
  1525. // window to be seen.
  1526. FrameRect.left = WorkRect.left;
  1527. FrameRect.top = (WorkRect.bottom - WorkRect.top) - FrameRect.bottom;
  1528. }
  1529. //
  1530. // Create the frame
  1531. //
  1532. g_hwndFrame = CreateWindow(szClassName,
  1533. g_MainTitleText,
  1534. WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN
  1535. | WS_VISIBLE,
  1536. FrameRect.left,
  1537. FrameRect.top,
  1538. FrameRect.right,
  1539. FrameRect.bottom,
  1540. NULL,
  1541. NULL,
  1542. g_hInst,
  1543. NULL
  1544. );
  1545. //
  1546. // Initialize the debugger
  1547. //
  1548. if ( !g_hwndFrame || !g_hwndMDIClient )
  1549. {
  1550. return FALSE;
  1551. }
  1552. //
  1553. // Get handle to main menu, window submenu, MRU submenu
  1554. //
  1555. Dbg( g_hmenuMain = GetMenu(g_hwndFrame) );
  1556. g_hmenuMainSave = g_hmenuMain;
  1557. Dbg( g_hmenuWindowSub = GetSubMenu(g_hmenuMain, WINDOWMENU) );
  1558. Dbg( g_MruMenu = GetSubMenu(g_hmenuMain, FILEMENU) );
  1559. Dbg( g_MruMenu = GetSubMenu(g_MruMenu,
  1560. IDM_FILE_MRU_FILE1 - IDM_FILE - 1) );
  1561. //
  1562. // Init Items Colors ,Environment and RunDebug params to their default
  1563. // values 'They will later be overrided by the values in .INI file
  1564. // but we ensure to have something coherent even if we can't load
  1565. // the .INI file
  1566. //
  1567. InitDefaults();
  1568. SymSetParentWindow(g_hwndFrame);
  1569. //
  1570. // Initialize Keyboard Hook
  1571. //
  1572. hKeyHook = SetWindowsHookEx(WH_KEYBOARD,
  1573. KeyboardHook,
  1574. g_hInst,
  1575. GetCurrentThreadId()
  1576. );
  1577. return TRUE;
  1578. }
  1579. int
  1580. WINAPIV
  1581. main(
  1582. int argc,
  1583. PTSTR argv[ ],
  1584. PTSTR envp[]
  1585. )
  1586. /*++
  1587. Routine Description:
  1588. description-of-function.
  1589. Arguments:
  1590. argc - Supplies the count of arguments on command line.
  1591. argv - Supplies a pointer to an array of string pointers.
  1592. Return Value:
  1593. int - Returns the wParam from the WM_QUIT message.
  1594. None.
  1595. --*/
  1596. {
  1597. HRESULT Status;
  1598. CHAR helpfile[MAX_PATH];
  1599. g_ProgramName = argv[0];
  1600. g_hInst = GetModuleHandle(NULL);
  1601. g_DefPriority = GetPriorityClass(GetCurrentProcess());
  1602. GetEditorCommandDefaults();
  1603. Dbg(LoadString(g_hInst, SYS_Help_File, helpfile, sizeof(helpfile)));
  1604. MakeHelpFileName(helpfile);
  1605. // We need to initialize COM so that we can use SHBrowseForFolder.
  1606. if (FAILED(Status = CoInitializeEx(NULL, COM_THREAD_MODEL)))
  1607. {
  1608. InternalError(Status, "CoInitializeEx");
  1609. return FALSE;
  1610. }
  1611. // Initialize enough of the GUI to bring up the top level window
  1612. // so the menus can be activated.
  1613. if (!InitGUI())
  1614. {
  1615. InternalError(E_OUTOFMEMORY, "InitGUI");
  1616. return FALSE;
  1617. }
  1618. if (!CreateUiInterfaces(FALSE, NULL))
  1619. {
  1620. InternalError(E_OUTOFMEMORY, "CreateUiInterfaces");
  1621. return FALSE;
  1622. }
  1623. // Select the default workspace.
  1624. if ((Status = UiSwitchWorkspace(WSP_NAME_BASE, g_WorkspaceDefaultName,
  1625. WSP_CREATE_ALWAYS, WSP_APPLY_DEFAULT,
  1626. NULL)) != S_OK)
  1627. {
  1628. //InternalError(Status, "DefaultWorkspace");
  1629. }
  1630. // Parse the command line.
  1631. // We need to do this before any GUI window is created to support the
  1632. // journaling option.
  1633. if (!ParseCommandLine(TRUE))
  1634. {
  1635. return FALSE;
  1636. }
  1637. // Enter main message loop.
  1638. for (;;)
  1639. {
  1640. WaitMessage();
  1641. ProcessPendingMessages();
  1642. if (g_Exit)
  1643. {
  1644. break;
  1645. }
  1646. //
  1647. // Check for any engine work that needs to be done.
  1648. //
  1649. ULONG EventSeq = g_CodeBufferSequence;
  1650. if (EventSeq != g_CodeDisplaySequence)
  1651. {
  1652. // We don't want to stall the engine during
  1653. // file loading so capture the state and then
  1654. // release the lock.
  1655. Dbg_EnterCriticalSection(&g_QuickLock);
  1656. ULONG64 Ip = g_CodeIp;
  1657. char FoundFile[MAX_SOURCE_PATH];
  1658. char SymFile[MAX_SOURCE_PATH];
  1659. char PathComp[MAX_SOURCE_PATH];
  1660. strcpy(FoundFile, g_CodeFileFound);
  1661. strcpy(SymFile, g_CodeSymFile);
  1662. strcpy(PathComp, g_CodePathComponent);
  1663. ULONG Line = g_CodeLine;
  1664. BOOL UserActivated = g_CodeUserActivated;
  1665. Dbg_LeaveCriticalSection(&g_QuickLock);
  1666. UpdateCodeDisplay(Ip, FoundFile[0] ? FoundFile : NULL,
  1667. SymFile, PathComp[0] ? PathComp : NULL,
  1668. Line, UserActivated);
  1669. g_CodeDisplaySequence = EventSeq;
  1670. }
  1671. LockUiBuffer(&g_UiOutputBuffer);
  1672. if (g_UiOutputBuffer.GetDataLen() > 0 &&
  1673. (!g_HoldWaitOutput || !g_WaitingForEvent))
  1674. {
  1675. PSTR Text, End;
  1676. COLORREF Fg, Bg;
  1677. Text = (PSTR)g_UiOutputBuffer.GetDataBuffer();
  1678. End = Text + g_UiOutputBuffer.GetDataLen();
  1679. while (Text < End)
  1680. {
  1681. GetOutMaskColors(*(ULONG UNALIGNED *)Text, &Fg, &Bg);
  1682. Text += sizeof(ULONG);
  1683. CmdOutput(Text, Fg, Bg);
  1684. Text += strlen(Text) + 1;
  1685. }
  1686. g_UiOutputBuffer.Empty();
  1687. }
  1688. UnlockUiBuffer(&g_UiOutputBuffer);
  1689. }
  1690. TerminateApplication(FALSE);
  1691. // Keep the C++ compiler from whining
  1692. return 0;
  1693. }