From: Hugh McMaster Subject: [PATCH 1/2, resend] Add a new header for unified output handling in console-based programs Message-Id: Date: Thu, 26 Mar 2015 22:32:41 +1100 Wine has at least 11 programs that write output to the console. Each program, however, uses a different method to achieve the same result. These programs can be modified to use a unified console output method with only minor changes to each program's codebase. I have already converted six of these programs using this header. --- include/wine/program_output.h | 132 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 include/wine/program_output.h diff --git a/include/wine/program_output.h b/include/wine/program_output.h new file mode 100644 index 0000000..a040d56 --- /dev/null +++ b/include/wine/program_output.h @@ -0,0 +1,132 @@ +/* + * Output functions for Windows command line programs + * + * Copyright 2007 Tim Schwartz + * Copyright 2011 François Gouget + * Copyright 2015 Hugh McMaster + * + * 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 + */ + +#ifndef __WINE_WINE_PROGRAM_OUTPUT_H +#define __WINE_WINE_PROGRAM_OUTPUT_H + +#include +#include +#include +#include +#include + +static inline void WINEPROG_writeconsole(const WCHAR *str, int wlen) +{ + DWORD count, ret; + + ret = WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), str, wlen, &count, NULL); + if (!ret) + { + DWORD len; + char *ascii_string; + + /* 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); + ascii_string = HeapAlloc(GetProcessHeap(), 0, len * sizeof(char)); + if (!ascii_string) + return; + + WideCharToMultiByte(GetConsoleOutputCP(), 0, str, wlen, ascii_string, len, NULL, NULL); + WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), ascii_string, len, &count, FALSE); + HeapFree(GetProcessHeap(), 0, ascii_string); + } +} + +static inline void WINEPROG_vprintf(const WCHAR *fmt, ...) +{ + __ms_va_list args; + WCHAR str[1024]; + + __ms_va_start(args, fmt); + vsprintfW(str, fmt, args); + __ms_va_end(args); + + WINEPROG_writeconsole(str, lstrlenW(str)); +} + +static inline void WINEPROG_internal_error(const WCHAR *function, DWORD error_code, + UINT str_id, const WCHAR *str_fmt) +{ + WCHAR path[MAX_PATH], *app_name; + static const WCHAR fmtW[] = {'%','s',':',' ','%','s',' ','f','a','i','l','e','d',',',' ','l','e','=','%','u',0}; + + GetModuleFileNameW(NULL, path, sizeof(path)/sizeof(WCHAR)); + app_name = strrchrW(path, '\\') + 1; + + WINEPROG_vprintf(fmtW, app_name, function, error_code); + if (str_id) + { + static const WCHAR fmtW[] = {',',' ','i','d','=','%','u','.','\n',0}; + WINEPROG_vprintf(fmtW, str_id); + } + if (str_fmt) + { + static const WCHAR fmtW[] = {',',' ','f','m','t','=','%','s',0}; + WINEPROG_vprintf(fmtW, str_fmt); + } +} + +static inline void WINEPROG_formatstring(const WCHAR *fmt, __ms_va_list va_args) +{ + WCHAR *str; + DWORD len; + + SetLastError(NO_ERROR); + len = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER, + fmt, 0, 0, (WCHAR *)&str, 0, &va_args); + if (len == 0 && GetLastError() != NO_ERROR) + { + static const WCHAR formatmessageW[] = {'F','o','r','m','a','t','M','e','s','s','a','g','e',0}; + WINEPROG_internal_error(formatmessageW, GetLastError(), 0, fmt); + return; + } + WINEPROG_writeconsole(str, len); + LocalFree(str); +} + +static inline void WINEPROG_output_message(UINT str_id, ...) +{ + WCHAR fmt[1024]; + __ms_va_list va_args; + + if (!LoadStringW(GetModuleHandleW(NULL), str_id, fmt, sizeof(fmt)/sizeof(WCHAR))) + { + static const WCHAR loadstringW[] = {'L','o','a','d','S','t','r','i','n','g',0}; + WINEPROG_internal_error(loadstringW, GetLastError(), str_id, NULL); + return; + } + __ms_va_start(va_args, str_id); + WINEPROG_formatstring(fmt, va_args); + __ms_va_end(va_args); +} + +static inline void WINEPROG_output_array(const WCHAR *fmt, ...) +{ + __ms_va_list va_args; + + __ms_va_start(va_args, fmt); + WINEPROG_formatstring(fmt, va_args); + __ms_va_end(va_args); +} + +#endif /* __WINE_WINE_PROGRAM_OUTPUT_H */ -- 1.9.1