Signed-off-by: Hugh McMaster hugh.mcmaster@outlook.com --- programs/reg/export.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- programs/reg/reg.c | 4 ++-- programs/reg/reg.h | 2 ++ programs/reg/reg.rc | 1 + programs/reg/resource.h | 1 + programs/reg/tests/reg.c | 18 +++++++++--------- 6 files changed, 59 insertions(+), 12 deletions(-)
diff --git a/programs/reg/export.c b/programs/reg/export.c index 9d0d33274e..81ffd220a3 100644 --- a/programs/reg/export.c +++ b/programs/reg/export.c @@ -17,6 +17,7 @@ */
#include <windows.h> +#include <stdlib.h>
#include <wine/unicode.h> #include <wine/debug.h> @@ -25,6 +26,44 @@
WINE_DEFAULT_DEBUG_CHANNEL(reg);
+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) @@ -40,6 +79,8 @@ int reg_export(int argc, WCHAR *argv[]) { HKEY root, hkey; WCHAR *path, *long_key; + BOOL overwrite_file = FALSE; + HANDLE hFile;
if (argc == 3 || argc > 5) goto error; @@ -47,7 +88,7 @@ int reg_export(int argc, WCHAR *argv[]) if (!parse_registry_key(argv[2], &root, &path, &long_key)) return 1;
- if (argc == 5 && !is_overwrite_switch(argv[4])) + if (argc == 5 && !(overwrite_file = is_overwrite_switch(argv[4]))) goto error;
if (RegOpenKeyExW(root, path, 0, KEY_READ, &hkey)) @@ -56,7 +97,9 @@ int reg_export(int argc, WCHAR *argv[]) return 1; }
+ hFile = get_file_handle(argv[3], overwrite_file); FIXME(": operation not yet implemented\n"); + CloseHandle(hFile);
RegCloseKey(hkey);
diff --git a/programs/reg/reg.c b/programs/reg/reg.c index e26928470e..a3e2cf730a 100644 --- a/programs/reg/reg.c +++ b/programs/reg/reg.c @@ -111,7 +111,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;
@@ -176,7 +176,7 @@ static void WINAPIV 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]; diff --git a/programs/reg/reg.h b/programs/reg/reg.h index 3b5ab86ff9..35f22a5db6 100644 --- a/programs/reg/reg.h +++ b/programs/reg/reg.h @@ -27,7 +27,9 @@ void *heap_xalloc(size_t size); void *heap_xrealloc(void *buf, size_t size); BOOL heap_free(void *buf); +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); BOOL parse_registry_key(const WCHAR *key, HKEY *root, WCHAR **path, WCHAR **long_key);
diff --git a/programs/reg/reg.rc b/programs/reg/reg.rc index 2ac0b22809..9d8cb882c7 100644 --- a/programs/reg/reg.rc +++ b/programs/reg/reg.rc @@ -68,4 +68,5 @@ STRINGTABLE 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/programs/reg/resource.h b/programs/reg/resource.h index aef2ca9738..518f92ceac 100644 --- a/programs/reg/resource.h +++ b/programs/reg/resource.h @@ -58,3 +58,4 @@ #define STRING_ESCAPE_SEQUENCE 135 #define STRING_EXPORT_USAGE 136 #define STRING_INVALID_SYSTEM_KEY 137 +#define STRING_OVERWRITE_FILE 138 diff --git a/programs/reg/tests/reg.c b/programs/reg/tests/reg.c index 9e4a8145a6..62299aa268 100644 --- a/programs/reg/tests/reg.c +++ b/programs/reg/tests/reg.c @@ -4289,7 +4289,7 @@ static BOOL compare_export_(unsigned line, const char *filename, const char *exp lok(!lstrcmpW(fbuf, wstr), "export data does not match expected data\n");
ret = DeleteFileA(filename); - todo_wine lok(ret, "DeleteFile failed: %u\n", GetLastError()); + lok(ret, "DeleteFile failed: %u\n", GetLastError());
exit: HeapFree(GetProcessHeap(), 0, fbuf); @@ -4442,7 +4442,7 @@ static void test_export(void) else /* Windows XP (32-bit) and older */ win_skip("File overwrite flag [/y] not supported; skipping position tests\n");
- todo_wine ok(compare_export("file.reg", empty_key_test, 0), "compare_export() failed\n"); + ok(compare_export("file.reg", empty_key_test, TODO_REG_COMPARE), "compare_export() failed\n");
/* Test registry export with a simple data structure */ dword = 0x100; @@ -4451,7 +4451,7 @@ static void test_export(void)
run_reg_exe("reg export HKEY_CURRENT_USER\" KEY_BASE " file.reg", &r); todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); - todo_wine ok(compare_export("file.reg", simple_test, 0), "compare_export() failed\n"); + ok(compare_export("file.reg", simple_test, TODO_REG_COMPARE), "compare_export() failed\n");
/* Test registry export with a complex data structure */ add_key(hkey, "Subkey1", &subkey); @@ -4489,7 +4489,7 @@ static void test_export(void)
run_reg_exe("reg export HKEY_CURRENT_USER\" KEY_BASE " file.reg", &r); todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); - todo_wine ok(compare_export("file.reg", complex_test, 0), "compare_export() failed\n"); + ok(compare_export("file.reg", complex_test, TODO_REG_COMPARE), "compare_export() failed\n");
err = delete_tree(HKEY_CURRENT_USER, KEY_BASE); ok(err == ERROR_SUCCESS, "delete_tree() failed: %d\n", err); @@ -4503,7 +4503,7 @@ static void test_export(void)
run_reg_exe("reg export HKEY_CURRENT_USER\" KEY_BASE " file.reg", &r); todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); - todo_wine ok(compare_export("file.reg", key_order_test, 0), "compare_export() failed\n"); + ok(compare_export("file.reg", key_order_test, TODO_REG_COMPARE), "compare_export() failed\n");
delete_key(hkey, "Subkey1"); delete_key(hkey, "Subkey2"); @@ -4518,7 +4518,7 @@ static void test_export(void)
run_reg_exe("reg export HKEY_CURRENT_USER\" KEY_BASE " file.reg", &r); todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); - todo_wine ok(compare_export("file.reg", value_order_test, 0), "compare_export() failed\n"); + ok(compare_export("file.reg", value_order_test, TODO_REG_COMPARE), "compare_export() failed\n");
delete_key(HKEY_CURRENT_USER, KEY_BASE);
@@ -4536,7 +4536,7 @@ static void test_export(void)
run_reg_exe("reg export HKEY_CURRENT_USER\" KEY_BASE " file.reg", &r); todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); - todo_wine ok(compare_export("file.reg", empty_hex_test, 0), "compare_export() failed\n"); + ok(compare_export("file.reg", empty_hex_test, TODO_REG_COMPARE), "compare_export() failed\n");
delete_key(HKEY_CURRENT_USER, KEY_BASE);
@@ -4554,7 +4554,7 @@ static void test_export(void)
run_reg_exe("reg export HKEY_CURRENT_USER\" KEY_BASE " file.reg", &r); todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); - todo_wine ok(compare_export("file.reg", empty_hex_test2, 0), "compare_export() failed\n"); + ok(compare_export("file.reg", empty_hex_test2, TODO_REG_COMPARE), "compare_export() failed\n");
delete_key(HKEY_CURRENT_USER, KEY_BASE);
@@ -4573,7 +4573,7 @@ static void test_export(void)
run_reg_exe("reg export HKEY_CURRENT_USER\" KEY_BASE " file.reg", &r); todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); - todo_wine ok(compare_export("file.reg", hex_types_test, 0), "compare_export() failed\n"); + ok(compare_export("file.reg", hex_types_test, TODO_REG_COMPARE), "compare_export() failed\n");
delete_key(HKEY_CURRENT_USER, KEY_BASE); }