From: Hugh McMaster Subject: [PATCH] reg: Modernise print functions (updated) Message-Id: Date: Mon, 10 Nov 2014 23:21:56 +1100 This patch modernises reg.exe so its printf-type functions conform to the other Wine programs. It will also mean other developers do not have to add this functionality in various places, e.g. printing error messages. Update: I forgot to use __ms_va_start and __ms_va_end when using __ms_va_list. Fixed. From efd530e9ae1031e6f471b03c2b92f626252da237 Mon Sep 17 00:00:00 2001 From: Hugh McMaster Date: Mon, 10 Nov 2014 23:14:54 +1100 Subject: [PATCH] reg: Modernise print functions (updated) --- programs/reg/reg.c | 88 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 56 insertions(+), 32 deletions(-) diff --git a/programs/reg/reg.c b/programs/reg/reg.c index d299cbf..e9aecf3 100644 --- a/programs/reg/reg.c +++ b/programs/reg/reg.c @@ -18,53 +18,77 @@ #include #include +#include #include "reg.h" -static int reg_printfW(const WCHAR *msg, ...) +WINE_DEFAULT_DEBUG_CHANNEL(reg); + +static void output_write(const WCHAR *str, int wlen) { - va_list va_args; - int wlen; DWORD count, ret; - WCHAR msg_buffer[8192]; - - va_start(va_args, msg); - vsnprintfW(msg_buffer, 8192, msg, va_args); - va_end(va_args); - wlen = lstrlenW(msg_buffer); - ret = WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), msg_buffer, wlen, &count, NULL); + ret = WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), str, wlen, &count, NULL); if (!ret) { DWORD len; - char *msgA; - - /* On Windows WriteConsoleW() fails if the output is redirected. So fall - * back to WriteFile(), assuming the console encoding is still the right - * one in that case. - */ - len = WideCharToMultiByte(GetConsoleOutputCP(), 0, msg_buffer, wlen, - NULL, 0, NULL, NULL); - msgA = HeapAlloc(GetProcessHeap(), 0, len * sizeof(char)); - if (!msgA) - return 0; + char *strA; + + /* WriteConsole() fails on Windows if its output is redirected to a file. + * If this occurs, we should call WriteFile() and use an OEM codepage. */ + len = WideCharToMultiByte(GetConsoleOutputCP(), 0, str, wlen, NULL, 0, NULL, NULL); + strA = HeapAlloc(GetProcessHeap(), 0, len * sizeof(char)); + if (!strA) + return; + + WideCharToMultiByte(GetConsoleOutputCP(), 0, str, wlen, strA, len, NULL, NULL); + WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), strA, len, &count, FALSE); + HeapFree(GetProcessHeap(), 0, strA); + } +} + +static void output_vprintf(const WCHAR* fmt, __ms_va_list va_args) +{ + WCHAR *str; + int len; - WideCharToMultiByte(GetConsoleOutputCP(), 0, msg_buffer, wlen, msgA, len, - NULL, NULL); - WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), msgA, len, &count, FALSE); - HeapFree(GetProcessHeap(), 0, msgA); + SetLastError(NO_ERROR); + len = FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER, + fmt, 0, 0, (LPWSTR)&str, 0, &va_args); + if (len == 0 && GetLastError() != NO_ERROR) + { + WINE_FIXME("Could not format string: le=%u, fmt=%s\n", GetLastError(), wine_dbgstr_w(fmt)); + return; } + output_write(str, len); + LocalFree(str); +} + +static void __cdecl reg_message(int msg_id, ...) +{ + WCHAR fmt[1024]; + __ms_va_list va_args; - return count; + if (!LoadStringW(GetModuleHandleW(NULL), msg_id, fmt, sizeof(fmt)/sizeof(fmt[0]))) + { + WINE_FIXME("LoadString failed with %d\n", GetLastError()); + return; + } + + __ms_va_start(va_args, msg_id); + output_vprintf(fmt, va_args); + __ms_va_end(va_args); } -static int reg_message(int msg) +static void __cdecl reg_printfW(const WCHAR* msg, ...) { - static const WCHAR formatW[] = {'%','s',0}; - WCHAR msg_buffer[8192]; + __ms_va_list va_args; + WCHAR msg_buffer[1024]; + + __ms_va_start(va_args, msg); + vsnprintfW(msg_buffer, sizeof(msg_buffer)/sizeof(WCHAR), msg, va_args); + __ms_va_end(va_args); - LoadStringW(GetModuleHandleW(NULL), msg, msg_buffer, - sizeof(msg_buffer)/sizeof(WCHAR)); - return reg_printfW(formatW, msg_buffer); + output_write(msg_buffer, lstrlenW(msg_buffer)); } static HKEY get_rootkey(LPWSTR key) -- 1.9.1