reg: Merge common header #includes into reg.h.
[wine.git] / programs / reg / query.c
blobb24edb2f0b232230091ab7dc436d51bb9e7f5419
1 /*
2 * Copyright 2016-2017, 2021 Hugh McMaster
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.
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.
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
19 #include <stdio.h>
20 #include "reg.h"
22 static const WCHAR *reg_type_to_wchar(DWORD type)
24 int i, array_size = ARRAY_SIZE(type_rels);
26 for (i = 0; i < array_size; i++)
28 if (type == type_rels[i].type)
29 return type_rels[i].name;
32 return NULL;
35 static WCHAR *reg_data_to_wchar(DWORD type, const BYTE *src, DWORD size_bytes)
37 WCHAR *buffer = NULL;
38 int i;
40 switch (type)
42 case REG_SZ:
43 case REG_EXPAND_SZ:
44 buffer = heap_xalloc(size_bytes);
45 lstrcpyW(buffer, (WCHAR *)src);
46 break;
47 case REG_NONE:
48 case REG_BINARY:
50 WCHAR *ptr;
51 static const WCHAR fmt[] = {'%','0','2','X',0};
53 buffer = heap_xalloc((size_bytes * 2 + 1) * sizeof(WCHAR));
54 ptr = buffer;
55 for (i = 0; i < size_bytes; i++)
56 ptr += swprintf(ptr, 3, fmt, src[i]);
57 break;
59 case REG_DWORD:
60 /* case REG_DWORD_LITTLE_ENDIAN: */
61 case REG_DWORD_BIG_ENDIAN:
63 const int zero_x_dword = 10;
64 static const WCHAR fmt[] = {'0','x','%','x',0};
66 buffer = heap_xalloc((zero_x_dword + 1) * sizeof(WCHAR));
67 swprintf(buffer, zero_x_dword + 1, fmt, *(DWORD *)src);
68 break;
70 case REG_MULTI_SZ:
72 const int two_wchars = 2 * sizeof(WCHAR);
73 DWORD tmp_size;
74 const WCHAR *tmp = (const WCHAR *)src;
75 int len, destindex;
77 if (size_bytes <= two_wchars)
79 buffer = heap_xalloc(sizeof(WCHAR));
80 *buffer = 0;
81 return buffer;
84 tmp_size = size_bytes - two_wchars; /* exclude both null terminators */
85 buffer = heap_xalloc(tmp_size * 2 + sizeof(WCHAR));
86 len = tmp_size / sizeof(WCHAR);
88 for (i = 0, destindex = 0; i < len; i++, destindex++)
90 if (tmp[i])
91 buffer[destindex] = tmp[i];
92 else
94 buffer[destindex++] = '\\';
95 buffer[destindex] = '0';
98 buffer[destindex] = 0;
99 break;
102 return buffer;
105 static const WCHAR newlineW[] = {'\n',0};
107 static void output_value(const WCHAR *value_name, DWORD type, BYTE *data, DWORD data_size)
109 static const WCHAR fmt[] = {' ',' ',' ',' ','%','1',0};
110 WCHAR defval[32];
111 WCHAR *reg_data;
113 if (value_name && value_name[0])
114 output_string(fmt, value_name);
115 else
117 LoadStringW(GetModuleHandleW(NULL), STRING_DEFAULT_VALUE, defval, ARRAY_SIZE(defval));
118 output_string(fmt, defval);
120 output_string(fmt, reg_type_to_wchar(type));
122 if (data)
124 reg_data = reg_data_to_wchar(type, data, data_size);
125 output_string(fmt, reg_data);
126 heap_free(reg_data);
128 else
130 LoadStringW(GetModuleHandleW(NULL), STRING_VALUE_NOT_SET, defval, ARRAY_SIZE(defval));
131 output_string(fmt, defval);
133 output_string(newlineW);
136 static unsigned int num_values_found = 0;
138 static int query_value(HKEY key, WCHAR *value_name, WCHAR *path, BOOL recurse)
140 LONG rc;
141 DWORD max_data_bytes = 2048, data_size;
142 DWORD subkey_len;
143 DWORD type, path_len, i;
144 BYTE *data;
145 WCHAR fmt[] = {'%','1','\n',0};
146 WCHAR *subkey_name, *subkey_path;
147 HKEY subkey;
149 data = heap_xalloc(max_data_bytes);
151 for (;;)
153 data_size = max_data_bytes;
154 rc = RegQueryValueExW(key, value_name, NULL, &type, data, &data_size);
155 if (rc == ERROR_MORE_DATA)
157 max_data_bytes = data_size;
158 data = heap_xrealloc(data, max_data_bytes);
160 else break;
163 if (rc == ERROR_SUCCESS)
165 output_string(fmt, path);
166 output_value(value_name, type, data, data_size);
167 output_string(newlineW);
168 num_values_found++;
171 heap_free(data);
173 if (!recurse)
175 if (rc == ERROR_FILE_NOT_FOUND)
177 if (value_name && *value_name)
179 output_message(STRING_CANNOT_FIND);
180 return 1;
182 output_string(fmt, path);
183 output_value(NULL, REG_SZ, NULL, 0);
185 return 0;
188 subkey_name = heap_xalloc(MAX_SUBKEY_LEN * sizeof(WCHAR));
190 path_len = lstrlenW(path);
192 i = 0;
193 for (;;)
195 subkey_len = MAX_SUBKEY_LEN;
196 rc = RegEnumKeyExW(key, i, subkey_name, &subkey_len, NULL, NULL, NULL, NULL);
197 if (rc == ERROR_SUCCESS)
199 subkey_path = build_subkey_path(path, path_len, subkey_name, subkey_len);
200 if (!RegOpenKeyExW(key, subkey_name, 0, KEY_READ, &subkey))
202 query_value(subkey, value_name, subkey_path, recurse);
203 RegCloseKey(subkey);
205 heap_free(subkey_path);
206 i++;
208 else break;
211 heap_free(subkey_name);
212 return 0;
215 static int query_all(HKEY key, WCHAR *path, BOOL recurse)
217 LONG rc;
218 DWORD max_value_len = 256, value_len;
219 DWORD max_data_bytes = 2048, data_size;
220 DWORD subkey_len;
221 DWORD i, type, path_len;
222 WCHAR fmt[] = {'%','1','\n',0};
223 WCHAR fmt_path[] = {'%','1','\\','%','2','\n',0};
224 WCHAR *value_name, *subkey_name, *subkey_path;
225 BYTE *data;
226 HKEY subkey;
228 output_string(fmt, path);
230 value_name = heap_xalloc(max_value_len * sizeof(WCHAR));
231 data = heap_xalloc(max_data_bytes);
233 i = 0;
234 for (;;)
236 value_len = max_value_len;
237 data_size = max_data_bytes;
238 rc = RegEnumValueW(key, i, value_name, &value_len, NULL, &type, data, &data_size);
239 if (rc == ERROR_SUCCESS)
241 output_value(value_name, type, data, data_size);
242 i++;
244 else if (rc == ERROR_MORE_DATA)
246 if (data_size > max_data_bytes)
248 max_data_bytes = data_size;
249 data = heap_xrealloc(data, max_data_bytes);
251 else
253 max_value_len *= 2;
254 value_name = heap_xrealloc(value_name, max_value_len * sizeof(WCHAR));
257 else break;
260 heap_free(data);
261 heap_free(value_name);
263 if (i || recurse)
264 output_string(newlineW);
266 subkey_name = heap_xalloc(MAX_SUBKEY_LEN * sizeof(WCHAR));
268 path_len = lstrlenW(path);
270 i = 0;
271 for (;;)
273 subkey_len = MAX_SUBKEY_LEN;
274 rc = RegEnumKeyExW(key, i, subkey_name, &subkey_len, NULL, NULL, NULL, NULL);
275 if (rc == ERROR_SUCCESS)
277 if (recurse)
279 subkey_path = build_subkey_path(path, path_len, subkey_name, subkey_len);
280 if (!RegOpenKeyExW(key, subkey_name, 0, KEY_READ, &subkey))
282 query_all(subkey, subkey_path, recurse);
283 RegCloseKey(subkey);
285 heap_free(subkey_path);
287 else output_string(fmt_path, path, subkey_name);
288 i++;
290 else break;
293 heap_free(subkey_name);
295 if (i && !recurse)
296 output_string(newlineW);
298 return 0;
301 int reg_query(HKEY root, WCHAR *path, WCHAR *key_name, WCHAR *value_name,
302 BOOL value_empty, BOOL recurse)
304 HKEY key;
305 int ret;
307 if (RegOpenKeyExW(root, path, 0, KEY_READ, &key) != ERROR_SUCCESS)
309 output_message(STRING_CANNOT_FIND);
310 return 1;
313 output_string(newlineW);
315 if (value_name || value_empty)
317 ret = query_value(key, value_name, key_name, recurse);
318 if (recurse)
319 output_message(STRING_MATCHES_FOUND, num_values_found);
321 else
322 ret = query_all(key, key_name, recurse);
324 RegCloseKey(key);
326 return ret;