ReactOS  0.4.15-dev-4857-g47842d7
reg.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Andrew Riedi
3  * Copyright 2016-2017, 2021 Hugh McMaster
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19 
20 #include <stdio.h>
21 #include "reg.h"
22 #include <wine/debug.h>
23 
25 
26 static const struct
27 {
29  const WCHAR *short_name;
30  const WCHAR *long_name;
31 }
32 root_rels[] =
33 {
34  {HKEY_LOCAL_MACHINE, L"HKLM", L"HKEY_LOCAL_MACHINE"},
35  {HKEY_CURRENT_USER, L"HKCU", L"HKEY_CURRENT_USER"},
36  {HKEY_CLASSES_ROOT, L"HKCR", L"HKEY_CLASSES_ROOT"},
37  {HKEY_USERS, L"HKU", L"HKEY_USERS"},
38  {HKEY_CURRENT_CONFIG, L"HKCC", L"HKEY_CURRENT_CONFIG"},
39 };
40 
41 const struct reg_type_rels type_rels[] =
42 {
43  {REG_NONE, L"REG_NONE"},
44  {REG_SZ, L"REG_SZ"},
45  {REG_EXPAND_SZ, L"REG_EXPAND_SZ"},
46  {REG_BINARY, L"REG_BINARY"},
47  {REG_DWORD, L"REG_DWORD"},
48  {REG_DWORD_LITTLE_ENDIAN, L"REG_DWORD_LITTLE_ENDIAN"},
49  {REG_DWORD_BIG_ENDIAN, L"REG_DWORD_BIG_ENDIAN"},
50  {REG_MULTI_SZ, L"REG_MULTI_SZ"},
51 };
52 
53 void output_writeconsole(const WCHAR *str, DWORD wlen)
54 {
55  DWORD count, ret;
56 
58  if (!ret)
59  {
60  DWORD len;
61  char *msgA;
62 
63  /* On Windows WriteConsoleW() fails if the output is redirected. So fall
64  * back to WriteFile(), assuming the console encoding is still the right
65  * one in that case.
66  */
68  msgA = malloc(len);
69 
70  WideCharToMultiByte(GetConsoleOutputCP(), 0, str, wlen, msgA, len, NULL, NULL);
72  free(msgA);
73  }
74 }
75 
76 static void output_formatstring(const WCHAR *fmt, va_list va_args)
77 {
78  WCHAR *str;
79  DWORD len;
80 
82  fmt, 0, 0, (WCHAR *)&str, 0, &va_args);
83  if (len == 0 && GetLastError() != NO_ERROR)
84  {
85  WINE_FIXME("Could not format string: le=%u, fmt=%s\n", GetLastError(), wine_dbgstr_w(fmt));
86  return;
87  }
89  LocalFree(str);
90 }
91 
92 void WINAPIV output_message(unsigned int id, ...)
93 {
94  WCHAR *fmt = NULL;
95  int len;
96  va_list va_args;
97 
98  if (!(len = LoadStringW(GetModuleHandleW(NULL), id, (WCHAR *)&fmt, 0)))
99  {
100  WINE_FIXME("LoadString failed with %d\n", GetLastError());
101  return;
102  }
103 
104  len++;
105  fmt = malloc(len * sizeof(WCHAR));
106  if (!fmt) return;
107 
109 
110  va_start(va_args, id);
111  output_formatstring(fmt, va_args);
112  va_end(va_args);
113 
114  free(fmt);
115 }
116 
117 void WINAPIV output_string(const WCHAR *fmt, ...)
118 {
119  va_list va_args;
120 
121  va_start(va_args, fmt);
122  output_formatstring(fmt, va_args);
123  va_end(va_args);
124 }
125 
126 /* ask_confirm() adapted from programs/cmd/builtins.c */
127 BOOL ask_confirm(unsigned int msgid, WCHAR *reg_info)
128 {
129  HMODULE hmod;
130  WCHAR Ybuffer[4];
131  WCHAR Nbuffer[4];
132  WCHAR defval[32];
133  WCHAR answer[MAX_PATH];
134  WCHAR *str;
135  DWORD count;
136 
138  LoadStringW(hmod, STRING_YES, Ybuffer, ARRAY_SIZE(Ybuffer));
139  LoadStringW(hmod, STRING_NO, Nbuffer, ARRAY_SIZE(Nbuffer));
140  LoadStringW(hmod, STRING_DEFAULT_VALUE, defval, ARRAY_SIZE(defval));
141 
142  str = (reg_info && *reg_info) ? reg_info : defval;
143 
144  while (1)
145  {
146  output_message(msgid, str);
149  answer[0] = towupper(answer[0]);
150  if (answer[0] == Ybuffer[0])
151  return TRUE;
152  if (answer[0] == Nbuffer[0])
153  return FALSE;
154  }
155 }
156 
157 static inline BOOL path_rootname_cmp(const WCHAR *input_path, const WCHAR *rootkey_name)
158 {
159  DWORD length = lstrlenW(rootkey_name);
160 
161  return (!_wcsnicmp(input_path, rootkey_name, length) &&
162  (input_path[length] == 0 || input_path[length] == '\\'));
163 }
164 
166 {
167  DWORD i;
168 
169  for (i = 0; i < ARRAY_SIZE(root_rels); i++)
170  {
173  return root_rels[i].key;
174  }
175 
176  return NULL;
177 }
178 
179 static BOOL sane_path(const WCHAR *key)
180 {
181  unsigned int i = lstrlenW(key);
182 
183  if (i < 3 || (key[i - 1] == '\\' && key[i - 2] == '\\'))
184  {
186  return FALSE;
187  }
188 
189  if (key[0] == '\\' && key[1] == '\\' && key[2] != '\\')
190  {
192  return FALSE;
193  }
194 
195  return TRUE;
196 }
197 
198 WCHAR *build_subkey_path(WCHAR *path, DWORD path_len, WCHAR *subkey_name, DWORD subkey_len)
199 {
200  WCHAR *subkey_path;
201 
202  subkey_path = malloc((path_len + subkey_len + 2) * sizeof(WCHAR));
203  swprintf(subkey_path, L"%s\\%s", path, subkey_name);
204 
205  return subkey_path;
206 }
207 
209 {
210  int i, len;
211  WCHAR *long_key;
212 
213  for (i = 0; i < ARRAY_SIZE(root_rels); i++)
214  {
215  if (root == root_rels[i].key)
216  break;
217  }
218 
220 
221  if (!path)
222  {
223  long_key = malloc((len + 1) * sizeof(WCHAR));
224  lstrcpyW(long_key, root_rels[i].long_name);
225  return long_key;
226  }
227 
228  len += lstrlenW(path) + 1; /* add one for the concatenating backslash */
229  long_key = malloc((len + 1) * sizeof(WCHAR));
230  swprintf(long_key, L"%s\\%s", root_rels[i].long_name, path);
231  return long_key;
232 }
233 
235 {
236  WCHAR *p;
237 
238  if (!sane_path(key))
239  return FALSE;
240 
242  if (!*root)
243  {
245  return FALSE;
246  }
247 
248  *path = wcschr(key, '\\');
249 
250  if (!*path)
251  return TRUE;
252 
253  (*path)++;
254 
255  if (!**path)
256  {
258  return FALSE;
259  }
260 
261  p = *path + lstrlenW(*path) - 1;
262  if (*p == '\\') *p = 0;
263 
264  return TRUE;
265 }
266 
267 BOOL is_char(const WCHAR s, const WCHAR c)
268 {
269  return (s == c || s == towupper(c));
270 }
271 
272 BOOL is_switch(const WCHAR *s, const WCHAR c)
273 {
274  if (lstrlenW(s) > 2)
275  return FALSE;
276 
277  return ((s[0] == '/' || s[0] == '-') && is_char(s[1], c));
278 }
279 
280 static BOOL is_help_switch(const WCHAR *s)
281 {
282  return (is_switch(s, '?') || is_switch(s, 'h'));
283 }
284 
293 };
294 
295 static enum operations get_operation(const WCHAR *str, int *op_help)
296 {
297  struct op_info { const WCHAR *op; int id; int help_id; };
298 
299  static const struct op_info op_array[] =
300  {
301  { L"add", REG_ADD, STRING_ADD_USAGE },
302  { L"copy", REG_COPY, STRING_COPY_USAGE },
303  { L"delete", REG_DELETE, STRING_DELETE_USAGE },
304  { L"export", REG_EXPORT, STRING_EXPORT_USAGE },
305  { L"import", REG_IMPORT, STRING_IMPORT_USAGE },
306  { L"query", REG_QUERY, STRING_QUERY_USAGE },
307  { NULL, -1, 0 }
308  };
309 
310  const struct op_info *ptr;
311 
312  for (ptr = op_array; ptr->op; ptr++)
313  {
314  if (!lstrcmpiW(str, ptr->op))
315  {
316  *op_help = ptr->help_id;
317  return ptr->id;
318  }
319  }
320 
321  return REG_INVALID;
322 }
323 
324 int __cdecl wmain(int argc, WCHAR *argvW[])
325 {
326  int op, op_help;
327 
328  if (argc == 1)
329  {
332  return 1;
333  }
334 
335  if (is_help_switch(argvW[1]))
336  {
338  return 0;
339  }
340 
341  op = get_operation(argvW[1], &op_help);
342 
343  if (op == REG_INVALID)
344  {
347  return 1;
348  }
349  else if (argc == 2) /* Valid operation, no arguments supplied */
350  goto invalid;
351 
352  if (is_help_switch(argvW[2]))
353  {
354  if (argc > 3) goto invalid;
355 
356  output_message(op_help);
358  return 0;
359  }
360 
361  if (op == REG_ADD)
362  return reg_add(argc, argvW);
363 
364  if (op == REG_COPY)
365  return reg_copy(argc, argvW);
366 
367  if (op == REG_DELETE)
368  return reg_delete(argc, argvW);
369 
370  if (op == REG_EXPORT)
371  return reg_export(argc, argvW);
372 
373  if (op == REG_IMPORT)
374  return reg_import(argc, argvW);
375 
376  return reg_query(argc, argvW);
377 
378 invalid:
381  return 1;
382 }
#define HKEY_USERS
Definition: winreg.h:13
static const WCHAR invalid[]
Definition: assoc.c:39
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
static int argc
Definition: ServiceArgs.c:12
#define STRING_USAGE
Definition: resource.h:44
#define STRING_REG_VIEW_USAGE
Definition: resource.h:51
Definition: reg.c:291
#define WideCharToMultiByte
Definition: compat.h:111
#define __cdecl
Definition: accygwin.h:79
#define REG_BINARY
Definition: nt_native.h:1496
#define STRING_NO
Definition: resource.h:29
#define TRUE
Definition: types.h:120
char * wine_dbgstr_w(const wchar_t *wstr)
Definition: atltest.h:87
BOOL WINAPI DECLSPEC_HOTPATCH WriteConsoleW(IN HANDLE hConsoleOutput, IN CONST VOID *lpBuffer, IN DWORD nNumberOfCharsToWrite, OUT LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved)
Definition: readwrite.c:1447
#define HKEY_CURRENT_USER
Definition: winreg.h:11
GLuint GLuint GLsizei count
Definition: gl.h:1545
#define FORMAT_MESSAGE_FROM_STRING
Definition: winbase.h:418
#define free
Definition: debug_ros.c:5
_Check_return_ _CRTIMP int __cdecl _wcsnicmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)
#define STRING_QUERY_USAGE
Definition: resource.h:50
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1040
int reg_export(int argc, WCHAR *argvW[])
Definition: export.c:347
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:203
void WINAPIV output_message(unsigned int id,...)
Definition: reg.c:92
static BOOL is_help_switch(const WCHAR *s)
Definition: reg.c:280
DWORD WINAPI FormatMessageW(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPWSTR lpBuffer, DWORD nSize, __ms_va_list *args)
Definition: format_msg.c:583
#define HKEY_CURRENT_CONFIG
Definition: winreg.h:15
#define NO_ERROR
Definition: dderror.h:5
#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)
int WINAPI lstrcmpiW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:194
Definition: reg.c:287
#define L(x)
Definition: ntvdm.h:50
#define va_end(ap)
Definition: acmsvcex.h:90
#define FALSE
Definition: types.h:117
int reg_add(int argc, WCHAR *argvW[])
Definition: add.c:227
void WINAPIV output_string(const WCHAR *fmt,...)
Definition: reg.c:117
unsigned int BOOL
Definition: ntddk_ex.h:94
#define STRING_EXPORT_USAGE
Definition: resource.h:48
#define REG_MULTI_SZ
Definition: nt_native.h:1501
#define STRING_COPY_USAGE
Definition: resource.h:46
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
static PVOID ptr
Definition: dispmode.c:27
#define FORMAT_MESSAGE_ALLOCATE_BUFFER
Definition: winbase.h:416
static enum operations get_operation(const WCHAR *str, int *op_help)
Definition: reg.c:295
#define STRING_INVALID_KEY
Definition: resource.h:52
UINT WINAPI DECLSPEC_HOTPATCH GetConsoleOutputCP(VOID)
Definition: console.c:2451
const WCHAR * str
#define STRING_FUNC_HELP
Definition: resource.h:34
static void output_formatstring(const WCHAR *fmt, va_list va_args)
Definition: reg.c:76
#define STRING_INVALID_SYSTEM_KEY
Definition: resource.h:54
char * va_list
Definition: acmsvcex.h:78
int reg_query(int argc, WCHAR *argvW[])
Definition: query.c:339
#define STRING_YES
Definition: resource.h:28
#define STRING_IMPORT_USAGE
Definition: resource.h:49
#define STD_INPUT_HANDLE
Definition: winbase.h:264
_CRTIMP wchar_t *__cdecl _wcsupr(_Inout_z_ wchar_t *_String)
operations
Definition: reg.c:285
int reg_import(int argc, WCHAR *argvW[])
Definition: import.c:975
WCHAR * build_subkey_path(WCHAR *path, DWORD path_len, WCHAR *subkey_name, DWORD subkey_len)
Definition: reg.c:198
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
_CONST_RETURN wchar_t *__cdecl wcschr(_In_z_ const wchar_t *_Str, wchar_t _Ch)
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define STRING_INVALID_SYNTAX
Definition: resource.h:33
#define MAX_PATH
Definition: compat.h:34
const GLubyte * c
Definition: glext.h:8905
#define STRING_REG_HELP
Definition: resource.h:43
static BOOL path_rootname_cmp(const WCHAR *input_path, const WCHAR *rootkey_name)
Definition: reg.c:157
unsigned long DWORD
Definition: ntddk_ex.h:95
UINT op
Definition: effect.c:236
va_start(ap, x)
const WCHAR * short_name
Definition: reg.c:29
static int reg
Definition: i386-dis.c:1283
int ret
#define REG_DWORD_LITTLE_ENDIAN
Definition: nt_native.h:1498
WINE_DEFAULT_DEBUG_CHANNEL(reg)
HKEY key
Definition: reg.c:28
GLenum GLsizei len
Definition: glext.h:6722
GLdouble s
Definition: gl.h:2039
const WCHAR * long_name
Definition: reg.c:30
static BOOL sane_path(const WCHAR *key)
Definition: reg.c:179
#define STD_OUTPUT_HANDLE
Definition: winbase.h:265
WCHAR * get_long_key(HKEY root, WCHAR *path)
Definition: reg.c:208
int _cdecl swprintf(const WCHAR *,...)
BOOL is_switch(const WCHAR *s, const WCHAR c)
Definition: reg.c:272
#define WINAPIV
Definition: sdbpapi.h:64
int reg_delete(int argc, WCHAR *argvW[])
Definition: delete.c:134
const struct reg_type_rels type_rels[]
Definition: reg.c:41
#define REG_DWORD_BIG_ENDIAN
Definition: nt_native.h:1499
static PEXPLICIT_ACCESSW *static HMODULE hmod
Definition: security.c:141
#define STRING_DEFAULT_VALUE
Definition: resource.h:40
BOOL ask_confirm(unsigned int msgid, WCHAR *reg_info)
Definition: reg.c:127
static DWORD path_len
Definition: batch.c:31
#define lstrcpyW
Definition: compat.h:608
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
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1577
#define STRING_DELETE_USAGE
Definition: resource.h:47
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
#define NULL
Definition: types.h:112
int __cdecl wmain(int argc, WCHAR *argvW[])
Definition: reg.c:324
HKEY path_get_rootkey(const WCHAR *path)
Definition: reg.c:165
#define STRING_YESNO
Definition: resource.h:31
#define STRING_NO_REMOTE
Definition: resource.h:53
GLenum GLuint id
Definition: glext.h:5579
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
#define malloc
Definition: debug_ros.c:4
#define HKEY_CLASSES_ROOT
Definition: winreg.h:10
Definition: reg.c:286
#define towupper(c)
Definition: wctype.h:99
#define STRING_INVALID_OPTION
Definition: resource.h:55
#define REG_NONE
Definition: nt_native.h:1492
GLfloat GLfloat p
Definition: glext.h:8902
void output_writeconsole(const WCHAR *str, DWORD wlen)
Definition: reg.c:53
#define STRING_ADD_USAGE
Definition: resource.h:45
static const struct @2 root_rels[]
#define REG_DWORD
Definition: sdbapi.c:596
BOOL parse_registry_key(const WCHAR *key, HKEY *root, WCHAR **path)
Definition: reg.c:234
Definition: dsound.c:943
BOOL is_char(const WCHAR s, const WCHAR c)
Definition: reg.c:267
Definition: copy.c:22
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define WINE_FIXME
Definition: debug.h:366
#define REG_SZ
Definition: layer.c:22