On Tue, Apr 29, 2008 at 1:28 PM, Peter Beutner <[EMAIL PROTECTED]> wrote: > And the msg box will pop up.
Your right. I see unless report_missing_dll_verbose is unset then its going to spam on every dependent dll load failure for LoadLibrary. Here is your and my patch combined. Julliard: Can you comment please? Thanks -- Steven Edwards "There is one thing stronger than all the armies in the world, and that is an idea whose time has come." - Victor Hugo
From dfe53258c683c449087928707c3aeebb93a2f4dd Mon Sep 17 00:00:00 2001 From: Steven Edwards <[EMAIL PROTECTED]> Date: Sun, 27 Apr 2008 06:35:36 -0400 Subject: [PATCH] Graphically Report an error via a message box when an application is started from the Desktop environment. Thanks to Peter Beutner <[EMAIL PROTECTED]> for making the messagebox show something usable and not reporting a error everytime a dependant library called from LoadLibrary failed --- dlls/ntdll/loader.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++ programs/start/start.c | 4 +++ 2 files changed, 74 insertions(+), 0 deletions(-) diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index b0000b8..677a146 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -24,6 +24,7 @@ #include <assert.h> #include <stdarg.h> +#include <stdio.h> #ifdef HAVE_SYS_MMAN_H # include <sys/mman.h> #endif @@ -96,6 +97,7 @@ struct builtin_load_info static struct builtin_load_info default_load_info; static struct builtin_load_info *builtin_load_info = &default_load_info; +static int report_missing_dll_verbose; /* display msgbox if importing a dll fails */ static HANDLE main_exe_file; static UINT tls_module_count; /* number of modules with TLS directory */ static UINT tls_total_size; /* total size of TLS storage */ @@ -464,6 +466,68 @@ static FARPROC find_named_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY * } +/************************************************************************* + * get_msgbox_func + * + * FIXME: We need to do something similar to this in exception.c + * so that a present dll with a missing export will also get a messaebox + */ +static FARPROC get_msgbox_func(void) +{ + WCHAR user32[] = {'u','s','e','r','3','2','.','d','l','l',0}; + NTSTATUS status; + HMODULE hdll; + ANSI_STRING str; + UNICODE_STRING wstr; + FARPROC pMessageBoxA; + + RtlInitUnicodeString( &wstr, user32 ); + status = LdrLoadDll(0, 0, &wstr, &hdll); + if (status != STATUS_SUCCESS) + return NULL; + + RtlInitAnsiString( &str, "MessageBoxA" ); + status = LdrGetProcedureAddress( hdll, &str, 0, (void**)&pMessageBoxA ); + if (status != STATUS_SUCCESS) + return NULL; + + return pMessageBoxA; +} + + +/************************************************************************* + * report_missing_dll + * + * If we are called via start.exe.so from a Unix desktop then WINE_VERBOSE_DEBUG + * should be set to TRUE. This way users will not click on a desktop icon and + * have nothing happen if a required dll is missing. + */ +/* don't want to include winuser.h */ +#define MB_ICONERROR 0x00000010 +static void report_missing_dll(const char *dll, WCHAR* imported_by) +{ + static WCHAR debug_name[] = {'W','I','N','E','_','V','E','R','B','O','S','E','_','D','E','B','U','G',0}; + static WCHAR debug_value[] = {'T','R','U','E',0}; + UNICODE_STRING us_name, us_value; + FARPROC pMessageBoxA; + char msg[MAX_PATH]; + NTSTATUS nts0; + + RtlInitUnicodeString( &us_name, debug_name ); + RtlInitUnicodeString( &us_value, debug_value ); + nts0 = RtlQueryEnvironmentVariable_U(NULL,&us_name,&us_value); + + if (nts0 == STATUS_SUCCESS) + { + pMessageBoxA = get_msgbox_func(); + if(report_missing_dll_verbose && pMessageBoxA) { + snprintf(msg, MAX_PATH, "Library %s (which is needed by %s) not found\n", + dll, debugstr_w(imported_by)); + pMessageBoxA(NULL, msg, "Error: Failed to start application", MB_ICONERROR); + } + } +} + /************************************************************************* * import_dll @@ -514,8 +578,12 @@ static WINE_MODREF *import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *d if (status) { if (status == STATUS_DLL_NOT_FOUND) + { ERR("Library %s (which is needed by %s) not found\n", name, debugstr_w(current_modref->ldr.FullDllName.Buffer)); + + report_missing_dll(name, current_modref->ldr.FullDllName.Buffer); + } else ERR("Loading library %s (which is needed by %s) failed (error %x).\n", name, debugstr_w(current_modref->ldr.FullDllName.Buffer), status); @@ -2414,7 +2482,9 @@ void WINAPI LdrInitializeThunk( ULONG unknown1, ULONG unknown2, ULONG unknown3, actctx_init(); load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer; + report_missing_dll_verbose = 1; if ((status = fixup_imports( wm, load_path )) != STATUS_SUCCESS) goto error; + report_missing_dll_verbose = 0; if ((status = alloc_process_tls()) != STATUS_SUCCESS) goto error; if ((status = alloc_thread_tls()) != STATUS_SUCCESS) goto error; diff --git a/programs/start/start.c b/programs/start/start.c index c7a4ba4..a66e0ee 100644 --- a/programs/start/start.c +++ b/programs/start/start.c @@ -258,10 +258,14 @@ int wmain (int argc, WCHAR *argv[]) sei.lpParameters = args; if (unix_mode) { + WCHAR debug_name[] = {'W','I','N','E','_','V','E','R','B','O','S','E','_','D','E','B','U','G',0}; + WCHAR debug_value[] = {'T','R','U','E',0}; LPWSTR (*wine_get_dos_file_name_ptr)(LPCSTR); char* multibyte_unixpath; int multibyte_unixpath_len; + SetEnvironmentVariableW (debug_name, debug_value); + wine_get_dos_file_name_ptr = (void*)GetProcAddress(GetModuleHandle("KERNEL32"), "wine_get_dos_file_name"); if (!wine_get_dos_file_name_ptr) -- 1.5.3.7