https://git.reactos.org/?p=reactos.git;a=commitdiff;h=b50acff2bf0e38bdf1f25…
commit b50acff2bf0e38bdf1f25c707e331b5dc80964b7
Author: Amine Khaldi <amine.khaldi(a)reactos.org>
AuthorDate: Sun Jan 21 22:04:40 2018 +0100
Commit: Amine Khaldi <amine.khaldi(a)reactos.org>
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