This program is in GUI subsystem, but expects I/O with Unix console. This is a Wine specific behavior. So explicitely use unix fd instead of the inherited standard handles.
Wine-Bugs: https://bugs.winehq.org/show_bug.cgi?id=55723
Signed-off-by: Eric Pouech epouech@codeweavers.com
-- v5: regedit: Use message boxes by default for output. regsvr32: Use message boxes by default for output.
From: Eric Pouech epouech@codeweavers.com
regsvr32 is in GUI subsystem and shoudln't interact with console. Keeping unix I/O output in silent mode. Removing -c option as not existing in native.
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/msi/action.c | 4 +- programs/regsvr32/regsvr32.c | 77 +++++++++++++++++------------------- 2 files changed, 38 insertions(+), 43 deletions(-)
diff --git a/dlls/msi/action.c b/dlls/msi/action.c index 8b3d1c42aa5..575af431854 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -4581,8 +4581,8 @@ static UINT ACTION_RemoveIniValues( MSIPACKAGE *package )
static void register_dll( const WCHAR *dll, BOOL unregister ) { - static const WCHAR regW[] = L"regsvr32.exe "%s""; - static const WCHAR unregW[] = L"regsvr32.exe /u "%s""; + static const WCHAR regW[] = L"regsvr32.exe /s "%s""; + static const WCHAR unregW[] = L"regsvr32.exe /s /u "%s""; PROCESS_INFORMATION pi; STARTUPINFOW si; WCHAR *cmd; diff --git a/programs/regsvr32/regsvr32.c b/programs/regsvr32/regsvr32.c index 81caeb2c820..98038652505 100644 --- a/programs/regsvr32/regsvr32.c +++ b/programs/regsvr32/regsvr32.c @@ -24,6 +24,7 @@ #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <winternl.h> +#include <winnls.h> #include <ole2.h> #include "regsvr32.h" #include "wine/debug.h" @@ -34,51 +35,50 @@ typedef HRESULT (WINAPI *DLLREGISTER) (void); typedef HRESULT (WINAPI *DLLUNREGISTER) (void); typedef HRESULT (WINAPI *DLLINSTALL) (BOOL,LPCWSTR);
-static BOOL Silent = FALSE; +static BOOL Silent;
-static void WINAPIV output_write(UINT id, ...) +static void WINAPIV output_write(BOOL with_usage, UINT id, ...) { + WCHAR buffer[4096]; WCHAR fmt[1024]; va_list va_args; - WCHAR *str; - DWORD len, nOut; + DWORD len; + LCID current_lcid;
- if (Silent) return; + current_lcid = GetThreadLocale(); + if (Silent) /* force en-US not to have localized strings */ + SetThreadLocale(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT));
if (!LoadStringW(GetModuleHandleW(NULL), id, fmt, ARRAY_SIZE(fmt))) { WINE_FIXME("LoadString failed with %ld\n", GetLastError()); + SetThreadLocale(current_lcid); return; }
va_start(va_args, id); - len = FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER, - fmt, 0, 0, (LPWSTR)&str, 0, &va_args); + len = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, + fmt, 0, 0, buffer, ARRAY_SIZE(buffer), &va_args); va_end(va_args); if (len == 0 && GetLastError() != ERROR_NO_WORK_DONE) { WINE_FIXME("Could not format string: le=%lu, fmt=%s\n", GetLastError(), wine_dbgstr_w(fmt)); + SetThreadLocale(current_lcid); return; } - - /* WriteConsole fails if its output is redirected to a file. - * If this occurs, we should use an OEM codepage and call WriteFile. - */ - if (!WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), str, len, &nOut, NULL)) + if (with_usage && + !LoadStringW(GetModuleHandleW(NULL), STRING_USAGE, + &buffer[wcslen(buffer)], ARRAY_SIZE(buffer) - wcslen(buffer))) { - DWORD lenA; - char *strA; - - lenA = WideCharToMultiByte(GetOEMCP(), 0, str, len, NULL, 0, NULL, NULL); - strA = HeapAlloc(GetProcessHeap(), 0, lenA); - if (strA) - { - WideCharToMultiByte(GetOEMCP(), 0, str, len, strA, lenA, NULL, NULL); - WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), strA, lenA, &nOut, FALSE); - HeapFree(GetProcessHeap(), 0, strA); - } + WINE_FIXME("LoadString failed with %ld\n", GetLastError()); + SetThreadLocale(current_lcid); + return; } - LocalFree(str); + if (Silent) + MESSAGE("%ls", buffer); + else + MessageBoxW(NULL, buffer, L"RegSvr32", MB_OK); + SetThreadLocale(current_lcid); }
static LPCWSTR find_arg_start(LPCWSTR cmdline) @@ -180,13 +180,13 @@ static VOID *LoadProc(const WCHAR* strDll, const char* procName, HMODULE* DllHan IMAGE_NT_HEADERS *nt = RtlImageNtHeader( (HMODULE)((ULONG_PTR)module & ~3) ); reexec_self( nt->FileHeader.Machine ); } - output_write(STRING_DLL_LOAD_FAILED, strDll); + output_write(FALSE, STRING_DLL_LOAD_FAILED, strDll); ExitProcess(LOADLIBRARY_FAILED); } proc = (VOID *) GetProcAddress(*DllHandle, procName); if(!proc) { - output_write(STRING_PROC_NOT_IMPLEMENTED, procName, strDll); + output_write(FALSE, STRING_PROC_NOT_IMPLEMENTED, procName, strDll); FreeLibrary(*DllHandle); return NULL; } @@ -206,10 +206,10 @@ static int RegisterDll(const WCHAR* strDll, BOOL firstDll) hr = pfRegister(); if(FAILED(hr)) { - output_write(STRING_REGISTER_FAILED, strDll); + output_write(FALSE, STRING_REGISTER_FAILED, strDll); return DLLSERVER_FAILED; } - output_write(STRING_REGISTER_SUCCESSFUL, strDll); + output_write(FALSE, STRING_REGISTER_SUCCESSFUL, strDll);
if(DllHandle) FreeLibrary(DllHandle); @@ -229,10 +229,10 @@ static int UnregisterDll(const WCHAR* strDll, BOOL firstDll) hr = pfUnregister(); if(FAILED(hr)) { - output_write(STRING_UNREGISTER_FAILED, strDll); + output_write(FALSE, STRING_UNREGISTER_FAILED, strDll); return DLLSERVER_FAILED; } - output_write(STRING_UNREGISTER_SUCCESSFUL, strDll); + output_write(FALSE, STRING_UNREGISTER_SUCCESSFUL, strDll);
if(DllHandle) FreeLibrary(DllHandle); @@ -253,15 +253,15 @@ static int InstallDll(BOOL install, const WCHAR *strDll, const WCHAR *command_li if(FAILED(hr)) { if (install) - output_write(STRING_INSTALL_FAILED, strDll); + output_write(FALSE, STRING_INSTALL_FAILED, strDll); else - output_write(STRING_UNINSTALL_FAILED, strDll); + output_write(FALSE, STRING_UNINSTALL_FAILED, strDll); return DLLSERVER_FAILED; } if (install) - output_write(STRING_INSTALL_SUCCESSFUL, strDll); + output_write(FALSE, STRING_INSTALL_SUCCESSFUL, strDll); else - output_write(STRING_UNINSTALL_SUCCESSFUL, strDll); + output_write(FALSE, STRING_UNINSTALL_SUCCESSFUL, strDll);
if(DllHandle) FreeLibrary(DllHandle); @@ -340,12 +340,8 @@ int __cdecl wmain(int argc, WCHAR* argv[]) case 'n': CallRegister = FALSE; break; - case 'c': - /* console output */; - break; default: - output_write(STRING_UNRECOGNIZED_SWITCH, argv[i]); - output_write(STRING_USAGE); + output_write(TRUE, STRING_UNRECOGNIZED_SWITCH, argv[i]); return INVALID_ARG; } argv[i] = NULL; @@ -401,8 +397,7 @@ int __cdecl wmain(int argc, WCHAR* argv[])
if (!DllFound) { - output_write(STRING_HEADER); - output_write(STRING_USAGE); + output_write(TRUE, STRING_HEADER); return INVALID_ARG; }
From: Eric Pouech epouech@codeweavers.com
regedit is in GUI subsystem and shoudln't interact with console. Keeping unix I/O output in silent mode (forcing English locale for Unix integration).
Signed-off-by: Eric Pouech epouech@codeweavers.com --- programs/regedit/main.h | 2 +- programs/regedit/regedit.c | 103 +++++++++++++++++++------------------ programs/regedit/regproc.c | 11 ++-- 3 files changed, 62 insertions(+), 54 deletions(-)
diff --git a/programs/regedit/main.h b/programs/regedit/main.h index 310469f83f6..d9998d743a2 100644 --- a/programs/regedit/main.h +++ b/programs/regedit/main.h @@ -154,7 +154,7 @@ BOOL IsDefaultValue(HWND hwndLV, int i);
/* regedit.c */ void WINAPIV output_message(unsigned int id, ...); -void WINAPIV error_exit(unsigned int id, ...); +void WINAPIV error_exit(void);
/* regproc.c */ char *GetMultiByteString(const WCHAR *strW); diff --git a/programs/regedit/regedit.c b/programs/regedit/regedit.c index 03e0ec9c7cb..fd8a98ae8c0 100644 --- a/programs/regedit/regedit.c +++ b/programs/regedit/regedit.c @@ -28,74 +28,76 @@
WINE_DEFAULT_DEBUG_CHANNEL(regedit);
-static void output_writeconsole(const WCHAR *str, DWORD wlen) +static BOOL silent; + +static void output_formatstring(BOOL with_help, UINT id, va_list va_args) { - DWORD count; + WCHAR buffer[4096]; + WCHAR fmt[1536]; + DWORD len; + LCID current_lcid; + + if (silent && with_help) return; + + current_lcid = GetThreadLocale(); + if (silent) /* force en-US not to have localized strings */ + SetThreadLocale(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT));
- if (!WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), str, wlen, &count, NULL)) + if (!LoadStringW(GetModuleHandleW(NULL), id, fmt, ARRAY_SIZE(fmt))) { - DWORD len; - char *msgA; - - /* WriteConsole() fails on Windows if its output is redirected. If this occurs, - * we should call WriteFile() with OEM code page. - */ - len = WideCharToMultiByte(GetOEMCP(), 0, str, wlen, NULL, 0, NULL, NULL); - msgA = malloc(len); - if (!msgA) return; - - WideCharToMultiByte(GetOEMCP(), 0, str, wlen, msgA, len, NULL, NULL); - WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), msgA, len, &count, FALSE); - free(msgA); + WINE_FIXME("LoadString failed with %ld\n", GetLastError()); + if (silent) SetThreadLocale(current_lcid); + return; } -}
-static void output_formatstring(const WCHAR *fmt, va_list va_args) -{ - WCHAR *str; - DWORD len; - - len = FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER, - fmt, 0, 0, (WCHAR *)&str, 0, &va_args); + len = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, + fmt, 0, 0, buffer, ARRAY_SIZE(buffer), &va_args); if (len == 0 && GetLastError() != ERROR_NO_WORK_DONE) { WINE_FIXME("Could not format string: le=%lu, fmt=%s\n", GetLastError(), wine_dbgstr_w(fmt)); + if (silent) SetThreadLocale(current_lcid); return; } - output_writeconsole(str, len); - LocalFree(str); + if (with_help && + !LoadStringW(GetModuleHandleW(NULL), STRING_HELP, + &buffer[wcslen(buffer)], ARRAY_SIZE(buffer) - wcslen(buffer))) + { + WINE_FIXME("LoadString failed with %ld\n", GetLastError()); + if (silent) SetThreadLocale(current_lcid); + return; + } + if (silent) + { + MESSAGE("%ls", buffer); + SetThreadLocale(current_lcid); + } + else + MessageBoxW(NULL, buffer, MAKEINTRESOURCEW(IDS_APP_TITLE), MB_OK | MB_ICONHAND); }
void WINAPIV output_message(unsigned int id, ...) { - WCHAR fmt[1536]; va_list va_args;
- if (!LoadStringW(GetModuleHandleW(NULL), id, fmt, ARRAY_SIZE(fmt))) - { - WINE_FIXME("LoadString failed with %ld\n", GetLastError()); - return; - } va_start(va_args, id); - output_formatstring(fmt, va_args); + output_formatstring(FALSE, id, va_args); va_end(va_args); }
-void WINAPIV error_exit(unsigned int id, ...) +void WINAPIV error_exit(void) +{ + exit(0); /* regedit.exe always terminates with error code zero */ +} + +static void WINAPIV usage(unsigned int id, ...) { - WCHAR fmt[1536]; va_list va_args;
- if (!LoadStringW(GetModuleHandleW(NULL), id, fmt, ARRAY_SIZE(fmt))) - { - WINE_FIXME("LoadString failed with %lu\n", GetLastError()); - return; - } va_start(va_args, id); - output_formatstring(fmt, va_args); + output_formatstring(TRUE, id, va_args); va_end(va_args);
- exit(0); /* regedit.exe always terminates with error code zero */ + error_exit(); }
typedef enum { @@ -159,8 +161,8 @@ static void PerformRegAction(REGEDIT_ACTION action, WCHAR **argv, int *i) break; } default: - error_exit(STRING_UNHANDLED_ACTION); - break; + output_message(STRING_UNHANDLED_ACTION); + error_exit(); } }
@@ -195,7 +197,8 @@ BOOL ProcessCmdLine(WCHAR *cmdline) switch (towupper(argv[i][1])) { case '?': - error_exit(STRING_USAGE); + output_message(STRING_USAGE); + error_exit(); break; case 'D': action = ACTION_DELETE; @@ -210,12 +213,13 @@ BOOL ProcessCmdLine(WCHAR *cmdline) /* unhandled */; break; case 'S': + silent = TRUE; + break; case 'V': /* ignored */; break; default: - output_message(STRING_INVALID_SWITCH, argv[i]); - error_exit(STRING_HELP); + usage(STRING_INVALID_SWITCH, argv[i]); } }
@@ -225,13 +229,12 @@ BOOL ProcessCmdLine(WCHAR *cmdline) { case ACTION_ADD: case ACTION_EXPORT: - output_message(STRING_NO_FILENAME); + usage(STRING_NO_FILENAME); break; case ACTION_DELETE: - output_message(STRING_NO_REG_KEY); + usage(STRING_NO_REG_KEY); break; } - error_exit(STRING_HELP); }
for (; i < argc; i++) diff --git a/programs/regedit/regproc.c b/programs/regedit/regproc.c index 15a64fdf97d..0a580f0cd12 100644 --- a/programs/regedit/regproc.c +++ b/programs/regedit/regproc.c @@ -1091,11 +1091,15 @@ void delete_registry_key(WCHAR *reg_key_name) if (!(key_class = parse_key_name(reg_key_name, &key_name))) { if (key_name) *(key_name - 1) = 0; - error_exit(STRING_INVALID_SYSTEM_KEY, reg_key_name); + output_message(STRING_INVALID_SYSTEM_KEY, reg_key_name); + error_exit(); }
if (!key_name || !*key_name) - error_exit(STRING_DELETE_FAILED, reg_key_name); + { + output_message(STRING_DELETE_FAILED, reg_key_name); + error_exit(); + }
RegDeleteTreeW(key_class, key_name); } @@ -1411,7 +1415,8 @@ static FILE *REGPROC_open_export_file(WCHAR *file_name, BOOL unicode) if (!file) { _wperror(L"regedit"); - error_exit(STRING_CANNOT_OPEN_FILE, file_name); + output_message(STRING_CANNOT_OPEN_FILE, file_name); + error_exit(); } }
On Thu Nov 23 17:30:43 2023 +0000, Jacek Caban wrote:
dialog.c CI failures seem to be caused by those patches.
hopefully it's fixed in latest version
This merge request was approved by Jacek Caban.