ReactOS  0.4.15-dev-4920-g5fa8403
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 
35 static 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);
45  lstrcpyW(buffer, (WCHAR *)src);
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 
111 static const WCHAR *newlineW = L"\n";
112 
114 {
115  static const WCHAR *fmt = L" %1";
116  WCHAR defval[32];
117  WCHAR *reg_data;
118 
119  if (value_name && value_name[0])
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 
142 static unsigned int num_values_found = 0;
143 static REGSAM sam = 0;
144 
145 static 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;
150  DWORD type, path_len, i;
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;
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  {
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 
222 static 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;
229  DWORD i, type, path_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  {
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 
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 
339 int reg_query(int argc, WCHAR *argvW[])
340 {
341  HKEY root;
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;
367  sam |= KEY_WOW64_32KEY;
368  continue;
369  }
370  else if (!lstrcmpiW(str, L"reg:64"))
371  {
372  if (sam & KEY_WOW64_64KEY) goto invalid;
373  sam |= KEY_WOW64_64KEY;
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 
404 invalid:
407  return 1;
408 }
#define realloc
Definition: debug_ros.c:6
#define STRING_VALUE_NOT_SET
Definition: resource.h:85
static const WCHAR invalid[]
Definition: assoc.c:39
WCHAR * value_name
Definition: import.c:89
static int argc
Definition: ServiceArgs.c:12
#define MAX_SUBKEY_LEN
Definition: reg.h:26
#define ERROR_SUCCESS
Definition: deptool.c:10
#define REG_BINARY
Definition: nt_native.h:1496
#define KEY_READ
Definition: nt_native.h:1023
#define TRUE
Definition: types.h:120
GLsizei const GLchar ** path
Definition: glext.h:7234
#define free
Definition: debug_ros.c:5
struct _root root
GLuint buffer
Definition: glext.h:5915
void WINAPIV output_message(unsigned int id,...)
Definition: reg.c:92
WCHAR two_wchars[2]
Definition: import.c:83
#define lstrlenW
Definition: compat.h:609
static const WCHAR * reg_type_to_wchar(DWORD type)
Definition: query.c:22
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
static UINT array_size
Definition: msctf.c:67
int WINAPI lstrcmpiW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:194
#define L(x)
Definition: ntvdm.h:50
#define FALSE
Definition: types.h:117
void WINAPIV output_string(const WCHAR *fmt,...)
Definition: reg.c:117
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
#define REG_MULTI_SZ
Definition: nt_native.h:1501
static PVOID ptr
Definition: dispmode.c:27
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
int reg_query(int argc, WCHAR *argvW[])
Definition: query.c:339
_CRTIMP wchar_t *__cdecl _wcsupr(_Inout_z_ wchar_t *_String)
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
#define KEY_WOW64_64KEY
Definition: cmtypes.h:46
WCHAR * build_subkey_path(WCHAR *path, DWORD path_len, WCHAR *subkey_name, DWORD subkey_len)
Definition: reg.c:198
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
static unsigned int num_values_found
Definition: query.c:142
unsigned long DWORD
Definition: ntddk_ex.h:95
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
int ret
static int query_all(HKEY hkey, WCHAR *path, BOOL recurse, BOOL recursing)
Definition: query.c:222
HKEY hkey
Definition: import.c:87
#define STRING_MATCHES_FOUND
Definition: resource.h:86
static int run_query(HKEY root, WCHAR *path, WCHAR *key_name, WCHAR *value_name, BOOL value_empty, BOOL recurse)
Definition: query.c:311
GLenum GLsizei len
Definition: glext.h:6722
GLenum src
Definition: glext.h:6340
WCHAR * get_long_key(HKEY root, WCHAR *path)
Definition: reg.c:208
int _cdecl swprintf(const WCHAR *,...)
static WCHAR * reg_data_to_wchar(DWORD type, const BYTE *src, DWORD size_bytes)
Definition: query.c:35
#define ERROR_MORE_DATA
Definition: dderror.h:13
unsigned char BYTE
Definition: xxhash.c:193
const struct reg_type_rels type_rels[]
Definition: reg.c:41
#define REG_DWORD_BIG_ENDIAN
Definition: nt_native.h:1499
#define STRING_DEFAULT_VALUE
Definition: resource.h:40
static int query_value(HKEY hkey, WCHAR *value_name, WCHAR *path, BOOL recurse)
Definition: query.c:145
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
#define ARRAY_SIZE(a)
Definition: main.h:24
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
ACCESS_MASK REGSAM
Definition: winreg.h:69
#define NULL
Definition: types.h:112
WCHAR * key_name
Definition: import.c:88
#define STRING_KEY_NONEXIST
Definition: resource.h: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
static void output_value(const WCHAR *value_name, DWORD type, BYTE *data, DWORD data_size)
Definition: query.c:113
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
#define towlower(c)
Definition: wctype.h:97
#define malloc
Definition: debug_ros.c:4
#define KEY_WOW64_32KEY
Definition: cmtypes.h:45
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
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define REG_NONE
Definition: nt_native.h:1492
#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
static const WCHAR * newlineW
Definition: query.c:111
#define RegCloseKey(hKey)
Definition: registry.h:47
DWORD data_size
Definition: import.c:93
#define STRING_VALUE_NONEXIST
Definition: resource.h:39
#define REG_SZ
Definition: layer.c:22