https://git.reactos.org/?p=reactos.git;a=commitdiff;h=b50acff2bf0e38bdf1f25c707e331b5dc80964b7

commit b50acff2bf0e38bdf1f25c707e331b5dc80964b7
Author:     Amine Khaldi <[email protected]>
AuthorDate: Sun Jan 21 22:04:40 2018 +0100
Commit:     Amine Khaldi <[email protected]>
CommitDate: Sun Jan 21 22:04:40 2018 +0100

    [REG] Sync with Wine 3.0. CORE-14225
---
 base/applications/cmdutils/reg/CMakeLists.txt |   2 +-
 base/applications/cmdutils/reg/export.c       | 410 ++++++++++++++++++++++++++
 base/applications/cmdutils/reg/import.c       |   4 +
 base/applications/cmdutils/reg/lang/bg-BG.rc  |   3 +
 base/applications/cmdutils/reg/lang/cs-CZ.rc  |   3 +
 base/applications/cmdutils/reg/lang/da-DK.rc  |   3 +
 base/applications/cmdutils/reg/lang/de-DE.rc  |   3 +
 base/applications/cmdutils/reg/lang/en-US.rc  |   3 +
 base/applications/cmdutils/reg/lang/es-ES.rc  |   3 +
 base/applications/cmdutils/reg/lang/fr-FR.rc  |   3 +
 base/applications/cmdutils/reg/lang/it-IT.rc  |   3 +
 base/applications/cmdutils/reg/lang/ja-JP.rc  |   3 +
 base/applications/cmdutils/reg/lang/ko-KR.rc  |   3 +
 base/applications/cmdutils/reg/lang/lt-LT.rc  |   3 +
 base/applications/cmdutils/reg/lang/nl-NL.rc  |   3 +
 base/applications/cmdutils/reg/lang/no-NO.rc  |   3 +
 base/applications/cmdutils/reg/lang/pl-PL.rc  |   3 +
 base/applications/cmdutils/reg/lang/pt-PT.rc  |   3 +
 base/applications/cmdutils/reg/lang/ro-RO.rc  |   3 +
 base/applications/cmdutils/reg/lang/ru-RU.rc  |   3 +
 base/applications/cmdutils/reg/lang/sl-SI.rc  |   3 +
 base/applications/cmdutils/reg/lang/sq-AL.rc  |   3 +
 base/applications/cmdutils/reg/lang/sv-SE.rc  |   3 +
 base/applications/cmdutils/reg/lang/tr-TR.rc  |   3 +
 base/applications/cmdutils/reg/lang/uk-UA.rc  |   3 +
 base/applications/cmdutils/reg/lang/zh-CN.rc  |   3 +
 base/applications/cmdutils/reg/lang/zh-TW.rc  |   3 +
 base/applications/cmdutils/reg/reg.c          |  47 +--
 base/applications/cmdutils/reg/reg.h          |  10 +-
 base/applications/cmdutils/reg/resource.h     |  73 ++---
 media/doc/README.WINE                         |   2 +-
 31 files changed, 564 insertions(+), 56 deletions(-)

diff --git a/base/applications/cmdutils/reg/CMakeLists.txt 
b/base/applications/cmdutils/reg/CMakeLists.txt
index 56abc0f0ea..53d1fa4c2f 100644
--- a/base/applications/cmdutils/reg/CMakeLists.txt
+++ b/base/applications/cmdutils/reg/CMakeLists.txt
@@ -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
index 0000000000..24b9dc8374
--- /dev/null
+++ b/base/applications/cmdutils/reg/export.c
@@ -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;
+}
diff --git a/base/applications/cmdutils/reg/import.c 
b/base/applications/cmdutils/reg/import.c
index 8825765c6d..c4c988d7d1 100644
--- a/base/applications/cmdutils/reg/import.c
+++ b/base/applications/cmdutils/reg/import.c
@@ -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;
 
diff --git a/base/applications/cmdutils/reg/lang/bg-BG.rc 
b/base/applications/cmdutils/reg/lang/bg-BG.rc
index 884d55ee37..23fbfb0255 100644
--- a/base/applications/cmdutils/reg/lang/bg-BG.rc
+++ b/base/applications/cmdutils/reg/lang/bg-BG.rc
@@ -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?"
 }
diff --git a/base/applications/cmdutils/reg/lang/cs-CZ.rc 
b/base/applications/cmdutils/reg/lang/cs-CZ.rc
index f75f8fb36a..ab9bfde01e 100644
--- a/base/applications/cmdutils/reg/lang/cs-CZ.rc
+++ b/base/applications/cmdutils/reg/lang/cs-CZ.rc
@@ -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?"
 }
diff --git a/base/applications/cmdutils/reg/lang/da-DK.rc 
b/base/applications/cmdutils/reg/lang/da-DK.rc
index a151902421..6c8338ca0f 100644
--- a/base/applications/cmdutils/reg/lang/da-DK.rc
+++ b/base/applications/cmdutils/reg/lang/da-DK.rc
@@ -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?"
 }
diff --git a/base/applications/cmdutils/reg/lang/de-DE.rc 
b/base/applications/cmdutils/reg/lang/de-DE.rc
index 083b7e73c1..ec0cd460ed 100644
--- a/base/applications/cmdutils/reg/lang/de-DE.rc
+++ b/base/applications/cmdutils/reg/lang/de-DE.rc
@@ -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?"
 }
diff --git a/base/applications/cmdutils/reg/lang/en-US.rc 
b/base/applications/cmdutils/reg/lang/en-US.rc
index 3aae61e02c..9c9bef54ed 100644
--- a/base/applications/cmdutils/reg/lang/en-US.rc
+++ b/base/applications/cmdutils/reg/lang/en-US.rc
@@ -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?"
 }
diff --git a/base/applications/cmdutils/reg/lang/es-ES.rc 
b/base/applications/cmdutils/reg/lang/es-ES.rc
index ea9cb3bd27..60bb78af8e 100644
--- a/base/applications/cmdutils/reg/lang/es-ES.rc
+++ b/base/applications/cmdutils/reg/lang/es-ES.rc
@@ -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?"
 }
diff --git a/base/applications/cmdutils/reg/lang/fr-FR.rc 
b/base/applications/cmdutils/reg/lang/fr-FR.rc
index 3e891d3186..89aceb9079 100644
--- a/base/applications/cmdutils/reg/lang/fr-FR.rc
+++ b/base/applications/cmdutils/reg/lang/fr-FR.rc
@@ -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?"
 }
diff --git a/base/applications/cmdutils/reg/lang/it-IT.rc 
b/base/applications/cmdutils/reg/lang/it-IT.rc
index 63cbc5c803..c2ad7f34e5 100644
--- a/base/applications/cmdutils/reg/lang/it-IT.rc
+++ b/base/applications/cmdutils/reg/lang/it-IT.rc
@@ -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?"
 }
diff --git a/base/applications/cmdutils/reg/lang/ja-JP.rc 
b/base/applications/cmdutils/reg/lang/ja-JP.rc
index 7b1c018fbf..07e7fd73bf 100644
--- a/base/applications/cmdutils/reg/lang/ja-JP.rc
+++ b/base/applications/cmdutils/reg/lang/ja-JP.rc
@@ -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?"
 }
diff --git a/base/applications/cmdutils/reg/lang/ko-KR.rc 
b/base/applications/cmdutils/reg/lang/ko-KR.rc
index 2bbe277d1a..ba9af4b55a 100644
--- a/base/applications/cmdutils/reg/lang/ko-KR.rc
+++ b/base/applications/cmdutils/reg/lang/ko-KR.rc
@@ -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?"
 }
diff --git a/base/applications/cmdutils/reg/lang/lt-LT.rc 
b/base/applications/cmdutils/reg/lang/lt-LT.rc
index 75bbcc21d8..c8feef0d97 100644
--- a/base/applications/cmdutils/reg/lang/lt-LT.rc
+++ b/base/applications/cmdutils/reg/lang/lt-LT.rc
@@ -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?"
 }
diff --git a/base/applications/cmdutils/reg/lang/nl-NL.rc 
b/base/applications/cmdutils/reg/lang/nl-NL.rc
index b2fb857f89..a62f1780fa 100644
--- a/base/applications/cmdutils/reg/lang/nl-NL.rc
+++ b/base/applications/cmdutils/reg/lang/nl-NL.rc
@@ -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?"
 }
diff --git a/base/applications/cmdutils/reg/lang/no-NO.rc 
b/base/applications/cmdutils/reg/lang/no-NO.rc
index 5d6b79e0b9..b9c269e1c3 100644
--- a/base/applications/cmdutils/reg/lang/no-NO.rc
+++ b/base/applications/cmdutils/reg/lang/no-NO.rc
@@ -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?"
 }
diff --git a/base/applications/cmdutils/reg/lang/pl-PL.rc 
b/base/applications/cmdutils/reg/lang/pl-PL.rc
index e3d2116fb6..92f98dccae 100644
--- a/base/applications/cmdutils/reg/lang/pl-PL.rc
+++ b/base/applications/cmdutils/reg/lang/pl-PL.rc
@@ -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?"
 }
diff --git a/base/applications/cmdutils/reg/lang/pt-PT.rc 
b/base/applications/cmdutils/reg/lang/pt-PT.rc
index f6ee64dd82..dd39615452 100644
--- a/base/applications/cmdutils/reg/lang/pt-PT.rc
+++ b/base/applications/cmdutils/reg/lang/pt-PT.rc
@@ -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?"
 }
diff --git a/base/applications/cmdutils/reg/lang/ro-RO.rc 
b/base/applications/cmdutils/reg/lang/ro-RO.rc
index ebcbe182c0..5c613624d9 100644
--- a/base/applications/cmdutils/reg/lang/ro-RO.rc
+++ b/base/applications/cmdutils/reg/lang/ro-RO.rc
@@ -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?"
 }
diff --git a/base/applications/cmdutils/reg/lang/ru-RU.rc 
b/base/applications/cmdutils/reg/lang/ru-RU.rc
index 04ad38c66e..f8d3d8afbe 100644
--- a/base/applications/cmdutils/reg/lang/ru-RU.rc
+++ b/base/applications/cmdutils/reg/lang/ru-RU.rc
@@ -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?"
 }
diff --git a/base/applications/cmdutils/reg/lang/sl-SI.rc 
b/base/applications/cmdutils/reg/lang/sl-SI.rc
index e7d631e80b..cd22ffe74c 100644
--- a/base/applications/cmdutils/reg/lang/sl-SI.rc
+++ b/base/applications/cmdutils/reg/lang/sl-SI.rc
@@ -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?"
 }
diff --git a/base/applications/cmdutils/reg/lang/sq-AL.rc 
b/base/applications/cmdutils/reg/lang/sq-AL.rc
index 3b0dba526f..2c4d2f5f4c 100644
--- a/base/applications/cmdutils/reg/lang/sq-AL.rc
+++ b/base/applications/cmdutils/reg/lang/sq-AL.rc
@@ -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?"
 }
diff --git a/base/applications/cmdutils/reg/lang/sv-SE.rc 
b/base/applications/cmdutils/reg/lang/sv-SE.rc
index 774bf95814..978e704c6a 100644
--- a/base/applications/cmdutils/reg/lang/sv-SE.rc
+++ b/base/applications/cmdutils/reg/lang/sv-SE.rc
@@ -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?"
 }
diff --git a/base/applications/cmdutils/reg/lang/tr-TR.rc 
b/base/applications/cmdutils/reg/lang/tr-TR.rc
index 9061740de6..e46733002c 100644
--- a/base/applications/cmdutils/reg/lang/tr-TR.rc
+++ b/base/applications/cmdutils/reg/lang/tr-TR.rc
@@ -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?"
 }
diff --git a/base/applications/cmdutils/reg/lang/uk-UA.rc 
b/base/applications/cmdutils/reg/lang/uk-UA.rc
index b5a8b68e6d..7ca1cff6a5 100644
--- a/base/applications/cmdutils/reg/lang/uk-UA.rc
+++ b/base/applications/cmdutils/reg/lang/uk-UA.rc
@@ -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?"
 }
diff --git a/base/applications/cmdutils/reg/lang/zh-CN.rc 
b/base/applications/cmdutils/reg/lang/zh-CN.rc
index c952714bd1..6dbe375963 100644
--- a/base/applications/cmdutils/reg/lang/zh-CN.rc
+++ b/base/applications/cmdutils/reg/lang/zh-CN.rc
@@ -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?"
 }
diff --git a/base/applications/cmdutils/reg/lang/zh-TW.rc 
b/base/applications/cmdutils/reg/lang/zh-TW.rc
index e6c5a6e8ee..b9cff9a283 100644
--- a/base/applications/cmdutils/reg/lang/zh-TW.rc
+++ b/base/applications/cmdutils/reg/lang/zh-TW.rc
@@ -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?"
 }
diff --git a/base/applications/cmdutils/reg/reg.c 
b/base/applications/cmdutils/reg/reg.c
index 5a857dea95..b9db08e787 100644
--- a/base/applications/cmdutils/reg/reg.c
+++ b/base/applications/cmdutils/reg/reg.c
@@ -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;
 
diff --git a/base/applications/cmdutils/reg/reg.h 
b/base/applications/cmdutils/reg/reg.h
index 14c05b13d4..eb792bbf88 100644
--- a/base/applications/cmdutils/reg/reg.h
+++ b/base/applications/cmdutils/reg/reg.h
@@ -22,15 +22,23 @@
 #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__ */
diff --git a/base/applications/cmdutils/reg/resource.h 
b/base/applications/cmdutils/reg/resource.h
index 0f57663183..84cbe906b9 100644
--- a/base/applications/cmdutils/reg/resource.h
+++ b/base/applications/cmdutils/reg/resource.h
@@ -23,38 +23,41 @@
 //#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
diff --git a/media/doc/README.WINE b/media/doc/README.WINE
index 69bf99b9c6..5e66b918b0 100644
--- a/media/doc/README.WINE
+++ b/media/doc/README.WINE
@@ -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

Reply via email to