[PATCH] winedbg: add a crash dialog for --auto mode

Mikołaj Zalewski mikolaj at zalewski.pl
Sat Dec 20 07:58:29 CST 2008


---
 programs/winedbg/Makefile.in  |    5 +-
 programs/winedbg/crashdlg.c   |  193 +++++++++++++++++++++++++++++++++++++++++
 programs/winedbg/debugger.h   |   10 ++-
 programs/winedbg/resource.h   |   34 +++++++
 programs/winedbg/rsrc.rc      |   26 ++++++
 programs/winedbg/rsrc_En.rc   |   52 +++++++++++
 programs/winedbg/tgt_active.c |   32 +++++---
 programs/winedbg/winedbg.c    |   58 +++++++------
 8 files changed, 371 insertions(+), 39 deletions(-)

diff --git a/programs/winedbg/Makefile.in b/programs/winedbg/Makefile.in
index 395869e..b4dd150 100644
--- a/programs/winedbg/Makefile.in
+++ b/programs/winedbg/Makefile.in
@@ -5,7 +5,7 @@ VPATH     = @srcdir@
 MODULE    = winedbg.exe
 APPMODE   = -mconsole
 IMPORTS   = psapi dbghelp advapi32 kernel32 ntdll
-DELAYIMPORTS = user32
+DELAYIMPORTS = user32 gdi32
 EXTRALIBS = @LIBPOLL@
 
 C_SRCS = \
@@ -14,6 +14,7 @@ C_SRCS = \
 	be_ppc.c \
 	be_x86_64.c \
 	break.c \
+	crashdlg.c \
 	db_disasm.c \
 	display.c \
 	expr.c \
@@ -29,6 +30,8 @@ C_SRCS = \
 	types.c \
 	winedbg.c
 
+RC_SRCS = rsrc.rc
+
 LEX_SRCS   = debug.l
 BISON_SRCS = dbg.y
 
diff --git a/programs/winedbg/crashdlg.c b/programs/winedbg/crashdlg.c
new file mode 100644
index 0000000..957fb75
--- /dev/null
+++ b/programs/winedbg/crashdlg.c
@@ -0,0 +1,193 @@
+/*
+ * The dialog that displays after a crash
+ *
+ * Copyright 2008 Mikolaj Zalewski
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "resource.h"
+#include "debugger.h"
+#include "wingdi.h"
+#include "winuser.h"
+
+#include <wine/debug.h>
+#include <wine/unicode.h>
+
+WINE_DEFAULT_DEBUG_CHANNEL(winedbg);
+
+#define MAX_PROGRAM_NAME_LENGTH 80
+
+/* needed for get_process_image_name */
+#include "winternl.h"
+#define STATUS_SUCCESS                   ((NTSTATUS) 0x00000000)
+#define STATUS_INFO_LENGTH_MISMATCH      ((NTSTATUS) 0xC0000004)
+
+/* FIXME: we should use psapi.GetProcessImageFileName when it works */
+static LPWSTR get_process_image_name(HANDLE hProcess)
+{
+    UNICODE_STRING *output;
+    ULONG size, returned;
+    NTSTATUS status;
+
+    status = NtQueryInformationProcess(hProcess, ProcessImageFileName, NULL, 0, &size);
+    if (status != STATUS_INFO_LENGTH_MISMATCH)
+    {
+        WINE_FIXME("First query returned %08x\n", status);
+        return NULL;
+    }
+
+    output = HeapAlloc(GetProcessHeap(), 0, size);
+    status = NtQueryInformationProcess(hProcess, ProcessImageFileName, output, size, &returned);
+    if (status != STATUS_SUCCESS)
+    {
+        WINE_FIXME("Second query returned %08x\n", status);
+        HeapFree(GetProcessHeap(), 0, output);
+        return NULL;
+    }
+
+    return output->Buffer;
+}
+
+int msgbox_res_id(HWND hwnd, UINT textId, UINT captionId, UINT uType)
+{
+    WCHAR caption[256];
+    WCHAR text[256];
+    LoadStringW(GetModuleHandleW(NULL), captionId, caption, sizeof(caption)/sizeof(caption[0]));
+    LoadStringW(GetModuleHandleW(NULL), textId, text, sizeof(text)/sizeof(text[0]));
+    return MessageBoxW(hwnd, text, caption, uType);
+}
+
+static WCHAR *get_program_name(HANDLE hProcess)
+{
+    LPWSTR image_name;
+    WCHAR *programname;
+
+    image_name = get_process_image_name(hProcess);
+    if (image_name == NULL)
+    {
+        static WCHAR unidentified[MAX_PROGRAM_NAME_LENGTH];
+        LoadStringW(GetModuleHandleW(NULL), IDS_UNIDENTIFIED,
+                unidentified, MAX_PROGRAM_NAME_LENGTH);
+        return unidentified;
+    }
+
+    programname = strrchrW(image_name, '\\');
+    if (programname != NULL)
+        programname++;
+    else
+        programname = image_name;
+    /* don't display a too long string to the user */
+    if (strlenW(programname) > MAX_PROGRAM_NAME_LENGTH)
+    {
+        programname[MAX_PROGRAM_NAME_LENGTH - 4] = '.';
+        programname[MAX_PROGRAM_NAME_LENGTH - 3] = '.';
+        programname[MAX_PROGRAM_NAME_LENGTH - 2] = '.';
+        programname[MAX_PROGRAM_NAME_LENGTH - 1] = 0;
+    }
+
+    /* TODO: if the image has a VERSIONINFO, we could try to find there a more
+     * user-friendly program name */
+
+    /* we waist some memory for the full path and UNICODE_STRING header, but
+     * that's OK, as this function is called only once */
+    return programname;
+}
+
+static LPWSTR g_ProgramName;
+static HFONT g_hBoldFont;
+static HMENU g_hDebugMenu = NULL;
+
+static void set_bold_font(HWND hDlg)
+{
+    HFONT hNormalFont = (HFONT)SendDlgItemMessageW(hDlg, IDC_STATIC_TXT1,
+            WM_GETFONT, 0, 0);
+    LOGFONTW font;
+    GetObjectW(hNormalFont, sizeof(LOGFONTW), &font);
+    font.lfWeight = FW_BOLD;
+    g_hBoldFont = CreateFontIndirectW(&font);
+    SendDlgItemMessageW(hDlg, IDC_STATIC_TXT1, WM_SETFONT, (WPARAM)g_hBoldFont, TRUE);
+}
+
+static void set_message_with_filename(HWND hDlg)
+{
+    WCHAR originalText[1000];
+    WCHAR newText[1000 + MAX_PROGRAM_NAME_LENGTH];
+
+    GetDlgItemTextW(hDlg, IDC_STATIC_TXT1, originalText,
+            sizeof(originalText)/sizeof(originalText[0]));
+    wsprintfW(newText, originalText, g_ProgramName);
+    SetDlgItemTextW(hDlg, IDC_STATIC_TXT1, newText);
+}
+
+static INT_PTR WINAPI DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+    switch (msg)
+    {
+    case WM_INITDIALOG:
+    {
+        set_bold_font(hwnd);
+        set_message_with_filename(hwnd);
+        return TRUE;
+    }
+    case WM_CTLCOLORSTATIC:
+    {
+        /* WM_CTLCOLOR* don't use DWLP_MSGRESULT */
+        INT_PTR id = GetDlgCtrlID((HWND)lParam);
+        if (id == IDC_STATIC_BG || id == IDC_STATIC_TXT1)
+            return (LONG_PTR)GetSysColorBrush(COLOR_WINDOW);
+
+        return FALSE;
+    }
+    case WM_RBUTTONDOWN:
+    {
+        POINT mousePos;
+        if (!(wParam & MK_SHIFT))
+            return FALSE;
+        if (g_hDebugMenu == NULL)
+            g_hDebugMenu = LoadMenuW(GetModuleHandleW(NULL), MAKEINTRESOURCEW(IDM_DEBUG_POPUP));
+        GetCursorPos(&mousePos);
+        TrackPopupMenu(GetSubMenu(g_hDebugMenu, 0), TPM_RIGHTBUTTON, mousePos.x, mousePos.y,
+                0, hwnd, NULL);
+        return TRUE;
+    }
+    case WM_COMMAND:
+        switch (LOWORD(wParam))
+        {
+            case IDOK:
+            case IDCANCEL:
+            case ID_DEBUG:
+                EndDialog(hwnd, LOWORD(wParam));
+                return TRUE;
+        }
+        return TRUE;
+    }
+    return FALSE;
+}
+
+BOOL display_crash_dialog()
+{
+    INT_PTR result;
+    /* dbg_curr_process->handle is not set */
+    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dbg_curr_pid);
+    g_ProgramName = get_program_name(hProcess);
+    CloseHandle(hProcess);
+    result = DialogBoxW(GetModuleHandleW(NULL), MAKEINTRESOURCEW(IDD_CRASH_DLG), NULL, DlgProc);
+    if (result == ID_DEBUG) {
+        AllocConsole();
+        return FALSE;
+    }
+    return TRUE;
+}
diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h
index 319f0dc..d37aecb 100644
--- a/programs/winedbg/debugger.h
+++ b/programs/winedbg/debugger.h
@@ -300,6 +300,10 @@ extern void             break_suspend_execution(void);
 extern void             break_restart_execution(int count);
 extern int              break_add_condition(int bpnum, struct expr* exp);
 
+  /* crashdlg.c */
+extern BOOL             display_crash_dialog();
+extern int              msgbox_res_id(HWND hwnd, UINT textId, UINT captionId, UINT uType);
+
   /* dbg.y */
 extern void             parser(const char*);
 extern void             parser_handle(HANDLE);
@@ -459,6 +463,8 @@ extern BOOL             dbg_init(HANDLE hProc, const WCHAR* in, BOOL invade);
 extern BOOL             dbg_load_module(HANDLE hProc, HANDLE hFile, const WCHAR* name, DWORD base, DWORD size);
 extern BOOL             dbg_get_debuggee_info(HANDLE hProcess, IMAGEHLP_MODULE* imh_mod);
 extern void             dbg_set_option(const char*, const char*);
+extern void             dbg_start_interactive(HANDLE hFile);
+extern void             dbg_init_console(void);
 
   /* gdbproxy.c */
 extern int              gdb_main(int argc, char* argv[]);
diff --git a/programs/winedbg/resource.h b/programs/winedbg/resource.h
new file mode 100644
index 0000000..49d19ef
--- /dev/null
+++ b/programs/winedbg/resource.h
@@ -0,0 +1,34 @@
+/*
+ * Resource IDs (resource.h)
+ *
+ * Copyright 2008 Mikolaj Zalewski
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+
+#define IDD_CRASH_DLG   100
+
+#define IDC_STATIC_BG   100
+#define IDC_STATIC_TXT1 101
+#define IDC_STATIC_TXT2 102
+
+#define IDM_DEBUG_POPUP 100
+
+#define ID_DEBUG        200
+
+#define IDS_AUTO_CAPTION      16
+#define IDS_INVALID_PARAMS    17
+#define IDS_UNIDENTIFIED      18
diff --git a/programs/winedbg/rsrc.rc b/programs/winedbg/rsrc.rc
new file mode 100644
index 0000000..1c202a9
--- /dev/null
+++ b/programs/winedbg/rsrc.rc
@@ -0,0 +1,26 @@
+/*
+ * Resources (rsrc.rc)
+ *
+ * Copyright 2008 Mikolaj Zalewski
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <windef.h>
+#include <winuser.h>
+
+#include "resource.h"
+
+#include "rsrc_En.rc"
diff --git a/programs/winedbg/rsrc_En.rc b/programs/winedbg/rsrc_En.rc
new file mode 100644
index 0000000..893542e
--- /dev/null
+++ b/programs/winedbg/rsrc_En.rc
@@ -0,0 +1,52 @@
+/*
+ * English Language Support
+ *
+ * Copyright 2008 Mikolaj Zalewski
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
+
+IDM_DEBUG_POPUP MENU
+BEGIN
+    POPUP ""
+    BEGIN
+        MENUITEM "&Debug", ID_DEBUG
+    END
+END
+
+IDD_CRASH_DLG DIALOGEX 100, 100, 273, 175
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Program Error"
+FONT 8, "Tahoma"
+BEGIN
+    LTEXT           "",IDC_STATIC_BG,0,0,273,52,WS_BORDER,0
+    LTEXT           "The program %s has met a serious problem and needs to close. We are sorry for the inconvinience.",
+                    IDC_STATIC_TXT1,27,10,224,30
+    LTEXT           "This can be caused by a problem in the program or a deficiency in Wine. \
+                    You may want to check http://appdb.winehq.org if there are some  \
+                    tips about running this applicaiton.\n\n\
+                    If this problem is not present under Windows and it has not been reported \
+                    yet, you can report it at http://bugs.winehq.org",IDC_STATIC_TXT2,27,60,224,100
+    DEFPUSHBUTTON   "Close", IDOK, 205, 151, 60, 16, WS_TABSTOP
+END
+
+STRINGTABLE
+BEGIN
+    IDS_AUTO_CAPTION     "Wine program crash"
+    IDS_INVALID_PARAMS   "Internal errors - invalid parameters received"
+    IDS_UNIDENTIFIED     "(unidentified)"
+END
diff --git a/programs/winedbg/tgt_active.c b/programs/winedbg/tgt_active.c
index f5ea8f2..1a98ea7 100644
--- a/programs/winedbg/tgt_active.c
+++ b/programs/winedbg/tgt_active.c
@@ -27,6 +27,7 @@
 
 #include "debugger.h"
 #include "psapi.h"
+#include "resource.h"
 #include "winternl.h"
 #include "wine/debug.h"
 #include "wine/exception.h"
@@ -45,9 +46,9 @@ static void dbg_init_current_thread(void* start)
 {
     if (start)
     {
-	if (dbg_curr_process->threads && 
+	if (dbg_curr_process->threads &&
             !dbg_curr_process->threads->next && /* first thread ? */
-	    DBG_IVAR(BreakAllThreadsStartup)) 
+	    DBG_IVAR(BreakAllThreadsStartup))
         {
 	    ADDRESS64   addr;
 
@@ -898,7 +899,16 @@ enum dbg_start dbg_active_auto(int argc, char* argv[])
         /* auto mode */
         argc--; argv++;
         ds = dbg_active_attach(argc, argv);
-        if (ds != start_ok) return ds;
+        if (ds != start_ok) {
+            msgbox_res_id(NULL, IDS_INVALID_PARAMS, IDS_AUTO_CAPTION, MB_OK);
+            return ds;
+        }
+        if (!display_crash_dialog()) {
+            dbg_init_console();
+            dbg_start_interactive(INVALID_HANDLE_VALUE);
+            return start_ok;
+        }
+
         hFile = parser_generate_command_file("echo Modules:", "info share",
                                              "echo Threads:", "info threads",
                                              "backtrace", "detach", NULL);
diff --git a/programs/winedbg/winedbg.c b/programs/winedbg/winedbg.c
index d1df695..5d5f610 100644
--- a/programs/winedbg/winedbg.c
+++ b/programs/winedbg/winedbg.c
@@ -556,8 +556,11 @@ static BOOL WINAPI ctrl_c_handler(DWORD dwCtrlType)
     return FALSE;
 }
 
-static void dbg_init_console(void)
+void dbg_init_console(void)
 {
+    /* set the output handle */
+    dbg_houtput = GetStdHandle(STD_OUTPUT_HANDLE);
+
     /* set our control-C handler */
     SetConsoleCtrlHandler(ctrl_c_handler, TRUE);
 
@@ -587,6 +590,23 @@ static int dbg_winedbg_usage(BOOL advanced)
     return -1;
 }
 
+void dbg_start_interactive(HANDLE hFile)
+{
+    if (dbg_curr_process)
+    {
+        dbg_printf("WineDbg starting on pid %04x\n", dbg_curr_pid);
+        if (dbg_curr_process->active_debuggee) dbg_active_wait_for_first_exception();
+    }
+
+    dbg_interactiveP = TRUE;
+    parser_handle(hFile);
+
+    while (dbg_process_list)
+        dbg_process_list->process_io->close_process(dbg_process_list, FALSE);
+
+    dbg_save_internal_vars();
+}
+
 struct backend_cpu* be_cpu;
 #ifdef __i386__
 extern struct backend_cpu be_i386;
@@ -698,19 +718,7 @@ int main(int argc, char** argv)
     case start_error_init:      return -1;
     }
 
-    if (dbg_curr_process)
-    {
-        dbg_printf("WineDbg starting on pid %04x\n", dbg_curr_pid);
-        if (dbg_curr_process->active_debuggee) dbg_active_wait_for_first_exception();
-    }
-
-    dbg_interactiveP = TRUE;
-    parser_handle(hFile);
-
-    while (dbg_process_list)
-        dbg_process_list->process_io->close_process(dbg_process_list, FALSE);
-
-    dbg_save_internal_vars();
+    dbg_start_interactive(hFile);
 
     return 0;
 }
-- 
1.4.4.2


--------------000005050306070604010508--



More information about the wine-patches mailing list