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.

1806 lines
50 KiB

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