1291 lines
40 KiB
C++
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);
|
|
}
|
|
}
|