windows-nt/Source/XPSP1/NT/sdktools/debuggers/windbg/prcmain.cpp
2020-09-26 16:20:57 +08:00

1291 lines
40 KiB
C++

/*++
Copyright (c) 1999-2001 Microsoft Corporation
Module Name:
prcmain.cpp
Abstract:
Contains the main window proc.
--*/
#include "precomp.hxx"
#pragma hdrstop
#define TOOLBAR_UPDATE_TIMER_ID 0x100
#define WINDBG_START_DLG_FLAGS (OFN_HIDEREADONLY | \
OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST)
// Path of the last files opened from a file open dlg box.
TCHAR g_ExeFilePath[_MAX_PATH];
TCHAR g_DumpFilePath[_MAX_PATH];
TCHAR g_SrcFilePath[_MAX_PATH];
BOOL g_fCheckFileDate;
// Last menu id & id state.
UINT g_LastMenuId;
UINT g_LastMenuIdState;
ULONG g_LastMapLetter;
void
ShowMapDlg(void)
{
CONNECTDLGSTRUCT ConnDlg;
NETRESOURCE NetRes;
ZeroMemory(&NetRes, sizeof(NetRes));
NetRes.dwType = RESOURCETYPE_DISK;
ConnDlg.cbStructure = sizeof(ConnDlg);
ConnDlg.hwndOwner = g_hwndFrame;
ConnDlg.lpConnRes = &NetRes;
ConnDlg.dwFlags = CONNDLG_USE_MRU;
if (WNetConnectionDialog1(&ConnDlg) == NO_ERROR)
{
g_LastMapLetter = ConnDlg.dwDevNum;
}
}
void
ShowDisconnDlg(void)
{
WNetDisconnectDialog(g_hwndFrame, RESOURCETYPE_DISK);
}
void
SaveFileOpenPath(PTSTR Path, PTSTR Global, ULONG WspIndex)
{
TCHAR Drive[_MAX_DRIVE];
TCHAR Dir[_MAX_DIR];
TCHAR NewPath[_MAX_PATH];
_tsplitpath(Path, Drive, Dir, NULL, NULL);
_tmakepath(NewPath, Drive, Dir, NULL, NULL);
if (_strcmpi(NewPath, Global) != 0)
{
_tcscpy(Global, NewPath);
if (g_Workspace != NULL)
{
g_Workspace->SetString(WspIndex, Global);
}
}
}
/*** MainWndProc
**
** Synopsis:
**
** Entry:
**
** Returns:
**
** Description:
** Processes window messages.
**
*/
LRESULT
CALLBACK
MainWndProc(
HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam
)
{
static UINT s_MenuItemSelected;
HWND CommonWin;
PCOMMONWIN_DATA CommonWinData;
HRESULT Status;
ULONG OutMask;
if (message == g_FindMsgString)
{
FINDREPLACE* FindRep = (FINDREPLACE*)lParam;
if (g_FindLast != NULL)
{
// Clear old find.
g_FindLast->Find(NULL, 0);
g_FindLast = NULL;
}
if (FindRep->Flags & FR_DIALOGTERM)
{
// Dialog has closed.
g_FindDialog = NULL;
}
else
{
CommonWin = MDIGetActive(g_hwndMDIClient, NULL);
if (CommonWin != NULL &&
(CommonWinData = GetCommonWinData(CommonWin)) != NULL)
{
CommonWinData->Find(FindRep->lpstrFindWhat,
(FindRep->Flags & (FR_DOWN | FR_MATCHCASE |
FR_WHOLEWORD)));
g_FindLast = CommonWinData;
}
}
return 0;
}
switch (message)
{
case WM_CREATE:
{
CLIENTCREATESTRUCT ccs;
TCHAR szClass[MAX_MSG_TXT];
// Find window menu where children will be listed.
ccs.hWindowMenu = GetSubMenu(GetMenu(hwnd), WINDOWMENU);
ccs.idFirstChild = IDM_FIRSTCHILD;
// Create the MDI client filling the client area.
g_hwndMDIClient = CreateWindow(_T("mdiclient"),
NULL,
WS_CHILD | WS_CLIPCHILDREN,
0, 0, 0, 0,
hwnd,
(HMENU) 0xCAC,
g_hInst,
(PTSTR)&ccs
);
if (g_hwndMDIClient == NULL)
{
return -1;
}
//
// Nothing interesting, here, just
// trying to turn the Toolbar & Status bar into a
// black box, so that the variables, etc. aren't
// scattered all over the place.
//
if (!CreateToolbar(hwnd))
{
return -1;
}
if (!CreateStatusBar(hwnd))
{
return -1;
}
ShowWindow(g_hwndMDIClient, SW_SHOW);
InitializeMenu(GetMenu(hwnd));
g_hmenuMain = GetMenu(hwnd);
if (g_hmenuMain == NULL)
{
return -1;
}
//
// Create a one second timer to constantly update the state of the toolbar
//
SetTimer(hwnd, TOOLBAR_UPDATE_TIMER_ID, 1000, NULL);
}
break;
case WM_TIMER:
EnableToolbarControls();
return 0;
case WM_NOTIFY:
{
if (lParam == 0)
{
break;
}
LPNMHDR lpnmhdr = (LPNMHDR) lParam;
switch (lpnmhdr->code)
{
case TTN_NEEDTEXT:
{
LPTOOLTIPTEXT lpToolTipText = (LPTOOLTIPTEXT) lParam;
lpToolTipText->lpszText = GetToolTipTextFor_Toolbar
((UINT) lpToolTipText->hdr.idFrom);
}
break;
}
}
break;
case WM_QUERYOPEN:
if (g_fCheckFileDate)
{
g_fCheckFileDate = FALSE;
PostMessage(g_hwndFrame, WM_ACTIVATEAPP, 1, 0L);
}
goto DefProcessing;
case WM_COMMAND:
{
WORD wNotifyCode = HIWORD(wParam); // notification code
WORD wItemId = LOWORD(wParam); // item, control, or
// accelerator identifier
HWND hwndCtl = (HWND) lParam; // handle of control
switch (wItemId)
{
case IDM_FILE_OPEN_EXECUTABLE:
{
PTSTR Path;
DWORD Flags = WINDBG_START_DLG_FLAGS;
Path = (PTSTR)malloc(_MAX_PATH * 4 * sizeof(TCHAR));
if (Path == NULL)
{
break;
}
*Path = 0;
if (StartFileDlg(hwnd,
DLG_Browse_Executable_Title,
DEF_Ext_EXE,
IDM_FILE_OPEN,
IDD_DLG_FILEOPEN_EXPLORER_EXTENSION_EXE_ARGS,
g_ExeFilePath,
Path,
&Flags,
OpenExeWithArgsHookProc) &&
*Path)
{
_tcscat(Path, szOpenExeArgs);
SetAllocString(&g_DebugCommandLine, Path);
if (g_ExplicitWorkspace && g_Workspace != NULL)
{
g_Workspace->
SetUlong(WSP_GLOBAL_EXE_CREATE_FLAGS,
g_DebugCreateFlags);
g_Workspace->
SetString(WSP_GLOBAL_EXE_COMMAND_LINE,
Path);
}
SaveFileOpenPath(Path, g_ExeFilePath,
WSP_GLOBAL_EXE_FILE_PATH);
StartDebugging();
}
if (g_DebugCommandLine != Path)
{
free(Path);
}
}
break;
case IDM_FILE_ATTACH:
StartDialog(IDD_DLG_ATTACH_PROCESS, DlgProc_AttachProcess,
NULL);
break;
case IDM_FILE_OPEN_CRASH_DUMP:
{
PTSTR Path;
DWORD Flags = WINDBG_START_DLG_FLAGS;
Path = (PTSTR)malloc(_MAX_PATH * sizeof(TCHAR));
if (Path == NULL)
{
break;
}
Dbg(LoadString(g_hInst, DEF_Dump_File,
Path, _MAX_PATH));
if (StartFileDlg(hwnd,
DLG_Browse_CrashDump_Title,
DEF_Ext_DUMP,
0,
0,
g_DumpFilePath,
Path,
&Flags,
NULL))
{
SetAllocString(&g_DumpFile, Path);
if (g_ExplicitWorkspace && g_Workspace != NULL)
{
g_Workspace->
SetString(WSP_GLOBAL_DUMP_FILE_NAME,
Path);
}
SaveFileOpenPath(Path, g_DumpFilePath,
WSP_GLOBAL_DUMP_FILE_PATH);
StartDebugging();
}
if (g_DumpFile != Path)
{
free(Path);
}
}
break;
case IDM_FILE_CONNECT_TO_REMOTE:
StartDialog(IDD_DLG_CONNECTTOREMOTE, DlgProc_ConnectToRemote,
NULL);
break;
case IDM_FILE_KERNEL_DEBUG:
StartKdPropSheet();
break;
case IDM_FILE_SYMBOL_PATH:
StartDialog(IDD_DLG_SYMBOLS, DlgProc_SymbolPath, NULL);
break;
case IDM_FILE_IMAGE_PATH:
StartDialog(IDD_DLG_IMAGE_PATH, DlgProc_ImagePath, NULL);
break;
case IDM_FILE_SOURCE_PATH:
StartDialog(IDD_DLG_SOURCE_PATH, DlgProc_SourcePath, NULL);
break;
case IDM_FILE_OPEN_WORKSPACE:
StartDialog(IDD_DLG_WORKSPACE_IO, DlgProc_OpenWorkspace,
FALSE);
break;
case IDM_FILE_SAVE_WORKSPACE:
// No prompt, because we know the user wants to save.
if (g_Workspace != NULL)
{
g_Workspace->Flush(TRUE, FALSE);
}
break;
case IDM_FILE_SAVE_WORKSPACE_AS:
if (g_Workspace != NULL)
{
StartDialog(IDD_DLG_WORKSPACE_IO, DlgProc_SaveWorkspaceAs,
TRUE);
}
break;
case IDM_FILE_CLEAR_WORKSPACE:
StartDialog(IDD_DLG_CLEAR_WORKSPACE, DlgProc_ClearWorkspace,
NULL);
break;
case IDM_FILE_DELETE_WORKSPACES:
StartDialog(IDD_DLG_DELETE_WORKSPACES,
DlgProc_DeleteWorkspaces, NULL);
break;
case IDM_FILE_MAP_NET_DRIVE:
ShowMapDlg();
break;
case IDM_FILE_DISCONN_NET_DRIVE:
ShowDisconnDlg();
break;
case IDM_FILE_MRU_FILE1:
case IDM_FILE_MRU_FILE2:
case IDM_FILE_MRU_FILE3:
case IDM_FILE_MRU_FILE4:
case IDM_FILE_MRU_FILE5:
case IDM_FILE_MRU_FILE6:
case IDM_FILE_MRU_FILE7:
case IDM_FILE_MRU_FILE8:
case IDM_FILE_MRU_FILE9:
case IDM_FILE_MRU_FILE10:
case IDM_FILE_MRU_FILE11:
case IDM_FILE_MRU_FILE12:
case IDM_FILE_MRU_FILE13:
case IDM_FILE_MRU_FILE14:
case IDM_FILE_MRU_FILE15:
case IDM_FILE_MRU_FILE16:
case IDM_FILE_OPEN:
{
TCHAR Path[_MAX_PATH];
if (IDM_FILE_OPEN == wItemId)
{
DWORD dwFlags = WINDBG_START_DLG_FLAGS;
Path[0] = 0;
if (!StartFileDlg(hwnd,
DLG_Open_Filebox_Title,
DEF_Ext_SOURCE,
IDM_FILE_OPEN,
0,
g_SrcFilePath,
Path,
&dwFlags,
DlgFile
))
{
// User canceled, bail out
break;
}
}
else
{
WORD wFileIdx = wItemId - IDM_FILE_MRU_FILE1;
// Sanity check
Assert(wFileIdx < MAX_MRU_FILES);
_tcscpy(Path, g_MruFiles[wFileIdx]->FileName);
}
OpenOrActivateFile(Path, NULL, -1, TRUE, TRUE);
SaveFileOpenPath(Path, g_SrcFilePath,
WSP_GLOBAL_SRC_FILE_PATH);
}
break;
case IDM_FILE_CLOSE:
{
HWND hwndChild = MDIGetActive(g_hwndMDIClient, NULL);
if (hwndChild)
{
SendMessage(g_hwndMDIClient, WM_MDIDESTROY,
(WPARAM)hwndChild, 0L);
}
}
break;
case IDM_FILE_EXIT:
PostMessage(hwnd, WM_CLOSE, 0, 0L);
break;
case IDM_EDIT_COPY:
CommonWin = MDIGetActive(g_hwndMDIClient, NULL);
if (!CommonWin)
{
return 0;
}
CommonWinData = GetCommonWinData(CommonWin);
if (CommonWinData)
{
CommonWinData->Copy();
}
break;
case IDM_EDIT_PASTE:
CommonWin = MDIGetActive(g_hwndMDIClient, NULL);
if (!CommonWin)
{
return 0;
}
CommonWinData = GetCommonWinData(CommonWin);
if (CommonWinData)
{
CommonWinData->Paste();
}
break;
case IDM_EDIT_CUT:
CommonWin = MDIGetActive(g_hwndMDIClient, NULL);
if (!CommonWin)
{
return 0;
}
CommonWinData = GetCommonWinData(CommonWin);
if (CommonWinData)
{
CommonWinData->Cut();
}
break;
case IDM_EDIT_SELECT_ALL:
CommonWin = MDIGetActive(g_hwndMDIClient, NULL);
if (CommonWin == NULL)
{
return 0;
}
CommonWinData = GetCommonWinData(CommonWin);
if (CommonWinData != NULL)
{
CommonWinData->SelectAll();
}
break;
case IDM_EDIT_ADD_TO_COMMAND_HISTORY:
StartDialog(IDD_DLG_ADD_TO_COMMAND_HISTORY,
DlgProc_AddToCommandHistory, FALSE);
break;
case IDM_EDIT_CLEAR_COMMAND_HISTORY:
ClearCmdWindow();
break;
case IDM_EDIT_FIND:
// FindNext box may already be there.
if (g_FindDialog != NULL)
{
SetFocus(g_FindDialog);
}
else
{
ZeroMemory(&g_FindRep, sizeof(g_FindRep));
g_FindRep.lStructSize = sizeof(g_FindRep);
g_FindRep.hwndOwner = g_hwndFrame;
g_FindRep.Flags = FR_DOWN;
g_FindRep.lpstrFindWhat = g_FindText;
g_FindRep.wFindWhatLen = sizeof(g_FindText);
g_FindDialog = FindText(&g_FindRep);
}
break;
case IDM_EDIT_PROPERTIES:
{
HWND hwndmdi = MDIGetActive(g_hwndMDIClient, NULL);
if (hwndmdi) {
MEMWIN_DATA * pMemWinData = GetMemWinData(hwndmdi);
Assert(pMemWinData);
if ( pMemWinData->HasEditableProperties() ) {
if (pMemWinData->EditProperties()) {
pMemWinData->UiRequestRead();
}
}
}
}
break;
case IDM_EDIT_GOTO_LINE:
CommonWin = MDIGetActive(g_hwndMDIClient, NULL);
if (CommonWin)
{
CommonWinData = GetCommonWinData(CommonWin);
Assert(CommonWinData);
StartDialog(IDD_DLG_GOTO_LINE, DlgProc_GotoLine,
(LPARAM)CommonWinData);
}
break;
case IDM_EDIT_GOTO_ADDRESS:
StartDialog(IDD_DLG_GOTO_ADDRESS, DlgProc_GotoAddress, NULL);
break;
case IDM_VIEW_REGISTERS:
New_OpenDebugWindow(CPU_WINDOW, TRUE, NTH_OPEN_ALWAYS); // User activated
EnableToolbarControls();
break;
case IDM_VIEW_WATCH:
New_OpenDebugWindow(WATCH_WINDOW, TRUE, NTH_OPEN_ALWAYS); // User activated
EnableToolbarControls();
break;
case IDM_VIEW_LOCALS:
New_OpenDebugWindow(LOCALS_WINDOW, TRUE, NTH_OPEN_ALWAYS); // User activated
EnableToolbarControls();
break;
case IDM_VIEW_DISASM:
New_OpenDebugWindow(DISASM_WINDOW, TRUE, NTH_OPEN_ALWAYS); // User activated
EnableToolbarControls();
break;
case IDM_VIEW_COMMAND:
New_OpenDebugWindow(CMD_WINDOW, FALSE, NTH_OPEN_ALWAYS); // Not user activated
EnableToolbarControls();
break;
case IDM_VIEW_MEMORY:
New_OpenDebugWindow(MEM_WINDOW, TRUE, NTH_OPEN_ALWAYS); // User activated
EnableToolbarControls();
break;
case IDM_VIEW_CALLSTACK:
New_OpenDebugWindow(CALLS_WINDOW, TRUE, NTH_OPEN_ALWAYS); // User activated
EnableToolbarControls();
break;
case IDM_VIEW_SCRATCH:
New_OpenDebugWindow(SCRATCH_PAD_WINDOW, TRUE, NTH_OPEN_ALWAYS); // User activated
EnableToolbarControls();
break;
case IDM_VIEW_PROCESS_THREAD:
New_OpenDebugWindow(PROCESS_THREAD_WINDOW, TRUE, NTH_OPEN_ALWAYS); // User activated
EnableToolbarControls();
break;
case IDM_VIEW_TOGGLE_VERBOSE:
g_pUiClient->GetOtherOutputMask(g_pDbgClient, &OutMask);
OutMask ^= DEBUG_OUTPUT_VERBOSE;
g_pUiClient->SetOtherOutputMask(g_pDbgClient, OutMask);
g_pUiControl->SetLogMask(OutMask);
CmdLogFmt("Verbose mode %s.\n",
(OutMask & DEBUG_OUTPUT_VERBOSE) ? "ON" : "OFF");
CheckMenuItem(g_hmenuMain,
IDM_VIEW_TOGGLE_VERBOSE,
(OutMask & DEBUG_OUTPUT_VERBOSE) ?
MF_CHECKED : MF_UNCHECKED);
break;
case IDM_VIEW_SHOW_VERSION:
Status = g_pUiControl->
OutputVersionInformation(DEBUG_OUTCTL_AMBIENT);
if (Status == HRESULT_FROM_WIN32(ERROR_BUSY))
{
CmdLogFmt("Engine is busy, try again\n");
}
else if (Status != S_OK)
{
CmdLogFmt("Unable to show version information, 0x%X\n",
Status);
}
break;
case IDM_VIEW_TOOLBAR:
{
BOOL bVisible = !IsWindowVisible(GetHwnd_Toolbar());
CheckMenuItem(g_hmenuMain,
IDM_VIEW_TOOLBAR,
bVisible ? MF_CHECKED : MF_UNCHECKED
);
Show_Toolbar(bVisible);
if (g_Workspace != NULL)
{
g_Workspace->SetUlong(WSP_GLOBAL_VIEW_TOOL_BAR,
bVisible);
}
}
break;
case IDM_VIEW_STATUS:
{
BOOL bVisible = !IsWindowVisible(GetHwnd_StatusBar());
CheckMenuItem(g_hmenuMain,
IDM_VIEW_STATUS,
bVisible ? MF_CHECKED : MF_UNCHECKED
);
Show_StatusBar(bVisible);
if (g_Workspace != NULL)
{
g_Workspace->SetUlong(WSP_GLOBAL_VIEW_STATUS_BAR,
bVisible);
}
}
break;
case IDM_VIEW_FONT:
SelectFont(hwnd, FONT_FIXED);
break;
case IDM_VIEW_OPTIONS:
StartDialog(IDD_DLG_OPTIONS, DlgProc_Options, NULL);
break;
case IDM_DEBUG_RESTART:
if (g_EngineThreadId)
{
AddEnumCommand(UIC_RESTART);
}
else if (g_CommandLineStart == 1)
{
ParseCommandLine(FALSE);
}
break;
case IDM_DEBUG_EVENT_FILTERS:
StartDialog(IDD_DLG_EVENT_FILTERS, DlgProc_EventFilters, NULL);
break;
case IDM_DEBUG_GO:
CmdExecuteCmd(_T("g"), UIC_EXECUTE);
break;
case IDM_DEBUG_GO_HANDLED:
CmdExecuteCmd(_T("gh"), UIC_EXECUTE);
break;
case IDM_DEBUG_GO_UNHANDLED:
CmdExecuteCmd(_T("gn"), UIC_EXECUTE);
break;
case IDM_DEBUG_RUNTOCURSOR:
{
char CodeExpr[MAX_OFFSET_EXPR];
CommonWin = MDIGetActive(g_hwndMDIClient, NULL);
if (CommonWin != NULL &&
(CommonWinData = GetCommonWinData(CommonWin)) != NULL &&
(CommonWinData->CodeExprAtCaret(CodeExpr, NULL)))
{
PrintStringCommand(UIC_EXECUTE, "g %s", CodeExpr);
}
break;
}
case IDM_DEBUG_STEPINTO:
CmdExecuteCmd( _T("t"), UIC_EXECUTE );
break;
case IDM_DEBUG_STEPOVER:
CmdExecuteCmd( _T("p"), UIC_EXECUTE );
break;
case IDM_DEBUG_STEPOUT:
if (g_EventReturnAddr != DEBUG_INVALID_OFFSET)
{
PrintStringCommand(UIC_EXECUTE,
"g 0x%I64x", g_EventReturnAddr);
}
break;
case IDM_DEBUG_BREAK:
g_pUiControl->SetInterrupt(DEBUG_INTERRUPT_ACTIVE);
break;
case IDM_DEBUG_STOPDEBUGGING:
StopDebugging(HIWORD(wParam) != 0xffff);
break;
case IDM_EDIT_TOGGLEBREAKPOINT:
case IDM_EDIT_BREAKPOINTS:
if ( !IS_TARGET_HALTED() )
{
ErrorBox(NULL, 0, ERR_Cant_Modify_BP_While_Running);
break;
}
if (wItemId == IDM_EDIT_TOGGLEBREAKPOINT)
{
// If a disassembly or source window is up
// try and toggle a breakpoint at the current
// line.
CommonWin = MDIGetActive(g_hwndMDIClient, NULL);
if (CommonWin != NULL &&
(CommonWinData =
GetCommonWinData(CommonWin)) != NULL)
{
if (CommonWinData->m_enumType == DISASM_WINDOW ||
CommonWinData->m_enumType == DOC_WINDOW ||
CommonWinData->m_enumType == CALLS_WINDOW)
{
CommonWinData->ToggleBpAtCaret();
break;
}
}
}
// menu got us here or we are not in a code window
StartDialog(IDD_DLG_BREAKPOINTS, DlgProc_SetBreak, NULL);
break;
case IDM_EDIT_LOG_FILE:
StartDialog(IDD_DLG_LOG_FILE, DlgProc_LogFile, NULL);
break;
case IDM_DEBUG_MODULES:
StartDialog(IDD_DLG_MODULES, DlgProc_Modules, NULL);
break;
case IDM_WINDOW_TILE_HORZ:
case IDM_WINDOW_TILE_VERT:
SendMessage(g_hwndMDIClient,
WM_MDITILE,
(IDM_WINDOW_TILE_HORZ == wItemId) ? MDITILE_HORIZONTAL : MDITILE_VERTICAL,
0L
);
break;
case IDM_WINDOW_CASCADE:
SendMessage(g_hwndMDIClient, WM_MDICASCADE, 0, 0L);
break;
case IDM_WINDOW_ARRANGE_ICONS:
SendMessage(g_hwndMDIClient, WM_MDIICONARRANGE, 0, 0L);
break;
case IDM_WINDOW_ARRANGE:
Arrange();
break;
case IDM_WINDOW_AUTO_ARRANGE:
g_WinOptions ^= WOPT_AUTO_ARRANGE;
if (g_AutoArrangeWarningCount != 0xffffffff)
{
g_AutoArrangeWarningCount = 0;
}
if (g_Workspace != NULL)
{
g_Workspace->SetUlong(WSP_GLOBAL_WINDOW_OPTIONS,
g_WinOptions);
}
break;
case IDM_WINDOW_ARRANGE_ALL:
g_WinOptions ^= WOPT_ARRANGE_ALL;
if (g_WinOptions & WOPT_AUTO_ARRANGE)
{
Arrange();
}
if (g_Workspace != NULL)
{
g_Workspace->SetUlong(WSP_GLOBAL_WINDOW_OPTIONS,
g_WinOptions);
}
break;
case IDM_WINDOW_OVERLAY_SOURCE:
g_WinOptions ^= WOPT_OVERLAY_SOURCE;
UpdateSourceOverlay();
if (g_Workspace != NULL)
{
g_Workspace->SetUlong(WSP_GLOBAL_WINDOW_OPTIONS,
g_WinOptions);
}
break;
case IDM_WINDOW_AUTO_DISASM:
g_WinOptions ^= WOPT_AUTO_DISASM;
if (g_Workspace != NULL)
{
g_Workspace->SetUlong(WSP_GLOBAL_WINDOW_OPTIONS,
g_WinOptions);
}
break;
case IDM_HELP_CONTENTS:
// Display the table of contents
OpenHelpTopic(HELP_TOPIC_TABLE_OF_CONTENTS);
break;
case IDM_HELP_INDEX:
OpenHelpIndex("");
break;
case IDM_HELP_SEARCH:
OpenHelpSearch("");
break;
case IDM_HELP_ABOUT:
ShellAbout( hwnd, g_MainTitleText, NULL, NULL );
break;
//**************************************************
// The following commands are not accessible via menus
case IDM_DEBUG_SOURCE_MODE:
SetSrcMode_StatusBar(!GetSrcMode_StatusBar());
EnableToolbarControls();
if (GetSrcMode_StatusBar())
{
AddStringCommand(UIC_INVISIBLE_EXECUTE, "l+t");
}
else
{
AddStringCommand(UIC_INVISIBLE_EXECUTE, "l-t");
}
break;
case IDM_DEBUG_SOURCE_MODE_ON:
SetSrcMode_StatusBar(TRUE);
EnableToolbarControls();
AddStringCommand(UIC_INVISIBLE_EXECUTE, "l+t");
break;
case IDM_DEBUG_SOURCE_MODE_OFF:
SetSrcMode_StatusBar(FALSE);
EnableToolbarControls();
AddStringCommand(UIC_INVISIBLE_EXECUTE, "l-t");
break;
case IDM_KDEBUG_TOGGLE_BAUDRATE:
//
// This method is reentrant so we can call it directly
//
g_pUiClient->SetKernelConnectionOptions("cycle_speed");
break;
case IDM_KDEBUG_TOGGLE_DEBUG:
g_pUiClient->GetOtherOutputMask(g_pDbgClient, &OutMask);
OutMask ^= DEBUG_IOUTPUT_KD_PROTOCOL;
g_pUiClient->SetOtherOutputMask(g_pDbgClient, OutMask);
g_pUiControl->SetLogMask(OutMask);
break;
case IDM_KDEBUG_TOGGLE_INITBREAK:
{
ULONG EngOptions;
LPSTR DebugAction;
//
// These methods are reentrant so we can call directly
//
//
// Toggle between the following possibilities-
//
// (0) no breakin
// (1) -b style (same as Control-C up the wire)
// (2) -d style (stop on first dll load).
//
// NB -b and -d could both be on the command line
// but become mutually exclusive via this method.
// (Maybe should be a single enum type).
//
g_pUiControl->GetEngineOptions(&EngOptions);
if (EngOptions & DEBUG_ENGOPT_INITIAL_BREAK)
{
//
// Was type 1, go to type 2.
//
EngOptions |= DEBUG_ENGOPT_INITIAL_MODULE_BREAK;
EngOptions &= ~DEBUG_ENGOPT_INITIAL_BREAK;
DebugAction = "breakin on first symbol load";
}
else if (EngOptions & DEBUG_ENGOPT_INITIAL_MODULE_BREAK)
{
//
// Was type 2, go to type 0.
//
EngOptions &= ~DEBUG_ENGOPT_INITIAL_MODULE_BREAK;
DebugAction = "NOT breakin";
}
else
{
//
// Was type 0, go to type 1.
//
EngOptions |= DEBUG_ENGOPT_INITIAL_BREAK;
DebugAction = "request initial breakpoint";
}
g_pUiControl->SetEngineOptions(EngOptions);
CmdLogFmt("Will %s at next boot.\n", DebugAction);
}
break;
case IDM_KDEBUG_RECONNECT:
//
// This method is reentrant so we can call it directly
//
g_pUiClient->SetKernelConnectionOptions("resync");
break;
default:
goto DefProcessing;
}
}
break;
case WM_INITMENU:
// TOOLBAR handling - a menu item has been selected.
// Catches keyboard menu selecting.
if (GetWindowLong(hwnd, GWL_STYLE) & WS_ICONIC) {
break;
}
InitializeMenu((HMENU)wParam);
break;
case WM_MENUSELECT:
{
WORD wMenuItem = (UINT) LOWORD(wParam); // menu item or submenu index
WORD wFlags = (UINT) HIWORD(wParam); // menu flags
HMENU hmenu = (HMENU) lParam; // handle of menu clicked
g_LastMenuId = LOWORD(wParam);
if (0xFFFF == wFlags && NULL == hmenu)
{
//
// Menu is closed, clear the Status Bar.
//
s_MenuItemSelected = 0;
SetMessageText_StatusBar(SYS_Clear);
}
else if ( wFlags & MF_POPUP )
{
//
// Get the menu ID for the pop-up menu.
//
s_MenuItemSelected =
((wMenuItem + 1) * IDM_BASE) | MENU_SIGNATURE;
}
else
{
//
// Get the menu ID for the menu item.
//
s_MenuItemSelected = wMenuItem;
}
}
break;
case WM_ENTERIDLE:
SetMessageText_StatusBar(s_MenuItemSelected);
break;
case WM_CLOSE:
TerminateApplication(TRUE);
break;
case WM_DRAWITEM:
switch (wParam)
{
case IDC_STATUS_BAR:
OwnerDrawItem_StatusBar((LPDRAWITEMSTRUCT) lParam);
return TRUE;
}
goto DefProcessing;
case WM_DESTROY:
TerminateStatusBar();
PostQuitMessage(0);
break;
case WM_MOVE:
// This is to let the edit window
// set a position of IME conversion window
if ( MDIGetActive(g_hwndMDIClient, NULL) )
{
SendMessage(MDIGetActive(g_hwndMDIClient, NULL), WM_MOVE, 0, 0);
}
if (g_Workspace != NULL)
{
g_Workspace->AddDirty(WSPF_DIRTY_WINDOWS);
}
break;
case WM_SIZE:
{
RECT rc;
int nToolbarHeight = 0; // Toolbar
int nStatusHeight = 0; // status bar
int OldToolbarHeight = 0;
if ( IsWindowVisible(GetHwnd_Toolbar()) )
{
GetWindowRect(GetHwnd_Toolbar(), &rc);
OldToolbarHeight = rc.bottom - rc.top;
}
GetClientRect (hwnd, &rc);
// First lets resize the toolbar
SendMessage(GetHwnd_Toolbar(), WM_SIZE, wParam,
MAKELPARAM(rc.right - rc.left, rc.bottom - rc.top));
// 2nd resize the status bar
WM_SIZE_StatusBar(wParam, MAKELPARAM(rc.right - rc.left, rc.bottom - rc.top));
//On creation or resize, size the MDI client,
//status line and toolbar.
if ( IsWindowVisible(GetHwnd_StatusBar()) )
{
RECT rcStatusBar;
GetWindowRect(GetHwnd_StatusBar(), &rcStatusBar);
nStatusHeight = rcStatusBar.bottom - rcStatusBar.top;
}
if (IsWindowVisible(GetHwnd_Toolbar()))
{
RECT rcToolbar;
GetWindowRect(GetHwnd_Toolbar(), &rcToolbar);
nToolbarHeight = rcToolbar.bottom - rcToolbar.top;
}
g_MdiWidth = rc.right - rc.left;
g_MdiHeight = rc.bottom - rc.top - nStatusHeight - nToolbarHeight;
MoveWindow(g_hwndMDIClient,
rc.left, rc.top + nToolbarHeight,
g_MdiWidth, g_MdiHeight,
TRUE
);
SendMessage(g_hwndMDIClient, WM_MDIICONARRANGE, 0, 0L);
// This is to let the edit window
// set a position of IME conversion window
if ( MDIGetActive(g_hwndMDIClient, NULL) )
{
SendMessage(MDIGetActive(g_hwndMDIClient, NULL), WM_MOVE, 0, 0);
}
if (OldToolbarHeight != nToolbarHeight)
{
RedrawWindow(g_hwndMDIClient, NULL, NULL,
RDW_ERASE | RDW_INVALIDATE | RDW_FRAME |
RDW_UPDATENOW | RDW_ALLCHILDREN);
}
}
if (g_Workspace != NULL)
{
g_Workspace->AddDirty(WSPF_DIRTY_WINDOWS);
}
break;
case WU_START_ENGINE:
{
//
// Go start the debugger engine if the appropriate debugger
// parameters were passed in
//
DWORD Id;
// Start the engine thread.
g_EngineThread = CreateThread(NULL, 0, EngineLoop, NULL, 0, &Id);
if (g_EngineThread == NULL)
{
ErrorBox(NULL, 0, ERR_Engine_Failed);
break;
}
}
break;
case WU_ENGINE_STARTED:
if ((HRESULT)lParam == S_OK)
{
UpdateTitleSessionText();
if (GetCmdHwnd() == NULL)
{
// If the engine is started, show the command window
// by default
New_OpenDebugWindow(CMD_WINDOW, FALSE, NTH_OPEN_ALWAYS);
}
}
break;
case WU_ENGINE_IDLE:
if (g_InitialCommand != NULL)
{
CmdLogFmt("Processing initial command '%s'\n",
g_InitialCommand);
CmdExecuteCmd(g_InitialCommand, UIC_EXECUTE);
free(g_InitialCommand);
g_InitialCommand = NULL;
}
break;
case WU_SWITCH_WORKSPACE:
UiDelayedSwitchWorkspace();
break;
case WU_UPDATE:
// Global engine status has changed, such as
// the current process and thread. Update
// global UI elements.
SetPidTid_StatusBar(g_CurProcessId, g_CurProcessSysId,
g_CurThreadId, g_CurThreadSysId);
if (wParam == UPDATE_BUFFER)
{
SetSrcMode_StatusBar(lParam == DEBUG_LEVEL_SOURCE);
}
else if (wParam == UPDATE_EXEC &&
GetProcessThreadHwnd())
{
GetProcessThreadWinData(GetProcessThreadHwnd())->
OnUpdate(UPDATE_EXEC);
}
break;
DefProcessing:
default:
return DefFrameProc(hwnd, g_hwndMDIClient, message, wParam, lParam);
}
return (0L);
}
void
TerminateApplication(BOOL Cancellable)
{
if (g_EngineThreadId != 0 &&
(g_AttachProcessFlags & DEBUG_ATTACH_NONINVASIVE))
{
if (QuestionBox(STR_Abandoning_Noninvasive_Debuggee, MB_OKCANCEL) ==
IDCANCEL)
{
return;
}
}
if (g_Workspace != NULL)
{
if (g_Workspace->Flush(FALSE, Cancellable) == S_FALSE)
{
// User cancelled things so don't terminate.
return;
}
}
// Destroy windows to get window cleanup behavior.
// This must occur before g_Exit is set so that
// the engine thread doesn't come around and kill things.
DestroyWindow(g_hwndFrame);
g_Exit = TRUE;
ULONG Code;
if (!g_RemoteClient && g_DebugCommandLine != NULL)
{
// Return exit code of last process to exit.
Code = g_LastProcessExitCode;
}
else
{
Code = S_OK;
}
if (g_EngineThreadId != 0)
{
UpdateEngine();
// If the engine thread is idle it'll exit and call
// ExitDebugger. The engine may be waiting and
// not responsive, though, so only wait a little while before
// bailing out.
Sleep(1000);
if (g_pUiClient != NULL)
{
g_pUiClient->EndSession(DEBUG_END_REENTRANT);
}
ExitProcess(Code);
}
else
{
ExitDebugger(g_pUiClient, Code);
}
}