ReactOS  0.4.15-dev-4917-g934e521
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 
22 struct 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 
29 enum operation {
33 };
34 
35 static void output_error(LONG rc)
36 {
37  if (rc == ERROR_FILE_NOT_FOUND)
39  else
41 }
42 
44 {
45  HMODULE hmod;
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;
52  DWORD count;
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 
80 static 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;
86  DWORD type, dispos, i;
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 
183 cleanup:
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 
193 int 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;
221  sam |= KEY_WOW64_32KEY;
222  continue;
223  }
224  else if (!lstrcmpiW(str, L"reg:64"))
225  {
226  if (sam & KEY_WOW64_64KEY) goto invalid;
227  sam |= KEY_WOW64_64KEY;
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 
261 invalid:
264  return 1;
265 }
static const WCHAR invalid[]
Definition: assoc.c:39
static int argc
Definition: ServiceArgs.c:12
#define max(a, b)
Definition: svc.c:63
Definition: pdh_main.c:93
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
#define STRING_NO
Definition: resource.h:29
#define KEY_READ
Definition: nt_native.h:1023
#define TRUE
Definition: types.h:120
GLuint GLuint GLsizei count
Definition: gl.h:1545
#define free
Definition: debug_ros.c:5
#define STRING_ALL
Definition: resource.h:30
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:203
void WINAPIV output_message(unsigned int id,...)
Definition: reg.c:92
#define REG_OPENED_EXISTING_KEY
Definition: nt_native.h:1085
Definition: copy.c:31
#define lstrlenW
Definition: compat.h:609
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
WCHAR * path
Definition: copy.c:26
#define STRING_COPY_SRC_DEST_SAME
Definition: resource.h:67
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:1091
int WINAPI lstrcmpiW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:194
#define L(x)
Definition: ntvdm.h:50
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
const WCHAR * str
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:2853
#define STRING_FUNC_HELP
Definition: resource.h:34
HKEY root
Definition: copy.c:23
#define STRING_YES
Definition: resource.h:28
#define STD_INPUT_HANDLE
Definition: winbase.h:264
_CRTIMP wchar_t *__cdecl _wcsupr(_Inout_z_ wchar_t *_String)
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
#define KEY_WRITE
Definition: nt_native.h:1031
#define KEY_WOW64_64KEY
Definition: cmtypes.h:46
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:4899
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
Definition: copy.c:32
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4120
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define STRING_INVALID_SYNTAX
Definition: resource.h:33
#define MAX_PATH
Definition: compat.h:34
unsigned long DWORD
Definition: ntddk_ex.h:95
UINT op
Definition: effect.c:236
static enum operation ask_overwrite_value(WCHAR *path, WCHAR *value)
Definition: copy.c:43
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
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:3690
#define STRING_YESNOALL
Definition: resource.h:32
Definition: copy.c:30
GLsizei const GLfloat * value
Definition: glext.h:6069
GLenum src
Definition: glext.h:6340
int _cdecl swprintf(const WCHAR *,...)
unsigned char BYTE
Definition: xxhash.c:193
WCHAR * subkey
Definition: copy.c:24
static PEXPLICIT_ACCESSW *static HMODULE hmod
Definition: security.c:141
operation
Definition: copy.c:29
#define STRING_ACCESS_DENIED
Definition: resource.h:35
#define STRING_DEFAULT_VALUE
Definition: resource.h:40
HKEY hkey
Definition: copy.c:25
static DWORD path_len
Definition: batch.c:31
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 reg_copy(int argc, WCHAR *argvW[])
Definition: copy.c:193
#define ARRAY_SIZE(a)
Definition: main.h:24
static void output_error(LONG rc)
Definition: copy.c:35
ACCESS_MASK REGSAM
Definition: winreg.h:69
#define NULL
Definition: types.h:112
#define STRING_KEY_NONEXIST
Definition: resource.h:38
static ACCESS_MASK const OBJECT_ATTRIBUTES ULONG const UNICODE_STRING ULONG PULONG dispos
Definition: reg.c:130
#define STRING_COPY_CONFIRM
Definition: resource.h:68
Definition: name.c:38
static REGSAM sam
Definition: query.c:143
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3356
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
#define towlower(c)
Definition: wctype.h:97
char * cleanup(char *str)
Definition: wpickclick.c:99
#define malloc
Definition: debug_ros.c:4
#define KEY_WOW64_32KEY
Definition: cmtypes.h:45
static char * dest
Definition: rtl.c:135
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:2527
#define towupper(c)
Definition: wctype.h:99
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
BOOL parse_registry_key(const WCHAR *key, HKEY *root, WCHAR **path)
Definition: reg.c:234
static int run_copy(struct key *src, struct key *dest, REGSAM sam, BOOL recurse, BOOL force)
Definition: copy.c:80
#define RegCloseKey(hKey)
Definition: registry.h:47
Definition: copy.c:22
GLuint const GLchar * name
Definition: glext.h:6031