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
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
;
35 static WCHAR
*reg_data_to_wchar(DWORD type
, const BYTE
*src
, DWORD size_bytes
)
44 buffer
= heap_xalloc(size_bytes
);
45 lstrcpyW(buffer
, (WCHAR
*)src
);
51 static const WCHAR fmt
[] = {'%','0','2','X',0};
53 buffer
= heap_xalloc((size_bytes
* 2 + 1) * sizeof(WCHAR
));
55 for (i
= 0; i
< size_bytes
; i
++)
56 ptr
+= swprintf(ptr
, 3, fmt
, src
[i
]);
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
);
72 const int two_wchars
= 2 * sizeof(WCHAR
);
74 const WCHAR
*tmp
= (const WCHAR
*)src
;
77 if (size_bytes
<= two_wchars
)
79 buffer
= heap_xalloc(sizeof(WCHAR
));
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
++)
91 buffer
[destindex
] = tmp
[i
];
94 buffer
[destindex
++] = '\\';
95 buffer
[destindex
] = '0';
98 buffer
[destindex
] = 0;
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};
113 if (value_name
&& value_name
[0])
114 output_string(fmt
, value_name
);
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
));
124 reg_data
= reg_data_to_wchar(type
, data
, data_size
);
125 output_string(fmt
, reg_data
);
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
)
141 DWORD max_data_bytes
= 2048, data_size
;
143 DWORD type
, path_len
, i
;
145 WCHAR fmt
[] = {'%','1','\n',0};
146 WCHAR
*subkey_name
, *subkey_path
;
149 data
= heap_xalloc(max_data_bytes
);
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
);
163 if (rc
== ERROR_SUCCESS
)
165 output_string(fmt
, path
);
166 output_value(value_name
, type
, data
, data_size
);
167 output_string(newlineW
);
175 if (rc
== ERROR_FILE_NOT_FOUND
)
177 if (value_name
&& *value_name
)
179 output_message(STRING_CANNOT_FIND
);
182 output_string(fmt
, path
);
183 output_value(NULL
, REG_SZ
, NULL
, 0);
188 subkey_name
= heap_xalloc(MAX_SUBKEY_LEN
* sizeof(WCHAR
));
190 path_len
= lstrlenW(path
);
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
);
205 heap_free(subkey_path
);
211 heap_free(subkey_name
);
215 static int query_all(HKEY key
, WCHAR
*path
, BOOL recurse
)
218 DWORD max_value_len
= 256, value_len
;
219 DWORD max_data_bytes
= 2048, data_size
;
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
;
228 output_string(fmt
, path
);
230 value_name
= heap_xalloc(max_value_len
* sizeof(WCHAR
));
231 data
= heap_xalloc(max_data_bytes
);
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
);
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
);
254 value_name
= heap_xrealloc(value_name
, max_value_len
* sizeof(WCHAR
));
261 heap_free(value_name
);
264 output_string(newlineW
);
266 subkey_name
= heap_xalloc(MAX_SUBKEY_LEN
* sizeof(WCHAR
));
268 path_len
= lstrlenW(path
);
273 subkey_len
= MAX_SUBKEY_LEN
;
274 rc
= RegEnumKeyExW(key
, i
, subkey_name
, &subkey_len
, NULL
, NULL
, NULL
, NULL
);
275 if (rc
== ERROR_SUCCESS
)
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
);
285 heap_free(subkey_path
);
287 else output_string(fmt_path
, path
, subkey_name
);
293 heap_free(subkey_name
);
296 output_string(newlineW
);
301 int reg_query(HKEY root
, WCHAR
*path
, WCHAR
*key_name
, WCHAR
*value_name
,
302 BOOL value_empty
, BOOL recurse
)
307 if (RegOpenKeyExW(root
, path
, 0, KEY_READ
, &key
) != ERROR_SUCCESS
)
309 output_message(STRING_CANNOT_FIND
);
313 output_string(newlineW
);
315 if (value_name
|| value_empty
)
317 ret
= query_value(key
, value_name
, key_name
, recurse
);
319 output_message(STRING_MATCHES_FOUND
, num_values_found
);
322 ret
= query_all(key
, key_name
, recurse
);