ReactOS 0.4.15-dev-7958-gcd0bb1a
query.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 <stdio.h>
20#include "reg.h"
21
23{
25
26 for (i = 0; i < array_size; i++)
27 {
28 if (type == type_rels[i].type)
29 return type_rels[i].name;
30 }
31
32 return NULL;
33}
34
35static WCHAR *reg_data_to_wchar(DWORD type, const BYTE *src, DWORD size_bytes)
36{
37 WCHAR *buffer = NULL;
38 int i;
39
40 switch (type)
41 {
42 case REG_SZ:
43 case REG_EXPAND_SZ:
44 buffer = malloc(size_bytes);
46 break;
47 case REG_NONE:
48 case REG_BINARY:
49 {
50 WCHAR *ptr;
51
52 buffer = malloc((size_bytes * 2 + 1) * sizeof(WCHAR));
53
54 if (!size_bytes)
55 {
56 *buffer = 0;
57 break;
58 }
59
60 ptr = buffer;
61
62 for (i = 0; i < size_bytes; i++)
63 ptr += swprintf(ptr, L"%02X", src[i]);
64 break;
65 }
66 case REG_DWORD:
67 /* case REG_DWORD_LITTLE_ENDIAN: */
69 {
70 const int zero_x_dword = 10;
71
72 buffer = malloc((zero_x_dword + 1) * sizeof(WCHAR));
73 swprintf(buffer, L"0x%x", *(DWORD *)src);
74 break;
75 }
76 case REG_MULTI_SZ:
77 {
78 const int two_wchars = 2 * sizeof(WCHAR);
79 DWORD tmp_size;
80 const WCHAR *tmp = (const WCHAR *)src;
81 int len, destindex;
82
83 if (size_bytes <= two_wchars)
84 {
85 buffer = malloc(sizeof(WCHAR));
86 *buffer = 0;
87 return buffer;
88 }
89
90 tmp_size = size_bytes - two_wchars; /* exclude both null terminators */
91 buffer = malloc(tmp_size * 2 + sizeof(WCHAR));
92 len = tmp_size / sizeof(WCHAR);
93
94 for (i = 0, destindex = 0; i < len; i++, destindex++)
95 {
96 if (tmp[i])
97 buffer[destindex] = tmp[i];
98 else
99 {
100 buffer[destindex++] = '\\';
101 buffer[destindex] = '0';
102 }
103 }
104 buffer[destindex] = 0;
105 break;
106 }
107 }
108 return buffer;
109}
110
111static const WCHAR *newlineW = L"\n";
112
113static void output_value(const WCHAR *value_name, DWORD type, BYTE *data, DWORD data_size)
114{
115 static const WCHAR *fmt = L" %1";
116 WCHAR defval[32];
117 WCHAR *reg_data;
118
119 if (value_name && value_name[0])
120 output_string(fmt, value_name);
121 else
122 {
124 output_string(fmt, defval);
125 }
127
128 if (data)
129 {
130 reg_data = reg_data_to_wchar(type, data, data_size);
131 output_string(fmt, reg_data);
132 free(reg_data);
133 }
134 else
135 {
137 output_string(fmt, defval);
138 }
140}
141
142static unsigned int num_values_found = 0;
143static REGSAM sam = 0;
144
145static int query_value(HKEY hkey, WCHAR *value_name, WCHAR *path, BOOL recurse)
146{
147 LONG rc;
148 DWORD max_data_bytes = 2048, data_size;
149 DWORD subkey_len;
151 BYTE *data;
152 static const WCHAR *fmt = L"%1\n";
153 WCHAR *subkey_name, *subkey_path;
154 HKEY subkey;
155
156 data = malloc(max_data_bytes);
157
158 for (;;)
159 {
160 data_size = max_data_bytes;
161 rc = RegQueryValueExW(hkey, value_name, NULL, &type, data, &data_size);
162 if (rc == ERROR_MORE_DATA)
163 {
164 max_data_bytes = data_size;
165 data = realloc(data, max_data_bytes);
166 }
167 else break;
168 }
169
170 if (rc == ERROR_SUCCESS)
171 {
173 output_value(value_name, type, data, data_size);
176 }
177
178 free(data);
179
180 if (!recurse)
181 {
182 if (rc == ERROR_FILE_NOT_FOUND)
183 {
184 if (value_name && *value_name)
185 {
187 return 1;
188 }
191 }
192 return 0;
193 }
194
195 subkey_name = malloc(MAX_SUBKEY_LEN * sizeof(WCHAR));
196
198
199 i = 0;
200 for (;;)
201 {
202 subkey_len = MAX_SUBKEY_LEN;
203 rc = RegEnumKeyExW(hkey, i, subkey_name, &subkey_len, NULL, NULL, NULL, NULL);
204 if (rc == ERROR_SUCCESS)
205 {
206 subkey_path = build_subkey_path(path, path_len, subkey_name, subkey_len);
207 if (!RegOpenKeyExW(hkey, subkey_name, 0, KEY_READ|sam, &subkey))
208 {
209 query_value(subkey, value_name, subkey_path, recurse);
210 RegCloseKey(subkey);
211 }
212 free(subkey_path);
213 i++;
214 }
215 else break;
216 }
217
218 free(subkey_name);
219 return 0;
220}
221
222static int query_all(HKEY hkey, WCHAR *path, BOOL recurse, BOOL recursing)
223{
224 LONG rc;
225 DWORD num_subkeys, num_values;
226 DWORD max_value_len = 256, value_len;
227 DWORD max_data_bytes = 2048, data_size;
228 DWORD subkey_len;
230 WCHAR *value_name, *subkey_name, *subkey_path;
231 BYTE *data;
232 HKEY subkey;
233
234 rc = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, &num_subkeys, NULL,
235 NULL, &num_values, NULL, NULL, NULL, NULL);
236 if (rc) return 1;
237
238 if (num_values || recursing)
239 output_string(L"%1\n", path);
240
241 value_name = malloc(max_value_len * sizeof(WCHAR));
242 data = malloc(max_data_bytes);
243
244 i = 0;
245 for (;;)
246 {
247 value_len = max_value_len;
248 data_size = max_data_bytes;
249 rc = RegEnumValueW(hkey, i, value_name, &value_len, NULL, &type, data, &data_size);
250 if (rc == ERROR_SUCCESS)
251 {
252 output_value(value_name, type, data, data_size);
253 i++;
254 }
255 else if (rc == ERROR_MORE_DATA)
256 {
257 if (data_size > max_data_bytes)
258 {
259 max_data_bytes = data_size;
260 data = realloc(data, max_data_bytes);
261 }
262 else
263 {
264 max_value_len *= 2;
265 value_name = realloc(value_name, max_value_len * sizeof(WCHAR));
266 }
267 }
268 else break;
269 }
270
271 free(data);
272 free(value_name);
273
274 if (i || recursing)
276
277 if (!num_subkeys)
278 return 0;
279
280 subkey_name = malloc(MAX_SUBKEY_LEN * sizeof(WCHAR));
281
283
284 i = 0;
285 for (;;)
286 {
287 subkey_len = MAX_SUBKEY_LEN;
288 rc = RegEnumKeyExW(hkey, i, subkey_name, &subkey_len, NULL, NULL, NULL, NULL);
289 if (rc == ERROR_SUCCESS)
290 {
291 if (recurse)
292 {
293 subkey_path = build_subkey_path(path, path_len, subkey_name, subkey_len);
294 if (!RegOpenKeyExW(hkey, subkey_name, 0, KEY_READ|sam, &subkey))
295 {
296 query_all(subkey, subkey_path, recurse, TRUE);
297 RegCloseKey(subkey);
298 }
299 free(subkey_path);
300 }
301 else output_string(L"%1\\%2\n", path, subkey_name);
302 i++;
303 }
304 else break;
305 }
306
307 free(subkey_name);
308 return 0;
309}
310
311static int run_query(HKEY root, WCHAR *path, WCHAR *key_name, WCHAR *value_name,
312 BOOL value_empty, BOOL recurse)
313{
314 HKEY hkey;
315 int ret;
316
317 if (RegOpenKeyExW(root, path, 0, KEY_READ|sam, &hkey))
318 {
320 return 1;
321 }
322
324
325 if (value_name || value_empty)
326 {
327 ret = query_value(hkey, value_name, key_name, recurse);
328 if (recurse)
330 }
331 else
332 ret = query_all(hkey, key_name, recurse, FALSE);
333
334 RegCloseKey(hkey);
335
336 return ret;
337}
338
339int reg_query(int argc, WCHAR *argvW[])
340{
341 HKEY root;
342 WCHAR *path, *key_name, *value_name = NULL;
343 BOOL value_empty = FALSE, recurse = FALSE;
344 int i;
345
346 if (!parse_registry_key(argvW[2], &root, &path))
347 return 1;
348
349 for (i = 3; i < argc; i++)
350 {
351 WCHAR *str;
352
353 if (argvW[i][0] != '/' && argvW[i][0] != '-')
354 goto invalid;
355
356 str = &argvW[i][1];
357
358 if (!lstrcmpiW(str, L"ve"))
359 {
360 if (value_empty) goto invalid;
361 value_empty = TRUE;
362 continue;
363 }
364 else if (!lstrcmpiW(str, L"reg:32"))
365 {
366 if (sam & KEY_WOW64_32KEY) goto invalid;
368 continue;
369 }
370 else if (!lstrcmpiW(str, L"reg:64"))
371 {
372 if (sam & KEY_WOW64_64KEY) goto invalid;
374 continue;
375 }
376 else if (!str[0] || str[1])
377 goto invalid;
378
379 switch (towlower(*str))
380 {
381 case 'v':
382 if (value_name || !(value_name = argvW[++i]))
383 goto invalid;
384 break;
385 case 's':
386 if (recurse) goto invalid;
387 recurse = TRUE;
388 break;
389 default:
390 goto invalid;
391 }
392 }
393
394 if (value_name && value_empty)
395 goto invalid;
396
398 goto invalid;
399
401
402 return run_query(root, path, key_name, value_name, value_empty, recurse);
403
404invalid:
407 return 1;
408}
static int argc
Definition: ServiceArgs.c:12
static int query_all(HKEY hkey, WCHAR *path, BOOL recurse, BOOL recursing)
Definition: query.c:222
static const WCHAR * newlineW
Definition: query.c:111
static int query_value(HKEY hkey, WCHAR *value_name, WCHAR *path, BOOL recurse)
Definition: query.c:145
static WCHAR * reg_data_to_wchar(DWORD type, const BYTE *src, DWORD size_bytes)
Definition: query.c:35
static void output_value(const WCHAR *value_name, DWORD type, BYTE *data, DWORD data_size)
Definition: query.c:113
static const WCHAR * reg_type_to_wchar(DWORD type)
Definition: query.c:22
static unsigned int num_values_found
Definition: query.c:142
static int run_query(HKEY root, WCHAR *path, WCHAR *key_name, WCHAR *value_name, BOOL value_empty, BOOL recurse)
Definition: query.c:311
static REGSAM sam
Definition: query.c:143
int reg_query(int argc, WCHAR *argvW[])
Definition: query.c:339
WCHAR * get_long_key(HKEY root, WCHAR *path)
Definition: reg.c:208
WCHAR * build_subkey_path(WCHAR *path, DWORD path_len, WCHAR *subkey_name, DWORD subkey_len)
Definition: reg.c:198
void WINAPIV output_string(const WCHAR *fmt,...)
Definition: reg.c:117
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 MAX_SUBKEY_LEN
Definition: reg.h:26
#define STRING_VALUE_NOT_SET
Definition: resource.h:85
#define STRING_INVALID_SYNTAX
Definition: resource.h:33
#define STRING_DEFAULT_VALUE
Definition: resource.h:40
#define STRING_FUNC_HELP
Definition: resource.h:34
#define STRING_VALUE_NONEXIST
Definition: resource.h:39
#define STRING_KEY_NONEXIST
Definition: resource.h:38
#define STRING_MATCHES_FOUND
Definition: resource.h:86
#define ARRAY_SIZE(A)
Definition: main.h:33
#define RegCloseKey(hKey)
Definition: registry.h:49
struct _root root
#define ERROR_MORE_DATA
Definition: dderror.h:13
#define realloc
Definition: debug_ros.c:6
#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 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 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 lstrcpyW
Definition: compat.h:749
#define lstrlenW
Definition: compat.h:750
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
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLenum src
Definition: glext.h:6340
GLuint buffer
Definition: glext.h:5915
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
#define REG_SZ
Definition: layer.c:22
int WINAPI lstrcmpiW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:194
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
static PVOID ptr
Definition: dispmode.c:27
static DWORD path_len
Definition: batch.c:31
static const WCHAR invalid[]
Definition: assoc.c:39
static UINT array_size
Definition: msctf.c:67
#define REG_BINARY
Definition: nt_native.h:1496
#define KEY_READ
Definition: nt_native.h:1023
#define REG_DWORD_BIG_ENDIAN
Definition: nt_native.h:1499
#define REG_MULTI_SZ
Definition: nt_native.h:1501
#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
_CRTIMP wchar_t *__cdecl _wcsupr(_Inout_z_ wchar_t *_String)
Definition: dsound.c:943
#define towlower(c)
Definition: wctype.h:97
int ret
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