ReactOS 0.4.15-dev-7834-g00c4b3d
copy.c
Go to the documentation of this file.
1/*
2 * Copyright 2021 Hugh McMaster
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19#include <stdio.h>
20#include "reg.h"
21
22struct key {
23 HKEY root; /* system key */
24 WCHAR *subkey; /* relative path to subkey */
25 HKEY hkey; /* handle to opened or created key */
26 WCHAR *path; /* full path to subkey */
27};
28
33};
34
35static void output_error(LONG rc)
36{
37 if (rc == ERROR_FILE_NOT_FOUND)
39 else
41}
42
44{
46 static WCHAR Ybuffer[4];
47 static WCHAR Nbuffer[4];
48 static WCHAR Abuffer[4];
49 static WCHAR defval[32];
50 WCHAR answer[MAX_PATH];
51 WCHAR *str;
53
55 LoadStringW(hmod, STRING_YES, Ybuffer, ARRAY_SIZE(Ybuffer));
56 LoadStringW(hmod, STRING_NO, Nbuffer, ARRAY_SIZE(Nbuffer));
57 LoadStringW(hmod, STRING_ALL, Abuffer, ARRAY_SIZE(Abuffer));
59
60 str = (value && *value) ? value : defval;
61
62 while (1)
63 {
66
68
69 *answer = towupper(*answer);
70
71 if (*answer == *Ybuffer)
72 return COPY_YES;
73 if (*answer == *Nbuffer)
74 return COPY_NO;
75 if (*answer == *Abuffer)
76 return COPY_ALL;
77 }
78}
79
80static int run_copy(struct key *src, struct key *dest, REGSAM sam, BOOL recurse, BOOL force)
81{
82 LONG rc;
83 DWORD max_subkey_len;
84 DWORD max_name_len, name_len;
85 DWORD max_data_size, data_size;
87 WCHAR *name = NULL;
88 BYTE *data = NULL;
89
90 if ((rc = RegOpenKeyExW(src->root, src->subkey, 0, KEY_READ|sam, &src->hkey)))
91 {
92 output_error(rc);
93 return 1;
94 }
95
96 if ((rc = RegCreateKeyExW(dest->root, dest->subkey, 0, NULL, REG_OPTION_NON_VOLATILE,
97 KEY_READ|KEY_WRITE|sam, NULL, &dest->hkey, &dispos)))
98 {
99 RegCloseKey(src->hkey);
100 output_error(rc);
101 return 1;
102 }
103
104 rc = RegQueryInfoKeyW(src->hkey, NULL, NULL, NULL, NULL, &max_subkey_len, NULL,
105 NULL, &max_name_len, &max_data_size, NULL, NULL);
106 if (rc) goto cleanup;
107
108 max_name_len = max(max_subkey_len, max_name_len) + 1;
109
110 if (!(name = malloc(max_name_len * sizeof(WCHAR))))
111 {
113 goto cleanup;
114 }
115
116 if (!(data = malloc(max_data_size)))
117 {
119 goto cleanup;
120 }
121
122 for (i = 0; ; i++)
123 {
124 name_len = max_name_len;
125 data_size = max_data_size;
126
127 rc = RegEnumValueW(src->hkey, i, name, &name_len, NULL, &type, data, &data_size);
128 if (rc == ERROR_NO_MORE_ITEMS) break;
129 if (rc) goto cleanup;
130
131 if (!force && dispos == REG_OPENED_EXISTING_KEY)
132 {
133 if (!RegQueryValueExW(dest->hkey, name, NULL, NULL, NULL, NULL))
134 {
135 enum operation op;
136
137 op = ask_overwrite_value(src->path, name);
138 if (op == COPY_NO) continue;
139 if (op == COPY_ALL) force = TRUE;
140 }
141 }
142
143 if ((rc = RegSetValueExW(dest->hkey, name, 0, type, data, data_size)))
144 {
145 output_error(rc);
146 goto cleanup;
147 }
148 }
149
150 for (i = 0; recurse; i++)
151 {
152 struct key subkey_src, subkey_dest;
153 size_t path_len;
154
155 name_len = max_name_len;
156
157 rc = RegEnumKeyExW(src->hkey, i, name, &name_len, NULL, NULL, NULL, NULL);
158 if (rc) break;
159
160 subkey_src.root = src->hkey;
161 subkey_src.subkey = name;
162
163 subkey_dest.root = dest->hkey;
164 subkey_dest.subkey = name;
165
166 path_len = lstrlenW(src->path) + name_len + 2;
167
168 if (!(subkey_src.path = malloc(path_len * sizeof(WCHAR))))
169 {
171 goto cleanup;
172 }
173
174 swprintf(subkey_src.path, L"%s\\%s", src->path, name);
175
176 rc = run_copy(&subkey_src, &subkey_dest, sam, TRUE, force);
177
178 free(subkey_src.path);
179
180 if (rc) goto cleanup;
181 }
182
183cleanup:
184 free(name);
185 free(data);
186
187 RegCloseKey(src->hkey);
188 RegCloseKey(dest->hkey);
189
190 return rc != ERROR_NO_MORE_ITEMS;
191}
192
193int reg_copy(int argc, WCHAR *argvW[])
194{
195 struct key src, dest;
196 BOOL recurse = FALSE, force = FALSE;
197 REGSAM sam = 0;
198 int i;
199
200 if (argc == 3)
201 goto invalid;
202
203 if (!parse_registry_key(argvW[2], &src.root, &src.subkey))
204 return 1;
205
206 if (!parse_registry_key(argvW[3], &dest.root, &dest.subkey))
207 return 1;
208
209 for (i = 4; i < argc; i++)
210 {
211 WCHAR *str;
212
213 if (argvW[i][0] != '/' && argvW[i][0] != '-')
214 goto invalid;
215
216 str = &argvW[i][1];
217
218 if (!lstrcmpiW(str, L"reg:32"))
219 {
220 if (sam & KEY_WOW64_32KEY) goto invalid;
222 continue;
223 }
224 else if (!lstrcmpiW(str, L"reg:64"))
225 {
226 if (sam & KEY_WOW64_64KEY) goto invalid;
228 continue;
229 }
230 else if (!str[0] || str[1])
231 goto invalid;
232
233 switch (towlower(*str))
234 {
235 case 's':
236 if (recurse) goto invalid;
237 recurse = TRUE;
238 break;
239 case 'f':
240 if (force) goto invalid;
241 force = TRUE;
242 break;
243 default:
244 goto invalid;
245 }
246 }
247
249 goto invalid;
250
251 if (src.root == dest.root && !lstrcmpiW(src.subkey, dest.subkey))
252 {
254 return 1;
255 }
256
257 src.path = src.subkey;
258
259 return run_copy(&src, &dest, sam, recurse, force);
260
261invalid:
264 return 1;
265}
static int argc
Definition: ServiceArgs.c:12
static int run_copy(struct key *src, struct key *dest, REGSAM sam, BOOL recurse, BOOL force)
Definition: copy.c:80
static enum operation ask_overwrite_value(WCHAR *path, WCHAR *value)
Definition: copy.c:43
static void output_error(LONG rc)
Definition: copy.c:35
operation
Definition: copy.c:29
@ COPY_ALL
Definition: copy.c:32
@ COPY_YES
Definition: copy.c:31
@ COPY_NO
Definition: copy.c:30
int reg_copy(int argc, WCHAR *argvW[])
Definition: copy.c:193
static REGSAM sam
Definition: query.c:143
void WINAPIV output_message(unsigned int id,...)
Definition: reg.c:92
BOOL parse_registry_key(const WCHAR *key, HKEY *root, WCHAR **path)
Definition: reg.c:234
#define STRING_NO
Definition: resource.h:29
#define STRING_COPY_CONFIRM
Definition: resource.h:68
#define STRING_INVALID_SYNTAX
Definition: resource.h:33
#define STRING_DEFAULT_VALUE
Definition: resource.h:40
#define STRING_YESNOALL
Definition: resource.h:32
#define STRING_FUNC_HELP
Definition: resource.h:34
#define STRING_ALL
Definition: resource.h:30
#define STRING_KEY_NONEXIST
Definition: resource.h:38
#define STRING_ACCESS_DENIED
Definition: resource.h:35
#define STRING_COPY_SRC_DEST_SAME
Definition: resource.h:67
#define STRING_YES
Definition: resource.h:28
#define ARRAY_SIZE(A)
Definition: main.h:33
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:203
#define RegCloseKey(hKey)
Definition: registry.h:49
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
UINT op
Definition: effect.c:236
LONG WINAPI RegCreateKeyExW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ DWORD Reserved, _In_opt_ LPWSTR lpClass, _In_ DWORD dwOptions, _In_ REGSAM samDesired, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _Out_ PHKEY phkResult, _Out_opt_ LPDWORD lpdwDisposition)
Definition: reg.c:1096
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
LONG WINAPI RegEnumKeyExW(_In_ HKEY hKey, _In_ DWORD dwIndex, _Out_ LPWSTR lpName, _Inout_ LPDWORD lpcbName, _Reserved_ LPDWORD lpReserved, _Out_opt_ LPWSTR lpClass, _Inout_opt_ LPDWORD lpcbClass, _Out_opt_ PFILETIME lpftLastWriteTime)
Definition: reg.c:2504
LONG WINAPI RegSetValueExW(_In_ HKEY hKey, _In_ LPCWSTR lpValueName, _In_ DWORD Reserved, _In_ DWORD dwType, _In_ CONST BYTE *lpData, _In_ DWORD cbData)
Definition: reg.c:4882
LONG WINAPI RegEnumValueW(_In_ HKEY hKey, _In_ DWORD index, _Out_ LPWSTR value, _Inout_ PDWORD val_count, _Reserved_ PDWORD reserved, _Out_opt_ PDWORD type, _Out_opt_ LPBYTE data, _Inout_opt_ PDWORD count)
Definition: reg.c:2830
LONG WINAPI RegQueryInfoKeyW(HKEY hKey, LPWSTR lpClass, LPDWORD lpcClass, LPDWORD lpReserved, LPDWORD lpcSubKeys, LPDWORD lpcMaxSubKeyLen, LPDWORD lpcMaxClassLen, LPDWORD lpcValues, LPDWORD lpcMaxValueNameLen, LPDWORD lpcMaxValueLen, LPDWORD lpcbSecurityDescriptor, PFILETIME lpftLastWriteTime)
Definition: reg.c:3662
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
#define MAX_PATH
Definition: compat.h:34
#define lstrlenW
Definition: compat.h:750
static void cleanup(void)
Definition: main.c:1335
BOOL WINAPI DECLSPEC_HOTPATCH ReadConsoleW(IN HANDLE hConsoleInput, OUT LPVOID lpBuffer, IN DWORD nNumberOfCharsToRead, OUT LPDWORD lpNumberOfCharsRead, IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL)
Definition: readwrite.c:1174
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
#define swprintf
Definition: precomp.h:40
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLenum src
Definition: glext.h:6340
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
int WINAPI lstrcmpiW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:194
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
static DWORD path_len
Definition: batch.c:31
static PEXPLICIT_ACCESSW *static HMODULE hmod
Definition: security.c:143
static ACCESS_MASK const OBJECT_ATTRIBUTES ULONG const UNICODE_STRING ULONG PULONG dispos
Definition: reg.c:132
static char * dest
Definition: rtl.c:135
static const WCHAR invalid[]
Definition: assoc.c:39
#define KEY_READ
Definition: nt_native.h:1023
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
#define KEY_WRITE
Definition: nt_native.h:1031
#define REG_OPENED_EXISTING_KEY
Definition: nt_native.h:1085
#define L(x)
Definition: ntvdm.h:50
long LONG
Definition: pedump.c:60
const WCHAR * str
_CRTIMP wchar_t *__cdecl _wcsupr(_Inout_z_ wchar_t *_String)
Definition: copy.c:22
HKEY root
Definition: copy.c:23
WCHAR * path
Definition: copy.c:26
WCHAR * name
Definition: path.c:43
HKEY hkey
Definition: copy.c:25
WCHAR * subkey
Definition: copy.c:24
Definition: name.c:39
#define max(a, b)
Definition: svc.c:63
#define towlower(c)
Definition: wctype.h:97
#define towupper(c)
Definition: wctype.h:99
Definition: pdh_main.c:94
#define STD_INPUT_HANDLE
Definition: winbase.h:267
ACCESS_MASK REGSAM
Definition: winreg.h:69
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
#define KEY_WOW64_32KEY
Definition: cmtypes.h:45
#define KEY_WOW64_64KEY
Definition: cmtypes.h:46
__wchar_t WCHAR
Definition: xmlstorage.h:180
unsigned char BYTE
Definition: xxhash.c:193