[PATCH 2/3] regedit: Use WINAPI functions for better internationalization

Hugh McMaster hugh.mcmaster at outlook.com
Tue Jul 5 00:15:35 CDT 2016


Signed-off-by: Hugh McMaster <hugh.mcmaster at outlook.com>
---
 programs/regedit/regedit.c  | 106 ++++++++++++++++++++++++++++----------------
 programs/regedit/regedit.rc |  37 ++++++++++++++++
 programs/regedit/resource.h |  10 +++++
 3 files changed, 114 insertions(+), 39 deletions(-)

diff --git a/programs/regedit/regedit.c b/programs/regedit/regedit.c
index ae268b6..04dd317 100644
--- a/programs/regedit/regedit.c
+++ b/programs/regedit/regedit.c
@@ -23,38 +23,66 @@
 #include <windows.h>
 #include <shellapi.h>
 #include "wine/unicode.h"
+#include "wine/debug.h"
 #include "regproc.h"
+#include "resource.h"
 
-static const char *usage =
-    "Usage:\n"
-    "    regedit filename\n"
-    "    regedit /E filename [regpath]\n"
-    "    regedit /D regpath\n"
-    "\n"
-    "filename - registry file name\n"
-    "regpath - name of the registry key\n"
-    "\n"
-    "When called without any switches, adds the content of the specified\n"
-    "file to the registry\n"
-    "\n"
-    "Switches:\n"
-    "    /E - exports contents of the specified registry key to the specified\n"
-    "	file. Exports the whole registry if no key is specified.\n"
-    "    /D - deletes specified registry key\n"
-    "    /S - silent execution, can be used with any other switch.\n"
-    "	Default. The only existing mode, exists for compatibility with Windows regedit.\n"
-    "    /V - advanced mode, can be used with any other switch.\n"
-    "	Ignored, exists for compatibility with Windows regedit.\n"
-    "    /L - location of system.dat file. Can be used with any other switch.\n"
-    "	Ignored. Exists for compatibility with Windows regedit.\n"
-    "    /R - location of user.dat file. Can be used with any other switch.\n"
-    "	Ignored. Exists for compatibility with Windows regedit.\n"
-    "    /? - print this help. Any other switches are ignored.\n"
-    "    /C - create registry from file. Not implemented.\n"
-    "\n"
-    "The switches are case-insensitive, can be prefixed either by '-' or '/'.\n"
-    "This program is command-line compatible with Microsoft Windows\n"
-    "regedit.\n";
+WINE_DEFAULT_DEBUG_CHANNEL(regedit);
+
+static void output_writeconsole(const WCHAR *str, DWORD wlen)
+{
+    DWORD count, ret;
+
+    ret = WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), str, wlen, &count, NULL);
+    if (!ret)
+    {
+        DWORD len;
+        char  *msgA;
+
+        /* WriteConsole() fails on Windows if its output is redirected. If this occurs,
+         * we should call WriteFile() and assume the console encoding is still correct.
+         */
+        len = WideCharToMultiByte(GetConsoleOutputCP(), 0, str, wlen, NULL, 0, NULL, NULL);
+        msgA = HeapAlloc(GetProcessHeap(), 0, len);
+        if (!msgA) return;
+
+        WideCharToMultiByte(GetConsoleOutputCP(), 0, str, wlen, msgA, len, NULL, NULL);
+        WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), msgA, len, &count, FALSE);
+        HeapFree(GetProcessHeap(), 0, msgA);
+    }
+}
+
+static void output_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)
+    {
+        WINE_FIXME("Could not format string: le=%u, fmt=%s\n", GetLastError(), wine_dbgstr_w(fmt));
+        return;
+    }
+    output_writeconsole(str, len);
+    LocalFree(str);
+}
+
+static void __cdecl output_message(unsigned int id, ...)
+{
+    WCHAR fmt[1536];
+    __ms_va_list va_args;
+
+    if (!LoadStringW(GetModuleHandleW(NULL), id, fmt, sizeof(fmt)/sizeof(*fmt)))
+    {
+        WINE_FIXME("LoadString failed with %d\n", GetLastError());
+        return;
+    }
+    __ms_va_start(va_args, id);
+    output_formatstring(fmt, va_args);
+    __ms_va_end(va_args);
+}
 
 typedef enum {
     ACTION_ADD, ACTION_EXPORT, ACTION_DELETE
@@ -84,8 +112,7 @@ static BOOL PerformRegAction(REGEDIT_ACTION action, WCHAR **argv, int *i)
                 }
                 if (size == 0)
                 {
-                    fprintf(stderr, "regedit: File not found \"%ls\" (%d)\n",
-                            filename, GetLastError());
+                    output_message(STRING_FILE_NOT_FOUND, filename);
                     exit(1);
                 }
                 reg_file = _wfopen(realname, rb_mode);
@@ -93,7 +120,7 @@ static BOOL PerformRegAction(REGEDIT_ACTION action, WCHAR **argv, int *i)
                 {
                     WCHAR regedit[] = {'r','e','g','e','d','i','t',0};
                     _wperror(regedit);
-                    fprintf(stderr, "regedit: Can't open file \"%ls\"\n", filename);
+                    output_message(STRING_CANNOT_OPEN_FILE, filename);
                     exit(1);
                 }
                 import_registry_file(reg_file);
@@ -119,7 +146,7 @@ static BOOL PerformRegAction(REGEDIT_ACTION action, WCHAR **argv, int *i)
             break;
         }
     default:
-        fprintf(stderr, "regedit: Unhandled action!\n");
+        output_message(STRING_UNHANDLED_ACTION);
         exit(1);
         break;
     }
@@ -157,7 +184,7 @@ BOOL ProcessCmdLine(WCHAR *cmdline)
         switch (toupperW(argv[i][1]))
         {
         case '?':
-            fprintf(stderr, usage);
+            output_message(STRING_USAGE);
             exit(0);
             break;
         case 'D':
@@ -176,7 +203,8 @@ BOOL ProcessCmdLine(WCHAR *cmdline)
             /* ignored */;
             break;
         default:
-            fprintf(stderr, "regedit: Invalid switch [%ls]\n", argv[i]);
+            output_message(STRING_INVALID_SWITCH, argv[i]);
+            output_message(STRING_HELP);
             exit(1);
         }
     }
@@ -187,13 +215,13 @@ BOOL ProcessCmdLine(WCHAR *cmdline)
         {
         case ACTION_ADD:
         case ACTION_EXPORT:
-            fprintf(stderr, "regedit: No file name was specified\n\n");
+            output_message(STRING_NO_FILENAME);
             break;
         case ACTION_DELETE:
-            fprintf(stderr,"regedit: No registry key was specified for removal\n\n");
+            output_message(STRING_NO_REG_KEY);
             break;
         }
-        fprintf(stderr, usage);
+        output_message(STRING_HELP);
         exit(1);
     }
 
diff --git a/programs/regedit/regedit.rc b/programs/regedit/regedit.rc
index 2a331c9..18d19b5 100644
--- a/programs/regedit/regedit.rc
+++ b/programs/regedit/regedit.rc
@@ -328,6 +328,43 @@ IDC_REGEDIT ACCELERATORS
     VK_F5,	ID_VIEW_REFRESH, VIRTKEY
 }
 
+/* Command-line strings */
+STRINGTABLE
+{
+    STRING_USAGE, "Usage:\n\
+\  regedit [options] [filename] [reg_key]\n\
+\n\
+\Options:\n\
+\  [no option]    Launch the graphical version of this program.\n\
+\  /L:system.dat  The location of the system.dat file to be modified.\n\
+\                 Compatible with any other switch. Ignored.\n\
+\  /R:user.dat    The location of the user.dat file to be modified.\n\
+\                 Compatible with any other switch. Ignored.\n\
+\  /C             Import the contents of a registry file.\n\
+\  /D             Delete a specified registry key.\n\
+\  /E             Export the contents of a specified registry key to a file.\n\
+\                 If no key is specified, the entire registry is exported.\n\
+\  /S             Silent mode. No messages will be displayed.\n\
+\  /V             Launch the GUI in advanced mode. Ignored.\n\
+\  /?             Display this information and exit.\n\
+\  [filename]     The location of the file containing registry information to\n\
+\                 be imported. When used with [/E], this option specifies the\n\
+\                 file location where registry information will be exported.\n\
+\  [reg_key]      The registry key to be modified.\n\
+\n\
+\Usage examples:\n\
+\  regedit \"import.reg\"\n\
+\  regedit /E \"export.reg\" \"HKEY_CURRENT_USER\\Console\"\n\
+\  regedit /D \"HKEY_LOCAL_MACHINE\\Error\\Path\"\n"
+    STRING_INVALID_SWITCH, "regedit: Invalid or unrecognized switch [%1]\n"
+    STRING_HELP, "Type \"regedit /?\" for help.\n"
+    STRING_NO_FILENAME, "regedit: No filename was specified.\n"
+    STRING_NO_REG_KEY, "regedit: No registry key was specified for removal.\n"
+    STRING_FILE_NOT_FOUND, "regedit: The file '%1' was not found.\n"
+    STRING_CANNOT_OPEN_FILE, "regedit: Unable to open the file '%1'.\n"
+    STRING_UNHANDLED_ACTION, "regedit: Unhandled action.\n"
+}
+
 /* define language neutral resources */
 
 LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
diff --git a/programs/regedit/resource.h b/programs/regedit/resource.h
index 020765e..37051d8 100644
--- a/programs/regedit/resource.h
+++ b/programs/regedit/resource.h
@@ -157,3 +157,13 @@
 #define IDC_EXPORT_PATH                 103
 
 #define IDC_STATIC                      -1
+
+/* Command-line strings */
+#define STRING_USAGE                    3001
+#define STRING_INVALID_SWITCH           3002
+#define STRING_HELP                     3003
+#define STRING_NO_FILENAME              3004
+#define STRING_NO_REG_KEY               3005
+#define STRING_FILE_NOT_FOUND           3006
+#define STRING_CANNOT_OPEN_FILE         3007
+#define STRING_UNHANDLED_ACTION         3008
-- 
2.7.4




More information about the wine-patches mailing list