[REG] Sync with Wine 3.0. CORE-14225
authorAmine Khaldi <amine.khaldi@reactos.org>
Sun, 21 Jan 2018 21:04:40 +0000 (22:04 +0100)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sun, 21 Jan 2018 21:04:40 +0000 (22:04 +0100)
31 files changed:
base/applications/cmdutils/reg/CMakeLists.txt
base/applications/cmdutils/reg/export.c [new file with mode: 0644]
base/applications/cmdutils/reg/import.c
base/applications/cmdutils/reg/lang/bg-BG.rc
base/applications/cmdutils/reg/lang/cs-CZ.rc
base/applications/cmdutils/reg/lang/da-DK.rc
base/applications/cmdutils/reg/lang/de-DE.rc
base/applications/cmdutils/reg/lang/en-US.rc
base/applications/cmdutils/reg/lang/es-ES.rc
base/applications/cmdutils/reg/lang/fr-FR.rc
base/applications/cmdutils/reg/lang/it-IT.rc
base/applications/cmdutils/reg/lang/ja-JP.rc
base/applications/cmdutils/reg/lang/ko-KR.rc
base/applications/cmdutils/reg/lang/lt-LT.rc
base/applications/cmdutils/reg/lang/nl-NL.rc
base/applications/cmdutils/reg/lang/no-NO.rc
base/applications/cmdutils/reg/lang/pl-PL.rc
base/applications/cmdutils/reg/lang/pt-PT.rc
base/applications/cmdutils/reg/lang/ro-RO.rc
base/applications/cmdutils/reg/lang/ru-RU.rc
base/applications/cmdutils/reg/lang/sl-SI.rc
base/applications/cmdutils/reg/lang/sq-AL.rc
base/applications/cmdutils/reg/lang/sv-SE.rc
base/applications/cmdutils/reg/lang/tr-TR.rc
base/applications/cmdutils/reg/lang/uk-UA.rc
base/applications/cmdutils/reg/lang/zh-CN.rc
base/applications/cmdutils/reg/lang/zh-TW.rc
base/applications/cmdutils/reg/reg.c
base/applications/cmdutils/reg/reg.h
base/applications/cmdutils/reg/resource.h
media/doc/README.WINE

index 56abc0f..53d1fa4 100644 (file)
@@ -2,7 +2,7 @@
 remove_definitions(-D_WIN32_WINNT=0x502)
 add_definitions(-D_WIN32_WINNT=0x600)
 
-add_executable(reg import.c reg.c reg.rc)
+add_executable(reg export.c import.c reg.c reg.rc)
 set_module_type(reg win32cui UNICODE)
 target_link_libraries(reg wine)
 add_importlibs(reg advapi32 advapi32_vista user32 msvcrt kernel32 ntdll)
diff --git a/base/applications/cmdutils/reg/export.c b/base/applications/cmdutils/reg/export.c
new file mode 100644 (file)
index 0000000..24b9dc8
--- /dev/null
@@ -0,0 +1,410 @@
+/*
+ * Copyright 2017 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
+ */
+
+#include <windef.h>
+#include <winbase.h>
+#include <winreg.h>
+#include <stdlib.h>
+
+#include <wine/unicode.h>
+
+#include "reg.h"
+
+static void write_file(HANDLE hFile, const WCHAR *str)
+{
+    DWORD written;
+
+    WriteFile(hFile, str, lstrlenW(str) * sizeof(WCHAR), &written, NULL);
+}
+
+static WCHAR *escape_string(WCHAR *str, size_t str_len, size_t *line_len)
+{
+    size_t i, escape_count, pos;
+    WCHAR *buf;
+
+    for (i = 0, escape_count = 0; i < str_len; i++)
+    {
+        WCHAR c = str[i];
+        if (c == '\r' || c == '\n' || c == '\\' || c == '"' || c == '\0')
+            escape_count++;
+    }
+
+    buf = heap_xalloc((str_len + escape_count + 1) * sizeof(WCHAR));
+
+    for (i = 0, pos = 0; i < str_len; i++, pos++)
+    {
+        WCHAR c = str[i];
+
+        switch (c)
+        {
+        case '\r':
+            buf[pos++] = '\\';
+            buf[pos] = 'r';
+            break;
+        case '\n':
+            buf[pos++] = '\\';
+            buf[pos] = 'n';
+            break;
+        case '\\':
+            buf[pos++] = '\\';
+            buf[pos] = '\\';
+            break;
+        case '"':
+            buf[pos++] = '\\';
+            buf[pos] = '"';
+            break;
+        case '\0':
+            buf[pos++] = '\\';
+            buf[pos] = '0';
+            break;
+        default:
+            buf[pos] = c;
+        }
+    }
+
+    buf[pos] = 0;
+    *line_len = pos;
+    return buf;
+}
+
+static size_t export_value_name(HANDLE hFile, WCHAR *name, size_t len)
+{
+    static const WCHAR quoted_fmt[] = {'"','%','s','"','=',0};
+    static const WCHAR default_name[] = {'@','=',0};
+    size_t line_len;
+
+    if (name && *name)
+    {
+        WCHAR *str = escape_string(name, len, &line_len);
+        WCHAR *buf = heap_xalloc((line_len + 4) * sizeof(WCHAR));
+        line_len = sprintfW(buf, quoted_fmt, str);
+        write_file(hFile, buf);
+        heap_free(buf);
+        heap_free(str);
+    }
+    else
+    {
+        line_len = lstrlenW(default_name);
+        write_file(hFile, default_name);
+    }
+
+    return line_len;
+}
+
+static void export_string_data(WCHAR **buf, WCHAR *data, size_t size)
+{
+    size_t len = 0, line_len;
+    WCHAR *str;
+    static const WCHAR fmt[] = {'"','%','s','"',0};
+
+    if (size)
+        len = size / sizeof(WCHAR) - 1;
+    str = escape_string(data, len, &line_len);
+    *buf = heap_xalloc((line_len + 3) * sizeof(WCHAR));
+    sprintfW(*buf, fmt, str);
+    heap_free(str);
+}
+
+static void export_dword_data(WCHAR **buf, DWORD *data)
+{
+    static const WCHAR fmt[] = {'d','w','o','r','d',':','%','0','8','x',0};
+
+    *buf = heap_xalloc(15 * sizeof(WCHAR));
+    sprintfW(*buf, fmt, *data);
+}
+
+static size_t export_hex_data_type(HANDLE hFile, DWORD type)
+{
+    static const WCHAR hex[] = {'h','e','x',':',0};
+    static const WCHAR hexp_fmt[] = {'h','e','x','(','%','x',')',':',0};
+    size_t line_len;
+
+    if (type == REG_BINARY)
+    {
+        line_len = lstrlenW(hex);
+        write_file(hFile, hex);
+    }
+    else
+    {
+        WCHAR *buf = heap_xalloc(15 * sizeof(WCHAR));
+        line_len = sprintfW(buf, hexp_fmt, type);
+        write_file(hFile, buf);
+        heap_free(buf);
+    }
+
+    return line_len;
+}
+
+#define MAX_HEX_CHARS 77
+
+static void export_hex_data(HANDLE hFile, WCHAR **buf, DWORD type,
+                            DWORD line_len, void *data, DWORD size)
+{
+    static const WCHAR fmt[] = {'%','0','2','x',0};
+    static const WCHAR hex_concat[] = {'\\','\r','\n',' ',' ',0};
+    size_t num_commas, i, pos;
+
+    line_len += export_hex_data_type(hFile, type);
+
+    if (!size) return;
+
+    num_commas = size - 1;
+    *buf = heap_xalloc(size * 3 * sizeof(WCHAR));
+
+    for (i = 0, pos = 0; i < size; i++)
+    {
+        pos += sprintfW(*buf + pos, fmt, ((BYTE *)data)[i]);
+        if (i == num_commas) break;
+        (*buf)[pos++] = ',';
+        (*buf)[pos] = 0;
+        line_len += 3;
+
+        if (line_len >= MAX_HEX_CHARS)
+        {
+            write_file(hFile, *buf);
+            write_file(hFile, hex_concat);
+            line_len = 2;
+            pos = 0;
+        }
+    }
+}
+
+static void export_newline(HANDLE hFile)
+{
+    static const WCHAR newline[] = {'\r','\n',0};
+
+    write_file(hFile, newline);
+}
+
+static void export_data(HANDLE hFile, WCHAR *value_name, DWORD value_len,
+                        DWORD type, void *data, size_t size)
+{
+    WCHAR *buf = NULL;
+    size_t line_len = export_value_name(hFile, value_name, value_len);
+
+    switch (type)
+    {
+    case REG_SZ:
+        export_string_data(&buf, data, size);
+        break;
+    case REG_DWORD:
+        if (size)
+        {
+            export_dword_data(&buf, data);
+            break;
+        }
+        /* fall through */
+    case REG_NONE:
+    case REG_EXPAND_SZ:
+    case REG_BINARY:
+    case REG_MULTI_SZ:
+    default:
+        export_hex_data(hFile, &buf, type, line_len, data, size);
+        break;
+    }
+
+    if (size || type == REG_SZ)
+    {
+        write_file(hFile, buf);
+        heap_free(buf);
+    }
+
+    export_newline(hFile);
+}
+
+static void export_key_name(HANDLE hFile, WCHAR *name)
+{
+    static const WCHAR fmt[] = {'\r','\n','[','%','s',']','\r','\n',0};
+    WCHAR *buf;
+
+    buf = heap_xalloc((lstrlenW(name) + 7) * sizeof(WCHAR));
+    sprintfW(buf, fmt, name);
+    write_file(hFile, buf);
+    heap_free(buf);
+}
+
+static int export_registry_data(HANDLE hFile, HKEY key, WCHAR *path)
+{
+    LONG rc;
+    DWORD max_value_len = 256, value_len;
+    DWORD max_data_bytes = 2048, data_size;
+    DWORD subkey_len;
+    DWORD i, type, path_len;
+    WCHAR *value_name, *subkey_name, *subkey_path;
+    BYTE *data;
+    HKEY subkey;
+
+    export_key_name(hFile, path);
+
+    value_name = heap_xalloc(max_value_len * sizeof(WCHAR));
+    data = heap_xalloc(max_data_bytes);
+
+    i = 0;
+    for (;;)
+    {
+        value_len = max_value_len;
+        data_size = max_data_bytes;
+        rc = RegEnumValueW(key, i, value_name, &value_len, NULL, &type, data, &data_size);
+
+        if (rc == ERROR_SUCCESS)
+        {
+            export_data(hFile, value_name, value_len, type, data, data_size);
+            i++;
+        }
+        else if (rc == ERROR_MORE_DATA)
+        {
+            if (data_size > max_data_bytes)
+            {
+                max_data_bytes = data_size;
+                data = heap_xrealloc(data, max_data_bytes);
+            }
+            else
+            {
+                max_value_len *= 2;
+                value_name = heap_xrealloc(value_name, max_value_len * sizeof(WCHAR));
+            }
+        }
+        else break;
+    }
+
+    heap_free(data);
+    heap_free(value_name);
+
+    subkey_name = heap_xalloc(MAX_SUBKEY_LEN * sizeof(WCHAR));
+
+    path_len = lstrlenW(path);
+
+    i = 0;
+    for (;;)
+    {
+        subkey_len = MAX_SUBKEY_LEN;
+        rc = RegEnumKeyExW(key, i, subkey_name, &subkey_len, NULL, NULL, NULL, NULL);
+        if (rc == ERROR_SUCCESS)
+        {
+            subkey_path = build_subkey_path(path, path_len, subkey_name, subkey_len);
+            if (!RegOpenKeyExW(key, subkey_name, 0, KEY_READ, &subkey))
+            {
+                export_registry_data(hFile, subkey, subkey_path);
+                RegCloseKey(subkey);
+            }
+            heap_free(subkey_path);
+            i++;
+        }
+        else break;
+    }
+
+    heap_free(subkey_name);
+    return 0;
+}
+
+static void export_file_header(HANDLE hFile)
+{
+    static const WCHAR header[] = { 0xfeff,'W','i','n','d','o','w','s',' ',
+                                   'R','e','g','i','s','t','r','y',' ','E','d','i','t','o','r',' ',
+                                   'V','e','r','s','i','o','n',' ','5','.','0','0','\r','\n'};
+
+    write_file(hFile, header);
+}
+
+static HANDLE create_file(const WCHAR *filename, DWORD action)
+{
+    return CreateFileW(filename, GENERIC_WRITE, 0, NULL, action, FILE_ATTRIBUTE_NORMAL, NULL);
+}
+
+static HANDLE get_file_handle(WCHAR *filename, BOOL overwrite_file)
+{
+    HANDLE hFile = create_file(filename, overwrite_file ? CREATE_ALWAYS : CREATE_NEW);
+
+    if (hFile == INVALID_HANDLE_VALUE)
+    {
+        DWORD error = GetLastError();
+
+        if (error == ERROR_FILE_EXISTS)
+        {
+            if (!ask_confirm(STRING_OVERWRITE_FILE, filename))
+            {
+                output_message(STRING_CANCELLED);
+                exit(0);
+            }
+
+            hFile = create_file(filename, CREATE_ALWAYS);
+        }
+        else
+        {
+            WCHAR *str;
+
+            FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+                           FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, 0, (WCHAR *)&str, 0, NULL);
+            output_writeconsole(str, lstrlenW(str));
+            LocalFree(str);
+            exit(1);
+        }
+    }
+
+    return hFile;
+}
+
+static BOOL is_overwrite_switch(const WCHAR *s)
+{
+    if (strlenW(s) > 2)
+        return FALSE;
+
+    if ((s[0] == '/' || s[0] == '-') && (s[1] == 'y' || s[1] == 'Y'))
+        return TRUE;
+
+    return FALSE;
+}
+
+int reg_export(int argc, WCHAR *argv[])
+{
+    HKEY root, hkey;
+    WCHAR *path, *long_key;
+    BOOL overwrite_file = FALSE;
+    HANDLE hFile;
+    int ret;
+
+    if (argc == 3 || argc > 5)
+        goto error;
+
+    if (!parse_registry_key(argv[2], &root, &path, &long_key))
+        return 1;
+
+    if (argc == 5 && !(overwrite_file = is_overwrite_switch(argv[4])))
+        goto error;
+
+    if (RegOpenKeyExW(root, path, 0, KEY_READ, &hkey))
+    {
+        output_message(STRING_INVALID_KEY);
+        return 1;
+    }
+
+    hFile = get_file_handle(argv[3], overwrite_file);
+    export_file_header(hFile);
+    ret = export_registry_data(hFile, hkey, long_key);
+    export_newline(hFile);
+    CloseHandle(hFile);
+
+    RegCloseKey(hkey);
+
+    return ret;
+
+error:
+    output_message(STRING_INVALID_SYNTAX);
+    output_message(STRING_FUNC_HELP, struprW(argv[1]));
+    return 1;
+}
index 8825765..c4c988d 100644 (file)
@@ -785,6 +785,9 @@ static WCHAR *hex_data_state(struct parser *parser, WCHAR *pos)
 {
     WCHAR *line = pos;
 
+    if (!*line)
+        goto set_value;
+
     if (!convert_hex_csv_to_hex(parser, &line))
         goto invalid;
 
@@ -796,6 +799,7 @@ static WCHAR *hex_data_state(struct parser *parser, WCHAR *pos)
 
     prepare_hex_string_data(parser);
 
+set_value:
     set_state(parser, SET_VALUE);
     return line;
 
index 884d55e..23fbfb0 100644 (file)
@@ -37,4 +37,7 @@ STRINGTABLE
     STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n"
     STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n"
     STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\\%1!c!]\n"
+    STRING_EXPORT_USAGE, "REG EXPORT key_name file.reg [/y]\n"
+    STRING_INVALID_SYSTEM_KEY, "reg: Invalid system key [%1]\n"
+    STRING_OVERWRITE_FILE, "The file '%1' already exists. Do you want to overwrite it?"
 }
index f75f8fb..ab9bfde 100644 (file)
@@ -42,4 +42,7 @@ STRINGTABLE
     STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n"
     STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n"
     STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\\%1!c!]\n"
+    STRING_EXPORT_USAGE, "REG EXPORT key_name file.reg [/y]\n"
+    STRING_INVALID_SYSTEM_KEY, "reg: Invalid system key [%1]\n"
+    STRING_OVERWRITE_FILE, "The file '%1' already exists. Do you want to overwrite it?"
 }
index a151902..6c8338c 100644 (file)
@@ -37,4 +37,7 @@ STRINGTABLE
     STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n"
     STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n"
     STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\\%1!c!]\n"
+    STRING_EXPORT_USAGE, "REG EXPORT key_name file.reg [/y]\n"
+    STRING_INVALID_SYSTEM_KEY, "reg: Invalid system key [%1]\n"
+    STRING_OVERWRITE_FILE, "The file '%1' already exists. Do you want to overwrite it?"
 }
index 083b7e7..ec0cd46 100644 (file)
@@ -37,4 +37,7 @@ STRINGTABLE
     STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n"
     STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n"
     STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\\%1!c!]\n"
+    STRING_EXPORT_USAGE, "REG EXPORT key_name file.reg [/y]\n"
+    STRING_INVALID_SYSTEM_KEY, "reg: Invalid system key [%1]\n"
+    STRING_OVERWRITE_FILE, "The file '%1' already exists. Do you want to overwrite it?"
 }
index 3aae61e..9c9bef5 100644 (file)
@@ -37,4 +37,7 @@ STRINGTABLE
     STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n"
     STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n"
     STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\\%1!c!]\n"
+    STRING_EXPORT_USAGE, "REG EXPORT key_name file.reg [/y]\n"
+    STRING_INVALID_SYSTEM_KEY, "reg: Invalid system key [%1]\n"
+    STRING_OVERWRITE_FILE, "The file '%1' already exists. Do you want to overwrite it?"
 }
index ea9cb3b..60bb78a 100644 (file)
@@ -37,4 +37,7 @@ STRINGTABLE
     STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n"
     STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n"
     STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\\%1!c!]\n"
+    STRING_EXPORT_USAGE, "REG EXPORT key_name file.reg [/y]\n"
+    STRING_INVALID_SYSTEM_KEY, "reg: Invalid system key [%1]\n"
+    STRING_OVERWRITE_FILE, "The file '%1' already exists. Do you want to overwrite it?"
 }
index 3e891d3..89aceb9 100644 (file)
@@ -37,4 +37,7 @@ STRINGTABLE
     STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n"
     STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n"
     STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\\%1!c!]\n"
+    STRING_EXPORT_USAGE, "REG EXPORT key_name file.reg [/y]\n"
+    STRING_INVALID_SYSTEM_KEY, "reg: Invalid system key [%1]\n"
+    STRING_OVERWRITE_FILE, "The file '%1' already exists. Do you want to overwrite it?"
 }
index 63cbc5c..c2ad7f3 100644 (file)
@@ -37,4 +37,7 @@ STRINGTABLE
     STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n"
     STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n"
     STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\\%1!c!]\n"
+    STRING_EXPORT_USAGE, "REG EXPORT key_name file.reg [/y]\n"
+    STRING_INVALID_SYSTEM_KEY, "reg: Invalid system key [%1]\n"
+    STRING_OVERWRITE_FILE, "The file '%1' already exists. Do you want to overwrite it?"
 }
index 7b1c018..07e7fd7 100644 (file)
@@ -37,4 +37,7 @@ STRINGTABLE
     STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n"
     STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n"
     STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\\%1!c!]\n"
+    STRING_EXPORT_USAGE, "REG EXPORT key_name file.reg [/y]\n"
+    STRING_INVALID_SYSTEM_KEY, "reg: Invalid system key [%1]\n"
+    STRING_OVERWRITE_FILE, "The file '%1' already exists. Do you want to overwrite it?"
 }
index 2bbe277..ba9af4b 100644 (file)
@@ -37,4 +37,7 @@ STRINGTABLE
     STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n"
     STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n"
     STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\\%1!c!]\n"
+    STRING_EXPORT_USAGE, "REG EXPORT key_name file.reg [/y]\n"
+    STRING_INVALID_SYSTEM_KEY, "reg: Invalid system key [%1]\n"
+    STRING_OVERWRITE_FILE, "The file '%1' already exists. Do you want to overwrite it?"
 }
index 75bbcc2..c8feef0 100644 (file)
@@ -37,4 +37,7 @@ STRINGTABLE
     STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n"
     STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n"
     STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\\%1!c!]\n"
+    STRING_EXPORT_USAGE, "REG EXPORT key_name file.reg [/y]\n"
+    STRING_INVALID_SYSTEM_KEY, "reg: Invalid system key [%1]\n"
+    STRING_OVERWRITE_FILE, "The file '%1' already exists. Do you want to overwrite it?"
 }
index b2fb857..a62f178 100644 (file)
@@ -37,4 +37,7 @@ STRINGTABLE
     STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n"
     STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n"
     STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\\%1!c!]\n"
+    STRING_EXPORT_USAGE, "REG EXPORT key_name file.reg [/y]\n"
+    STRING_INVALID_SYSTEM_KEY, "reg: Invalid system key [%1]\n"
+    STRING_OVERWRITE_FILE, "The file '%1' already exists. Do you want to overwrite it?"
 }
index 5d6b79e..b9c269e 100644 (file)
@@ -37,4 +37,7 @@ STRINGTABLE
     STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n"
     STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n"
     STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\\%1!c!]\n"
+    STRING_EXPORT_USAGE, "REG EXPORT key_name file.reg [/y]\n"
+    STRING_INVALID_SYSTEM_KEY, "reg: Invalid system key [%1]\n"
+    STRING_OVERWRITE_FILE, "The file '%1' already exists. Do you want to overwrite it?"
 }
index e3d2116..92f98dc 100644 (file)
@@ -37,4 +37,7 @@ STRINGTABLE
     STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n"
     STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n"
     STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\\%1!c!]\n"
+    STRING_EXPORT_USAGE, "REG EXPORT key_name file.reg [/y]\n"
+    STRING_INVALID_SYSTEM_KEY, "reg: Invalid system key [%1]\n"
+    STRING_OVERWRITE_FILE, "The file '%1' already exists. Do you want to overwrite it?"
 }
index f6ee64d..dd39615 100644 (file)
@@ -37,4 +37,7 @@ STRINGTABLE
     STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n"
     STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n"
     STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\\%1!c!]\n"
+    STRING_EXPORT_USAGE, "REG EXPORT key_name file.reg [/y]\n"
+    STRING_INVALID_SYSTEM_KEY, "reg: Invalid system key [%1]\n"
+    STRING_OVERWRITE_FILE, "The file '%1' already exists. Do you want to overwrite it?"
 }
index ebcbe18..5c61362 100644 (file)
@@ -43,4 +43,7 @@ STRINGTABLE
     STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n"
     STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n"
     STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\\%1!c!]\n"
+    STRING_EXPORT_USAGE, "REG EXPORT key_name file.reg [/y]\n"
+    STRING_INVALID_SYSTEM_KEY, "reg: Invalid system key [%1]\n"
+    STRING_OVERWRITE_FILE, "The file '%1' already exists. Do you want to overwrite it?"
 }
index 04ad38c..f8d3d8a 100644 (file)
@@ -37,4 +37,7 @@ STRINGTABLE
     STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n"
     STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n"
     STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\\%1!c!]\n"
+    STRING_EXPORT_USAGE, "REG EXPORT key_name file.reg [/y]\n"
+    STRING_INVALID_SYSTEM_KEY, "reg: Invalid system key [%1]\n"
+    STRING_OVERWRITE_FILE, "The file '%1' already exists. Do you want to overwrite it?"
 }
index e7d631e..cd22ffe 100644 (file)
@@ -37,4 +37,7 @@ STRINGTABLE
     STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n"
     STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n"
     STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\\%1!c!]\n"
+    STRING_EXPORT_USAGE, "REG EXPORT key_name file.reg [/y]\n"
+    STRING_INVALID_SYSTEM_KEY, "reg: Invalid system key [%1]\n"
+    STRING_OVERWRITE_FILE, "The file '%1' already exists. Do you want to overwrite it?"
 }
index 3b0dba5..2c4d2f5 100644 (file)
@@ -41,4 +41,7 @@ STRINGTABLE
     STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n"
     STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n"
     STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\\%1!c!]\n"
+    STRING_EXPORT_USAGE, "REG EXPORT key_name file.reg [/y]\n"
+    STRING_INVALID_SYSTEM_KEY, "reg: Invalid system key [%1]\n"
+    STRING_OVERWRITE_FILE, "The file '%1' already exists. Do you want to overwrite it?"
 }
index 774bf95..978e704 100644 (file)
@@ -37,4 +37,7 @@ STRINGTABLE
     STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n"
     STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n"
     STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\\%1!c!]\n"
+    STRING_EXPORT_USAGE, "REG EXPORT key_name file.reg [/y]\n"
+    STRING_INVALID_SYSTEM_KEY, "reg: Invalid system key [%1]\n"
+    STRING_OVERWRITE_FILE, "The file '%1' already exists. Do you want to overwrite it?"
 }
index 9061740..e467330 100644 (file)
@@ -39,4 +39,7 @@ STRINGTABLE
     STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n"
     STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n"
     STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\\%1!c!]\n"
+    STRING_EXPORT_USAGE, "REG EXPORT key_name file.reg [/y]\n"
+    STRING_INVALID_SYSTEM_KEY, "reg: Invalid system key [%1]\n"
+    STRING_OVERWRITE_FILE, "The file '%1' already exists. Do you want to overwrite it?"
 }
index b5a8b68..7ca1cff 100644 (file)
@@ -37,4 +37,7 @@ STRINGTABLE
     STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n"
     STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n"
     STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\\%1!c!]\n"
+    STRING_EXPORT_USAGE, "REG EXPORT key_name file.reg [/y]\n"
+    STRING_INVALID_SYSTEM_KEY, "reg: Invalid system key [%1]\n"
+    STRING_OVERWRITE_FILE, "The file '%1' already exists. Do you want to overwrite it?"
 }
index c952714..6dbe375 100644 (file)
@@ -39,4 +39,7 @@ STRINGTABLE
     STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n"
     STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n"
     STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\\%1!c!]\n"
+    STRING_EXPORT_USAGE, "REG EXPORT key_name file.reg [/y]\n"
+    STRING_INVALID_SYSTEM_KEY, "reg: Invalid system key [%1]\n"
+    STRING_OVERWRITE_FILE, "The file '%1' already exists. Do you want to overwrite it?"
 }
index e6c5a6e..b9cff9a 100644 (file)
@@ -39,4 +39,7 @@ STRINGTABLE
     STRING_FILE_NOT_FOUND, "reg: The file '%1' was not found.\n"
     STRING_OPEN_KEY_FAILED, "reg: Unable to open the registry key '%1'.\n"
     STRING_ESCAPE_SEQUENCE, "reg: Unrecognized escape sequence [\\%1!c!]\n"
+    STRING_EXPORT_USAGE, "REG EXPORT key_name file.reg [/y]\n"
+    STRING_INVALID_SYSTEM_KEY, "reg: Invalid system key [%1]\n"
+    STRING_OVERWRITE_FILE, "The file '%1' already exists. Do you want to overwrite it?"
 }
index 5a857de..b9db08e 100644 (file)
@@ -81,6 +81,8 @@ type_rels[] =
     {REG_MULTI_SZ, type_multi_sz},
 };
 
+static const WCHAR newlineW[] = {'\n',0};
+
 void *heap_xalloc(size_t size)
 {
     void *buf = HeapAlloc(GetProcessHeap(), 0, size);
@@ -115,7 +117,7 @@ BOOL heap_free(void *buf)
     return HeapFree(GetProcessHeap(), 0, buf);
 }
 
-static void output_writeconsole(const WCHAR *str, DWORD wlen)
+void output_writeconsole(const WCHAR *str, DWORD wlen)
 {
     DWORD count, ret;
 
@@ -155,7 +157,7 @@ static void output_formatstring(const WCHAR *fmt, __ms_va_list va_args)
     LocalFree(str);
 }
 
-void __cdecl output_message(unsigned int id, ...)
+void WINAPIV output_message(unsigned int id, ...)
 {
     WCHAR fmt[1024];
     __ms_va_list va_args;
@@ -170,7 +172,7 @@ void __cdecl output_message(unsigned int id, ...)
     __ms_va_end(va_args);
 }
 
-static void __cdecl output_string(const WCHAR *fmt, ...)
+static void WINAPIV output_string(const WCHAR *fmt, ...)
 {
     __ms_va_list va_args;
 
@@ -180,7 +182,7 @@ static void __cdecl output_string(const WCHAR *fmt, ...)
 }
 
 /* ask_confirm() adapted from programs/cmd/builtins.c */
-static BOOL ask_confirm(unsigned int msgid, WCHAR *reg_info)
+BOOL ask_confirm(unsigned int msgid, WCHAR *reg_info)
 {
     HMODULE hmod;
     WCHAR Ybuffer[4];
@@ -614,7 +616,6 @@ static const WCHAR *reg_type_to_wchar(DWORD type)
 static void output_value(const WCHAR *value_name, DWORD type, BYTE *data, DWORD data_size)
 {
     static const WCHAR fmt[] = {' ',' ',' ',' ','%','1',0};
-    static const WCHAR newlineW[] = {'\n',0};
     WCHAR defval[32];
     WCHAR *reg_data;
 
@@ -641,7 +642,7 @@ static void output_value(const WCHAR *value_name, DWORD type, BYTE *data, DWORD
     output_string(newlineW);
 }
 
-static WCHAR *build_subkey_path(WCHAR *path, DWORD path_len, WCHAR *subkey_name, DWORD subkey_len)
+WCHAR *build_subkey_path(WCHAR *path, DWORD path_len, WCHAR *subkey_name, DWORD subkey_len)
 {
     WCHAR *subkey_path;
     static const WCHAR fmt[] = {'%','s','\\','%','s',0};
@@ -654,8 +655,6 @@ static WCHAR *build_subkey_path(WCHAR *path, DWORD path_len, WCHAR *subkey_name,
 
 static unsigned int num_values_found = 0;
 
-#define MAX_SUBKEY_LEN   257
-
 static int query_value(HKEY key, WCHAR *value_name, WCHAR *path, BOOL recurse)
 {
     LONG rc;
@@ -664,7 +663,6 @@ static int query_value(HKEY key, WCHAR *value_name, WCHAR *path, BOOL recurse)
     DWORD type, path_len, i;
     BYTE *data;
     WCHAR fmt[] = {'%','1','\n',0};
-    WCHAR newlineW[] = {'\n',0};
     WCHAR *subkey_name, *subkey_path;
     HKEY subkey;
 
@@ -744,7 +742,6 @@ static int query_all(HKEY key, WCHAR *path, BOOL recurse)
     WCHAR fmt[] = {'%','1','\n',0};
     WCHAR fmt_path[] = {'%','1','\\','%','2','\n',0};
     WCHAR *value_name, *subkey_name, *subkey_path;
-    WCHAR newlineW[] = {'\n',0};
     BYTE *data;
     HKEY subkey;
 
@@ -825,7 +822,6 @@ static int reg_query(HKEY root, WCHAR *path, WCHAR *key_name, WCHAR *value_name,
                      BOOL value_empty, BOOL recurse)
 {
     HKEY key;
-    WCHAR newlineW[] = {'\n',0};
     int ret;
 
     if (RegOpenKeyExW(root, path, 0, KEY_READ, &key) != ERROR_SUCCESS)
@@ -877,32 +873,41 @@ static WCHAR *get_long_key(HKEY root, WCHAR *path)
     return long_key;
 }
 
-static BOOL parse_registry_key(const WCHAR *key, HKEY *root, WCHAR **path, WCHAR **long_key)
+BOOL parse_registry_key(const WCHAR *key, HKEY *root, WCHAR **path, WCHAR **long_key)
 {
     if (!sane_path(key))
         return FALSE;
 
+    *path = strchrW(key, '\\');
+    if (*path) (*path)++;
+
     *root = path_get_rootkey(key);
     if (!*root)
     {
-        output_message(STRING_INVALID_KEY);
+        if (*path) *(*path - 1) = 0;
+        output_message(STRING_INVALID_SYSTEM_KEY, key);
         return FALSE;
     }
 
-    *path = strchrW(key, '\\');
-    if (*path) (*path)++;
-
     *long_key = get_long_key(*root, *path);
 
     return TRUE;
 }
 
-static BOOL is_help_switch(const WCHAR *s)
+static BOOL is_switch(const WCHAR *s, const WCHAR c)
 {
     if (strlenW(s) > 2)
         return FALSE;
 
-    if ((s[0] == '/' || s[0] == '-') && (s[1] == 'h' || s[1] == '?'))
+    if ((s[0] == '/' || s[0] == '-') && (s[1] == c || s[1] == toupperW(c)))
+        return TRUE;
+
+    return FALSE;
+}
+
+static BOOL is_help_switch(const WCHAR *s)
+{
+    if (is_switch(s, '?') || is_switch(s, 'h'))
         return TRUE;
 
     return FALSE;
@@ -912,6 +917,7 @@ enum operations {
     REG_ADD,
     REG_DELETE,
     REG_IMPORT,
+    REG_EXPORT,
     REG_QUERY,
     REG_INVALID
 };
@@ -923,6 +929,7 @@ static enum operations get_operation(const WCHAR *str, int *op_help)
     static const WCHAR add[] = {'a','d','d',0};
     static const WCHAR delete[] = {'d','e','l','e','t','e',0};
     static const WCHAR import[] = {'i','m','p','o','r','t',0};
+    static const WCHAR export[] = {'e','x','p','o','r','t',0};
     static const WCHAR query[] = {'q','u','e','r','y',0};
 
     static const struct op_info op_array[] =
@@ -930,6 +937,7 @@ static enum operations get_operation(const WCHAR *str, int *op_help)
         { add,     REG_ADD,     STRING_ADD_USAGE },
         { delete,  REG_DELETE,  STRING_DELETE_USAGE },
         { import,  REG_IMPORT,  STRING_IMPORT_USAGE },
+        { export,  REG_EXPORT,  STRING_EXPORT_USAGE },
         { query,   REG_QUERY,   STRING_QUERY_USAGE },
         { NULL,    -1,          0 }
     };
@@ -998,6 +1006,9 @@ int wmain(int argc, WCHAR *argvW[])
     if (op == REG_IMPORT)
         return reg_import(argvW[2]);
 
+    if (op == REG_EXPORT)
+        return reg_export(argc, argvW);
+
     if (!parse_registry_key(argvW[2], &root, &path, &key_name))
         return 1;
 
index 14c05b1..eb792bb 100644 (file)
 #include "resource.h"
 
 #define ARRAY_SIZE(A) (sizeof(A)/sizeof(*A))
+#define MAX_SUBKEY_LEN   257
 
 /* reg.c */
 void *heap_xalloc(size_t size);
 void *heap_xrealloc(void *buf, size_t size);
 BOOL heap_free(void *buf);
-void __cdecl output_message(unsigned int id, ...);
+void output_writeconsole(const WCHAR *str, DWORD wlen);
+void WINAPIV output_message(unsigned int id, ...);
+BOOL ask_confirm(unsigned int msgid, WCHAR *reg_info);
 HKEY path_get_rootkey(const WCHAR *path);
+WCHAR *build_subkey_path(WCHAR *path, DWORD path_len, WCHAR *subkey_name, DWORD subkey_len);
+BOOL parse_registry_key(const WCHAR *key, HKEY *root, WCHAR **path, WCHAR **long_key);
 
 /* import.c */
 int reg_import(const WCHAR *filename);
 
+/* export.c */
+int reg_export(int argc, WCHAR *argv[]);
+
 #endif /* __REG_H__ */
index 0f57663..84cbe90 100644 (file)
 //#include <windef.h>
 
 /* Translation IDs. */
-#define STRING_USAGE            101
-#define STRING_ADD_USAGE        102
-#define STRING_DELETE_USAGE     103
-#define STRING_QUERY_USAGE      104
-#define STRING_SUCCESS          105
-#define STRING_INVALID_KEY      106
-#define STRING_INVALID_CMDLINE  107
-#define STRING_NO_REMOTE        108
-#define STRING_CANNOT_FIND      109
-#define STRING_UNSUPPORTED_TYPE 110
-#define STRING_MISSING_INTEGER  111
-#define STRING_MISSING_HEXDATA  112
-#define STRING_UNHANDLED_TYPE   113
-#define STRING_OVERWRITE_VALUE  114
-#define STRING_YESNO            115
-#define STRING_YES              116
-#define STRING_NO               117
-#define STRING_CANCELLED        118
-#define STRING_DEFAULT_VALUE    119
-#define STRING_DELETE_VALUE     120
-#define STRING_DELETE_VALUEALL  121
-#define STRING_DELETE_SUBKEY    122
-#define STRING_INVALID_STRING   123
-#define STRING_VALUEALL_FAILED  124
-#define STRING_GENERAL_FAILURE  125
-#define STRING_MATCHES_FOUND    126
-#define STRING_INVALID_SYNTAX   127
-#define STRING_INVALID_OPTION   128
-#define STRING_REG_HELP         129
-#define STRING_FUNC_HELP        130
-#define STRING_VALUE_NOT_SET    131
-#define STRING_IMPORT_USAGE     132
-#define STRING_FILE_NOT_FOUND   133
-#define STRING_OPEN_KEY_FAILED  134
-#define STRING_ESCAPE_SEQUENCE  135
+#define STRING_USAGE                  101
+#define STRING_ADD_USAGE              102
+#define STRING_DELETE_USAGE           103
+#define STRING_QUERY_USAGE            104
+#define STRING_SUCCESS                105
+#define STRING_INVALID_KEY            106
+#define STRING_INVALID_CMDLINE        107
+#define STRING_NO_REMOTE              108
+#define STRING_CANNOT_FIND            109
+#define STRING_UNSUPPORTED_TYPE       110
+#define STRING_MISSING_INTEGER        111
+#define STRING_MISSING_HEXDATA        112
+#define STRING_UNHANDLED_TYPE         113
+#define STRING_OVERWRITE_VALUE        114
+#define STRING_YESNO                  115
+#define STRING_YES                    116
+#define STRING_NO                     117
+#define STRING_CANCELLED              118
+#define STRING_DEFAULT_VALUE          119
+#define STRING_DELETE_VALUE           120
+#define STRING_DELETE_VALUEALL        121
+#define STRING_DELETE_SUBKEY          122
+#define STRING_INVALID_STRING         123
+#define STRING_VALUEALL_FAILED        124
+#define STRING_GENERAL_FAILURE        125
+#define STRING_MATCHES_FOUND          126
+#define STRING_INVALID_SYNTAX         127
+#define STRING_INVALID_OPTION         128
+#define STRING_REG_HELP               129
+#define STRING_FUNC_HELP              130
+#define STRING_VALUE_NOT_SET          131
+#define STRING_IMPORT_USAGE           132
+#define STRING_FILE_NOT_FOUND         133
+#define STRING_OPEN_KEY_FAILED        134
+#define STRING_ESCAPE_SEQUENCE        135
+#define STRING_EXPORT_USAGE           136
+#define STRING_INVALID_SYSTEM_KEY     137
+#define STRING_OVERWRITE_FILE         138
index 69bf99b..5e66b91 100644 (file)
@@ -227,7 +227,7 @@ reactos/win32ss/printing/monitors/localmon/ui/  # Synced to WineStaging-2.9 (kno
 ReactOS shares the following programs with Winehq.
 
 reactos/base/applications/cmdutils/cscript  # Synced to WineStaging-2.9
-reactos/base/applications/cmdutils/reg      # Synced to WineStaging-2.16
+reactos/base/applications/cmdutils/reg      # Synced to Wine-3.0
 reactos/base/applications/cmdutils/schtasks # Synced to WineStaging-2.9
 reactos/base/applications/cmdutils/taskkill # Synced to WineStaging-2.9
 reactos/base/applications/cmdutils/wmic     # Synced to WineStaging-2.9