[PATCH 1/2] Add a new header for unified output handling in console-based programs

Hugh McMaster hugh.mcmaster at outlook.com
Tue Mar 17 07:16:39 CDT 2015


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
that requires only minor changes to each program's codebase.

I have already converted six of Wine's console-based 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 <winbase.h>
+#include <wincon.h>
+#include <winnls.h>
+#include <winuser.h>
+#include <wine/unicode.h>
+
+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




More information about the wine-patches mailing list