[PATCH] reg: Prompt the user to confirm whether they want to overwrite existing values when copying a key
Hugh McMaster
hugh.mcmaster at outlook.com
Thu Jun 3 08:32:26 CDT 2021
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48000
Signed-off-by: Hugh McMaster <hugh.mcmaster at outlook.com>
---
programs/reg/copy.c | 79 +++++++++++++++++++++++++++++++++++++++--
programs/reg/reg.rc | 5 ++-
programs/reg/resource.h | 3 ++
3 files changed, 83 insertions(+), 4 deletions(-)
diff --git a/programs/reg/copy.c b/programs/reg/copy.c
index 208adc46e00..3ede5440cb6 100644
--- a/programs/reg/copy.c
+++ b/programs/reg/copy.c
@@ -16,12 +16,20 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#include <stdio.h>
#include "reg.h"
struct key {
HKEY root; /* system key */
- WCHAR *subkey; /* path to subkey */
+ WCHAR *subkey; /* relative path to subkey */
HKEY hkey; /* handle to opened or created key */
+ WCHAR *path; /* full path to subkey */
+};
+
+enum operation {
+ COPY_NO,
+ COPY_YES,
+ COPY_ALL
};
static void output_error(LONG rc)
@@ -32,13 +40,50 @@ static void output_error(LONG rc)
output_message(STRING_ACCESS_DENIED);
}
+static enum operation ask_overwrite_value(WCHAR *path, WCHAR *value)
+{
+ HMODULE hmod;
+ static WCHAR Ybuffer[4];
+ static WCHAR Nbuffer[4];
+ static WCHAR Abuffer[4];
+ static WCHAR defval[32];
+ WCHAR answer[MAX_PATH];
+ WCHAR *str;
+ DWORD count;
+
+ hmod = GetModuleHandleW(NULL);
+ LoadStringW(hmod, STRING_YES, Ybuffer, ARRAY_SIZE(Ybuffer));
+ LoadStringW(hmod, STRING_NO, Nbuffer, ARRAY_SIZE(Nbuffer));
+ LoadStringW(hmod, STRING_ALL, Abuffer, ARRAY_SIZE(Abuffer));
+ LoadStringW(hmod, STRING_DEFAULT_VALUE, defval, ARRAY_SIZE(defval));
+
+ str = (value && *value) ? value : defval;
+
+ while (1)
+ {
+ output_message(STRING_COPY_CONFIRM, path, str);
+ output_message(STRING_YESNOALL);
+
+ ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE), answer, ARRAY_SIZE(answer), &count, NULL);
+
+ *answer = towupper(*answer);
+
+ if (*answer == *Ybuffer)
+ return COPY_YES;
+ if (*answer == *Nbuffer)
+ return COPY_NO;
+ if (*answer == *Abuffer)
+ return COPY_ALL;
+ }
+}
+
static int run_copy(struct key *src, struct key *dest, BOOL recurse, BOOL force)
{
LONG rc;
DWORD max_subkey_len;
DWORD max_name_len, name_len;
DWORD max_data_size, data_size;
- DWORD type, i;
+ DWORD type, dispos, i;
WCHAR *name = NULL;
BYTE *data = NULL;
@@ -49,7 +94,7 @@ static int run_copy(struct key *src, struct key *dest, BOOL recurse, BOOL force)
}
if ((rc = RegCreateKeyExW(dest->root, dest->subkey, 0, NULL, REG_OPTION_NON_VOLATILE,
- KEY_WRITE, NULL, &dest->hkey, NULL)))
+ KEY_READ|KEY_WRITE, NULL, &dest->hkey, &dispos)))
{
RegCloseKey(src->hkey);
output_error(rc);
@@ -83,6 +128,18 @@ static int run_copy(struct key *src, struct key *dest, BOOL recurse, BOOL force)
if (rc == ERROR_NO_MORE_ITEMS) break;
if (rc) goto cleanup;
+ if (!force && dispos == REG_OPENED_EXISTING_KEY)
+ {
+ if (!RegQueryValueExW(dest->hkey, name, NULL, NULL, NULL, NULL))
+ {
+ enum operation op;
+
+ op = ask_overwrite_value(src->path, name);
+ if (op == COPY_NO) continue;
+ if (op == COPY_ALL) force = TRUE;
+ }
+ }
+
if ((rc = RegSetValueExW(dest->hkey, name, 0, type, data, data_size)))
{
output_error(rc);
@@ -93,6 +150,7 @@ static int run_copy(struct key *src, struct key *dest, BOOL recurse, BOOL force)
for (i = 0; recurse; i++)
{
struct key subkey_src, subkey_dest;
+ size_t path_len;
name_len = max_name_len;
@@ -105,7 +163,20 @@ static int run_copy(struct key *src, struct key *dest, BOOL recurse, BOOL force)
subkey_dest.root = dest->hkey;
subkey_dest.subkey = name;
+ path_len = lstrlenW(src->path) + name_len + 2;
+
+ if (!(subkey_src.path = malloc(path_len * sizeof(WCHAR))))
+ {
+ rc = ERROR_NOT_ENOUGH_MEMORY;
+ goto cleanup;
+ }
+
+ swprintf(subkey_src.path, path_len, L"%s\\%s", src->path, name);
+
rc = run_copy(&subkey_src, &subkey_dest, TRUE, force);
+
+ free(subkey_src.path);
+
if (rc) goto cleanup;
}
@@ -169,6 +240,8 @@ int reg_copy(int argc, WCHAR *argvW[])
return 1;
}
+ src.path = src.subkey;
+
return run_copy(&src, &dest, recurse, force);
invalid:
diff --git a/programs/reg/reg.rc b/programs/reg/reg.rc
index 89df2c45c4c..a3c53cf41b4 100644
--- a/programs/reg/reg.rc
+++ b/programs/reg/reg.rc
@@ -122,9 +122,11 @@ STRINGTABLE
STRING_MISSING_HEXDATA, "reg: The option [/d] must be followed by a valid hexadecimal value\n"
STRING_UNHANDLED_TYPE, "reg: Unhandled registry data type [/t 0x%1!x!, /d %2]\n"
STRING_OVERWRITE_VALUE, "The registry value '%1' already exists. Do you want to overwrite it?"
- STRING_YESNO, " (Yes|No)"
STRING_YES, "#msgctxt#Yes key#Y"
STRING_NO, "#msgctxt#No key#N"
+ STRING_ALL, "#msgctxt#All key#A"
+ STRING_YESNO, " (Yes|No)"
+ STRING_YESNOALL, " (Yes|No|All)"
STRING_CANCELLED, "reg: The registry operation was cancelled\n"
STRING_DEFAULT_VALUE, "(Default)"
STRING_DELETE_VALUE, "Are you sure you want to delete the registry value '%1'?"
@@ -199,4 +201,5 @@ STRINGTABLE
\ This option does not modify subkeys and values that only exist in <key2>.\n\n"
STRING_COPY_SRC_DEST_SAME, "reg: The source and destination keys cannot be the same\n"
+ STRING_COPY_CONFIRM, "The value '%1\\%2' already exists in the destination key. Do you want to overwrite it?"
}
diff --git a/programs/reg/resource.h b/programs/reg/resource.h
index 92d82d80a9b..f33d3da69be 100644
--- a/programs/reg/resource.h
+++ b/programs/reg/resource.h
@@ -25,7 +25,9 @@
/* Shared */
#define STRING_YES 100
#define STRING_NO 101
+#define STRING_ALL 102
#define STRING_YESNO 103
+#define STRING_YESNOALL 104
#define STRING_INVALID_SYNTAX 105
#define STRING_FUNC_HELP 106
#define STRING_ACCESS_DENIED 107
@@ -61,6 +63,7 @@
/* copy.c */
#define STRING_COPY_SRC_DEST_SAME 250
+#define STRING_COPY_CONFIRM 251
/* delete.c */
#define STRING_DELETE_VALUE 300
--
2.32.0.rc2
More information about the wine-devel
mailing list