ReactOS 0.4.16-dev-338-g34e76ad
add.c
Go to the documentation of this file.
1/*
2 * Copyright 2016-2017, 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 <errno.h>
20#include "reg.h"
21
22static DWORD wchar_get_type(const WCHAR *type_name)
23{
24 DWORD i;
25
26 if (!type_name)
27 return REG_SZ;
28
29 for (i = 0; i < ARRAY_SIZE(type_rels); i++)
30 {
31 if (!wcsicmp(type_rels[i].name, type_name))
32 return type_rels[i].type;
33 }
34
35 return ~0u;
36}
37
38/* hexchar_to_byte from programs/regedit/hexedit.c */
39static inline BYTE hexchar_to_byte(WCHAR ch)
40{
41 if (ch >= '0' && ch <= '9')
42 return ch - '0';
43 else if (ch >= 'a' && ch <= 'f')
44 return ch - 'a' + 10;
45 else if (ch >= 'A' && ch <= 'F')
46 return ch - 'A' + 10;
47 else
48 return -1;
49}
50
52 BYTE **data_bytes, DWORD *size_bytes)
53{
54 static const WCHAR empty;
55
56 *size_bytes = 0;
57
58 if (!data) data = &empty;
59
60 switch (reg_type)
61 {
62 case REG_NONE:
63 case REG_SZ:
64 case REG_EXPAND_SZ:
65 {
66 *size_bytes = (lstrlenW(data) + 1) * sizeof(WCHAR);
67 *data_bytes = malloc(*size_bytes);
68 lstrcpyW((WCHAR *)*data_bytes, data);
69 break;
70 }
71 case REG_DWORD:
72 /* case REG_DWORD_LITTLE_ENDIAN: */
73 case REG_DWORD_BIG_ENDIAN: /* Yes, this is correct! */
74 {
75 LPWSTR rest;
76 unsigned long val;
77 val = wcstoul(data, &rest, (towlower(data[1]) == 'x') ? 16 : 10);
78 if (*rest || data[0] == '-' || (val == ~0u && errno == ERANGE)) {
80 return FALSE;
81 }
82 *size_bytes = sizeof(DWORD);
83 *data_bytes = malloc(*size_bytes);
84 *(DWORD *)*data_bytes = val;
85 break;
86 }
87 case REG_BINARY:
88 {
89 BYTE hex0, hex1, *ptr;
90 int i = 0, destByteIndex = 0, datalen = lstrlenW(data);
91
92 if (!datalen) return TRUE;
93
94 *size_bytes = ((datalen + datalen % 2) / 2) * sizeof(BYTE);
95 *data_bytes = malloc(*size_bytes);
96
97 if (datalen % 2)
98 {
99 hex1 = hexchar_to_byte(data[i++]);
100 if (hex1 == 0xFF)
101 goto no_hex_data;
102 *data_bytes[destByteIndex++] = hex1;
103 }
104
105 ptr = *data_bytes;
106
107 for (; i + 1 < datalen; i += 2)
108 {
109 hex0 = hexchar_to_byte(data[i]);
110 hex1 = hexchar_to_byte(data[i + 1]);
111 if (hex0 == 0xFF || hex1 == 0xFF)
112 goto no_hex_data;
113 ptr[destByteIndex++] = (hex0 << 4) | hex1;
114 }
115 break;
116
117 no_hex_data:
118 free(*data_bytes);
119 *data_bytes = NULL;
121 return FALSE;
122 }
123 case REG_MULTI_SZ:
124 {
125 int i, destindex, len = lstrlenW(data);
126 WCHAR *buffer = malloc((len + 2) * sizeof(WCHAR));
127
128 for (i = 0, destindex = 0; i < len; i++, destindex++)
129 {
130 if (!separator && data[i] == '\\' && data[i + 1] == '0')
131 {
132 buffer[destindex] = 0;
133 i++;
134 }
135 else if (data[i] == separator)
136 buffer[destindex] = 0;
137 else
138 buffer[destindex] = data[i];
139
140 if (destindex && !buffer[destindex - 1] && (!buffer[destindex] || destindex == 1))
141 {
142 free(buffer);
144 return FALSE;
145 }
146 }
147 buffer[destindex] = 0;
148 if (destindex && buffer[destindex - 1])
149 buffer[++destindex] = 0;
150 *size_bytes = (destindex + 1) * sizeof(WCHAR);
151 *data_bytes = (BYTE *)buffer;
152 break;
153 }
154 default:
156 }
157
158 return TRUE;
159}
160
161static int run_add(HKEY root, WCHAR *path, REGSAM sam, WCHAR *value_name, BOOL value_empty,
163{
164 HKEY hkey;
165 DWORD dispos, data_type, data_size;
166 BYTE *reg_data = NULL;
167 LONG rc;
168
170 KEY_READ|KEY_WRITE|sam, NULL, &hkey, &dispos))
171 {
173 return 1;
174 }
175
176 if (!force && dispos == REG_OPENED_EXISTING_KEY)
177 {
178 if (RegQueryValueExW(hkey, value_name, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
179 {
180 if (!ask_confirm(STRING_OVERWRITE_VALUE, value_name))
181 {
182 RegCloseKey(hkey);
184 return 0;
185 }
186 }
187 }
188
189 data_type = wchar_get_type(type);
190
191 if (data_type == ~0u)
192 {
193 RegCloseKey(hkey);
195 return 1;
196 }
197
198 if ((data_type == REG_DWORD || data_type == REG_DWORD_BIG_ENDIAN) && !data)
199 {
200 RegCloseKey(hkey);
202 return 1;
203 }
204
205 if (!get_regdata(data, data_type, separator, &reg_data, &data_size))
206 {
207 RegCloseKey(hkey);
208 return 1;
209 }
210
211 rc = RegSetValueExW(hkey, value_name, 0, data_type, reg_data, data_size);
212
213 free(reg_data);
214 RegCloseKey(hkey);
215
216 if (rc)
217 {
219 return 1;
220 }
221
223
224 return 0;
225}
226
227int reg_add(int argc, WCHAR *argvW[])
228{
229 HKEY root;
230 WCHAR *path, *value_name = NULL, *type = NULL, *data = NULL, separator = '\0';
231 BOOL value_empty = FALSE, force = FALSE;
232 REGSAM sam = 0;
233 int i;
234
235 if (!parse_registry_key(argvW[2], &root, &path))
236 return 1;
237
238 for (i = 3; i < argc; i++)
239 {
240 WCHAR *str;
241
242 if (argvW[i][0] != '/' && argvW[i][0] != '-')
243 goto invalid;
244
245 str = &argvW[i][1];
246
247 if (!lstrcmpiW(str, L"ve"))
248 {
249 if (value_empty) goto invalid;
250 value_empty = TRUE;
251 continue;
252 }
253 else if (!lstrcmpiW(str, L"reg:32"))
254 {
255 if (sam & KEY_WOW64_32KEY) goto invalid;
257 continue;
258 }
259 else if (!lstrcmpiW(str, L"reg:64"))
260 {
261 if (sam & KEY_WOW64_64KEY) goto invalid;
263 continue;
264 }
265 else if (!str[0] || str[1])
266 goto invalid;
267
268 switch (towlower(*str))
269 {
270 case 'v':
271 if (value_name || !(value_name = argvW[++i]))
272 goto invalid;
273 break;
274 case 't':
275 if (type || !(type = argvW[++i]))
276 goto invalid;
277 break;
278 case 'd':
279 if (data || !(data = argvW[++i]))
280 goto invalid;
281 break;
282 case 's':
283 str = argvW[++i];
284 if (separator || !str || lstrlenW(str) != 1)
285 goto invalid;
286 separator = str[0];
287 break;
288 case 'f':
289 if (force) goto invalid;
290 force = TRUE;
291 break;
292 default:
293 goto invalid;
294 }
295 }
296
297 if (value_name && value_empty)
298 goto invalid;
299
301 goto invalid;
302
303 return run_add(root, path, sam, value_name, value_empty, type, separator, data, force);
304
305invalid:
308 return 1;
309}
static int argc
Definition: ServiceArgs.c:12
#define ERANGE
Definition: acclib.h:92
static int run_add(HKEY root, WCHAR *path, REGSAM sam, WCHAR *value_name, BOOL value_empty, WCHAR *type, WCHAR separator, WCHAR *data, BOOL force)
Definition: add.c:161
static BYTE hexchar_to_byte(WCHAR ch)
Definition: add.c:39
int reg_add(int argc, WCHAR *argvW[])
Definition: add.c:227
static BOOL get_regdata(const WCHAR *data, DWORD reg_type, WCHAR separator, BYTE **data_bytes, DWORD *size_bytes)
Definition: add.c:51
static DWORD wchar_get_type(const WCHAR *type_name)
Definition: add.c:22
static REGSAM sam
Definition: query.c:143
BOOL ask_confirm(unsigned int msgid, WCHAR *reg_info)
Definition: reg.c:127
void WINAPIV output_message(unsigned int id,...)
Definition: reg.c:92
const struct reg_type_rels type_rels[]
Definition: reg.c:41
BOOL parse_registry_key(const WCHAR *key, HKEY *root, WCHAR **path)
Definition: reg.c:234
#define STRING_SUCCESS
Definition: resource.h:36
#define STRING_MISSING_NUMBER
Definition: resource.h:58
#define STRING_CANCELLED
Definition: resource.h:37
#define STRING_INVALID_SYNTAX
Definition: resource.h:33
#define STRING_OVERWRITE_VALUE
Definition: resource.h:63
#define STRING_MISSING_HEXDATA
Definition: resource.h:59
#define STRING_FUNC_HELP
Definition: resource.h:34
#define STRING_UNSUPPORTED_TYPE
Definition: resource.h:62
#define STRING_UNHANDLED_TYPE
Definition: resource.h:61
#define STRING_ACCESS_DENIED
Definition: resource.h:35
#define STRING_INVALID_CMDLINE
Definition: resource.h:64
#define STRING_INVALID_STRING
Definition: resource.h:60
#define ARRAY_SIZE(A)
Definition: main.h:20
#define RegCloseKey(hKey)
Definition: registry.h:49
struct _root root
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
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 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 RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
static const WCHAR empty[]
Definition: main.c:47
#define lstrcpyW
Definition: compat.h:749
#define wcsicmp
Definition: compat.h:15
#define lstrlenW
Definition: compat.h:750
static const WCHAR separator[]
Definition: asmname.c:65
int WINAPI lstrcmpiW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4262
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
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint buffer
Definition: glext.h:5915
GLuint GLfloat * val
Definition: glext.h:7180
GLenum GLsizei len
Definition: glext.h:6722
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
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 * u
Definition: glfuncs.h:240
_Check_return_ unsigned long __cdecl wcstoul(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
int const JOCTET unsigned int datalen
Definition: jpeglib.h:1031
#define REG_SZ
Definition: layer.c:22
static PVOID ptr
Definition: dispmode.c:27
static ACCESS_MASK const OBJECT_ATTRIBUTES ULONG const UNICODE_STRING ULONG PULONG dispos
Definition: reg.c:132
static const WCHAR invalid[]
Definition: assoc.c:39
#define REG_BINARY
Definition: nt_native.h:1496
#define KEY_READ
Definition: nt_native.h:1023
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
#define REG_DWORD_BIG_ENDIAN
Definition: nt_native.h:1499
#define REG_MULTI_SZ
Definition: nt_native.h:1501
#define KEY_WRITE
Definition: nt_native.h:1031
#define DWORD
Definition: nt_native.h:44
#define REG_OPENED_EXISTING_KEY
Definition: nt_native.h:1085
#define REG_NONE
Definition: nt_native.h:1492
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
#define L(x)
Definition: ntvdm.h:50
long LONG
Definition: pedump.c:60
const WCHAR * str
#define REG_DWORD
Definition: sdbapi.c:596
#define errno
Definition: errno.h:18
_CRTIMP wchar_t *__cdecl _wcsupr(_Inout_z_ wchar_t *_String)
Definition: name.c:39
#define towlower(c)
Definition: wctype.h:97
type_t * reg_type(type_t *type, const char *name, struct namespace *namespace, int t)
ACCESS_MASK REGSAM
Definition: winreg.h:69
#define KEY_WOW64_32KEY
Definition: cmtypes.h:45
#define KEY_WOW64_64KEY
Definition: cmtypes.h:46
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
unsigned char BYTE
Definition: xxhash.c:193