1 /* GIO - GLib Input, Output and Streaming Library
2 *
3 * Copyright (C) 2014 Руслан Ижбулатов <lrn1986@gmail.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20 #include "config.h"
21 #include "ginitable.h"
22 #include "gwin32registrykey.h"
23 #include <gio/gioerror.h>
24 #ifdef _MSC_VER
25 #pragma warning ( disable:4005 )
26 #endif
27 #include <windows.h>
28 #include <ntstatus.h>
29 #include <winternl.h>
30
31 #ifndef _WDMDDK_
32 typedef enum _KEY_INFORMATION_CLASS {
33 KeyBasicInformation,
34 KeyNodeInformation,
35 KeyFullInformation,
36 KeyNameInformation,
37 KeyCachedInformation,
38 KeyFlagsInformation,
39 KeyVirtualizationInformation,
40 KeyHandleTagsInformation,
41 MaxKeyInfoClass
42 } KEY_INFORMATION_CLASS;
43
44 typedef struct _KEY_BASIC_INFORMATION {
45 LARGE_INTEGER LastWriteTime;
46 ULONG TitleIndex;
47 ULONG NameLength;
48 WCHAR Name[1];
49 } KEY_BASIC_INFORMATION, *PKEY_BASIC_INFORMATION;
50 #endif
51
52 #if !defined (__OBJECT_ATTRIBUTES_DEFINED) && defined (__MINGW32_)
53 #define __OBJECT_ATTRIBUTES_DEFINED
54 typedef struct _OBJECT_ATTRIBUTES {
55 ULONG Length;
56 #ifdef _WIN64
57 ULONG pad1;
58 #endif
59 HANDLE RootDirectory;
60 PUNICODE_STRING ObjectName;
61 ULONG Attributes;
62 #ifdef _WIN64
63 ULONG pad2;
64 #endif
65 PVOID SecurityDescriptor;
66 PVOID SecurityQualityOfService;
67 } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
68 #endif
69
70 #ifndef HKEY_CURRENT_USER_LOCAL_SETTINGS
71 #define HKEY_CURRENT_USER_LOCAL_SETTINGS ((HKEY) (ULONG_PTR)((LONG)0x80000007))
72 #endif
73
74 #if !defined (__UNICODE_STRING_DEFINED) && defined (__MINGW32_)
75 #define __UNICODE_STRING_DEFINED
76 typedef struct _UNICODE_STRING {
77 USHORT Length;
78 USHORT MaximumLength;
79 PWSTR Buffer;
80 } UNICODE_STRING, *PUNICODE_STRING;
81 #endif
82 typedef const UNICODE_STRING* PCUNICODE_STRING;
83
84 typedef NTSTATUS
85 (NTAPI * NtQueryKeyFunc)(HANDLE key_handle,
86 KEY_INFORMATION_CLASS key_info_class,
87 PVOID key_info_buffer,
88 ULONG key_info_buffer_size,
89 PULONG result_size);
90
91 typedef NTSTATUS
92 (NTAPI * NtNotifyChangeMultipleKeysFunc)(HANDLE key_handle,
93 ULONG subkey_count,
94 POBJECT_ATTRIBUTES subkeys,
95 HANDLE event,
96 PIO_APC_ROUTINE apc_routine,
97 PVOID apc_closure,
98 PIO_STATUS_BLOCK status_block,
99 ULONG filter,
100 BOOLEAN watch_tree,
101 PVOID buffer,
102 ULONG buffer_size,
103 BOOLEAN async);
104
105 static NtQueryKeyFunc nt_query_key = NULL;
106 static NtNotifyChangeMultipleKeysFunc nt_notify_change_multiple_keys = NULL;
107
108 #define G_WIN32_KEY_UNWATCHED 0
109 #define G_WIN32_KEY_WATCHED 1
110 #define G_WIN32_KEY_UNCHANGED 0
111 #define G_WIN32_KEY_CHANGED 1
112 #define G_WIN32_KEY_UNKNOWN -1
113
114 enum
115 {
116 PROP_0,
117 PROP_PATH,
118 PROP_PATH_UTF16,
119 PROP_MAX,
120 };
121
122 typedef enum
123 {
124 G_WIN32_REGISTRY_UPDATED_NOTHING = 0,
125 G_WIN32_REGISTRY_UPDATED_PATH = 1,
126 } GWin32RegistryKeyUpdateFlag;
127
128 static gsize
g_utf16_len(const gunichar2 * str)129 g_utf16_len (const gunichar2 *str)
130 {
131 gsize result;
132
133 for (result = 0; str[0] != 0; str++, result++)
134 ;
135
136 return result;
137 }
138
139 static gunichar2 *
g_wcsdup(const gunichar2 * str,gssize str_len)140 g_wcsdup (const gunichar2 *str, gssize str_len)
141 {
142 gsize str_len_unsigned;
143 gsize str_size;
144
145 g_return_val_if_fail (str != NULL, NULL);
146
147 if (str_len < 0)
148 str_len_unsigned = g_utf16_len (str);
149 else
150 str_len_unsigned = (gsize) str_len;
151
152 g_assert (str_len_unsigned <= G_MAXSIZE / sizeof (gunichar2) - 1);
153 str_size = (str_len_unsigned + 1) * sizeof (gunichar2);
154
155 return g_memdup2 (str, str_size);
156 }
157
158 /**
159 * g_win32_registry_subkey_iter_copy:
160 * @iter: an iterator
161 *
162 * Creates a dynamically-allocated copy of an iterator. Dynamically-allocated
163 * state of the iterator is duplicated too.
164 *
165 * Returns: (transfer full): a copy of the @iter,
166 * free with g_win32_registry_subkey_iter_free ()
167 *
168 * Since: 2.46
169 **/
170 GWin32RegistrySubkeyIter *
g_win32_registry_subkey_iter_copy(const GWin32RegistrySubkeyIter * iter)171 g_win32_registry_subkey_iter_copy (const GWin32RegistrySubkeyIter *iter)
172 {
173 GWin32RegistrySubkeyIter *new_iter;
174
175 g_return_val_if_fail (iter != NULL, NULL);
176
177 new_iter = g_new0 (GWin32RegistrySubkeyIter, 1);
178
179 new_iter->key = g_object_ref (iter->key);
180 new_iter->counter = iter->counter;
181 new_iter->subkey_count = iter->subkey_count;
182 new_iter->subkey_name = g_wcsdup (iter->subkey_name, iter->subkey_name_size);
183 new_iter->subkey_name_size = iter->subkey_name_size;
184
185 if (iter->subkey_name_u8)
186 new_iter->subkey_name_u8 = iter->subkey_name_u8;
187 else
188 new_iter->subkey_name_u8 = NULL;
189
190 return new_iter;
191 }
192
193 /**
194 * g_win32_registry_subkey_iter_free:
195 * @iter: a dynamically-allocated iterator
196 *
197 * Free an iterator allocated on the heap. For iterators that are allocated
198 * on the stack use g_win32_registry_subkey_iter_clear () instead.
199 *
200 * Since: 2.46
201 **/
202 void
g_win32_registry_subkey_iter_free(GWin32RegistrySubkeyIter * iter)203 g_win32_registry_subkey_iter_free (GWin32RegistrySubkeyIter *iter)
204 {
205 g_return_if_fail (iter != NULL);
206
207 g_object_unref (iter->key);
208 g_free (iter->subkey_name);
209 g_free (iter->subkey_name_u8);
210 g_free (iter);
211 }
212
213 /**
214 * g_win32_registry_subkey_iter_assign:
215 * @iter: a #GWin32RegistrySubkeyIter
216 * @other: another #GWin32RegistrySubkeyIter
217 *
218 * Assigns the value of @other to @iter. This function
219 * is not useful in applications, because iterators can be assigned
220 * with `GWin32RegistrySubkeyIter i = j;`. The
221 * function is used by language bindings.
222 *
223 * Since: 2.46
224 **/
225 void
g_win32_registry_subkey_iter_assign(GWin32RegistrySubkeyIter * iter,const GWin32RegistrySubkeyIter * other)226 g_win32_registry_subkey_iter_assign (GWin32RegistrySubkeyIter *iter,
227 const GWin32RegistrySubkeyIter *other)
228 {
229 g_return_if_fail (iter != NULL);
230 g_return_if_fail (other != NULL);
231
232 *iter = *other;
233 }
234
235
G_DEFINE_BOXED_TYPE(GWin32RegistrySubkeyIter,g_win32_registry_subkey_iter,g_win32_registry_subkey_iter_copy,g_win32_registry_subkey_iter_free)236 G_DEFINE_BOXED_TYPE (GWin32RegistrySubkeyIter, g_win32_registry_subkey_iter,
237 g_win32_registry_subkey_iter_copy,
238 g_win32_registry_subkey_iter_free)
239
240 /**
241 * g_win32_registry_value_iter_copy:
242 * @iter: an iterator
243 *
244 * Creates a dynamically-allocated copy of an iterator. Dynamically-allocated
245 * state of the iterator is duplicated too.
246 *
247 * Returns: (transfer full): a copy of the @iter,
248 * free with g_win32_registry_value_iter_free ().
249 *
250 * Since: 2.46
251 **/
252 GWin32RegistryValueIter *
253 g_win32_registry_value_iter_copy (const GWin32RegistryValueIter *iter)
254 {
255 GWin32RegistryValueIter *new_iter;
256
257 g_return_val_if_fail (iter != NULL, NULL);
258
259 new_iter = g_new0 (GWin32RegistryValueIter, 1);
260
261 new_iter->key = g_object_ref (iter->key);
262 new_iter->counter = iter->counter;
263 new_iter->value_count = iter->value_count;
264 new_iter->value_name = g_wcsdup (iter->value_name, iter->value_name_size);
265 new_iter->value_name_size = iter->value_name_size;
266
267 if (iter->value_data != NULL)
268 new_iter->value_data = g_memdup2 (iter->value_data, iter->value_data_size);
269
270 new_iter->value_data_size = iter->value_data_size;
271
272 if (iter->value_name_u8 != NULL)
273 new_iter->value_name_u8 = g_strdup (iter->value_name_u8);
274
275 new_iter->value_name_u8_len = iter->value_name_u8_len;
276
277 if (iter->value_data_u8 != NULL)
278 new_iter->value_data_u8 = g_strdup (iter->value_data_u8);
279
280 new_iter->value_data_u8_size = iter->value_data_u8_size;
281
282 if (iter->value_data_expanded != NULL)
283 new_iter->value_data_expanded = g_wcsdup ((gunichar2 *) iter->value_data_expanded,
284 iter->value_data_expanded_charsize * sizeof (gunichar2));
285
286 new_iter->value_data_expanded_charsize = iter->value_data_expanded_charsize;
287
288 if (iter->value_data_expanded_u8 != NULL)
289 new_iter->value_data_expanded_u8 = g_memdup2 (iter->value_data_expanded_u8,
290 iter->value_data_expanded_charsize);
291
292 new_iter->value_data_expanded_u8_size = iter->value_data_expanded_charsize;
293
294 return new_iter;
295 }
296
297 /**
298 * g_win32_registry_value_iter_free:
299 * @iter: a dynamically-allocated iterator
300 *
301 * Free an iterator allocated on the heap. For iterators that are allocated
302 * on the stack use g_win32_registry_value_iter_clear () instead.
303 *
304 * Since: 2.46
305 **/
306 void
g_win32_registry_value_iter_free(GWin32RegistryValueIter * iter)307 g_win32_registry_value_iter_free (GWin32RegistryValueIter *iter)
308 {
309 g_return_if_fail (iter != NULL);
310
311 g_object_unref (iter->key);
312 g_free (iter->value_name);
313 g_free (iter->value_data);
314 g_free (iter->value_data_expanded);
315 g_free (iter->value_name_u8);
316 g_free (iter->value_data_u8);
317 g_free (iter->value_data_expanded_u8);
318 g_free (iter);
319 }
320
321 /**
322 * g_win32_registry_value_iter_assign:
323 * @iter: a #GWin32RegistryValueIter
324 * @other: another #GWin32RegistryValueIter
325 *
326 * Assigns the value of @other to @iter. This function
327 * is not useful in applications, because iterators can be assigned
328 * with `GWin32RegistryValueIter i = j;`. The
329 * function is used by language bindings.
330 *
331 * Since: 2.46
332 **/
333 void
g_win32_registry_value_iter_assign(GWin32RegistryValueIter * iter,const GWin32RegistryValueIter * other)334 g_win32_registry_value_iter_assign (GWin32RegistryValueIter *iter,
335 const GWin32RegistryValueIter *other)
336 {
337 g_return_if_fail (iter != NULL);
338 g_return_if_fail (other != NULL);
339
340 *iter = *other;
341 }
342
343 G_DEFINE_BOXED_TYPE (GWin32RegistryValueIter, g_win32_registry_value_iter,
344 g_win32_registry_value_iter_copy,
345 g_win32_registry_value_iter_free)
346
347 /**
348 * SECTION:gwin32registrykey
349 * @title: GWin32RegistryKey
350 * @short_description: W32 registry access helper
351 * @include: gio/win32/gwin32registrykey.h
352 *
353 * #GWin32RegistryKey represents a single Windows Registry key.
354 *
355 * #GWin32RegistryKey is used by a number of helper functions that read
356 * Windows Registry. All keys are opened with read-only access, and at
357 * the moment there is no API for writing into registry keys or creating
358 * new ones.
359 *
360 * #GWin32RegistryKey implements the #GInitable interface, so if it is manually
361 * constructed by e.g. g_object_new() you must call g_initable_init() and check
362 * the results before using the object. This is done automatically
363 * in g_win32_registry_key_new() and g_win32_registry_key_get_child(), so these
364 * functions can return %NULL.
365 *
366 * To increase efficiency, a UTF-16 variant is available for all functions
367 * that deal with key or value names in the registry. Use these to perform
368 * deep registry queries or other operations that require querying a name
369 * of a key or a value and then opening it (or querying its data). The use
370 * of UTF-16 functions avoids the overhead of converting names to UTF-8 and
371 * back.
372 *
373 * All functions operate in current user's context (it is not possible to
374 * access registry tree of a different user).
375 *
376 * Key paths must use '\\' as a separator, '/' is not supported. Key names
377 * must not include '\\', because it's used as a separator. Value names
378 * can include '\\'.
379 *
380 * Key and value names are not case sensitive.
381 *
382 * Full key name (excluding the pre-defined ancestor's name) can't exceed
383 * 255 UTF-16 characters, give or take. Value name can't exceed 16383 UTF-16
384 * characters. Tree depth is limited to 512 levels.
385 **/
386
387 struct _GWin32RegistryKeyPrivate {
388 /* Ancestor of this key. May not be the immediate parent, because
389 * RegOpenKeyEx() allows grand*-children to be opened transitively.
390 * May be NULL.
391 */
392 GWin32RegistryKey *ancestor;
393
394 /* Handle to the key */
395 HKEY handle;
396
397 /* Full absolute path of the key, in UTF-16. Always allocated.
398 * Can become out of sync if the key is renamed from while we have it
399 * open, check watch_indicator to see if anything changed.
400 */
401 gunichar2 *absolute_path_w;
402
403 /* Full absolute path of the key, in UTF-8. Allocated when needed by
404 * converting the UTF-16 value from absolute_path_w. */
405 gchar *absolute_path;
406
407 /* TRUE if this object represents one of the pre-defined keys
408 * (and thus must not be closed).
409 */
410 gboolean predefined;
411
412 /* Set to G_WIN32_KEY_UNWATCHED if the key is not being watched.
413 * Set to G_WIN32_KEY_WATCHED when the key is put on watch notification.
414 */
415 gint watch_indicator;
416
417 /* Set to G_WIN32_KEY_UNKNOWN while the key is not being watched.
418 * Set to G_WIN32_KEY_UNCHANGED once the key is put under watch.
419 * Set to G_WIN32_KEY_CHANGED by the watch notification APC on key change.
420 */
421 gint change_indicator;
422
423 /* Unset after the key is changed, individual bits are set when their
424 * respective key parameters are updated from the registry.
425 * This prevents GLib from re-querying things like key name each time
426 * one is requested by the client while key is in G_WIN32_KEY_CHANGED state.
427 */
428 GWin32RegistryKeyUpdateFlag update_flags;
429
430 GWin32RegistryKeyWatchCallbackFunc callback;
431
432 gpointer user_data;
433 };
434
435 static void g_win32_registry_key_initable_iface_init (GInitableIface *iface);
436 static gboolean g_win32_registry_key_initable_init (GInitable *initable,
437 GCancellable *cancellable,
438 GError **error);
439
440 G_DEFINE_TYPE_WITH_CODE (GWin32RegistryKey, g_win32_registry_key, G_TYPE_OBJECT,
441 G_ADD_PRIVATE (GWin32RegistryKey)
442 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
443 g_win32_registry_key_initable_iface_init));
444
445 static void
g_win32_registry_key_dispose(GObject * object)446 g_win32_registry_key_dispose (GObject *object)
447 {
448 GWin32RegistryKey *key;
449 GWin32RegistryKeyPrivate *priv;
450
451 key = G_WIN32_REGISTRY_KEY (object);
452 priv = key->priv;
453
454 g_clear_object (&priv->ancestor);
455 g_clear_pointer (&priv->absolute_path_w, g_free);
456 g_clear_pointer (&priv->absolute_path, g_free);
457
458 if (!priv->predefined && priv->handle != INVALID_HANDLE_VALUE)
459 {
460 RegCloseKey (priv->handle);
461 priv->handle = INVALID_HANDLE_VALUE;
462 }
463
464 G_OBJECT_CLASS (g_win32_registry_key_parent_class)->dispose (object);
465 }
466
467 /**
468 * g_win32_registry_key_new:
469 * @path: absolute full name of a key to open (in UTF-8)
470 * @error: (nullable): a pointer to a %NULL #GError, or %NULL
471 *
472 * Creates an object that represents a registry key specified by @path.
473 * @path must start with one of the following pre-defined names:
474 * - HKEY_CLASSES_ROOT
475 * - HKEY_CURRENT_CONFIG
476 * - HKEY_CURRENT_USER
477 * - HKEY_CURRENT_USER_LOCAL_SETTINGS
478 * - HKEY_LOCAL_MACHINE
479 * - HKEY_PERFORMANCE_DATA
480 * - HKEY_PERFORMANCE_NLSTEXT
481 * - HKEY_PERFORMANCE_TEXT
482 * - HKEY_USERS
483 * @path must not end with '\\'.
484 *
485 * Returns: (nullable) (transfer full): a #GWin32RegistryKey or %NULL if can't
486 * be opened. Free with g_object_unref().
487 */
488 GWin32RegistryKey *
g_win32_registry_key_new(const gchar * path,GError ** error)489 g_win32_registry_key_new (const gchar *path,
490 GError **error)
491 {
492 g_return_val_if_fail (path != NULL, NULL);
493
494 return g_initable_new (G_TYPE_WIN32_REGISTRY_KEY,
495 NULL,
496 error,
497 "path",
498 path,
499 NULL);
500 }
501
502 /**
503 * g_win32_registry_key_new_w:
504 * @path: (in) (transfer none): absolute full name of a key to open (in UTF-16)
505 * @error: (inout) (optional) (nullable): a pointer to a %NULL #GError, or %NULL
506 *
507 * Creates an object that represents a registry key specified by @path.
508 * @path must start with one of the following pre-defined names:
509 * - HKEY_CLASSES_ROOT
510 * - HKEY_CURRENT_CONFIG
511 * - HKEY_CURRENT_USER
512 * - HKEY_CURRENT_USER_LOCAL_SETTINGS
513 * - HKEY_LOCAL_MACHINE
514 * - HKEY_PERFORMANCE_DATA
515 * - HKEY_PERFORMANCE_NLSTEXT
516 * - HKEY_PERFORMANCE_TEXT
517 * - HKEY_USERS
518 * @path must not end with L'\\'.
519 *
520 * Returns: (nullable) (transfer full): a #GWin32RegistryKey or %NULL if can't
521 * be opened. Free with g_object_unref().
522 */
523 GWin32RegistryKey *
g_win32_registry_key_new_w(const gunichar2 * path,GError ** error)524 g_win32_registry_key_new_w (const gunichar2 *path,
525 GError **error)
526 {
527 GObject *result;
528
529 g_return_val_if_fail (path != NULL, NULL);
530
531 result = g_initable_new (G_TYPE_WIN32_REGISTRY_KEY,
532 NULL,
533 error,
534 "path-utf16",
535 g_wcsdup (path, -1),
536 NULL);
537
538 return result ? G_WIN32_REGISTRY_KEY (result) : NULL;
539 }
540
541 static void
g_win32_registry_key_initable_iface_init(GInitableIface * iface)542 g_win32_registry_key_initable_iface_init (GInitableIface *iface)
543 {
544 iface->init = g_win32_registry_key_initable_init;
545 }
546
547 static gboolean
g_win32_registry_key_initable_init(GInitable * initable,GCancellable * cancellable,GError ** error)548 g_win32_registry_key_initable_init (GInitable *initable,
549 GCancellable *cancellable,
550 GError **error)
551 {
552 GWin32RegistryKey *key;
553 GWin32RegistryKeyPrivate *priv;
554 gunichar2 *path;
555 gunichar2 *first_chunk_end;
556 gsize first_chunk_len;
557 gunichar2 *second_chunk_begin;
558 gunichar2 *first_chunk;
559 HKEY ancestor;
560 HKEY key_handle;
561 LONG opened;
562
563 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (initable), FALSE);
564 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
565
566 key = G_WIN32_REGISTRY_KEY (initable);
567 priv = key->priv;
568
569 if (priv->absolute_path_w == NULL)
570 {
571 priv->absolute_path_w = g_utf8_to_utf16 (priv->absolute_path,
572 -1,
573 NULL,
574 NULL,
575 error);
576
577 if (priv->absolute_path_w == NULL)
578 return FALSE;
579 }
580
581 path = priv->absolute_path_w;
582
583 first_chunk_end = wcschr (path, L'\\');
584
585 if (first_chunk_end == NULL)
586 first_chunk_end = &path[wcslen (path)];
587
588 first_chunk_len = first_chunk_end - path;
589 first_chunk = g_wcsdup (path, -1);
590 first_chunk[first_chunk_len] = L'\0';
591 if (wcscmp (first_chunk, L"HKEY_CLASSES_ROOT") == 0)
592 ancestor = HKEY_CLASSES_ROOT;
593 else if (wcscmp (first_chunk, L"HKEY_LOCAL_MACHINE") == 0)
594 ancestor = HKEY_LOCAL_MACHINE;
595 else if (wcscmp (first_chunk, L"HKEY_CURRENT_USER") == 0)
596 ancestor = HKEY_CURRENT_USER;
597 else if (wcscmp (first_chunk, L"HKEY_CURRENT_CONFIG") == 0)
598 ancestor = HKEY_CURRENT_CONFIG;
599 else if (wcscmp (first_chunk, L"HKEY_CURRENT_USER_LOCAL_SETTINGS") == 0)
600 ancestor = HKEY_CURRENT_USER_LOCAL_SETTINGS;
601 else if (wcscmp (first_chunk, L"HKEY_USERS") == 0)
602 ancestor = HKEY_USERS;
603 else if (wcscmp (first_chunk, L"HKEY_PERFORMANCE_DATA") == 0)
604 ancestor = HKEY_PERFORMANCE_DATA;
605 else if (wcscmp (first_chunk, L"HKEY_PERFORMANCE_NLSTEXT") == 0)
606 ancestor = HKEY_PERFORMANCE_NLSTEXT;
607 else if (wcscmp (first_chunk, L"HKEY_PERFORMANCE_TEXT") == 0)
608 ancestor = HKEY_PERFORMANCE_TEXT;
609 else
610 {
611 g_critical ("Root key '%S' is not a pre-defined key", first_chunk);
612 g_free (first_chunk);
613 return FALSE;
614 }
615
616 g_free (first_chunk);
617
618 second_chunk_begin = first_chunk_end;
619
620 while (second_chunk_begin[0] != L'\0' && second_chunk_begin[0] == L'\\')
621 second_chunk_begin++;
622
623 if (second_chunk_begin != first_chunk_end && second_chunk_begin[0] == L'\0')
624 {
625 g_critical ("Key name '%S' ends with '\\'", path);
626 return FALSE;
627 }
628
629 opened = RegOpenKeyExW (ancestor, second_chunk_begin, 0, KEY_READ, &key_handle);
630
631 if (opened != ERROR_SUCCESS)
632 {
633 g_set_error (error, G_IO_ERROR, g_io_error_from_win32_error (opened),
634 "Failed to open registry key '%S'", path);
635 return FALSE;
636 }
637
638 priv->ancestor = NULL;
639 priv->handle = key_handle;
640 priv->predefined = (second_chunk_begin[0] == L'\0');
641
642 return TRUE;
643 }
644
645 /**
646 * g_win32_registry_key_get_child:
647 * @key: (in) (transfer none): a parent #GWin32RegistryKey
648 * @subkey: (in) (transfer none): name of a child key to open (in UTF-8), relative to @key
649 * @error: (inout) (optional) (nullable): a pointer to a %NULL #GError, or %NULL
650 *
651 * Opens a @subkey of the @key.
652 *
653 * Returns: (nullable): a #GWin32RegistryKey or %NULL if can't be opened. Free
654 * with g_object_unref().
655 */
656 GWin32RegistryKey *
g_win32_registry_key_get_child(GWin32RegistryKey * key,const gchar * subkey,GError ** error)657 g_win32_registry_key_get_child (GWin32RegistryKey *key,
658 const gchar *subkey,
659 GError **error)
660 {
661 gunichar2 *subkey_w;
662 GWin32RegistryKey *result = NULL;
663
664 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), NULL);
665 g_return_val_if_fail (subkey != NULL, NULL);
666 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
667
668 subkey_w = g_utf8_to_utf16 (subkey, -1, NULL, NULL, error);
669
670 if (subkey_w != NULL)
671 {
672 result = g_win32_registry_key_get_child_w (key, subkey_w, error);
673 g_free (subkey_w);
674 }
675
676 return result;
677 }
678
679 /**
680 * g_win32_registry_key_get_child_w:
681 * @key: (in) (transfer none): a parent #GWin32RegistryKey
682 * @subkey: (in) (transfer none): name of a child key to open (in UTF-8), relative to @key
683 * @error: (inout) (optional) (nullable): a pointer to a %NULL #GError, or %NULL
684 *
685 * Opens a @subkey of the @key.
686 *
687 * Returns: (nullable): a #GWin32RegistryKey or %NULL if can't be opened. Free
688 * with g_object_unref().
689 */
690 GWin32RegistryKey *
g_win32_registry_key_get_child_w(GWin32RegistryKey * key,const gunichar2 * subkey,GError ** error)691 g_win32_registry_key_get_child_w (GWin32RegistryKey *key,
692 const gunichar2 *subkey,
693 GError **error)
694 {
695 HKEY key_handle;
696 LONG opened;
697 const gunichar2 *end_of_subkey;
698 gsize subkey_len;
699 GWin32RegistryKey *result;
700 const gunichar2 *key_path;
701
702 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), NULL);
703 g_return_val_if_fail (subkey != NULL, NULL);
704 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
705
706 if (subkey[0] == L'\\')
707 {
708 g_critical ("Subkey name '%S' starts with '\\'", subkey);
709 return NULL;
710 }
711
712 subkey_len = wcslen (subkey);
713 end_of_subkey = &subkey[subkey_len];
714
715 if (subkey_len == 0)
716 end_of_subkey = subkey;
717
718 if (end_of_subkey[0] == L'\\')
719 {
720 g_critical ("Subkey name '%S' ends with '\\'", subkey);
721 return NULL;
722 }
723
724 key_path = g_win32_registry_key_get_path_w (key);
725 opened = RegOpenKeyExW (key->priv->handle, subkey, 0, KEY_READ, &key_handle);
726
727 if (opened != ERROR_SUCCESS)
728 {
729 g_set_error (error, G_IO_ERROR, g_io_error_from_win32_error (opened),
730 "Failed to open registry subkey '%S' of key '%S'",
731 subkey, key_path);
732 return NULL;
733 }
734
735 result = g_object_new (G_TYPE_WIN32_REGISTRY_KEY, NULL);
736
737 result->priv->handle = key_handle;
738 result->priv->absolute_path_w =
739 g_malloc ((wcslen (key_path) + 2 + subkey_len) * sizeof (gunichar2));
740 result->priv->absolute_path_w[0] = L'\0';
741 wcscat (&result->priv->absolute_path_w[0], key_path);
742 wcscat (&result->priv->absolute_path_w[wcslen (key_path)], L"\\");
743 wcscat (&result->priv->absolute_path_w[wcslen (key_path) + 1], subkey);
744 result->priv->predefined = (subkey[0] == L'\0' && key->priv->predefined);
745
746 if (subkey[0] != L'\0')
747 result->priv->ancestor = g_object_ref (key);
748 else
749 result->priv->ancestor = NULL;
750
751 result->priv->change_indicator = G_WIN32_KEY_UNKNOWN;
752
753 return result;
754 }
755
756 /**
757 * g_win32_registry_subkey_iter_init:
758 * @iter: (in) (transfer none): a pointer to a #GWin32RegistrySubkeyIter
759 * @key: (in) (transfer none): a #GWin32RegistryKey to iterate over
760 * @error: (inout) (optional) (nullable): a pointer to %NULL #GError, or %NULL
761 *
762 * Initialises (without allocating) a #GWin32RegistrySubkeyIter. @iter may be
763 * completely uninitialised prior to this call; its old value is
764 * ignored.
765 *
766 * The iterator remains valid for as long as @key exists.
767 * Clean up its internal buffers with a call to
768 * g_win32_registry_subkey_iter_clear() when done.
769 *
770 * Returns: %TRUE if iterator was initialized successfully, %FALSE on error.
771 *
772 * Since: 2.46
773 **/
774 gboolean
g_win32_registry_subkey_iter_init(GWin32RegistrySubkeyIter * iter,GWin32RegistryKey * key,GError ** error)775 g_win32_registry_subkey_iter_init (GWin32RegistrySubkeyIter *iter,
776 GWin32RegistryKey *key,
777 GError **error)
778 {
779 LONG status;
780 DWORD subkey_count;
781 DWORD max_subkey_len;
782
783 g_return_val_if_fail (iter != NULL, FALSE);
784 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), FALSE);
785 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
786
787 status = RegQueryInfoKeyW (key->priv->handle,
788 NULL, NULL, NULL,
789 &subkey_count, &max_subkey_len,
790 NULL, NULL, NULL, NULL, NULL, NULL);
791
792 if (status != ERROR_SUCCESS)
793 {
794 g_set_error (error, G_IO_ERROR, g_io_error_from_win32_error (status),
795 "Failed to query info for registry key '%S'",
796 g_win32_registry_key_get_path_w (key));
797 return FALSE;
798 }
799
800 iter->key = g_object_ref (key);
801 iter->counter = -1;
802 iter->subkey_count = subkey_count;
803 iter->subkey_name_size = sizeof (gunichar2) * (max_subkey_len + 1);
804 iter->subkey_name = g_malloc (iter->subkey_name_size);
805 iter->subkey_name_u8 = NULL;
806
807 return TRUE;
808 }
809
810 /**
811 * g_win32_registry_subkey_iter_clear:
812 * @iter: (in) (transfer none): a #GWin32RegistrySubkeyIter
813 *
814 * Frees internal buffers of a #GWin32RegistrySubkeyIter.
815 *
816 * Since: 2.46
817 **/
818 void
g_win32_registry_subkey_iter_clear(GWin32RegistrySubkeyIter * iter)819 g_win32_registry_subkey_iter_clear (GWin32RegistrySubkeyIter *iter)
820 {
821 g_return_if_fail (iter != NULL);
822
823 g_free (iter->subkey_name);
824 g_free (iter->subkey_name_u8);
825 g_clear_object (&iter->key);
826 }
827
828 /**
829 * g_win32_registry_subkey_iter_n_subkeys:
830 * @iter: (in) (transfer none): a #GWin32RegistrySubkeyIter
831 *
832 * Queries the number of subkeys items in the key that we are
833 * iterating over. This is the total number of subkeys -- not the number
834 * of items remaining.
835 *
836 * This information is accurate at the point of iterator initialization,
837 * and may go out of sync with reality even while subkeys are enumerated.
838 *
839 * Returns: the number of subkeys in the key
840 *
841 * Since: 2.46
842 **/
843 gsize
g_win32_registry_subkey_iter_n_subkeys(GWin32RegistrySubkeyIter * iter)844 g_win32_registry_subkey_iter_n_subkeys (GWin32RegistrySubkeyIter *iter)
845 {
846 g_return_val_if_fail (iter != NULL, 0);
847
848 return iter->subkey_count;
849 }
850
851 /**
852 * g_win32_registry_subkey_iter_next:
853 * @iter: (in) (transfer none): a #GWin32RegistrySubkeyIter
854 * @skip_errors: (in): %TRUE if iterator should silently ignore errors (such as
855 * the actual number of subkeys being less than expected) and
856 * proceed forward
857 * @error: (nullable): a pointer to %NULL #GError, or %NULL
858 *
859 * Moves iterator to the next subkey.
860 * Enumeration errors can be ignored if @skip_errors is %TRUE
861 *
862 * Here is an example for iterating with g_win32_registry_subkey_iter_next():
863 * |[<!-- language="C" -->
864 * // recursively iterate a key
865 * void
866 * iterate_key_recursive (GWin32RegistryKey *key)
867 * {
868 * GWin32RegistrySubkeyIter iter;
869 * gchar *name;
870 * GWin32RegistryKey *child;
871 *
872 * if (!g_win32_registry_subkey_iter_init (&iter, key, NULL))
873 * return;
874 *
875 * while (g_win32_registry_subkey_iter_next (&iter, TRUE, NULL))
876 * {
877 * if (!g_win32_registry_subkey_iter_get_name (&iter, &name, NULL, NULL))
878 * continue;
879 *
880 * g_print ("subkey '%s'\n", name);
881 * child = g_win32_registry_key_get_child (key, name, NULL);
882 *
883 * if (child)
884 * iterate_key_recursive (child);
885 * }
886 *
887 * g_win32_registry_subkey_iter_clear (&iter);
888 * }
889 * ]|
890 *
891 * Returns: %TRUE if next subkey info was retrieved, %FALSE otherwise.
892 *
893 * Since: 2.46
894 **/
895 gboolean
g_win32_registry_subkey_iter_next(GWin32RegistrySubkeyIter * iter,gboolean skip_errors,GError ** error)896 g_win32_registry_subkey_iter_next (GWin32RegistrySubkeyIter *iter,
897 gboolean skip_errors,
898 GError **error)
899 {
900 LONG status;
901 DWORD subkey_len;
902
903 g_return_val_if_fail (iter != NULL, FALSE);
904 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
905
906 if G_UNLIKELY (iter->counter >= iter->subkey_count)
907 {
908 g_critical ("g_win32_registry_subkey_iter_get_next_w: must not be called again "
909 "after FALSE has already been returned.");
910 return FALSE;
911 }
912
913 while (TRUE)
914 {
915 iter->counter += 1;
916
917 if (iter->counter >= iter->subkey_count)
918 return FALSE;
919
920 /* Including 0-terminator */
921 subkey_len = iter->subkey_name_size;
922 status = RegEnumKeyExW (iter->key->priv->handle,
923 iter->counter,
924 iter->subkey_name,
925 &subkey_len,
926 NULL, NULL, NULL, NULL);
927
928 if (status == ERROR_SUCCESS)
929 {
930 iter->subkey_name_len = subkey_len;
931
932 return TRUE;
933 }
934
935 if (!skip_errors)
936 {
937 g_set_error (error, G_IO_ERROR, g_io_error_from_win32_error (status),
938 "Failed to enumerate subkey #%d for key '%S'",
939 iter->counter, g_win32_registry_key_get_path_w (iter->key));
940 iter->subkey_count = 0;
941
942 return FALSE;
943 }
944 }
945 }
946
947 /**
948 * g_win32_registry_subkey_iter_get_name_w:
949 * @iter: (in) (transfer none): a #GWin32RegistrySubkeyIter
950 * @subkey_name: (out callee-allocates) (transfer none): Pointer to a location
951 * to store the name of a subkey (in UTF-16).
952 * @subkey_name_len: (out) (optional) (transfer none): Pointer to a location
953 * to store the length of @subkey_name, in gunichar2s, excluding
954 * NUL-terminator.
955 * %NULL if length is not needed.
956 * @error: (nullable): a pointer to %NULL #GError, or %NULL
957 *
958 * Same as g_win32_registry_subkey_iter_get_next(), but outputs UTF-16-encoded
959 * data, without converting it to UTF-8 first.
960 *
961 * Returns: %TRUE if the name was retrieved, %FALSE otherwise.
962 *
963 * Since: 2.46
964 **/
965 gboolean
g_win32_registry_subkey_iter_get_name_w(GWin32RegistrySubkeyIter * iter,gunichar2 ** subkey_name,gsize * subkey_name_len,GError ** error)966 g_win32_registry_subkey_iter_get_name_w (GWin32RegistrySubkeyIter *iter,
967 gunichar2 **subkey_name,
968 gsize *subkey_name_len,
969 GError **error)
970 {
971 g_return_val_if_fail (iter != NULL, FALSE);
972 g_return_val_if_fail (subkey_name != NULL, FALSE);
973 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
974
975 if G_UNLIKELY (iter->counter >= iter->subkey_count)
976 {
977 g_critical ("g_win32_registry_subkey_iter_get_name_w: must not be called "
978 "after FALSE has already been returned by "
979 "g_win32_registry_subkey_iter_next.");
980 return FALSE;
981 }
982
983 *subkey_name = iter->subkey_name;
984
985 if (subkey_name_len)
986 *subkey_name_len = iter->subkey_name_len;
987
988 return TRUE;
989 }
990
991 /**
992 * g_win32_registry_subkey_iter_get_name:
993 * @iter: (in) (transfer none): a #GWin32RegistrySubkeyIter
994 * @subkey_name: (out callee-allocates) (transfer none): Pointer to a location
995 * to store the name of a subkey (in UTF-8). Free with g_free().
996 * @subkey_name_len: (out) (optional): Pointer to a location to store the
997 * length of @subkey_name, in gchars, excluding NUL-terminator.
998 * %NULL if length is not needed.
999 * @error: (nullable): a pointer to %NULL #GError, or %NULL
1000 *
1001 * Gets the name of the subkey at the @iter potision.
1002 *
1003 * Returns: %TRUE if the name was retrieved, %FALSE otherwise.
1004 *
1005 * Since: 2.46
1006 **/
1007 gboolean
g_win32_registry_subkey_iter_get_name(GWin32RegistrySubkeyIter * iter,gchar ** subkey_name,gsize * subkey_name_len,GError ** error)1008 g_win32_registry_subkey_iter_get_name (GWin32RegistrySubkeyIter *iter,
1009 gchar **subkey_name,
1010 gsize *subkey_name_len,
1011 GError **error)
1012 {
1013 glong subkey_name_len_glong;
1014
1015 g_return_val_if_fail (iter != NULL, FALSE);
1016 g_return_val_if_fail (subkey_name != NULL, FALSE);
1017 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1018
1019 if G_UNLIKELY (iter->counter >= iter->subkey_count)
1020 {
1021 g_critical ("g_win32_registry_subkey_iter_get_name_w: must not be called "
1022 "after FALSE has already been returned by "
1023 "g_win32_registry_subkey_iter_next.");
1024 return FALSE;
1025 }
1026
1027 g_clear_pointer (&iter->subkey_name_u8, g_free);
1028 iter->subkey_name_u8 = g_utf16_to_utf8 (iter->subkey_name,
1029 iter->subkey_name_len,
1030 NULL,
1031 &subkey_name_len_glong,
1032 error);
1033
1034 if (iter->subkey_name_u8 != NULL)
1035 {
1036 *subkey_name_len = subkey_name_len_glong;
1037 return TRUE;
1038 }
1039
1040 return FALSE;
1041 }
1042
1043 /**
1044 * g_win32_registry_value_iter_init:
1045 * @iter: (in) (transfer none): a pointer to a #GWin32RegistryValueIter
1046 * @key: (in) (transfer none): a #GWin32RegistryKey to iterate over
1047 * @error: (nullable): a pointer to %NULL #GError, or %NULL
1048 *
1049 * Initialises (without allocating) a #GWin32RegistryValueIter. @iter may be
1050 * completely uninitialised prior to this call; its old value is
1051 * ignored.
1052 *
1053 * The iterator remains valid for as long as @key exists.
1054 * Clean up its internal buffers with a call to
1055 * g_win32_registry_value_iter_clear() when done.
1056 *
1057 * Returns: %TRUE if iterator was initialized successfully, %FALSE on error.
1058 *
1059 * Since: 2.46
1060 **/
1061 gboolean
g_win32_registry_value_iter_init(GWin32RegistryValueIter * iter,GWin32RegistryKey * key,GError ** error)1062 g_win32_registry_value_iter_init (GWin32RegistryValueIter *iter,
1063 GWin32RegistryKey *key,
1064 GError **error)
1065 {
1066 LONG status;
1067 DWORD value_count;
1068 DWORD max_value_len;
1069 DWORD max_data_len;
1070
1071 g_return_val_if_fail (iter != NULL, FALSE);
1072 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), FALSE);
1073 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1074
1075 status = RegQueryInfoKeyW (key->priv->handle,
1076 NULL, NULL, NULL, NULL, NULL, NULL,
1077 &value_count, &max_value_len,
1078 &max_data_len, NULL, NULL);
1079
1080 if (status != ERROR_SUCCESS)
1081 {
1082 g_set_error (error, G_IO_ERROR, g_io_error_from_win32_error (status),
1083 "Failed to query info for registry key '%S'",
1084 g_win32_registry_key_get_path_w (key));
1085 return FALSE;
1086 }
1087
1088 iter->key = g_object_ref (key);
1089 iter->counter = -1;
1090 iter->value_count = value_count;
1091 iter->value_name_size = sizeof (gunichar2) * (max_value_len + 1);
1092 iter->value_name = g_malloc (iter->value_name_size);
1093 /* FIXME: max_value_data_len is said to have no size limit in newer W32
1094 * versions (and its size limit in older ones is 1MB!). Consider limiting it
1095 * with a hard-coded value, or by allowing the user to choose a limit.
1096 */
1097 /* Two extra gunichar2s is for cases when a string was stored in the
1098 * Registry without a 0-terminator (for multiline strings - 00-terminator),
1099 * and we need to terminate it ourselves.
1100 */
1101 iter->value_data_size = max_data_len + sizeof (gunichar2) * 2;
1102 iter->value_data = g_malloc (iter->value_data_size);
1103 iter->value_name_u8 = NULL;
1104 iter->value_data_u8 = NULL;
1105 iter->value_data_expanded = NULL;
1106 iter->value_data_expanded_charsize = 0;
1107 iter->value_data_expanded_u8 = NULL;
1108 iter->value_data_expanded_u8_size = 0;
1109 return TRUE;
1110 }
1111
1112 /**
1113 * g_win32_registry_value_iter_clear:
1114 * @iter: (in) (transfer none): a #GWin32RegistryValueIter
1115 *
1116 * Frees internal buffers of a #GWin32RegistryValueIter.
1117 *
1118 * Since: 2.46
1119 **/
1120 void
g_win32_registry_value_iter_clear(GWin32RegistryValueIter * iter)1121 g_win32_registry_value_iter_clear (GWin32RegistryValueIter *iter)
1122 {
1123 g_return_if_fail (iter != NULL);
1124
1125 g_free (iter->value_name);
1126 g_free (iter->value_data);
1127 g_free (iter->value_name_u8);
1128 g_free (iter->value_data_u8);
1129 g_free (iter->value_data_expanded);
1130 g_free (iter->value_data_expanded_u8);
1131 g_clear_object (&iter->key);
1132 }
1133
1134 /**
1135 * g_win32_registry_value_iter_n_values:
1136 * @iter: (in) (transfer none): a #GWin32RegistryValueIter
1137 *
1138 * Queries the number of values items in the key that we are
1139 * iterating over. This is the total number of values -- not the number
1140 * of items remaining.
1141 *
1142 * This information is accurate at the point of iterator initialization,
1143 * and may go out of sync with reality even while values are enumerated.
1144 *
1145 * Returns: the number of values in the key
1146 *
1147 * Since: 2.46
1148 **/
1149 gsize
g_win32_registry_value_iter_n_values(GWin32RegistryValueIter * iter)1150 g_win32_registry_value_iter_n_values (GWin32RegistryValueIter *iter)
1151 {
1152 g_return_val_if_fail (iter != NULL, 0);
1153
1154 return iter->value_count;
1155 }
1156
1157 static GWin32RegistryValueType
_g_win32_registry_type_w_to_g(DWORD value_type)1158 _g_win32_registry_type_w_to_g (DWORD value_type)
1159 {
1160 switch (value_type)
1161 {
1162 case REG_BINARY:
1163 return G_WIN32_REGISTRY_VALUE_BINARY;
1164 case REG_DWORD:
1165 return G_WIN32_REGISTRY_VALUE_UINT32;
1166 #if G_BYTE_ORDER == G_BIG_ENDIAN
1167 case REG_DWORD_LITTLE_ENDIAN:
1168 return G_WIN32_REGISTRY_VALUE_UINT32LE;
1169 #else
1170 case REG_DWORD_BIG_ENDIAN:
1171 return G_WIN32_REGISTRY_VALUE_UINT32BE;
1172 #endif
1173 case REG_EXPAND_SZ:
1174 return G_WIN32_REGISTRY_VALUE_EXPAND_STR;
1175 case REG_LINK:
1176 return G_WIN32_REGISTRY_VALUE_LINK;
1177 case REG_MULTI_SZ:
1178 return G_WIN32_REGISTRY_VALUE_MULTI_STR;
1179 case REG_NONE:
1180 return G_WIN32_REGISTRY_VALUE_NONE;
1181 case REG_QWORD:
1182 return G_WIN32_REGISTRY_VALUE_UINT64;
1183 #if G_BYTE_ORDER == G_BIG_ENDIAN
1184 case REG_QWORD_LITTLE_ENDIAN:
1185 return G_WIN32_REGISTRY_VALUE_UINT64LE;
1186 #endif
1187 case REG_SZ:
1188 return G_WIN32_REGISTRY_VALUE_STR;
1189 default:
1190 return G_WIN32_REGISTRY_VALUE_NONE;
1191 }
1192 }
1193
1194 static gsize
ensure_nul_termination(GWin32RegistryValueType value_type,guint8 * value_data,gsize value_data_size)1195 ensure_nul_termination (GWin32RegistryValueType value_type,
1196 guint8 *value_data,
1197 gsize value_data_size)
1198 {
1199 gsize new_size = value_data_size;
1200
1201 if (value_type == G_WIN32_REGISTRY_VALUE_EXPAND_STR ||
1202 value_type == G_WIN32_REGISTRY_VALUE_LINK ||
1203 value_type == G_WIN32_REGISTRY_VALUE_STR)
1204 {
1205 if ((value_data_size < 2) ||
1206 (value_data[value_data_size - 1] != 0) ||
1207 (value_data[value_data_size - 2] != 0))
1208 {
1209 value_data[value_data_size] = 0;
1210 value_data[value_data_size + 1] = 0;
1211 new_size += 2;
1212 }
1213 }
1214 else if (value_type == G_WIN32_REGISTRY_VALUE_MULTI_STR)
1215 {
1216 if ((value_data_size < 4) ||
1217 (value_data[value_data_size - 1] != 0) ||
1218 (value_data[value_data_size - 2] != 0) ||
1219 (value_data[value_data_size - 3] != 0) ||
1220 (value_data[value_data_size - 4] != 0))
1221 {
1222 value_data[value_data_size] = 0;
1223 value_data[value_data_size + 1] = 0;
1224 value_data[value_data_size + 2] = 0;
1225 value_data[value_data_size + 3] = 0;
1226 new_size += 4;
1227 }
1228 }
1229
1230 return new_size;
1231 }
1232
1233 /**
1234 * g_win32_registry_value_iter_next:
1235 * @iter: (in) (transfer none): a #GWin32RegistryValueIter
1236 * @skip_errors: (in): %TRUE if iterator should silently ignore errors (such as
1237 * the actual number of values being less than expected) and
1238 * proceed forward
1239 * @error: (nullable): a pointer to %NULL #GError, or %NULL
1240 *
1241 * Advances iterator to the next value in the key. If no more values remain then
1242 * FALSE is returned.
1243 * Enumeration errors can be ignored if @skip_errors is %TRUE
1244 *
1245 * Here is an example for iterating with g_win32_registry_value_iter_next():
1246 * |[<!-- language="C" -->
1247 * // iterate values of a key
1248 * void
1249 * iterate_values_recursive (GWin32RegistryKey *key)
1250 * {
1251 * GWin32RegistryValueIter iter;
1252 * gchar *name;
1253 * GWin32RegistryValueType val_type;
1254 * gchar *val_data;
1255 *
1256 * if (!g_win32_registry_value_iter_init (&iter, key, NULL))
1257 * return;
1258 *
1259 * while (g_win32_registry_value_iter_next (&iter, TRUE, NULL))
1260 * {
1261 * if ((!g_win32_registry_value_iter_get_value_type (&iter, &value)) ||
1262 * ((val_type != G_WIN32_REGISTRY_VALUE_STR) &&
1263 * (val_type != G_WIN32_REGISTRY_VALUE_EXPAND_STR)))
1264 * continue;
1265 *
1266 * if (g_win32_registry_value_iter_get_value (&iter, TRUE, &name, NULL,
1267 * &val_data, NULL, NULL))
1268 * g_print ("value '%s' = '%s'\n", name, val_data);
1269 * }
1270 *
1271 * g_win32_registry_value_iter_clear (&iter);
1272 * }
1273 * ]|
1274 *
1275 * Returns: %TRUE if next value info was retrieved, %FALSE otherwise.
1276 *
1277 * Since: 2.46
1278 **/
1279 gboolean
g_win32_registry_value_iter_next(GWin32RegistryValueIter * iter,gboolean skip_errors,GError ** error)1280 g_win32_registry_value_iter_next (GWin32RegistryValueIter *iter,
1281 gboolean skip_errors,
1282 GError **error)
1283 {
1284 LONG status;
1285 DWORD value_name_len_w;
1286 DWORD value_data_size_w;
1287 DWORD value_type_w;
1288 GWin32RegistryValueType value_type_g;
1289
1290 g_return_val_if_fail (iter != NULL, FALSE);
1291 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1292
1293 if G_UNLIKELY (iter->counter >= iter->value_count)
1294 {
1295 g_critical ("g_win32_registry_value_iter_next: must not be called "
1296 "again after FALSE has already been returned.");
1297 return FALSE;
1298 }
1299
1300 while (TRUE)
1301 {
1302 iter->counter += 1;
1303
1304 if (iter->counter >= iter->value_count)
1305 return FALSE;
1306
1307 g_clear_pointer (&iter->value_name_u8, g_free);
1308 g_clear_pointer (&iter->value_data_u8, g_free);
1309 g_clear_pointer (&iter->value_data_expanded_u8, g_free);
1310 /* Including 0-terminator */
1311 value_name_len_w = iter->value_name_size / sizeof (gunichar2);
1312 value_data_size_w = iter->value_data_size;
1313 status = RegEnumValueW (iter->key->priv->handle,
1314 iter->counter,
1315 iter->value_name,
1316 &value_name_len_w,
1317 NULL,
1318 &value_type_w,
1319 (LPBYTE) iter->value_data,
1320 &value_data_size_w);
1321
1322 if (status != ERROR_SUCCESS && !skip_errors)
1323 {
1324 g_set_error (error, G_IO_ERROR, g_io_error_from_win32_error (status),
1325 "Failed to enumerate value #%d for key '%S'",
1326 iter->counter, g_win32_registry_key_get_path_w (iter->key));
1327 iter->value_count = 0;
1328
1329 return FALSE;
1330 }
1331 else if (status != ERROR_SUCCESS && skip_errors)
1332 continue;
1333
1334 value_type_g = _g_win32_registry_type_w_to_g (value_type_w);
1335 value_data_size_w = ensure_nul_termination (value_type_g,
1336 iter->value_data,
1337 value_data_size_w);
1338 iter->value_type = value_type_g;
1339 iter->value_expanded_type = value_type_g;
1340 iter->value_actual_data_size = value_data_size_w;
1341 iter->value_name_len = value_name_len_w;
1342
1343 return TRUE;
1344 }
1345 }
1346
1347 /**
1348 * g_win32_registry_value_iter_get_value_type:
1349 * @iter: (in) (transfer none): a #GWin32RegistryValueIter
1350 * @value_type: (out): Pointer to a location to store the type of
1351 * the value.
1352 * @error: (nullable): a pointer to %NULL #GError, or %NULL
1353 *
1354 * Stores the type of the value currently being iterated over in @value_type.
1355 *
1356 * Returns: %TRUE if value type was retrieved, %FALSE otherwise.
1357 *
1358 * Since: 2.46
1359 **/
1360 gboolean
g_win32_registry_value_iter_get_value_type(GWin32RegistryValueIter * iter,GWin32RegistryValueType * value_type,GError ** error)1361 g_win32_registry_value_iter_get_value_type (GWin32RegistryValueIter *iter,
1362 GWin32RegistryValueType *value_type,
1363 GError **error)
1364 {
1365 g_return_val_if_fail (iter != NULL, FALSE);
1366 g_return_val_if_fail (value_type != NULL, FALSE);
1367 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1368
1369 if G_UNLIKELY (iter->counter >= iter->value_count)
1370 {
1371 g_critical ("g_win32_registry_value_iter_get_type: must not be called "
1372 "again after NULL has already been returned.");
1373 return FALSE;
1374 }
1375
1376 *value_type = iter->value_type;
1377
1378 return TRUE;
1379 }
1380
1381 /**
1382 * g_win32_registry_value_iter_get_name_w:
1383 * @iter: (in) (transfer none): a #GWin32RegistryValueIter
1384 * @value_name: (out callee-allocates) (transfer none): Pointer to a location
1385 * to store the name of a value (in UTF-16).
1386 * @value_name_len: (out) (optional): Pointer to a location to store the length
1387 * of @value_name, in gunichar2s, excluding NUL-terminator.
1388 * %NULL if length is not needed.
1389 * @error: (nullable): a pointer to %NULL #GError, or %NULL
1390 *
1391 * Stores the name of the value currently being iterated over in @value_name,
1392 * and its length - in @value_name (if not %NULL).
1393 *
1394 * Returns: %TRUE if value name was retrieved, %FALSE otherwise.
1395 *
1396 * Since: 2.46
1397 **/
1398 gboolean
g_win32_registry_value_iter_get_name_w(GWin32RegistryValueIter * iter,gunichar2 ** value_name,gsize * value_name_len,GError ** error)1399 g_win32_registry_value_iter_get_name_w (GWin32RegistryValueIter *iter,
1400 gunichar2 **value_name,
1401 gsize *value_name_len,
1402 GError **error)
1403 {
1404 g_return_val_if_fail (iter != NULL, FALSE);
1405 g_return_val_if_fail (value_name != NULL, FALSE);
1406 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1407
1408 if G_UNLIKELY (iter->counter >= iter->value_count)
1409 {
1410 g_critical ("g_win32_registry_value_iter_get_name_w: must not be called "
1411 "again after NULL has already been returned.");
1412 return FALSE;
1413 }
1414
1415 *value_name = iter->value_name;
1416
1417 if (value_name_len)
1418 *value_name_len = iter->value_name_len;
1419
1420 return TRUE;
1421 }
1422
1423 /**
1424 * g_win32_registry_value_iter_get_name:
1425 * @iter: (in) (transfer none): a #GWin32RegistryValueIter
1426 * @value_name: (out callee-allocates) (transfer none): Pointer to a location
1427 * to store the name of a value (in UTF-8).
1428 * @value_name_len: (out) (optional): Pointer to a location to store the length
1429 * of @value_name, in gchars, excluding NUL-terminator.
1430 * %NULL if length is not needed.
1431 * @error: (nullable): a pointer to %NULL #GError, or %NULL
1432 *
1433 * Stores the name of the value currently being iterated over in @value_name,
1434 * and its length - in @value_name_len (if not %NULL).
1435 *
1436 * Returns: %TRUE if value name was retrieved, %FALSE otherwise.
1437 *
1438 * Since: 2.46
1439 **/
1440 gboolean
g_win32_registry_value_iter_get_name(GWin32RegistryValueIter * iter,gchar ** value_name,gsize * value_name_len,GError ** error)1441 g_win32_registry_value_iter_get_name (GWin32RegistryValueIter *iter,
1442 gchar **value_name,
1443 gsize *value_name_len,
1444 GError **error)
1445 {
1446 glong value_name_len_glong;
1447
1448 g_return_val_if_fail (iter != NULL, FALSE);
1449 g_return_val_if_fail (value_name != NULL, FALSE);
1450 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1451
1452 if G_UNLIKELY (iter->counter >= iter->value_count)
1453 {
1454 g_critical ("g_win32_registry_value_iter_get_name: must not be called "
1455 "again after NULL has already been returned.");
1456 return FALSE;
1457 }
1458
1459 if (iter->value_name_u8 == NULL)
1460 {
1461 iter->value_name_u8 = g_utf16_to_utf8 (iter->value_name, iter->value_name_len, NULL,
1462 &value_name_len_glong, error);
1463
1464 if (iter->value_name_u8 == NULL)
1465 return FALSE;
1466 }
1467
1468 *value_name = iter->value_name_u8;
1469
1470 if (value_name_len)
1471 *value_name_len = iter->value_name_u8_len;
1472
1473 return TRUE;
1474 }
1475
1476 static gboolean
expand_value(gunichar2 * value,const gunichar2 * value_name,gpointer * expanded_value,gsize * expanded_charsize,GError ** error)1477 expand_value (gunichar2 *value,
1478 const gunichar2 *value_name,
1479 gpointer *expanded_value,
1480 gsize *expanded_charsize,
1481 GError **error)
1482 {
1483 DWORD value_data_expanded_charsize_w;
1484
1485 value_data_expanded_charsize_w =
1486 ExpandEnvironmentStringsW (value,
1487 (gunichar2 *) *expanded_value,
1488 *expanded_charsize);
1489
1490 if (value_data_expanded_charsize_w > *expanded_charsize)
1491 {
1492 *expanded_value = g_realloc (*expanded_value,
1493 value_data_expanded_charsize_w * sizeof (gunichar2));
1494 *expanded_charsize = value_data_expanded_charsize_w;
1495 value_data_expanded_charsize_w =
1496 ExpandEnvironmentStringsW (value,
1497 (gunichar2 *) *expanded_value,
1498 *expanded_charsize);
1499 }
1500
1501 if (value_data_expanded_charsize_w == 0)
1502 {
1503 g_set_error (error, G_IO_ERROR,
1504 g_io_error_from_win32_error (GetLastError ()),
1505 "Failed to expand data '%S' of value %S",
1506 value, value_name);
1507 return FALSE;
1508 }
1509
1510 return TRUE;
1511 }
1512
1513 /**
1514 * g_win32_registry_value_iter_get_data_w:
1515 * @iter: (in) (transfer none): a #GWin32RegistryValueIter
1516 * @auto_expand: (in): %TRUE to automatically expand G_WIN32_REGISTRY_VALUE_EXPAND_STR to
1517 * G_WIN32_REGISTRY_VALUE_STR
1518 * @value_data: (out callee-allocates) (optional) (transfer none): Pointer to a
1519 * location to store the data of the value (in UTF-16, if it's a string)
1520 * @value_data_size: (out) (optional): Pointer to a location to store the size
1521 * of @value_data, in bytes (including any NUL-terminators, if it's a string).
1522 * %NULL if length is not needed.
1523 * @error: (nullable): a pointer to %NULL #GError, or %NULL
1524 *
1525 * Stores the data of the value currently being iterated over in @value_data,
1526 * and its length - in @value_data_len (if not %NULL).
1527 *
1528 * Returns: %TRUE if value data was retrieved, %FALSE otherwise.
1529 *
1530 * Since: 2.46
1531 **/
1532 gboolean
g_win32_registry_value_iter_get_data_w(GWin32RegistryValueIter * iter,gboolean auto_expand,gpointer * value_data,gsize * value_data_size,GError ** error)1533 g_win32_registry_value_iter_get_data_w (GWin32RegistryValueIter *iter,
1534 gboolean auto_expand,
1535 gpointer *value_data,
1536 gsize *value_data_size,
1537 GError **error)
1538 {
1539 g_return_val_if_fail (iter != NULL, FALSE);
1540 g_return_val_if_fail (value_data != NULL, FALSE);
1541 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1542
1543 if G_UNLIKELY (iter->counter >= iter->value_count)
1544 {
1545 g_critical ("g_win32_registry_value_iter_get_data_w: must not be called "
1546 "again after FALSE has already been returned.");
1547 return FALSE;
1548 }
1549
1550 if (!auto_expand || (iter->value_type != G_WIN32_REGISTRY_VALUE_EXPAND_STR))
1551 {
1552 *value_data = iter->value_data;
1553
1554 if (value_data_size)
1555 *value_data_size = iter->value_actual_data_size;
1556
1557 return TRUE;
1558 }
1559
1560 if (iter->value_type == iter->value_expanded_type)
1561 {
1562 if (!expand_value ((gunichar2 *) iter->value_data,
1563 iter->value_name,
1564 (gpointer *) &iter->value_data_expanded,
1565 &iter->value_data_expanded_charsize,
1566 error))
1567 return FALSE;
1568
1569 iter->value_expanded_type = G_WIN32_REGISTRY_VALUE_STR;
1570 }
1571
1572 *value_data = iter->value_data_expanded;
1573
1574 if (value_data_size)
1575 *value_data_size = iter->value_data_expanded_charsize * sizeof (gunichar2);
1576
1577 return TRUE;
1578 }
1579
1580 /**
1581 * g_win32_registry_value_iter_get_data:
1582 * @iter: (in) (transfer none): a #GWin32RegistryValueIter
1583 * @auto_expand: (in): %TRUE to automatically expand G_WIN32_REGISTRY_VALUE_EXPAND_STR to
1584 * G_WIN32_REGISTRY_VALUE_STR
1585 * @value_data: (out callee-allocates) (optional) (transfer none): Pointer to a
1586 * location to store the data of the value (in UTF-8, if it's a string)
1587 * @value_data_size: (out) (optional): Pointer to a location to store the length
1588 * of @value_data, in bytes (including any NUL-terminators, if it's a string).
1589 * %NULL if length is not needed
1590 * @error: (nullable): a pointer to %NULL #GError, or %NULL
1591 *
1592 * Stores the data of the value currently being iterated over in @value_data,
1593 * and its length - in @value_data_len (if not %NULL).
1594 *
1595 * Returns: %TRUE if value data was retrieved, %FALSE otherwise.
1596 *
1597 * Since: 2.46
1598 **/
1599 gboolean
g_win32_registry_value_iter_get_data(GWin32RegistryValueIter * iter,gboolean auto_expand,gpointer * value_data,gsize * value_data_size,GError ** error)1600 g_win32_registry_value_iter_get_data (GWin32RegistryValueIter *iter,
1601 gboolean auto_expand,
1602 gpointer *value_data,
1603 gsize *value_data_size,
1604 GError **error)
1605 {
1606 gsize value_data_len_gsize;
1607 gpointer tmp;
1608 gsize tmp_size;
1609
1610 g_return_val_if_fail (iter != NULL, FALSE);
1611 g_return_val_if_fail (value_data != NULL, FALSE);
1612 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1613
1614 if G_UNLIKELY (iter->counter >= iter->value_count)
1615 {
1616 g_critical ("g_win32_registry_value_iter_get_data: must not be called "
1617 "again after FALSE has already been returned.");
1618 return FALSE;
1619 }
1620
1621 if (iter->value_type != G_WIN32_REGISTRY_VALUE_EXPAND_STR &&
1622 iter->value_type != G_WIN32_REGISTRY_VALUE_LINK &&
1623 iter->value_type != G_WIN32_REGISTRY_VALUE_STR &&
1624 iter->value_type != G_WIN32_REGISTRY_VALUE_MULTI_STR)
1625 {
1626 *value_data = iter->value_data;
1627
1628 if (value_data_size != NULL)
1629 *value_data_size = iter->value_actual_data_size;
1630
1631 return TRUE;
1632 }
1633
1634 if (!auto_expand || (iter->value_type != G_WIN32_REGISTRY_VALUE_EXPAND_STR))
1635 {
1636 if (iter->value_data_u8 == NULL)
1637 {
1638 iter->value_data_u8 = g_convert ((const gchar *) iter->value_data,
1639 iter->value_actual_data_size - sizeof (gunichar2) /* excl. 0 */,
1640 "UTF8", "UTF16", NULL,
1641 &value_data_len_gsize,
1642 error);
1643
1644 if (iter->value_data_u8 == NULL)
1645 return FALSE;
1646
1647 iter->value_data_u8_size = value_data_len_gsize + 1; /* incl. 0 */
1648 }
1649
1650 *value_data = iter->value_data_u8;
1651
1652 if (value_data_size != NULL)
1653 *value_data_size = iter->value_data_u8_size;
1654
1655 return TRUE;
1656 }
1657
1658 if (iter->value_data_expanded_u8 == NULL)
1659 {
1660 if (!g_win32_registry_value_iter_get_data_w (iter,
1661 TRUE,
1662 &tmp,
1663 &tmp_size,
1664 error))
1665 return FALSE;
1666
1667 iter->value_data_expanded_u8 = g_convert ((const gchar *) iter->value_data_expanded,
1668 iter->value_data_expanded_charsize * sizeof (gunichar2) - sizeof (gunichar2) /* excl. 0 */,
1669 "UTF8", "UTF16", NULL,
1670 &value_data_len_gsize,
1671 error);
1672
1673 if (iter->value_data_expanded_u8 == NULL)
1674 return FALSE;
1675
1676 iter->value_data_u8_size = value_data_len_gsize + 1; /* incl. 0 */
1677 }
1678
1679 *value_data = iter->value_data_expanded_u8;
1680
1681 if (value_data_size != NULL)
1682 *value_data_size = iter->value_data_expanded_u8_size;
1683
1684 return TRUE;
1685 }
1686
1687 static void
_g_win32_registry_key_reread_kernel(GWin32RegistryKey * key,GWin32RegistryKeyPrivate * buf)1688 _g_win32_registry_key_reread_kernel (GWin32RegistryKey *key,
1689 GWin32RegistryKeyPrivate *buf)
1690 {
1691 NTSTATUS status;
1692 KEY_BASIC_INFORMATION *basic_info;
1693 ULONG basic_info_size;
1694 ULONG datasize;
1695
1696 basic_info_size = 256 * sizeof (gunichar2) + sizeof (KEY_BASIC_INFORMATION);
1697 basic_info = g_malloc (basic_info_size + sizeof (gunichar2));
1698 status = nt_query_key (key->priv->handle,
1699 KeyBasicInformation,
1700 basic_info,
1701 basic_info_size,
1702 &datasize);
1703
1704 if (status == STATUS_BUFFER_OVERFLOW || status == STATUS_BUFFER_TOO_SMALL)
1705 {
1706 g_free (basic_info);
1707 basic_info_size = datasize;
1708 /* +1 for 0-terminator */
1709 basic_info = g_malloc (basic_info_size + sizeof (gunichar2));
1710 status = nt_query_key (key->priv->handle,
1711 KeyBasicInformation,
1712 basic_info,
1713 basic_info_size,
1714 &datasize);
1715 }
1716
1717 if (status != STATUS_SUCCESS)
1718 {
1719 g_free (basic_info);
1720 return;
1721 }
1722
1723 /* Ensure 0-termination */
1724 ((char *) basic_info)[datasize] = 0;
1725 ((char *) basic_info)[datasize + 1] = 0;
1726
1727 buf->absolute_path_w = g_wcsdup (&basic_info->Name[0],
1728 basic_info->NameLength + sizeof (gunichar2));
1729 g_free (basic_info);
1730 }
1731
1732 static void
_g_win32_registry_key_reread_user(GWin32RegistryKey * key,GWin32RegistryKeyPrivate * buf)1733 _g_win32_registry_key_reread_user (GWin32RegistryKey *key,
1734 GWin32RegistryKeyPrivate *buf)
1735 {
1736 /* Use RegQueryInfoKey(). It's just like NtQueryKey(), but can't query
1737 * key name.
1738 * Since right now we only need the name, this function is a noop.
1739 */
1740 }
1741
1742 static void
_g_win32_registry_key_reread(GWin32RegistryKey * key,GWin32RegistryKeyPrivate * buf)1743 _g_win32_registry_key_reread (GWin32RegistryKey *key,
1744 GWin32RegistryKeyPrivate *buf)
1745 {
1746 if (g_once_init_enter (&nt_query_key))
1747 {
1748 NtQueryKeyFunc func;
1749 HMODULE ntdll = GetModuleHandleW (L"ntdll.dll");
1750
1751 if (ntdll != NULL)
1752 func = (NtQueryKeyFunc) GetProcAddress (ntdll, "NtQueryKey");
1753 else
1754 func = NULL;
1755
1756 g_once_init_leave (&nt_query_key, func);
1757 }
1758
1759 /* Assume that predefined keys never get renamed. Also, their handles probably
1760 * won't be accepted by NtQueryKey(), i suspect.
1761 */
1762 if (nt_query_key != NULL && !key->priv->predefined)
1763 _g_win32_registry_key_reread_kernel (key, buf);
1764 else
1765 _g_win32_registry_key_reread_user (key, buf);
1766 }
1767
1768 static gboolean
_g_win32_registry_key_update_path(GWin32RegistryKey * key)1769 _g_win32_registry_key_update_path (GWin32RegistryKey *key)
1770 {
1771 GWin32RegistryKeyPrivate tmp;
1772 gboolean changed;
1773 gint change_indicator;
1774
1775 change_indicator = g_atomic_int_get (&key->priv->change_indicator);
1776
1777 if (change_indicator == G_WIN32_KEY_UNCHANGED)
1778 return FALSE;
1779
1780 tmp.absolute_path_w = NULL;
1781 _g_win32_registry_key_reread (key, &tmp);
1782 changed = FALSE;
1783
1784 if (wcscmp (key->priv->absolute_path_w, tmp.absolute_path_w) == 0)
1785 g_free (tmp.absolute_path_w);
1786 else
1787 {
1788 g_free (key->priv->absolute_path_w);
1789 key->priv->absolute_path_w = tmp.absolute_path_w;
1790 changed = TRUE;
1791 }
1792
1793 return changed;
1794 }
1795
1796 /**
1797 * g_win32_registry_key_get_path:
1798 * @key: (in) (transfer none): a #GWin32RegistryKey
1799 *
1800 * Get full path to the key
1801 *
1802 * Returns: (transfer none): a full path to the key (in UTF-8),
1803 * or %NULL if it can't be converted to UTF-8.
1804 *
1805 * Since: 2.46
1806 **/
1807 const gchar *
g_win32_registry_key_get_path(GWin32RegistryKey * key)1808 g_win32_registry_key_get_path (GWin32RegistryKey *key)
1809 {
1810 gint change_indicator;
1811
1812 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), NULL);
1813
1814 change_indicator = g_atomic_int_get (&key->priv->change_indicator);
1815
1816 if (change_indicator == G_WIN32_KEY_CHANGED &&
1817 !(key->priv->update_flags & G_WIN32_REGISTRY_UPDATED_PATH))
1818 {
1819 _g_win32_registry_key_update_path (key);
1820 key->priv->update_flags |= G_WIN32_REGISTRY_UPDATED_PATH;
1821 }
1822
1823 if (key->priv->absolute_path == NULL)
1824 {
1825 g_free (key->priv->absolute_path);
1826 key->priv->absolute_path =
1827 g_utf16_to_utf8 (key->priv->absolute_path_w, -1,
1828 NULL, NULL, NULL);
1829 }
1830
1831 return key->priv->absolute_path;
1832 }
1833
1834 /**
1835 * g_win32_registry_key_get_path_w:
1836 * @key: (in) (transfer none): a #GWin32RegistryKey
1837 *
1838 * Get full path to the key
1839 *
1840 * Returns: (transfer none): a full path to the key (in UTF-16)
1841 *
1842 * Since: 2.46
1843 **/
1844 const gunichar2 *
g_win32_registry_key_get_path_w(GWin32RegistryKey * key)1845 g_win32_registry_key_get_path_w (GWin32RegistryKey *key)
1846 {
1847 gint change_indicator;
1848
1849 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), NULL);
1850
1851 change_indicator = g_atomic_int_get (&key->priv->change_indicator);
1852
1853 if (change_indicator == G_WIN32_KEY_CHANGED)
1854 _g_win32_registry_key_update_path (key);
1855
1856 return key->priv->absolute_path_w;
1857 }
1858
1859 /**
1860 * g_win32_registry_key_get_value:
1861 * @key: (in) (transfer none): a #GWin32RegistryKey
1862 * @auto_expand: (in) %TRUE to automatically expand G_WIN32_REGISTRY_VALUE_EXPAND_STR
1863 * to G_WIN32_REGISTRY_VALUE_STR.
1864 * @value_name: (in) (transfer none): name of the value to get (in UTF-8).
1865 * Empty string means the '(Default)' value.
1866 * @value_type: (out) (optional): type of the value retrieved.
1867 * @value_data: (out callee-allocates) (optional): contents of the value.
1868 * @value_data_size: (out) (optional): size of the buffer pointed
1869 * by @value_data.
1870 * @error: (nullable): a pointer to %NULL #GError, or %NULL
1871 *
1872 * Get data from a value of a key. String data is guaranteed to be
1873 * appropriately terminated and will be in UTF-8.
1874 *
1875 * Returns: %TRUE on success, %FALSE on failure.
1876 *
1877 * Since: 2.46
1878 **/
1879 gboolean
g_win32_registry_key_get_value(GWin32RegistryKey * key,gboolean auto_expand,const gchar * value_name,GWin32RegistryValueType * value_type,gpointer * value_data,gsize * value_data_size,GError ** error)1880 g_win32_registry_key_get_value (GWin32RegistryKey *key,
1881 gboolean auto_expand,
1882 const gchar *value_name,
1883 GWin32RegistryValueType *value_type,
1884 gpointer *value_data,
1885 gsize *value_data_size,
1886 GError **error)
1887 {
1888 GWin32RegistryValueType value_type_g;
1889 gpointer value_data_w;
1890 gsize value_data_w_size;
1891 gunichar2 *value_name_w;
1892 gchar *value_data_u8;
1893 gsize value_data_u8_len;
1894 gboolean result;
1895
1896 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), FALSE);
1897 g_return_val_if_fail (value_name != NULL, FALSE);
1898 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1899
1900 /* No sense calling this function with all of these set to NULL */
1901 g_return_val_if_fail (value_type != NULL ||
1902 value_data != NULL ||
1903 value_data_size != NULL, FALSE);
1904
1905 value_name_w = g_utf8_to_utf16 (value_name, -1, NULL, NULL, error);
1906
1907 if (value_name_w == NULL)
1908 return FALSE;
1909
1910 result = g_win32_registry_key_get_value_w (key,
1911 auto_expand,
1912 value_name_w,
1913 &value_type_g,
1914 &value_data_w,
1915 &value_data_w_size,
1916 error);
1917
1918 g_free (value_name_w);
1919
1920 if (!result)
1921 return FALSE;
1922
1923 if (value_type_g == G_WIN32_REGISTRY_VALUE_EXPAND_STR ||
1924 value_type_g == G_WIN32_REGISTRY_VALUE_LINK ||
1925 value_type_g == G_WIN32_REGISTRY_VALUE_STR ||
1926 value_type_g == G_WIN32_REGISTRY_VALUE_MULTI_STR)
1927 {
1928 value_data_u8 = g_convert ((const gchar *) value_data_w,
1929 value_data_w_size - sizeof (gunichar2) /* excl. 0 */,
1930 "UTF8",
1931 "UTF16",
1932 NULL,
1933 &value_data_u8_len,
1934 error);
1935 g_free (value_data_w);
1936
1937 if (value_data_u8 == NULL)
1938 return FALSE;
1939
1940 if (value_data)
1941 *value_data = value_data_u8;
1942 else
1943 g_free (value_data_u8);
1944
1945 if (value_data_size)
1946 *value_data_size = value_data_u8_len + 1;
1947 }
1948 else
1949 {
1950 if (value_data)
1951 *value_data = value_data_w;
1952 else
1953 g_free (value_data_w);
1954
1955 if (value_data_size)
1956 *value_data_size = value_data_w_size;
1957 }
1958
1959 if (value_type)
1960 *value_type = value_type_g;
1961
1962 return TRUE;
1963 }
1964
1965 /**
1966 * g_win32_registry_key_get_value_w:
1967 * @key: (in) (transfer none): a #GWin32RegistryKey
1968 * @auto_expand: (in) %TRUE to automatically expand G_WIN32_REGISTRY_VALUE_EXPAND_STR
1969 * to G_WIN32_REGISTRY_VALUE_STR.
1970 * @value_name: (in) (transfer none): name of the value to get (in UTF-16).
1971 * Empty string means the '(Default)' value.
1972 * @value_type: (out) (optional): type of the value retrieved.
1973 * @value_data: (out callee-allocates) (optional): contents of the value.
1974 * @value_data_size: (out) (optional): size of the buffer pointed
1975 * by @value_data.
1976 * @error: (nullable): a pointer to %NULL #GError, or %NULL
1977 *
1978 * Get data from a value of a key.
1979 *
1980 * Get data from a value of a key. String data is guaranteed to be
1981 * appropriately terminated and will be in UTF-16.
1982 *
1983 * When calling with value_data == NULL (to get data size without getting
1984 * the data itself) remember that returned size corresponds to possibly
1985 * unterminated string data (if value is some kind of string), because
1986 * termination cannot be checked and fixed unless the data is retreived
1987 * too.
1988 *
1989 * Returns: %TRUE on success, %FALSE on failure.
1990 *
1991 * Since: 2.46
1992 **/
1993 gboolean
g_win32_registry_key_get_value_w(GWin32RegistryKey * key,gboolean auto_expand,const gunichar2 * value_name,GWin32RegistryValueType * value_type,gpointer * value_data,gsize * value_data_size,GError ** error)1994 g_win32_registry_key_get_value_w (GWin32RegistryKey *key,
1995 gboolean auto_expand,
1996 const gunichar2 *value_name,
1997 GWin32RegistryValueType *value_type,
1998 gpointer *value_data,
1999 gsize *value_data_size,
2000 GError **error)
2001 {
2002 LONG status;
2003 DWORD value_type_w;
2004 DWORD value_type_w2;
2005 char *req_value_data;
2006 GWin32RegistryValueType value_type_g;
2007 GWin32RegistryValueType value_type_g2;
2008 DWORD req_value_data_size;
2009 DWORD req_value_data_size2;
2010
2011 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), FALSE);
2012 g_return_val_if_fail (value_name != NULL, FALSE);
2013 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2014
2015 /* No sense calling this functions with all of these set to NULL */
2016 g_return_val_if_fail (value_type != NULL ||
2017 value_data != NULL ||
2018 value_data_size != NULL, FALSE);
2019
2020 req_value_data_size = 0;
2021 status = RegQueryValueExW (key->priv->handle,
2022 value_name,
2023 NULL,
2024 &value_type_w,
2025 NULL,
2026 &req_value_data_size);
2027
2028 if (status != ERROR_MORE_DATA && status != ERROR_SUCCESS)
2029 {
2030 g_set_error (error, G_IO_ERROR, g_io_error_from_win32_error (status),
2031 "Failed to query value '%S' for key '%S'",
2032 value_name, g_win32_registry_key_get_path_w (key));
2033
2034 return FALSE;
2035 }
2036
2037 value_type_g = _g_win32_registry_type_w_to_g (value_type_w);
2038
2039 if (value_data == NULL &&
2040 (!auto_expand || value_type_g != G_WIN32_REGISTRY_VALUE_EXPAND_STR))
2041 {
2042 if (value_type)
2043 *value_type = value_type_g;
2044
2045 if (value_data_size)
2046 *value_data_size = req_value_data_size;
2047
2048 return TRUE;
2049 }
2050
2051 req_value_data = g_malloc (req_value_data_size + sizeof (gunichar2) * 2);
2052 req_value_data_size2 = req_value_data_size;
2053 status = RegQueryValueExW (key->priv->handle,
2054 value_name,
2055 NULL,
2056 &value_type_w2,
2057 (gpointer) req_value_data,
2058 &req_value_data_size2);
2059
2060 if (status != ERROR_SUCCESS)
2061 {
2062 g_set_error (error, G_IO_ERROR, g_io_error_from_win32_error (status),
2063 "Failed to query value '%S' of size %lu for key '%S'",
2064 value_name,
2065 req_value_data_size,
2066 g_win32_registry_key_get_path_w (key));
2067 g_free (req_value_data);
2068 return FALSE;
2069 }
2070
2071 value_type_g2 = _g_win32_registry_type_w_to_g (value_type_w2);
2072
2073 if (value_type_w != value_type_w2)
2074 {
2075 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
2076 "Type of value '%S' of key '%S' changed from %u to %u"
2077 " between calls",
2078 value_name,
2079 g_win32_registry_key_get_path_w (key),
2080 value_type_g, value_type_g2);
2081 g_free (req_value_data);
2082 return FALSE;
2083 }
2084
2085 req_value_data_size = ensure_nul_termination (value_type_g,
2086 (guint8 *) req_value_data,
2087 req_value_data_size2);
2088
2089 if (value_type_g == G_WIN32_REGISTRY_VALUE_EXPAND_STR && auto_expand)
2090 {
2091 gsize value_data_expanded_charsize_w = 0;
2092 gunichar2 *value_data_expanded = NULL;
2093
2094 if (!expand_value ((gunichar2 *) req_value_data,
2095 value_name,
2096 (gpointer *) &value_data_expanded,
2097 &value_data_expanded_charsize_w,
2098 error))
2099 return FALSE;
2100
2101 g_free (req_value_data);
2102
2103 if (value_type)
2104 *value_type = G_WIN32_REGISTRY_VALUE_STR;
2105
2106 if (value_data)
2107 *value_data = value_data_expanded;
2108 else
2109 g_free (value_data_expanded);
2110
2111 if (value_data_size)
2112 *value_data_size = value_data_expanded_charsize_w * sizeof (gunichar2);
2113
2114 return TRUE;
2115 }
2116
2117 if (value_type)
2118 *value_type = value_type_g;
2119
2120 if (value_data_size)
2121 *value_data_size = req_value_data_size;
2122
2123 if (value_data)
2124 *value_data = req_value_data;
2125 else
2126 g_free (req_value_data);
2127
2128 return TRUE;
2129 }
2130
2131 static VOID NTAPI
key_changed(PVOID closure,PIO_STATUS_BLOCK status_block,ULONG reserved)2132 key_changed (PVOID closure,
2133 PIO_STATUS_BLOCK status_block,
2134 ULONG reserved)
2135 {
2136 GWin32RegistryKey *key = G_WIN32_REGISTRY_KEY (closure);
2137
2138 g_free (status_block);
2139 g_atomic_int_set (&key->priv->change_indicator, G_WIN32_KEY_CHANGED);
2140 g_atomic_int_set (&key->priv->watch_indicator, G_WIN32_KEY_UNWATCHED);
2141 key->priv->update_flags = G_WIN32_REGISTRY_UPDATED_NOTHING;
2142
2143 if (key->priv->callback)
2144 key->priv->callback (key, key->priv->user_data);
2145
2146 key->priv->callback = NULL;
2147 key->priv->user_data = NULL;
2148 g_object_unref (key);
2149 }
2150
2151 /**
2152 * g_win32_registry_key_watch:
2153 * @key: (in) (transfer none): a #GWin32RegistryKey
2154 * @watch_children: (in) %TRUE also watch the children of the @key, %FALSE
2155 * to watch the key only.
2156 * @watch_flags: (in): specifies the types of changes to watch for.
2157 * @callback: (in) (nullable): a function to invoke when a change occurs.
2158 * @user_data: (in) (nullable): a pointer to pass to @callback on invocation.
2159 * @error: (nullable): a pointer to %NULL #GError, or %NULL
2160 *
2161 * Puts @key under a watch.
2162 *
2163 * When the key changes, an APC will be queued in the current thread. The APC
2164 * will run when the current thread enters alertable state (GLib main loop
2165 * should do that; if you are not using it, see MSDN documentation for W32API
2166 * calls that put thread into alertable state). When it runs, it will
2167 * atomically switch an indicator in the @key. If a callback was specified,
2168 * it is invoked at that point. Subsequent calls to
2169 * g_win32_registry_key_has_changed() will return %TRUE, and the callback (if
2170 * it was specified) will not be invoked anymore.
2171 * Calling g_win32_registry_key_erase_change_indicator() will reset the indicator,
2172 * and g_win32_registry_key_has_changed() will start returning %FALSE.
2173 * To resume the watch, call g_win32_registry_key_watch_for_changes() again.
2174 *
2175 * Calling g_win32_registry_key_watch_for_changes() for a key that is already
2176 * being watched is allowed and affects nothing.
2177 *
2178 * The fact that the key is being watched will be used internally to update
2179 * key path (if it changes).
2180 *
2181 * Returns: %TRUE on success, %FALSE on failure.
2182 *
2183 * Since: 2.46
2184 **/
2185 gboolean
g_win32_registry_key_watch(GWin32RegistryKey * key,gboolean watch_children,GWin32RegistryKeyWatcherFlags watch_flags,GWin32RegistryKeyWatchCallbackFunc callback,gpointer user_data,GError ** error)2186 g_win32_registry_key_watch (GWin32RegistryKey *key,
2187 gboolean watch_children,
2188 GWin32RegistryKeyWatcherFlags watch_flags,
2189 GWin32RegistryKeyWatchCallbackFunc callback,
2190 gpointer user_data,
2191 GError **error)
2192 {
2193 ULONG filter;
2194 gboolean started_to_watch;
2195 NTSTATUS status;
2196 PIO_STATUS_BLOCK status_block;
2197
2198 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), FALSE);
2199
2200 filter = ((watch_flags & G_WIN32_REGISTRY_WATCH_NAME) ? REG_NOTIFY_CHANGE_NAME : 0) |
2201 ((watch_flags & G_WIN32_REGISTRY_WATCH_ATTRIBUTES) ? REG_NOTIFY_CHANGE_ATTRIBUTES : 0) |
2202 ((watch_flags & G_WIN32_REGISTRY_WATCH_VALUES) ? REG_NOTIFY_CHANGE_LAST_SET : 0) |
2203 ((watch_flags & G_WIN32_REGISTRY_WATCH_SECURITY) ? REG_NOTIFY_CHANGE_SECURITY : 0);
2204
2205 if (filter == 0)
2206 {
2207 g_critical ("No supported flags specified in watch_flags (%x)", (guint) watch_flags);
2208 return FALSE;
2209 }
2210
2211 if (g_once_init_enter (&nt_notify_change_multiple_keys))
2212 {
2213 NtNotifyChangeMultipleKeysFunc func;
2214 HMODULE ntdll = GetModuleHandle ("ntdll.dll");
2215
2216 if (ntdll != NULL)
2217 func = (NtNotifyChangeMultipleKeysFunc) GetProcAddress (ntdll, "NtNotifyChangeMultipleKeys");
2218 else
2219 func = NULL;
2220
2221 g_once_init_leave (&nt_notify_change_multiple_keys, func);
2222 }
2223
2224 if (nt_notify_change_multiple_keys== NULL)
2225 {
2226 g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
2227 "Couldn't get NtNotifyChangeMultipleKeys() from ntdll");
2228 return FALSE;
2229 }
2230
2231 started_to_watch =
2232 g_atomic_int_compare_and_exchange (&key->priv->watch_indicator,
2233 G_WIN32_KEY_UNWATCHED,
2234 G_WIN32_KEY_WATCHED);
2235
2236 if (!started_to_watch)
2237 return TRUE;
2238
2239 key->priv->callback = callback;
2240 key->priv->user_data = user_data;
2241
2242 g_atomic_int_set (&key->priv->change_indicator, G_WIN32_KEY_UNCHANGED);
2243
2244 /* Keep it alive until APC is called */
2245 g_object_ref (key);
2246
2247 status_block = g_malloc (sizeof (IO_STATUS_BLOCK));
2248
2249 status = nt_notify_change_multiple_keys (key->priv->handle,
2250 0,
2251 NULL,
2252 NULL,
2253 key_changed,
2254 (PVOID) key,
2255 status_block,
2256 filter,
2257 watch_children,
2258 NULL,
2259 0,
2260 TRUE);
2261
2262 g_assert (status != STATUS_SUCCESS);
2263
2264 if (status == STATUS_PENDING)
2265 return TRUE;
2266
2267 g_atomic_int_set (&key->priv->change_indicator, G_WIN32_KEY_UNKNOWN);
2268 g_atomic_int_set (&key->priv->watch_indicator, G_WIN32_KEY_UNWATCHED);
2269 g_object_unref (key);
2270 g_free (status_block);
2271
2272 return FALSE;
2273 }
2274
2275 /**
2276 * g_win32_registry_key_erase_change_indicator:
2277 * @key: (in) (transfer none): a #GWin32RegistryKey
2278 *
2279 * Erases change indicator of the @key.
2280 *
2281 * Subsequent calls to g_win32_registry_key_has_changed() will return %FALSE
2282 * until the key is put on watch again by calling
2283 * g_win32_registry_key_watch() again.
2284 *
2285 * Since: 2.46
2286 */
2287 void
g_win32_registry_key_erase_change_indicator(GWin32RegistryKey * key)2288 g_win32_registry_key_erase_change_indicator (GWin32RegistryKey *key)
2289 {
2290 g_return_if_fail (G_IS_WIN32_REGISTRY_KEY (key));
2291
2292 g_atomic_int_set (&key->priv->change_indicator, G_WIN32_KEY_UNKNOWN);
2293 }
2294
2295 /**
2296 * g_win32_registry_key_has_changed:
2297 * @key: (in) (transfer none): a #GWin32RegistryKey
2298 *
2299 * Check the @key's status indicator.
2300 *
2301 * Returns: %TRUE if the @key was put under watch at some point and has changed
2302 * since then, %FALSE if it either wasn't changed or wasn't watched at all.
2303 *
2304 * Since: 2.46
2305 */
2306 gboolean
g_win32_registry_key_has_changed(GWin32RegistryKey * key)2307 g_win32_registry_key_has_changed (GWin32RegistryKey *key)
2308 {
2309 gint changed;
2310
2311 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), FALSE);
2312
2313 changed = g_atomic_int_get (&key->priv->change_indicator);
2314
2315 return (changed == G_WIN32_KEY_CHANGED ? TRUE : FALSE);
2316 }
2317
2318 static void
g_win32_registry_key_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)2319 g_win32_registry_key_get_property (GObject *object,
2320 guint prop_id,
2321 GValue *value,
2322 GParamSpec *pspec)
2323 {
2324 GWin32RegistryKey *key = G_WIN32_REGISTRY_KEY (object);
2325
2326 switch (prop_id)
2327 {
2328 case PROP_PATH:
2329 g_value_set_string (value, g_win32_registry_key_get_path (key));
2330 break;
2331
2332 case PROP_PATH_UTF16:
2333 g_value_set_pointer (value, (gpointer) g_win32_registry_key_get_path_w (key));
2334 break;
2335
2336 default:
2337 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2338 }
2339 }
2340
2341 static void
g_win32_registry_key_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)2342 g_win32_registry_key_set_property (GObject *object,
2343 guint prop_id,
2344 const GValue *value,
2345 GParamSpec *pspec)
2346 {
2347 GWin32RegistryKey *key = G_WIN32_REGISTRY_KEY (object);
2348 GWin32RegistryKeyPrivate *priv = key->priv;
2349 const gchar *path;
2350 gunichar2 *path_w;
2351
2352 switch (prop_id)
2353 {
2354 case PROP_PATH:
2355 g_assert (priv->absolute_path_w == NULL);
2356 g_assert (priv->absolute_path == NULL);
2357 path = g_value_get_string (value);
2358
2359 if (path == NULL)
2360 break;
2361
2362 path_w = g_utf8_to_utf16 (path, -1, NULL, NULL, NULL);
2363
2364 if (path_w == NULL)
2365 break;
2366
2367 g_free (priv->absolute_path_w);
2368 g_free (priv->absolute_path);
2369 priv->absolute_path_w = path_w;
2370 priv->absolute_path = g_value_dup_string (value);
2371 break;
2372
2373 case PROP_PATH_UTF16:
2374 g_assert (priv->absolute_path_w == NULL);
2375 g_assert (priv->absolute_path == NULL);
2376 path_w = (gunichar2 *) g_value_get_pointer (value);
2377
2378 if (path_w == NULL)
2379 break;
2380
2381 priv->absolute_path_w = g_wcsdup (path_w, -1);
2382 break;
2383
2384 default:
2385 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2386 }
2387 }
2388
2389 static void
g_win32_registry_key_class_init(GWin32RegistryKeyClass * klass)2390 g_win32_registry_key_class_init (GWin32RegistryKeyClass *klass)
2391 {
2392 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
2393
2394 gobject_class->dispose = g_win32_registry_key_dispose;
2395 gobject_class->set_property = g_win32_registry_key_set_property;
2396 gobject_class->get_property = g_win32_registry_key_get_property;
2397
2398 /**
2399 * GWin32RegistryKey:path:
2400 *
2401 * A path to the key in the registry, in UTF-8.
2402 *
2403 * Since: 2.46
2404 */
2405 g_object_class_install_property (gobject_class,
2406 PROP_PATH,
2407 g_param_spec_string ("path",
2408 "Path",
2409 "Path to the key in the registry",
2410 NULL,
2411 G_PARAM_READWRITE |
2412 G_PARAM_CONSTRUCT_ONLY |
2413 G_PARAM_STATIC_STRINGS));
2414
2415 /**
2416 * GWin32RegistryKey:path-utf16:
2417 *
2418 * A path to the key in the registry, in UTF-16.
2419 *
2420 * Since: 2.46
2421 */
2422 g_object_class_install_property (gobject_class,
2423 PROP_PATH_UTF16,
2424 g_param_spec_pointer ("path-utf16",
2425 "Path (UTF-16)",
2426 "Path to the key in the registry, in UTF-16",
2427 G_PARAM_READWRITE |
2428 G_PARAM_CONSTRUCT_ONLY |
2429 G_PARAM_STATIC_STRINGS));
2430 }
2431
2432 static void
g_win32_registry_key_init(GWin32RegistryKey * key)2433 g_win32_registry_key_init (GWin32RegistryKey *key)
2434 {
2435 key->priv = g_win32_registry_key_get_instance_private (key);
2436 key->priv->change_indicator = G_WIN32_KEY_UNKNOWN;
2437 }
2438