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.

1451 lines
48 KiB

  1. /*++
  2. Copyright (c) 1999-2002 Microsoft Corporation
  3. Module Name:
  4. prcmain.cpp
  5. Abstract:
  6. Contains the main window proc.
  7. --*/
  8. #include "precomp.hxx"
  9. #pragma hdrstop
  10. #define TOOLBAR_UPDATE_TIMER_ID 0x100
  11. #define WINDBG_START_DLG_FLAGS (OFN_HIDEREADONLY | \
  12. OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST)
  13. // Path of the last files opened from a file open dlg box.
  14. TCHAR g_ExeFilePath[_MAX_PATH];
  15. TCHAR g_DumpFilePath[_MAX_PATH];
  16. TCHAR g_SrcFilePath[_MAX_PATH];
  17. TCHAR g_WriteTextFilePath[_MAX_PATH];
  18. TCHAR g_WorkspaceFilePath[_MAX_PATH];
  19. BOOL g_fCheckFileDate;
  20. // Last menu id & id state.
  21. UINT g_LastMenuId;
  22. UINT g_LastMenuIdState;
  23. ULONG g_LastMapLetter;
  24. void
  25. ShowMapDlg(void)
  26. {
  27. CONNECTDLGSTRUCT ConnDlg;
  28. NETRESOURCE NetRes;
  29. ZeroMemory(&NetRes, sizeof(NetRes));
  30. NetRes.dwType = RESOURCETYPE_DISK;
  31. ConnDlg.cbStructure = sizeof(ConnDlg);
  32. ConnDlg.hwndOwner = g_hwndFrame;
  33. ConnDlg.lpConnRes = &NetRes;
  34. ConnDlg.dwFlags = CONNDLG_USE_MRU;
  35. if (WNetConnectionDialog1(&ConnDlg) == NO_ERROR)
  36. {
  37. g_LastMapLetter = ConnDlg.dwDevNum;
  38. }
  39. }
  40. void
  41. ShowDisconnDlg(void)
  42. {
  43. WNetDisconnectDialog(g_hwndFrame, RESOURCETYPE_DISK);
  44. }
  45. void
  46. SaveFileOpenPath(PTSTR Path, PTSTR Global, BOOL SaveWsp, ULONG WspIndex)
  47. {
  48. TCHAR Drive[_MAX_DRIVE];
  49. TCHAR Dir[_MAX_DIR];
  50. TCHAR NewPath[_MAX_PATH];
  51. _tsplitpath(Path, Drive, Dir, NULL, NULL);
  52. _tmakepath(NewPath, Drive, Dir, NULL, NULL);
  53. if (WspIndex == WSP_GLOBAL_SRC_FILE_PATH)
  54. {
  55. // We've just referenced an interesting source file
  56. // so make sure the path is added to the current source
  57. // path.
  58. g_pUiLocSymbols->AppendSourcePath(NewPath);
  59. }
  60. if (_strcmpi(NewPath, Global) != 0)
  61. {
  62. _tcscpy(Global, NewPath);
  63. if (SaveWsp && g_Workspace != NULL)
  64. {
  65. g_Workspace->SetString(WspIndex, Global);
  66. }
  67. }
  68. }
  69. /*** MainWndProc
  70. **
  71. ** Synopsis:
  72. **
  73. ** Entry:
  74. **
  75. ** Returns:
  76. **
  77. ** Description:
  78. ** Processes window messages.
  79. **
  80. */
  81. LRESULT
  82. CALLBACK
  83. MainWndProc(
  84. HWND hwnd,
  85. UINT message,
  86. WPARAM wParam,
  87. LPARAM lParam
  88. )
  89. {
  90. static UINT s_MenuItemSelected;
  91. HWND CommonWin;
  92. PCOMMONWIN_DATA CommonWinData;
  93. HRESULT Status;
  94. ULONG OutMask;
  95. if (message == g_FindMsgString)
  96. {
  97. FINDREPLACE* FindRep = (FINDREPLACE*)lParam;
  98. if (g_FindLast != NULL)
  99. {
  100. // Clear old find.
  101. g_FindLast->Find(NULL, 0, TRUE);
  102. g_FindLast = NULL;
  103. }
  104. if (FindRep->Flags & FR_DIALOGTERM)
  105. {
  106. // Dialog has closed.
  107. g_FindDialog = NULL;
  108. }
  109. else
  110. {
  111. CommonWin = MDIGetActive(g_hwndMDIClient, NULL);
  112. if (CommonWin != NULL &&
  113. (CommonWinData = GetCommonWinData(CommonWin)) != NULL)
  114. {
  115. g_FindTextFlags = FindRep->Flags &
  116. (FR_DOWN | FR_MATCHCASE | FR_WHOLEWORD);
  117. CommonWinData->Find(FindRep->lpstrFindWhat,
  118. g_FindTextFlags, TRUE);
  119. g_FindLast = CommonWinData;
  120. }
  121. }
  122. return 0;
  123. }
  124. switch (message)
  125. {
  126. case WM_CREATE:
  127. {
  128. CLIENTCREATESTRUCT ccs;
  129. // Find window menu where children will be listed.
  130. ccs.hWindowMenu = GetSubMenu(GetMenu(hwnd), WINDOWMENU);
  131. ccs.idFirstChild = IDM_FIRSTCHILD;
  132. // Create the MDI client filling the client area.
  133. g_hwndMDIClient = CreateWindow(_T("mdiclient"),
  134. NULL,
  135. WS_CHILD | WS_CLIPCHILDREN,
  136. 0, 0, 0, 0,
  137. hwnd,
  138. (HMENU) 0xCAC,
  139. g_hInst,
  140. (PTSTR)&ccs
  141. );
  142. if (g_hwndMDIClient == NULL)
  143. {
  144. return -1;
  145. }
  146. //
  147. // Nothing interesting, here, just
  148. // trying to turn the Toolbar & Status bar into a
  149. // black box, so that the variables, etc. aren't
  150. // scattered all over the place.
  151. //
  152. if (!CreateToolbar(hwnd))
  153. {
  154. return -1;
  155. }
  156. if (!CreateStatusBar(hwnd))
  157. {
  158. return -1;
  159. }
  160. ShowWindow(g_hwndMDIClient, SW_SHOW);
  161. InitializeMenu(GetMenu(hwnd));
  162. g_hmenuMain = GetMenu(hwnd);
  163. if (g_hmenuMain == NULL)
  164. {
  165. return -1;
  166. }
  167. //
  168. // Create a one second timer to constantly update the state of the toolbar
  169. //
  170. SetTimer(hwnd, TOOLBAR_UPDATE_TIMER_ID, 1000, NULL);
  171. }
  172. break;
  173. case WM_TIMER:
  174. EnableToolbarControls();
  175. return 0;
  176. case WM_NOTIFY:
  177. {
  178. if (lParam == 0)
  179. {
  180. break;
  181. }
  182. LPNMHDR lpnmhdr = (LPNMHDR) lParam;
  183. switch (lpnmhdr->code)
  184. {
  185. case TTN_NEEDTEXT:
  186. {
  187. LPTOOLTIPTEXT lpToolTipText = (LPTOOLTIPTEXT) lParam;
  188. lpToolTipText->lpszText = GetToolTipTextFor_Toolbar
  189. ((UINT) lpToolTipText->hdr.idFrom);
  190. }
  191. break;
  192. }
  193. }
  194. break;
  195. case WM_QUERYOPEN:
  196. if (g_fCheckFileDate)
  197. {
  198. g_fCheckFileDate = FALSE;
  199. PostMessage(g_hwndFrame, WM_ACTIVATEAPP, 1, 0L);
  200. }
  201. goto DefProcessing;
  202. case WM_COMMAND:
  203. {
  204. WORD wNotifyCode = HIWORD(wParam); // notification code
  205. WORD wItemId = LOWORD(wParam); // item, control, or
  206. // accelerator identifier
  207. HWND hwndCtl = (HWND) lParam; // handle of control
  208. switch (wItemId)
  209. {
  210. case IDM_FILE_OPEN_EXECUTABLE:
  211. {
  212. PTSTR Path;
  213. DWORD Flags = WINDBG_START_DLG_FLAGS;
  214. ClearDebuggingParams();
  215. Path = (PTSTR)malloc(_MAX_PATH * 4 * sizeof(TCHAR));
  216. if (Path == NULL)
  217. {
  218. break;
  219. }
  220. *Path = 0;
  221. if (StartFileDlg(hwnd,
  222. DLG_Browse_Executable_Title,
  223. DEF_Ext_EXE,
  224. IDM_FILE_OPEN,
  225. IDD_DLG_FILEOPEN_EXPLORER_EXTENSION_EXE_ARGS,
  226. g_ExeFilePath,
  227. Path,
  228. &Flags,
  229. OpenExeWithArgsHookProc) &&
  230. *Path)
  231. {
  232. CatString(Path, szOpenExeArgs, 4 * _MAX_PATH);
  233. SetAllocString(&g_DebugCommandLine, Path);
  234. if (g_ExplicitWorkspace && g_Workspace != NULL)
  235. {
  236. g_Workspace->
  237. SetUlong(WSP_GLOBAL_EXE_CREATE_FLAGS,
  238. g_DebugCreateFlags);
  239. g_Workspace->
  240. SetString(WSP_GLOBAL_PROCESS_START_DIR,
  241. g_ProcessStartDir);
  242. g_Workspace->
  243. SetString(WSP_GLOBAL_EXE_COMMAND_LINE,
  244. Path);
  245. }
  246. SaveFileOpenPath(Path, g_ExeFilePath,
  247. TRUE, WSP_GLOBAL_EXE_FILE_PATH);
  248. StartDebugging();
  249. }
  250. if (g_DebugCommandLine != Path)
  251. {
  252. free(Path);
  253. }
  254. }
  255. break;
  256. case IDM_FILE_ATTACH:
  257. StartDialog(IDD_DLG_ATTACH_PROCESS, DlgProc_AttachProcess,
  258. NULL);
  259. break;
  260. case IDM_FILE_OPEN_CRASH_DUMP:
  261. {
  262. PTSTR Path;
  263. DWORD Flags = WINDBG_START_DLG_FLAGS;
  264. ClearDebuggingParams();
  265. Path = (PTSTR)malloc(_MAX_PATH * sizeof(TCHAR));
  266. if (Path == NULL)
  267. {
  268. break;
  269. }
  270. Dbg(LoadString(g_hInst, DEF_Dump_File,
  271. Path, _MAX_PATH));
  272. if (StartFileDlg(hwnd,
  273. DLG_Browse_CrashDump_Title,
  274. DEF_Ext_DUMP,
  275. 0,
  276. 0,
  277. g_DumpFilePath,
  278. Path,
  279. &Flags,
  280. NULL))
  281. {
  282. SetAllocString(&g_DumpFiles[0], Path);
  283. g_NumDumpFiles = 1;
  284. if (g_ExplicitWorkspace && g_Workspace != NULL)
  285. {
  286. g_Workspace->
  287. SetString(WSP_GLOBAL_DUMP_FILE_NAME,
  288. Path);
  289. }
  290. SaveFileOpenPath(Path, g_DumpFilePath,
  291. TRUE, WSP_GLOBAL_DUMP_FILE_PATH);
  292. StartDebugging();
  293. }
  294. if (g_DumpFiles[0] != Path)
  295. {
  296. free(Path);
  297. }
  298. }
  299. break;
  300. case IDM_FILE_CONNECT_TO_REMOTE:
  301. StartDialog(IDD_DLG_CONNECTTOREMOTE, DlgProc_ConnectToRemote,
  302. NULL);
  303. break;
  304. case IDM_FILE_KERNEL_DEBUG:
  305. StartKdPropSheet();
  306. break;
  307. case IDM_FILE_SYMBOL_PATH:
  308. StartDialog(IDD_DLG_SYMBOLS, DlgProc_SymbolPath, NULL);
  309. break;
  310. case IDM_FILE_IMAGE_PATH:
  311. StartDialog(IDD_DLG_IMAGE_PATH, DlgProc_ImagePath, NULL);
  312. break;
  313. case IDM_FILE_SOURCE_PATH:
  314. StartDialog(IDD_DLG_SOURCE_PATH, DlgProc_SourcePath, NULL);
  315. break;
  316. case IDM_FILE_OPEN_WORKSPACE:
  317. StartDialog(IDD_DLG_WORKSPACE_IO, DlgProc_OpenWorkspace,
  318. FALSE);
  319. break;
  320. case IDM_FILE_SAVE_WORKSPACE:
  321. // No prompt, because we know the user wants to save.
  322. if (g_Workspace != NULL)
  323. {
  324. g_Workspace->Flush(TRUE, FALSE);
  325. }
  326. break;
  327. case IDM_FILE_SAVE_WORKSPACE_AS:
  328. if (g_Workspace != NULL)
  329. {
  330. StartDialog(IDD_DLG_WORKSPACE_IO, DlgProc_SaveWorkspaceAs,
  331. TRUE);
  332. }
  333. break;
  334. case IDM_FILE_CLEAR_WORKSPACE:
  335. StartDialog(IDD_DLG_CLEAR_WORKSPACE, DlgProc_ClearWorkspace,
  336. NULL);
  337. break;
  338. case IDM_FILE_DELETE_WORKSPACES:
  339. StartDialog(IDD_DLG_DELETE_WORKSPACES,
  340. DlgProc_DeleteWorkspaces, NULL);
  341. break;
  342. case IDM_FILE_OPEN_WORKSPACE_FILE:
  343. {
  344. TCHAR Path[_MAX_PATH];
  345. DWORD dwFlags = WINDBG_START_DLG_FLAGS;
  346. Path[0] = 0;
  347. if (!StartFileDlg(hwnd,
  348. DLG_Open_Workspace_File_Title,
  349. DEF_Ext_Workspace,
  350. IDM_FILE_OPEN,
  351. 0,
  352. g_WorkspaceFilePath,
  353. Path,
  354. &dwFlags,
  355. DlgFile
  356. ))
  357. {
  358. // User canceled, bail out
  359. break;
  360. }
  361. SaveFileOpenPath(Path, g_WorkspaceFilePath,
  362. FALSE, 0);
  363. UiSwitchToExplicitWorkspace(WSP_NAME_FILE, Path);
  364. }
  365. break;
  366. case IDM_FILE_SAVE_WORKSPACE_FILE:
  367. if (g_Workspace != NULL)
  368. {
  369. TCHAR Path[_MAX_PATH];
  370. DWORD dwFlags = OFN_HIDEREADONLY | OFN_CREATEPROMPT |
  371. OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST;
  372. Path[0] = 0;
  373. if (!StartFileDlg(hwnd,
  374. DLG_Save_Workspace_File_Title,
  375. DEF_Ext_Workspace,
  376. IDM_FILE_OPEN,
  377. 0,
  378. g_WorkspaceFilePath,
  379. Path,
  380. &dwFlags,
  381. DlgFile
  382. ))
  383. {
  384. // User canceled, bail out
  385. break;
  386. }
  387. SaveFileOpenPath(Path, g_WorkspaceFilePath,
  388. FALSE, 0);
  389. UiSaveWorkspaceAs(WSP_NAME_FILE, Path);
  390. }
  391. break;
  392. case IDM_FILE_MAP_NET_DRIVE:
  393. ShowMapDlg();
  394. break;
  395. case IDM_FILE_DISCONN_NET_DRIVE:
  396. ShowDisconnDlg();
  397. break;
  398. case IDM_FILE_MRU_FILE1:
  399. case IDM_FILE_MRU_FILE2:
  400. case IDM_FILE_MRU_FILE3:
  401. case IDM_FILE_MRU_FILE4:
  402. case IDM_FILE_MRU_FILE5:
  403. case IDM_FILE_MRU_FILE6:
  404. case IDM_FILE_MRU_FILE7:
  405. case IDM_FILE_MRU_FILE8:
  406. case IDM_FILE_MRU_FILE9:
  407. case IDM_FILE_MRU_FILE10:
  408. case IDM_FILE_MRU_FILE11:
  409. case IDM_FILE_MRU_FILE12:
  410. case IDM_FILE_MRU_FILE13:
  411. case IDM_FILE_MRU_FILE14:
  412. case IDM_FILE_MRU_FILE15:
  413. case IDM_FILE_MRU_FILE16:
  414. case IDM_FILE_OPEN:
  415. {
  416. TCHAR Path[_MAX_PATH];
  417. if (IDM_FILE_OPEN == wItemId)
  418. {
  419. DWORD dwFlags = WINDBG_START_DLG_FLAGS;
  420. Path[0] = 0;
  421. if (!StartFileDlg(hwnd,
  422. DLG_Open_Filebox_Title,
  423. DEF_Ext_SOURCE,
  424. IDM_FILE_OPEN,
  425. 0,
  426. g_SrcFilePath,
  427. Path,
  428. &dwFlags,
  429. DlgFile
  430. ))
  431. {
  432. // User canceled, bail out
  433. break;
  434. }
  435. }
  436. else
  437. {
  438. WORD wFileIdx = wItemId - IDM_FILE_MRU_FILE1;
  439. // Sanity check
  440. Assert(wFileIdx < MAX_MRU_FILES);
  441. _tcscpy(Path, g_MruFiles[wFileIdx]->FileName);
  442. }
  443. OpenOrActivateFile(Path, NULL, NULL, -1, TRUE, TRUE);
  444. SaveFileOpenPath(Path, g_SrcFilePath,
  445. TRUE, WSP_GLOBAL_SRC_FILE_PATH);
  446. }
  447. break;
  448. case IDM_FILE_CLOSE:
  449. {
  450. HWND hwndChild = MDIGetActive(g_hwndMDIClient, NULL);
  451. if (hwndChild)
  452. {
  453. SendMessage(g_hwndMDIClient, WM_MDIDESTROY,
  454. (WPARAM)hwndChild, 0L);
  455. }
  456. }
  457. break;
  458. case IDM_FILE_EXIT:
  459. PostMessage(hwnd, WM_CLOSE, 0, 0L);
  460. break;
  461. case IDM_EDIT_COPY:
  462. CommonWin = MDIGetActive(g_hwndMDIClient, NULL);
  463. if (!CommonWin)
  464. {
  465. return 0;
  466. }
  467. CommonWinData = GetCommonWinData(CommonWin);
  468. if (CommonWinData)
  469. {
  470. CommonWinData->Copy();
  471. }
  472. break;
  473. case IDM_EDIT_PASTE:
  474. CommonWin = MDIGetActive(g_hwndMDIClient, NULL);
  475. if (!CommonWin)
  476. {
  477. return 0;
  478. }
  479. CommonWinData = GetCommonWinData(CommonWin);
  480. if (CommonWinData)
  481. {
  482. CommonWinData->Paste();
  483. }
  484. break;
  485. case IDM_EDIT_CUT:
  486. CommonWin = MDIGetActive(g_hwndMDIClient, NULL);
  487. if (!CommonWin)
  488. {
  489. return 0;
  490. }
  491. CommonWinData = GetCommonWinData(CommonWin);
  492. if (CommonWinData)
  493. {
  494. CommonWinData->Cut();
  495. }
  496. break;
  497. case IDM_EDIT_SELECT_ALL:
  498. CommonWin = MDIGetActive(g_hwndMDIClient, NULL);
  499. if (CommonWin == NULL)
  500. {
  501. return 0;
  502. }
  503. CommonWinData = GetCommonWinData(CommonWin);
  504. if (CommonWinData != NULL)
  505. {
  506. CommonWinData->SelectAll();
  507. }
  508. break;
  509. case IDM_EDIT_WRITE_TEXT_TO_FILE:
  510. if ((CommonWin = MDIGetActive(g_hwndMDIClient, NULL)) &&
  511. (CommonWinData = GetCommonWinData(CommonWin)) &&
  512. CommonWinData->CanWriteTextToFile())
  513. {
  514. DWORD dwFlags = OFN_HIDEREADONLY | OFN_CREATEPROMPT |
  515. OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST;
  516. TCHAR Path[_MAX_PATH];
  517. HANDLE File;
  518. Path[0] = 0;
  519. if (!StartFileDlg(hwnd,
  520. DLG_Write_Text_File_Title,
  521. DEF_Ext_TXT,
  522. 0,
  523. 0,
  524. g_WriteTextFilePath,
  525. Path,
  526. &dwFlags,
  527. DlgFile))
  528. {
  529. // User canceled, bail out
  530. break;
  531. }
  532. File = CreateFile(Path, GENERIC_WRITE, 0, NULL,
  533. CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
  534. NULL);
  535. if (!File || File == INVALID_HANDLE_VALUE)
  536. {
  537. Status = WIN32_LAST_STATUS();
  538. ErrorBox(NULL, 0, ERR_Create_File_Failed, Path,
  539. FormatStatusCode(Status),
  540. FormatStatus(Status));
  541. break;
  542. }
  543. SaveFileOpenPath(Path, g_WriteTextFilePath,
  544. FALSE, 0);
  545. Status = CommonWinData->WriteTextToFile(File);
  546. CloseHandle(File);
  547. if (Status != S_OK)
  548. {
  549. ErrorBox(NULL, 0, ERR_Write_Text_File_Failed,
  550. Path, FormatStatusCode(Status),
  551. FormatStatus(Status));
  552. DeleteFile(Path);
  553. }
  554. }
  555. break;
  556. case IDM_EDIT_ADD_TO_COMMAND_HISTORY:
  557. StartDialog(IDD_DLG_ADD_TO_COMMAND_HISTORY,
  558. DlgProc_AddToCommandHistory, FALSE);
  559. break;
  560. case IDM_EDIT_CLEAR_COMMAND_HISTORY:
  561. ClearCmdWindow();
  562. break;
  563. case IDM_EDIT_FIND_NEXT:
  564. if (!g_FindDialog &&
  565. g_FindText[0] &&
  566. (CommonWin = MDIGetActive(g_hwndMDIClient, NULL)) &&
  567. (CommonWinData = GetCommonWinData(CommonWin)))
  568. {
  569. ULONG Flags = g_FindTextFlags;
  570. // Repeat the last search. Invert
  571. // the direction on shift.
  572. if (GetKeyState(VK_SHIFT) < 0)
  573. {
  574. Flags ^= FR_DOWN;
  575. }
  576. CommonWinData->Find(g_FindText, Flags, FALSE);
  577. break;
  578. }
  579. // Fall through.
  580. case IDM_EDIT_FIND:
  581. // FindNext box may already be there.
  582. if (g_FindDialog != NULL)
  583. {
  584. SetFocus(g_FindDialog);
  585. }
  586. else
  587. {
  588. CommonWin = MDIGetActive(g_hwndMDIClient, NULL);
  589. if (CommonWin != NULL &&
  590. (CommonWinData = GetCommonWinData(CommonWin)) != NULL)
  591. {
  592. CommonWinData->SelectedText(g_FindText,
  593. DIMA(g_FindText));
  594. }
  595. ZeroMemory(&g_FindRep, sizeof(g_FindRep));
  596. g_FindRep.lStructSize = sizeof(g_FindRep);
  597. g_FindRep.hwndOwner = g_hwndFrame;
  598. g_FindRep.Flags = FR_DOWN;
  599. g_FindRep.lpstrFindWhat = g_FindText;
  600. g_FindRep.wFindWhatLen = DIMA(g_FindText);
  601. g_FindDialog = FindText(&g_FindRep);
  602. }
  603. break;
  604. case IDM_EDIT_PROPERTIES:
  605. {
  606. HWND hwndmdi = MDIGetActive(g_hwndMDIClient, NULL);
  607. if (hwndmdi) {
  608. MEMWIN_DATA * pMemWinData = GetMemWinData(hwndmdi);
  609. Assert(pMemWinData);
  610. if ( pMemWinData->HasEditableProperties() ) {
  611. if (pMemWinData->EditProperties()) {
  612. pMemWinData->UiRequestRead();
  613. }
  614. }
  615. }
  616. }
  617. break;
  618. case IDM_EDIT_GOTO_LINE:
  619. CommonWin = MDIGetActive(g_hwndMDIClient, NULL);
  620. if (CommonWin)
  621. {
  622. CommonWinData = GetCommonWinData(CommonWin);
  623. Assert(CommonWinData);
  624. StartDialog(IDD_DLG_GOTO_LINE, DlgProc_GotoLine,
  625. (LPARAM)CommonWinData);
  626. }
  627. break;
  628. case IDM_EDIT_GOTO_ADDRESS:
  629. StartDialog(IDD_DLG_GOTO_ADDRESS, DlgProc_GotoAddress, NULL);
  630. break;
  631. case IDM_EDIT_GOTO_CURRENT_IP:
  632. AddStringCommand(UIC_DISPLAY_CODE_EXPR, "@@masm(@$ip)");
  633. break;
  634. case IDM_VIEW_REGISTERS:
  635. New_OpenDebugWindow(CPU_WINDOW, TRUE, NTH_OPEN_ALWAYS); // User activated
  636. EnableToolbarControls();
  637. break;
  638. case IDM_VIEW_WATCH:
  639. New_OpenDebugWindow(WATCH_WINDOW, TRUE, NTH_OPEN_ALWAYS); // User activated
  640. EnableToolbarControls();
  641. break;
  642. case IDM_VIEW_LOCALS:
  643. New_OpenDebugWindow(LOCALS_WINDOW, TRUE, NTH_OPEN_ALWAYS); // User activated
  644. EnableToolbarControls();
  645. break;
  646. case IDM_VIEW_DISASM:
  647. New_OpenDebugWindow(DISASM_WINDOW, TRUE, NTH_OPEN_ALWAYS); // User activated
  648. EnableToolbarControls();
  649. break;
  650. case IDM_VIEW_COMMAND:
  651. New_OpenDebugWindow(CMD_WINDOW, FALSE, NTH_OPEN_ALWAYS); // Not user activated
  652. EnableToolbarControls();
  653. break;
  654. case IDM_VIEW_MEMORY:
  655. New_OpenDebugWindow(MEM_WINDOW, TRUE, NTH_OPEN_ALWAYS); // User activated
  656. EnableToolbarControls();
  657. break;
  658. case IDM_VIEW_CALLSTACK:
  659. New_OpenDebugWindow(CALLS_WINDOW, TRUE, NTH_OPEN_ALWAYS); // User activated
  660. EnableToolbarControls();
  661. break;
  662. case IDM_VIEW_SCRATCH:
  663. New_OpenDebugWindow(SCRATCH_PAD_WINDOW, TRUE, NTH_OPEN_ALWAYS); // User activated
  664. EnableToolbarControls();
  665. break;
  666. case IDM_VIEW_PROCESS_THREAD:
  667. New_OpenDebugWindow(PROCESS_THREAD_WINDOW, TRUE, NTH_OPEN_ALWAYS); // User activated
  668. EnableToolbarControls();
  669. break;
  670. case IDM_VIEW_TOGGLE_VERBOSE:
  671. g_pUiClient->GetOtherOutputMask(g_pDbgClient, &OutMask);
  672. OutMask ^= DEBUG_OUTPUT_VERBOSE;
  673. g_pUiClient->SetOtherOutputMask(g_pDbgClient, OutMask);
  674. g_pUiControl->SetLogMask(OutMask);
  675. CmdLogFmt("Verbose mode %s.\n",
  676. (OutMask & DEBUG_OUTPUT_VERBOSE) ? "ON" : "OFF");
  677. CheckMenuItem(g_hmenuMain,
  678. IDM_VIEW_TOGGLE_VERBOSE,
  679. (OutMask & DEBUG_OUTPUT_VERBOSE) ?
  680. MF_CHECKED : MF_UNCHECKED);
  681. break;
  682. case IDM_VIEW_SHOW_VERSION:
  683. Status = g_pUiControl->
  684. OutputVersionInformation(DEBUG_OUTCTL_AMBIENT);
  685. if (Status == HRESULT_FROM_WIN32(ERROR_BUSY))
  686. {
  687. CmdLogFmt("Engine is busy, try again\n");
  688. }
  689. else if (Status != S_OK)
  690. {
  691. CmdLogFmt("Unable to show version information, 0x%X\n",
  692. Status);
  693. }
  694. break;
  695. case IDM_VIEW_TOOLBAR:
  696. {
  697. BOOL bVisible = !g_ShowToolbar;
  698. CheckMenuItem(g_hmenuMain,
  699. IDM_VIEW_TOOLBAR,
  700. bVisible ? MF_CHECKED : MF_UNCHECKED
  701. );
  702. Show_Toolbar(bVisible);
  703. if (g_Workspace != NULL)
  704. {
  705. g_Workspace->SetUlong(WSP_GLOBAL_VIEW_TOOL_BAR,
  706. bVisible);
  707. }
  708. }
  709. break;
  710. case IDM_VIEW_STATUS:
  711. {
  712. BOOL bVisible = !g_ShowStatusBar;
  713. CheckMenuItem(g_hmenuMain,
  714. IDM_VIEW_STATUS,
  715. bVisible ? MF_CHECKED : MF_UNCHECKED
  716. );
  717. Show_StatusBar(bVisible);
  718. if (g_Workspace != NULL)
  719. {
  720. g_Workspace->SetUlong(WSP_GLOBAL_VIEW_STATUS_BAR,
  721. bVisible);
  722. }
  723. }
  724. break;
  725. case IDM_VIEW_FONT:
  726. SelectFont(hwnd, FONT_FIXED);
  727. break;
  728. case IDM_VIEW_OPTIONS:
  729. StartDialog(IDD_DLG_OPTIONS, DlgProc_Options, NULL);
  730. break;
  731. case IDM_DEBUG_RESTART:
  732. if (g_EngineThreadId)
  733. {
  734. AddEnumCommand(UIC_RESTART);
  735. }
  736. else if (g_CommandLineStart == 1)
  737. {
  738. ParseCommandLine(FALSE);
  739. }
  740. break;
  741. case IDM_DEBUG_EVENT_FILTERS:
  742. StartDialog(IDD_DLG_EVENT_FILTERS, DlgProc_EventFilters, NULL);
  743. break;
  744. case IDM_DEBUG_GO:
  745. CmdExecuteCmd(_T("g"), UIC_EXECUTE);
  746. break;
  747. case IDM_DEBUG_GO_HANDLED:
  748. CmdExecuteCmd(_T("gh"), UIC_EXECUTE);
  749. break;
  750. case IDM_DEBUG_GO_UNHANDLED:
  751. CmdExecuteCmd(_T("gn"), UIC_EXECUTE);
  752. break;
  753. case IDM_DEBUG_RUNTOCURSOR:
  754. {
  755. char CodeExpr[MAX_OFFSET_EXPR];
  756. CommonWin = MDIGetActive(g_hwndMDIClient, NULL);
  757. if (CommonWin != NULL &&
  758. (CommonWinData = GetCommonWinData(CommonWin)) != NULL &&
  759. SUCCEEDED(CommonWinData->
  760. CodeExprAtCaret(CodeExpr, DIMA(CodeExpr), NULL)))
  761. {
  762. PrintStringCommand(UIC_EXECUTE, "g %s", CodeExpr);
  763. }
  764. break;
  765. }
  766. case IDM_DEBUG_STEPINTO:
  767. CmdExecuteCmd( _T("t"), UIC_EXECUTE );
  768. break;
  769. case IDM_DEBUG_STEPOVER:
  770. CmdExecuteCmd( _T("p"), UIC_EXECUTE );
  771. break;
  772. case IDM_DEBUG_STEPOUT:
  773. AddStringCommand(UIC_EXECUTE, "g @@masm(@$ra)");
  774. break;
  775. case IDM_DEBUG_BREAK:
  776. g_pUiControl->SetInterrupt(DEBUG_INTERRUPT_ACTIVE);
  777. break;
  778. case IDM_DEBUG_STOPDEBUGGING:
  779. StopDebugging(HIWORD(wParam) != 0xffff);
  780. break;
  781. case IDM_EDIT_TOGGLEBREAKPOINT:
  782. case IDM_EDIT_BREAKPOINTS:
  783. if ( !IS_TARGET_HALTED() )
  784. {
  785. ErrorBox(NULL, 0, ERR_Cant_Modify_BP_While_Running);
  786. break;
  787. }
  788. if (wItemId == IDM_EDIT_TOGGLEBREAKPOINT)
  789. {
  790. // If a disassembly or source window is up
  791. // try and toggle a breakpoint at the current
  792. // line.
  793. CommonWin = MDIGetActive(g_hwndMDIClient, NULL);
  794. if (CommonWin != NULL &&
  795. (CommonWinData =
  796. GetCommonWinData(CommonWin)) != NULL)
  797. {
  798. if (CommonWinData->m_enumType == DISASM_WINDOW ||
  799. CommonWinData->m_enumType == DOC_WINDOW ||
  800. CommonWinData->m_enumType == CALLS_WINDOW)
  801. {
  802. CommonWinData->ToggleBpAtCaret();
  803. break;
  804. }
  805. }
  806. }
  807. // menu got us here or we are not in a code window
  808. StartDialog(IDD_DLG_BREAKPOINTS, DlgProc_SetBreak, NULL);
  809. break;
  810. case IDM_EDIT_LOG_FILE:
  811. StartDialog(IDD_DLG_LOG_FILE, DlgProc_LogFile, NULL);
  812. break;
  813. case IDM_DEBUG_MODULES:
  814. StartDialog(IDD_DLG_MODULES, DlgProc_Modules, NULL);
  815. break;
  816. case IDM_WINDOW_TILE_HORZ:
  817. case IDM_WINDOW_TILE_VERT:
  818. SendMessage(g_hwndMDIClient,
  819. WM_MDITILE,
  820. (IDM_WINDOW_TILE_HORZ == wItemId) ? MDITILE_HORIZONTAL : MDITILE_VERTICAL,
  821. 0L
  822. );
  823. break;
  824. case IDM_WINDOW_CASCADE:
  825. SendMessage(g_hwndMDIClient, WM_MDICASCADE, 0, 0L);
  826. break;
  827. case IDM_WINDOW_ARRANGE:
  828. Arrange();
  829. break;
  830. case IDM_WINDOW_ARRANGE_ICONS:
  831. SendMessage(g_hwndMDIClient, WM_MDIICONARRANGE, 0, 0L);
  832. break;
  833. case IDM_WINDOW_CLOSE_ALL_DOCWIN:
  834. CloseAllWindows(1 << DOC_WINDOW);
  835. break;
  836. case IDM_WINDOW_AUTO_ARRANGE:
  837. g_WinOptions ^= WOPT_AUTO_ARRANGE;
  838. if (g_AutoArrangeWarningCount != 0xffffffff)
  839. {
  840. g_AutoArrangeWarningCount = 0;
  841. }
  842. if (g_Workspace != NULL)
  843. {
  844. g_Workspace->SetUlong(WSP_GLOBAL_WINDOW_OPTIONS,
  845. g_WinOptions);
  846. }
  847. break;
  848. case IDM_WINDOW_ARRANGE_ALL:
  849. g_WinOptions ^= WOPT_ARRANGE_ALL;
  850. if (g_WinOptions & WOPT_AUTO_ARRANGE)
  851. {
  852. Arrange();
  853. }
  854. if (g_Workspace != NULL)
  855. {
  856. g_Workspace->SetUlong(WSP_GLOBAL_WINDOW_OPTIONS,
  857. g_WinOptions);
  858. }
  859. break;
  860. case IDM_WINDOW_OVERLAY_SOURCE:
  861. g_WinOptions ^= WOPT_OVERLAY_SOURCE;
  862. UpdateSourceOverlay();
  863. if (g_Workspace != NULL)
  864. {
  865. g_Workspace->SetUlong(WSP_GLOBAL_WINDOW_OPTIONS,
  866. g_WinOptions);
  867. }
  868. break;
  869. case IDM_WINDOW_AUTO_DISASM:
  870. g_WinOptions ^= WOPT_AUTO_DISASM;
  871. if (g_Workspace != NULL)
  872. {
  873. g_Workspace->SetUlong(WSP_GLOBAL_WINDOW_OPTIONS,
  874. g_WinOptions);
  875. }
  876. break;
  877. case IDM_HELP_CONTENTS:
  878. // Display the table of contents
  879. OpenHelpTopic(HELP_TOPIC_TABLE_OF_CONTENTS);
  880. break;
  881. case IDM_HELP_INDEX:
  882. OpenHelpIndex("");
  883. break;
  884. case IDM_HELP_SEARCH:
  885. OpenHelpSearch("");
  886. break;
  887. case IDM_HELP_ABOUT:
  888. ShellAbout( hwnd, g_MainTitleText, NULL, NULL );
  889. break;
  890. //**************************************************
  891. // The following commands are not accessible via menus
  892. case IDM_DEBUG_SOURCE_MODE:
  893. SetSrcMode_StatusBar(!GetSrcMode_StatusBar());
  894. EnableToolbarControls();
  895. if (GetSrcMode_StatusBar())
  896. {
  897. AddStringCommand(UIC_INVISIBLE_EXECUTE, "l+t");
  898. }
  899. else
  900. {
  901. AddStringCommand(UIC_INVISIBLE_EXECUTE, "l-t");
  902. }
  903. break;
  904. case IDM_DEBUG_SOURCE_MODE_ON:
  905. SetSrcMode_StatusBar(TRUE);
  906. EnableToolbarControls();
  907. AddStringCommand(UIC_INVISIBLE_EXECUTE, "l+t");
  908. break;
  909. case IDM_DEBUG_SOURCE_MODE_OFF:
  910. SetSrcMode_StatusBar(FALSE);
  911. EnableToolbarControls();
  912. AddStringCommand(UIC_INVISIBLE_EXECUTE, "l-t");
  913. break;
  914. case IDM_KDEBUG_TOGGLE_BAUDRATE:
  915. //
  916. // This method is reentrant so we can call it directly
  917. //
  918. g_pUiClient->SetKernelConnectionOptions("cycle_speed");
  919. break;
  920. case IDM_KDEBUG_TOGGLE_DEBUG:
  921. g_pUiClient->GetOtherOutputMask(g_pDbgClient, &OutMask);
  922. OutMask ^= DEBUG_IOUTPUT_KD_PROTOCOL;
  923. g_pUiClient->SetOtherOutputMask(g_pDbgClient, OutMask);
  924. g_pUiControl->SetLogMask(OutMask);
  925. break;
  926. case IDM_KDEBUG_TOGGLE_INITBREAK:
  927. {
  928. ULONG EngOptions;
  929. LPSTR DebugAction;
  930. //
  931. // These methods are reentrant so we can call directly
  932. //
  933. //
  934. // Toggle between the following possibilities-
  935. //
  936. // (0) no breakin
  937. // (1) -b style (same as Control-C up the wire)
  938. // (2) -d style (stop on first dll load).
  939. //
  940. // NB -b and -d could both be on the command line
  941. // but become mutually exclusive via this method.
  942. // (Maybe should be a single enum type).
  943. //
  944. g_pUiControl->GetEngineOptions(&EngOptions);
  945. if (EngOptions & DEBUG_ENGOPT_INITIAL_BREAK)
  946. {
  947. //
  948. // Was type 1, go to type 2.
  949. //
  950. EngOptions |= DEBUG_ENGOPT_INITIAL_MODULE_BREAK;
  951. EngOptions &= ~DEBUG_ENGOPT_INITIAL_BREAK;
  952. DebugAction = "breakin on first symbol load";
  953. }
  954. else if (EngOptions & DEBUG_ENGOPT_INITIAL_MODULE_BREAK)
  955. {
  956. //
  957. // Was type 2, go to type 0.
  958. //
  959. EngOptions &= ~DEBUG_ENGOPT_INITIAL_MODULE_BREAK;
  960. DebugAction = "NOT breakin";
  961. }
  962. else
  963. {
  964. //
  965. // Was type 0, go to type 1.
  966. //
  967. EngOptions |= DEBUG_ENGOPT_INITIAL_BREAK;
  968. DebugAction = "request initial breakpoint";
  969. }
  970. g_pUiControl->SetEngineOptions(EngOptions);
  971. CmdLogFmt("Will %s at next boot.\n", DebugAction);
  972. }
  973. break;
  974. case IDM_KDEBUG_RECONNECT:
  975. //
  976. // This method is reentrant so we can call it directly
  977. //
  978. g_pUiClient->SetKernelConnectionOptions("resync");
  979. break;
  980. default:
  981. goto DefProcessing;
  982. }
  983. }
  984. break;
  985. case WM_INITMENU:
  986. // TOOLBAR handling - a menu item has been selected.
  987. // Catches keyboard menu selecting.
  988. if (GetWindowLong(hwnd, GWL_STYLE) & WS_ICONIC) {
  989. break;
  990. }
  991. InitializeMenu((HMENU)wParam);
  992. break;
  993. case WM_MENUSELECT:
  994. {
  995. WORD wMenuItem = (UINT) LOWORD(wParam); // menu item or submenu index
  996. WORD wFlags = (UINT) HIWORD(wParam); // menu flags
  997. HMENU hmenu = (HMENU) lParam; // handle of menu clicked
  998. g_LastMenuId = LOWORD(wParam);
  999. if (0xFFFF == wFlags && NULL == hmenu)
  1000. {
  1001. //
  1002. // Menu is closed, clear the Status Bar.
  1003. //
  1004. s_MenuItemSelected = 0;
  1005. SetMessageText_StatusBar(SYS_Clear);
  1006. }
  1007. else if ( wFlags & MF_POPUP )
  1008. {
  1009. //
  1010. // Get the menu ID for the pop-up menu.
  1011. //
  1012. s_MenuItemSelected =
  1013. ((wMenuItem + 1) * IDM_BASE) | MENU_SIGNATURE;
  1014. }
  1015. else
  1016. {
  1017. //
  1018. // Get the menu ID for the menu item.
  1019. //
  1020. s_MenuItemSelected = wMenuItem;
  1021. }
  1022. }
  1023. break;
  1024. case WM_ENTERIDLE:
  1025. SetMessageText_StatusBar(s_MenuItemSelected);
  1026. break;
  1027. case WM_CLOSE:
  1028. TerminateApplication(TRUE);
  1029. break;
  1030. case WM_DRAWITEM:
  1031. switch (wParam)
  1032. {
  1033. case IDC_STATUS_BAR:
  1034. OwnerDrawItem_StatusBar((LPDRAWITEMSTRUCT) lParam);
  1035. return TRUE;
  1036. }
  1037. goto DefProcessing;
  1038. case WM_DESTROY:
  1039. TerminateStatusBar();
  1040. PostQuitMessage(0);
  1041. break;
  1042. case WM_MOVE:
  1043. // This is to let the edit window
  1044. // set a position of IME conversion window
  1045. if ( MDIGetActive(g_hwndMDIClient, NULL) )
  1046. {
  1047. SendMessage(MDIGetActive(g_hwndMDIClient, NULL), WM_MOVE, 0, 0);
  1048. }
  1049. if (g_Workspace != NULL)
  1050. {
  1051. g_Workspace->AddDirty(WSPF_DIRTY_WINDOWS);
  1052. }
  1053. break;
  1054. case WM_SIZE:
  1055. {
  1056. RECT rc;
  1057. int nToolbarHeight = 0; // Toolbar
  1058. int nStatusHeight = 0; // status bar
  1059. int OldToolbarHeight = 0;
  1060. if ( g_ShowToolbar )
  1061. {
  1062. GetWindowRect(GetHwnd_Toolbar(), &rc);
  1063. OldToolbarHeight = rc.bottom - rc.top;
  1064. }
  1065. GetClientRect (hwnd, &rc);
  1066. // First lets resize the toolbar
  1067. SendMessage(GetHwnd_Toolbar(), WM_SIZE, wParam,
  1068. MAKELPARAM(rc.right - rc.left, rc.bottom - rc.top));
  1069. // 2nd resize the status bar
  1070. WM_SIZE_StatusBar(wParam, MAKELPARAM(rc.right - rc.left, rc.bottom - rc.top));
  1071. //On creation or resize, size the MDI client,
  1072. //status line and toolbar.
  1073. if ( g_ShowStatusBar )
  1074. {
  1075. RECT rcStatusBar;
  1076. GetWindowRect(GetHwnd_StatusBar(), &rcStatusBar);
  1077. nStatusHeight = rcStatusBar.bottom - rcStatusBar.top;
  1078. }
  1079. if (g_ShowToolbar)
  1080. {
  1081. RECT rcToolbar;
  1082. GetWindowRect(GetHwnd_Toolbar(), &rcToolbar);
  1083. nToolbarHeight = rcToolbar.bottom - rcToolbar.top;
  1084. }
  1085. g_MdiWidth = rc.right - rc.left;
  1086. g_MdiHeight = rc.bottom - rc.top - nStatusHeight - nToolbarHeight;
  1087. MoveWindow(g_hwndMDIClient,
  1088. rc.left, rc.top + nToolbarHeight,
  1089. g_MdiWidth, g_MdiHeight,
  1090. TRUE
  1091. );
  1092. SendMessage(g_hwndMDIClient, WM_MDIICONARRANGE, 0, 0L);
  1093. // This is to let the edit window
  1094. // set a position of IME conversion window
  1095. if ( MDIGetActive(g_hwndMDIClient, NULL) )
  1096. {
  1097. SendMessage(MDIGetActive(g_hwndMDIClient, NULL), WM_MOVE, 0, 0);
  1098. }
  1099. if (OldToolbarHeight != nToolbarHeight)
  1100. {
  1101. RedrawWindow(g_hwndMDIClient, NULL, NULL,
  1102. RDW_ERASE | RDW_INVALIDATE | RDW_FRAME |
  1103. RDW_UPDATENOW | RDW_ALLCHILDREN);
  1104. }
  1105. }
  1106. if (g_Workspace != NULL)
  1107. {
  1108. g_Workspace->AddDirty(WSPF_DIRTY_WINDOWS);
  1109. }
  1110. break;
  1111. case WU_START_ENGINE:
  1112. {
  1113. //
  1114. // Go start the debugger engine if the appropriate debugger
  1115. // parameters were passed in
  1116. //
  1117. DWORD Id;
  1118. // Start the engine thread.
  1119. g_EngineThread = CreateThread(NULL, 0, EngineLoop, NULL, 0, &Id);
  1120. if (g_EngineThread == NULL)
  1121. {
  1122. ErrorBox(NULL, 0, ERR_Engine_Failed);
  1123. break;
  1124. }
  1125. }
  1126. break;
  1127. case WU_ENGINE_STARTED:
  1128. if ((HRESULT)lParam == S_OK)
  1129. {
  1130. UpdateTitleSessionText();
  1131. if (GetCmdHwnd() == NULL)
  1132. {
  1133. // If the engine is started, show the command window
  1134. // by default
  1135. New_OpenDebugWindow(CMD_WINDOW, FALSE, NTH_OPEN_ALWAYS);
  1136. }
  1137. }
  1138. break;
  1139. case WU_ENGINE_IDLE:
  1140. if (g_InitialCommand != NULL)
  1141. {
  1142. CmdLogFmt("Processing initial command '%s'\n",
  1143. g_InitialCommand);
  1144. CmdExecuteCmd(g_InitialCommand, UIC_EXECUTE);
  1145. free(g_InitialCommand);
  1146. g_InitialCommand = NULL;
  1147. }
  1148. break;
  1149. case WU_SWITCH_WORKSPACE:
  1150. UiDelayedSwitchWorkspace();
  1151. break;
  1152. case WU_UPDATE:
  1153. // Global engine status has changed, such as
  1154. // the current process and thread. Update
  1155. // global UI elements.
  1156. SetSysPidTid_StatusBar(g_CurSystemId, g_CurSystemName,
  1157. g_CurProcessId, g_CurProcessSysId,
  1158. g_CurThreadId, g_CurThreadSysId);
  1159. if (wParam == UPDATE_BUFFER)
  1160. {
  1161. SetSrcMode_StatusBar(lParam == DEBUG_LEVEL_SOURCE);
  1162. }
  1163. break;
  1164. DefProcessing:
  1165. default:
  1166. return DefFrameProc(hwnd, g_hwndMDIClient, message, wParam, lParam);
  1167. }
  1168. return (0L);
  1169. }
  1170. void
  1171. TerminateApplication(BOOL Cancellable)
  1172. {
  1173. if (g_EngineThreadId != 0 &&
  1174. (g_AttachProcessFlags & DEBUG_ATTACH_NONINVASIVE))
  1175. {
  1176. if (QuestionBox(STR_Abandoning_Noninvasive_Debuggee, MB_OKCANCEL) ==
  1177. IDCANCEL)
  1178. {
  1179. return;
  1180. }
  1181. }
  1182. if (g_Workspace != NULL)
  1183. {
  1184. if (g_Workspace->Flush(FALSE, Cancellable) == S_FALSE)
  1185. {
  1186. // User cancelled things so don't terminate.
  1187. return;
  1188. }
  1189. }
  1190. // Destroy windows to get window cleanup behavior.
  1191. // This must occur before g_Exit is set so that
  1192. // the engine thread doesn't come around and kill things.
  1193. DestroyWindow(g_hwndFrame);
  1194. g_Exit = TRUE;
  1195. ULONG Code;
  1196. if (!g_RemoteClient && g_DebugCommandLine != NULL)
  1197. {
  1198. // Return exit code of last process to exit.
  1199. Code = g_LastProcessExitCode;
  1200. }
  1201. else
  1202. {
  1203. Code = S_OK;
  1204. }
  1205. if (g_EngineThreadId != 0)
  1206. {
  1207. UpdateEngine();
  1208. // If the engine thread is idle it'll exit and call
  1209. // ExitDebugger. The engine may be waiting and
  1210. // not responsive, though, so only wait a little while before
  1211. // bailing out.
  1212. Sleep(1000);
  1213. if (g_pUiClient != NULL && !g_RemoteClient)
  1214. {
  1215. g_pUiClient->EndSession(DEBUG_END_REENTRANT);
  1216. }
  1217. ExitProcess(Code);
  1218. }
  1219. else
  1220. {
  1221. ExitDebugger(g_pUiClient, Code);
  1222. }
  1223. }