On Sat, Apr 26, 2008 at 1:53 PM, Steven Edwards <[EMAIL PROTECTED]> wrote: > > * have start.exe set an environment variable saying "show graphical error > box > > on dll load failure", and clear that before calling executed apps' > WinMain() > > (easy) > > So something like start.exe.so in Unix mode would set a variable like > VERSBOSE_USERDEBUG or which then we could query in the loader using > RtlQueryEnvironmentVariable_U or something that would trigger the > MessageBox from the example code I already wrote in ntdll?
So that worked. Comments are welcome! -- 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 a15c236827afb6a29673ea71c0defcbfc329d466 Mon Sep 17 00:00:00 2001 From: Steven Edwards <[EMAIL PROTECTED]> Date: Sun, 27 Apr 2008 06:35:36 -0400 Subject: [PATCH] Took a better stab at reporting when a dll is missing so users don't click on an application and have nothing happen --- dlls/ntdll/loader.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ programs/start/start.c | 4 +++ 2 files changed, 57 insertions(+), 0 deletions(-) diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index b0000b8..f5917e7 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -464,6 +464,52 @@ static FARPROC find_named_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY * } +/************************************************************************* + * report_error + * + * 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. + * FIXME: Add dialog for a missing export for a given dll + * FIXME: Make the error dialog tell the user what dll is missing + */ +FARPROC pMessageBoxW; +static NTSTATUS report_error() +{ + 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; + NTSTATUS nts0,nts1,nts2; + + RtlInitUnicodeString( &us_name, debug_name ); + RtlInitUnicodeString( &us_value, debug_value ); + nts0 = RtlQueryEnvironmentVariable_U(NULL,&us_name,&us_value); + + if (nts0 == STATUS_SUCCESS) + { + WCHAR user32[] = {'u','s','e','r','3','2','.','d','l','l',0}; + UNICODE_STRING wstr; + ANSI_STRING str; + HMODULE hdll; + + RtlInitUnicodeString( &wstr, user32 ); + nts1 = LdrLoadDll(0, 0, &wstr, &hdll); + if (nts1 != STATUS_SUCCESS) + { + ERR("couldn't load user32 to display error\n"); + return nts1; + } + + RtlInitAnsiString( &str, "MessageBoxW" ); + nts2 = LdrGetProcedureAddress( hdll, &str, 0, (void**)&pMessageBoxW ); + if (nts2 != STATUS_SUCCESS) + { + ERR("Couldn't import MessageBoxW\n"); + return nts2; + } + } + return nts0; +} /************************************************************************* * import_dll @@ -514,8 +560,15 @@ static WINE_MODREF *import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *d if (status) { if (status == STATUS_DLL_NOT_FOUND) + { + WCHAR dll_error[] = {'A',' ','r','e','q','i','u','r','e','d',' ','d','l','l',' ','w','a','s',' ','n','o','t',' ','f','o','u','n','d',0}; + NTSTATUS nts = report_error(); + if (nts == STATUS_SUCCESS) + pMessageBoxW(NULL,dll_error,NULL,NULL); + ERR("Library %s (which is needed by %s) not found\n", name, debugstr_w(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); 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