[PATCH 06/13] reg: Prompt the user to overwrite the export file if it already exists

Hugh McMaster hugh.mcmaster at outlook.com
Sun Dec 3 00:50:15 CST 2017


Signed-off-by: Hugh McMaster <hugh.mcmaster at 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);
 }
-- 
2.15.0




More information about the wine-devel mailing list