1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright (C) 2014 Руслан Ижбулатов <lrn1986@gmail.com>
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.
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.
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/>.
21 #include "ginitable.h"
22 #include "gwin32registrykey.h"
23 #include <gio/gioerror.h>
25 #pragma warning ( disable:4005 )
32 typedef enum _KEY_INFORMATION_CLASS {
39 KeyVirtualizationInformation,
40 KeyHandleTagsInformation,
42 } KEY_INFORMATION_CLASS;
44 typedef struct _KEY_BASIC_INFORMATION {
45 LARGE_INTEGER LastWriteTime;
49 } KEY_BASIC_INFORMATION, *PKEY_BASIC_INFORMATION;
52 #if !defined (__OBJECT_ATTRIBUTES_DEFINED) && defined (__MINGW32_)
53 #define __OBJECT_ATTRIBUTES_DEFINED
54 typedef struct _OBJECT_ATTRIBUTES {
60 PUNICODE_STRING ObjectName;
65 PVOID SecurityDescriptor;
66 PVOID SecurityQualityOfService;
67 } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
70 #ifndef HKEY_CURRENT_USER_LOCAL_SETTINGS
71 #define HKEY_CURRENT_USER_LOCAL_SETTINGS ((HKEY) (ULONG_PTR)((LONG)0x80000007))
74 #if !defined (__UNICODE_STRING_DEFINED) && defined (__MINGW32_)
75 #define __UNICODE_STRING_DEFINED
76 typedef struct _UNICODE_STRING {
80 } UNICODE_STRING, *PUNICODE_STRING;
82 typedef const UNICODE_STRING* PCUNICODE_STRING;
85 (NTAPI * NtQueryKeyFunc)(HANDLE key_handle,
86 KEY_INFORMATION_CLASS key_info_class,
87 PVOID key_info_buffer,
88 ULONG key_info_buffer_size,
92 (NTAPI * NtNotifyChangeMultipleKeysFunc)(HANDLE key_handle,
94 POBJECT_ATTRIBUTES subkeys,
96 PIO_APC_ROUTINE apc_routine,
98 PIO_STATUS_BLOCK status_block,
105 static NtQueryKeyFunc nt_query_key = NULL;
106 static NtNotifyChangeMultipleKeysFunc nt_notify_change_multiple_keys = NULL;
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
124 G_WIN32_REGISTRY_UPDATED_NOTHING = 0,
125 G_WIN32_REGISTRY_UPDATED_PATH = 1,
126 } GWin32RegistryKeyUpdateFlag;
129 g_utf16_len (const gunichar2 *str)
133 for (result = 0; str[0] != 0; str++, result++)
140 g_wcsdup (const gunichar2 *str, gssize str_len)
142 gsize str_len_unsigned;
145 g_return_val_if_fail (str != NULL, NULL);
148 str_len_unsigned = g_utf16_len (str);
150 str_len_unsigned = (gsize) str_len;
152 g_assert (str_len_unsigned <= G_MAXSIZE / sizeof (gunichar2) - 1);
153 str_size = (str_len_unsigned + 1) * sizeof (gunichar2);
155 return g_memdup2 (str, str_size);
159 * g_win32_registry_subkey_iter_copy:
162 * Creates a dynamically-allocated copy of an iterator. Dynamically-allocated
163 * state of the iterator is duplicated too.
165 * Returns: (transfer full): a copy of the @iter,
166 * free with g_win32_registry_subkey_iter_free ()
170 GWin32RegistrySubkeyIter *
171 g_win32_registry_subkey_iter_copy (const GWin32RegistrySubkeyIter *iter)
173 GWin32RegistrySubkeyIter *new_iter;
175 g_return_val_if_fail (iter != NULL, NULL);
177 new_iter = g_new0 (GWin32RegistrySubkeyIter, 1);
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;
185 if (iter->subkey_name_u8)
186 new_iter->subkey_name_u8 = iter->subkey_name_u8;
188 new_iter->subkey_name_u8 = NULL;
194 * g_win32_registry_subkey_iter_free:
195 * @iter: a dynamically-allocated iterator
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.
203 g_win32_registry_subkey_iter_free (GWin32RegistrySubkeyIter *iter)
205 g_return_if_fail (iter != NULL);
207 g_object_unref (iter->key);
208 g_free (iter->subkey_name);
209 g_free (iter->subkey_name_u8);
214 * g_win32_registry_subkey_iter_assign:
215 * @iter: a #GWin32RegistrySubkeyIter
216 * @other: another #GWin32RegistrySubkeyIter
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.
226 g_win32_registry_subkey_iter_assign (GWin32RegistrySubkeyIter *iter,
227 const GWin32RegistrySubkeyIter *other)
229 g_return_if_fail (iter != NULL);
230 g_return_if_fail (other != NULL);
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)
241 * g_win32_registry_value_iter_copy:
244 * Creates a dynamically-allocated copy of an iterator. Dynamically-allocated
245 * state of the iterator is duplicated too.
247 * Returns: (transfer full): a copy of the @iter,
248 * free with g_win32_registry_value_iter_free ().
252 GWin32RegistryValueIter *
253 g_win32_registry_value_iter_copy (const GWin32RegistryValueIter *iter)
255 GWin32RegistryValueIter *new_iter;
257 g_return_val_if_fail (iter != NULL, NULL);
259 new_iter = g_new0 (GWin32RegistryValueIter, 1);
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;
267 if (iter->value_data != NULL)
268 new_iter->value_data = g_memdup2 (iter->value_data, iter->value_data_size);
270 new_iter->value_data_size = iter->value_data_size;
272 if (iter->value_name_u8 != NULL)
273 new_iter->value_name_u8 = g_strdup (iter->value_name_u8);
275 new_iter->value_name_u8_len = iter->value_name_u8_len;
277 if (iter->value_data_u8 != NULL)
278 new_iter->value_data_u8 = g_strdup (iter->value_data_u8);
280 new_iter->value_data_u8_size = iter->value_data_u8_size;
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));
286 new_iter->value_data_expanded_charsize = iter->value_data_expanded_charsize;
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);
292 new_iter->value_data_expanded_u8_size = iter->value_data_expanded_charsize;
298 * g_win32_registry_value_iter_free:
299 * @iter: a dynamically-allocated iterator
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.
307 g_win32_registry_value_iter_free (GWin32RegistryValueIter *iter)
309 g_return_if_fail (iter != NULL);
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);
322 * g_win32_registry_value_iter_assign:
323 * @iter: a #GWin32RegistryValueIter
324 * @other: another #GWin32RegistryValueIter
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.
334 g_win32_registry_value_iter_assign (GWin32RegistryValueIter *iter,
335 const GWin32RegistryValueIter *other)
337 g_return_if_fail (iter != NULL);
338 g_return_if_fail (other != NULL);
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)
348 * SECTION:gwin32registrykey
349 * @title: GWin32RegistryKey
350 * @short_description: W32 registry access helper
351 * @include: gio/win32/gwin32registrykey.h
353 * #GWin32RegistryKey represents a single Windows Registry key.
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
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.
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
373 * All functions operate in current user's context (it is not possible to
374 * access registry tree of a different user).
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
380 * Key and value names are not case sensitive.
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.
387 struct _GWin32RegistryKeyPrivate {
388 /* Ancestor of this key. May not be the immediate parent, because
389 * RegOpenKeyEx() allows grand*-children to be opened transitively.
392 GWin32RegistryKey *ancestor;
394 /* Handle to the key */
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.
401 gunichar2 *absolute_path_w;
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;
407 /* TRUE if this object represents one of the pre-defined keys
408 * (and thus must not be closed).
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.
415 gint watch_indicator;
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.
421 gint change_indicator;
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.
428 GWin32RegistryKeyUpdateFlag update_flags;
430 GWin32RegistryKeyWatchCallbackFunc callback;
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,
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));
446 g_win32_registry_key_dispose (GObject *object)
448 GWin32RegistryKey *key;
449 GWin32RegistryKeyPrivate *priv;
451 key = G_WIN32_REGISTRY_KEY (object);
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);
458 if (!priv->predefined && priv->handle != INVALID_HANDLE_VALUE)
460 RegCloseKey (priv->handle);
461 priv->handle = INVALID_HANDLE_VALUE;
464 G_OBJECT_CLASS (g_win32_registry_key_parent_class)->dispose (object);
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
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
483 * @path must not end with '\\'.
485 * Returns: (nullable) (transfer full): a #GWin32RegistryKey or %NULL if can't
486 * be opened. Free with g_object_unref().
489 g_win32_registry_key_new (const gchar *path,
492 g_return_val_if_fail (path != NULL, NULL);
494 return g_initable_new (G_TYPE_WIN32_REGISTRY_KEY,
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
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
518 * @path must not end with L'\\'.
520 * Returns: (nullable) (transfer full): a #GWin32RegistryKey or %NULL if can't
521 * be opened. Free with g_object_unref().
524 g_win32_registry_key_new_w (const gunichar2 *path,
529 g_return_val_if_fail (path != NULL, NULL);
531 result = g_initable_new (G_TYPE_WIN32_REGISTRY_KEY,
538 return result ? G_WIN32_REGISTRY_KEY (result) : NULL;
542 g_win32_registry_key_initable_iface_init (GInitableIface *iface)
544 iface->init = g_win32_registry_key_initable_init;
548 g_win32_registry_key_initable_init (GInitable *initable,
549 GCancellable *cancellable,
552 GWin32RegistryKey *key;
553 GWin32RegistryKeyPrivate *priv;
555 gunichar2 *first_chunk_end;
556 gsize first_chunk_len;
557 gunichar2 *second_chunk_begin;
558 gunichar2 *first_chunk;
563 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (initable), FALSE);
564 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
566 key = G_WIN32_REGISTRY_KEY (initable);
569 if (priv->absolute_path_w == NULL)
571 priv->absolute_path_w = g_utf8_to_utf16 (priv->absolute_path,
577 if (priv->absolute_path_w == NULL)
581 path = priv->absolute_path_w;
583 first_chunk_end = wcschr (path, L'\\');
585 if (first_chunk_end == NULL)
586 first_chunk_end = &path[wcslen (path)];
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;
611 g_critical ("Root key '%S' is not a pre-defined key", first_chunk);
612 g_free (first_chunk);
616 g_free (first_chunk);
618 second_chunk_begin = first_chunk_end;
620 while (second_chunk_begin[0] != L'\0' && second_chunk_begin[0] == L'\\')
621 second_chunk_begin++;
623 if (second_chunk_begin != first_chunk_end && second_chunk_begin[0] == L'\0')
625 g_critical ("Key name '%S' ends with '\\'", path);
629 opened = RegOpenKeyExW (ancestor, second_chunk_begin, 0, KEY_READ, &key_handle);
631 if (opened != ERROR_SUCCESS)
633 g_set_error (error, G_IO_ERROR, g_io_error_from_win32_error (opened),
634 "Failed to open registry key '%S'", path);
638 priv->ancestor = NULL;
639 priv->handle = key_handle;
640 priv->predefined = (second_chunk_begin[0] == L'\0');
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
651 * Opens a @subkey of the @key.
653 * Returns: (nullable): a #GWin32RegistryKey or %NULL if can't be opened. Free
654 * with g_object_unref().
657 g_win32_registry_key_get_child (GWin32RegistryKey *key,
662 GWin32RegistryKey *result = NULL;
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);
668 subkey_w = g_utf8_to_utf16 (subkey, -1, NULL, NULL, error);
670 if (subkey_w != NULL)
672 result = g_win32_registry_key_get_child_w (key, subkey_w, error);
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
685 * Opens a @subkey of the @key.
687 * Returns: (nullable): a #GWin32RegistryKey or %NULL if can't be opened. Free
688 * with g_object_unref().
691 g_win32_registry_key_get_child_w (GWin32RegistryKey *key,
692 const gunichar2 *subkey,
697 const gunichar2 *end_of_subkey;
699 GWin32RegistryKey *result;
700 const gunichar2 *key_path;
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);
706 if (subkey[0] == L'\\')
708 g_critical ("Subkey name '%S' starts with '\\'", subkey);
712 subkey_len = wcslen (subkey);
713 end_of_subkey = &subkey[subkey_len];
716 end_of_subkey = subkey;
718 if (end_of_subkey[0] == L'\\')
720 g_critical ("Subkey name '%S' ends with '\\'", subkey);
724 key_path = g_win32_registry_key_get_path_w (key);
725 opened = RegOpenKeyExW (key->priv->handle, subkey, 0, KEY_READ, &key_handle);
727 if (opened != ERROR_SUCCESS)
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'",
735 result = g_object_new (G_TYPE_WIN32_REGISTRY_KEY, NULL);
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);
746 if (subkey[0] != L'\0')
747 result->priv->ancestor = g_object_ref (key);
749 result->priv->ancestor = NULL;
751 result->priv->change_indicator = G_WIN32_KEY_UNKNOWN;
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
762 * Initialises (without allocating) a #GWin32RegistrySubkeyIter. @iter may be
763 * completely uninitialised prior to this call; its old value is
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.
770 * Returns: %TRUE if iterator was initialized successfully, %FALSE on error.
775 g_win32_registry_subkey_iter_init (GWin32RegistrySubkeyIter *iter,
776 GWin32RegistryKey *key,
781 DWORD max_subkey_len;
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);
787 status = RegQueryInfoKeyW (key->priv->handle,
789 &subkey_count, &max_subkey_len,
790 NULL, NULL, NULL, NULL, NULL, NULL);
792 if (status != ERROR_SUCCESS)
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));
800 iter->key = g_object_ref (key);
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;
811 * g_win32_registry_subkey_iter_clear:
812 * @iter: (in) (transfer none): a #GWin32RegistrySubkeyIter
814 * Frees internal buffers of a #GWin32RegistrySubkeyIter.
819 g_win32_registry_subkey_iter_clear (GWin32RegistrySubkeyIter *iter)
821 g_return_if_fail (iter != NULL);
823 g_free (iter->subkey_name);
824 g_free (iter->subkey_name_u8);
825 g_clear_object (&iter->key);
829 * g_win32_registry_subkey_iter_n_subkeys:
830 * @iter: (in) (transfer none): a #GWin32RegistrySubkeyIter
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.
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.
839 * Returns: the number of subkeys in the key
844 g_win32_registry_subkey_iter_n_subkeys (GWin32RegistrySubkeyIter *iter)
846 g_return_val_if_fail (iter != NULL, 0);
848 return iter->subkey_count;
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
857 * @error: (nullable): a pointer to %NULL #GError, or %NULL
859 * Moves iterator to the next subkey.
860 * Enumeration errors can be ignored if @skip_errors is %TRUE
862 * Here is an example for iterating with g_win32_registry_subkey_iter_next():
863 * |[<!-- language="C" -->
864 * // recursively iterate a key
866 * iterate_key_recursive (GWin32RegistryKey *key)
868 * GWin32RegistrySubkeyIter iter;
870 * GWin32RegistryKey *child;
872 * if (!g_win32_registry_subkey_iter_init (&iter, key, NULL))
875 * while (g_win32_registry_subkey_iter_next (&iter, TRUE, NULL))
877 * if (!g_win32_registry_subkey_iter_get_name (&iter, &name, NULL, NULL))
880 * g_print ("subkey '%s'\n", name);
881 * child = g_win32_registry_key_get_child (key, name, NULL);
884 * iterate_key_recursive (child);
887 * g_win32_registry_subkey_iter_clear (&iter);
891 * Returns: %TRUE if next subkey info was retrieved, %FALSE otherwise.
896 g_win32_registry_subkey_iter_next (GWin32RegistrySubkeyIter *iter,
897 gboolean skip_errors,
903 g_return_val_if_fail (iter != NULL, FALSE);
904 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
906 if G_UNLIKELY (iter->counter >= iter->subkey_count)
908 g_critical ("g_win32_registry_subkey_iter_get_next_w: must not be called again "
909 "after FALSE has already been returned.");
917 if (iter->counter >= iter->subkey_count)
920 /* Including 0-terminator */
921 subkey_len = iter->subkey_name_size;
922 status = RegEnumKeyExW (iter->key->priv->handle,
926 NULL, NULL, NULL, NULL);
928 if (status == ERROR_SUCCESS)
930 iter->subkey_name_len = subkey_len;
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;
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
955 * %NULL if length is not needed.
956 * @error: (nullable): a pointer to %NULL #GError, or %NULL
958 * Same as g_win32_registry_subkey_iter_get_next(), but outputs UTF-16-encoded
959 * data, without converting it to UTF-8 first.
961 * Returns: %TRUE if the name was retrieved, %FALSE otherwise.
966 g_win32_registry_subkey_iter_get_name_w (GWin32RegistrySubkeyIter *iter,
967 const gunichar2 **subkey_name,
968 gsize *subkey_name_len,
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);
975 if G_UNLIKELY (iter->counter >= iter->subkey_count)
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.");
983 *subkey_name = iter->subkey_name;
986 *subkey_name_len = iter->subkey_name_len;
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
1001 * Gets the name of the subkey at the @iter potision.
1003 * Returns: %TRUE if the name was retrieved, %FALSE otherwise.
1008 g_win32_registry_subkey_iter_get_name (GWin32RegistrySubkeyIter *iter,
1009 const gchar **subkey_name,
1010 gsize *subkey_name_len,
1013 glong subkey_name_len_glong;
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);
1019 if G_UNLIKELY (iter->counter >= iter->subkey_count)
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.");
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,
1031 &subkey_name_len_glong,
1034 if (iter->subkey_name_u8 == NULL)
1037 *subkey_name = iter->subkey_name_u8;
1039 if (subkey_name_len)
1040 *subkey_name_len = subkey_name_len_glong;
1046 * g_win32_registry_value_iter_init:
1047 * @iter: (in) (transfer none): a pointer to a #GWin32RegistryValueIter
1048 * @key: (in) (transfer none): a #GWin32RegistryKey to iterate over
1049 * @error: (nullable): a pointer to %NULL #GError, or %NULL
1051 * Initialises (without allocating) a #GWin32RegistryValueIter. @iter may be
1052 * completely uninitialised prior to this call; its old value is
1055 * The iterator remains valid for as long as @key exists.
1056 * Clean up its internal buffers with a call to
1057 * g_win32_registry_value_iter_clear() when done.
1059 * Returns: %TRUE if iterator was initialized successfully, %FALSE on error.
1064 g_win32_registry_value_iter_init (GWin32RegistryValueIter *iter,
1065 GWin32RegistryKey *key,
1070 DWORD max_value_len;
1073 g_return_val_if_fail (iter != NULL, FALSE);
1074 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), FALSE);
1075 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1077 status = RegQueryInfoKeyW (key->priv->handle,
1078 NULL, NULL, NULL, NULL, NULL, NULL,
1079 &value_count, &max_value_len,
1080 &max_data_len, NULL, NULL);
1082 if (status != ERROR_SUCCESS)
1084 g_set_error (error, G_IO_ERROR, g_io_error_from_win32_error (status),
1085 "Failed to query info for registry key '%S'",
1086 g_win32_registry_key_get_path_w (key));
1090 iter->key = g_object_ref (key);
1092 iter->value_count = value_count;
1093 iter->value_name_size = sizeof (gunichar2) * (max_value_len + 1);
1094 iter->value_name = g_malloc (iter->value_name_size);
1095 /* FIXME: max_value_data_len is said to have no size limit in newer W32
1096 * versions (and its size limit in older ones is 1MB!). Consider limiting it
1097 * with a hard-coded value, or by allowing the user to choose a limit.
1099 /* Two extra gunichar2s is for cases when a string was stored in the
1100 * Registry without a 0-terminator (for multiline strings - 00-terminator),
1101 * and we need to terminate it ourselves.
1103 iter->value_data_size = max_data_len + sizeof (gunichar2) * 2;
1104 iter->value_data = g_malloc (iter->value_data_size);
1105 iter->value_name_u8 = NULL;
1106 iter->value_data_u8 = NULL;
1107 iter->value_data_expanded = NULL;
1108 iter->value_data_expanded_charsize = 0;
1109 iter->value_data_expanded_u8 = NULL;
1110 iter->value_data_expanded_u8_size = 0;
1115 * g_win32_registry_value_iter_clear:
1116 * @iter: (in) (transfer none): a #GWin32RegistryValueIter
1118 * Frees internal buffers of a #GWin32RegistryValueIter.
1123 g_win32_registry_value_iter_clear (GWin32RegistryValueIter *iter)
1125 g_return_if_fail (iter != NULL);
1127 g_free (iter->value_name);
1128 g_free (iter->value_data);
1129 g_free (iter->value_name_u8);
1130 g_free (iter->value_data_u8);
1131 g_free (iter->value_data_expanded);
1132 g_free (iter->value_data_expanded_u8);
1133 g_clear_object (&iter->key);
1137 * g_win32_registry_value_iter_n_values:
1138 * @iter: (in) (transfer none): a #GWin32RegistryValueIter
1140 * Queries the number of values items in the key that we are
1141 * iterating over. This is the total number of values -- not the number
1142 * of items remaining.
1144 * This information is accurate at the point of iterator initialization,
1145 * and may go out of sync with reality even while values are enumerated.
1147 * Returns: the number of values in the key
1152 g_win32_registry_value_iter_n_values (GWin32RegistryValueIter *iter)
1154 g_return_val_if_fail (iter != NULL, 0);
1156 return iter->value_count;
1159 static GWin32RegistryValueType
1160 _g_win32_registry_type_w_to_g (DWORD value_type)
1165 return G_WIN32_REGISTRY_VALUE_BINARY;
1167 return G_WIN32_REGISTRY_VALUE_UINT32;
1168 #if G_BYTE_ORDER == G_BIG_ENDIAN
1169 case REG_DWORD_LITTLE_ENDIAN:
1170 return G_WIN32_REGISTRY_VALUE_UINT32LE;
1172 case REG_DWORD_BIG_ENDIAN:
1173 return G_WIN32_REGISTRY_VALUE_UINT32BE;
1176 return G_WIN32_REGISTRY_VALUE_EXPAND_STR;
1178 return G_WIN32_REGISTRY_VALUE_LINK;
1180 return G_WIN32_REGISTRY_VALUE_MULTI_STR;
1182 return G_WIN32_REGISTRY_VALUE_NONE;
1184 return G_WIN32_REGISTRY_VALUE_UINT64;
1185 #if G_BYTE_ORDER == G_BIG_ENDIAN
1186 case REG_QWORD_LITTLE_ENDIAN:
1187 return G_WIN32_REGISTRY_VALUE_UINT64LE;
1190 return G_WIN32_REGISTRY_VALUE_STR;
1192 return G_WIN32_REGISTRY_VALUE_NONE;
1197 ensure_nul_termination (GWin32RegistryValueType value_type,
1199 gsize value_data_size)
1201 gsize new_size = value_data_size;
1203 if (value_type == G_WIN32_REGISTRY_VALUE_EXPAND_STR ||
1204 value_type == G_WIN32_REGISTRY_VALUE_LINK ||
1205 value_type == G_WIN32_REGISTRY_VALUE_STR)
1207 if ((value_data_size < 2) ||
1208 (value_data[value_data_size - 1] != 0) ||
1209 (value_data[value_data_size - 2] != 0))
1211 value_data[value_data_size] = 0;
1212 value_data[value_data_size + 1] = 0;
1216 else if (value_type == G_WIN32_REGISTRY_VALUE_MULTI_STR)
1218 if ((value_data_size < 4) ||
1219 (value_data[value_data_size - 1] != 0) ||
1220 (value_data[value_data_size - 2] != 0) ||
1221 (value_data[value_data_size - 3] != 0) ||
1222 (value_data[value_data_size - 4] != 0))
1224 value_data[value_data_size] = 0;
1225 value_data[value_data_size + 1] = 0;
1226 value_data[value_data_size + 2] = 0;
1227 value_data[value_data_size + 3] = 0;
1236 * g_win32_registry_value_iter_next:
1237 * @iter: (in) (transfer none): a #GWin32RegistryValueIter
1238 * @skip_errors: (in): %TRUE if iterator should silently ignore errors (such as
1239 * the actual number of values being less than expected) and
1241 * @error: (nullable): a pointer to %NULL #GError, or %NULL
1243 * Advances iterator to the next value in the key. If no more values remain then
1244 * FALSE is returned.
1245 * Enumeration errors can be ignored if @skip_errors is %TRUE
1247 * Here is an example for iterating with g_win32_registry_value_iter_next():
1248 * |[<!-- language="C" -->
1249 * // iterate values of a key
1251 * iterate_values_recursive (GWin32RegistryKey *key)
1253 * GWin32RegistryValueIter iter;
1255 * GWin32RegistryValueType val_type;
1258 * if (!g_win32_registry_value_iter_init (&iter, key, NULL))
1261 * while (g_win32_registry_value_iter_next (&iter, TRUE, NULL))
1263 * if ((!g_win32_registry_value_iter_get_value_type (&iter, &value)) ||
1264 * ((val_type != G_WIN32_REGISTRY_VALUE_STR) &&
1265 * (val_type != G_WIN32_REGISTRY_VALUE_EXPAND_STR)))
1268 * if (g_win32_registry_value_iter_get_value (&iter, TRUE, &name, NULL,
1269 * &val_data, NULL, NULL))
1270 * g_print ("value '%s' = '%s'\n", name, val_data);
1273 * g_win32_registry_value_iter_clear (&iter);
1277 * Returns: %TRUE if next value info was retrieved, %FALSE otherwise.
1282 g_win32_registry_value_iter_next (GWin32RegistryValueIter *iter,
1283 gboolean skip_errors,
1287 DWORD value_name_len_w;
1288 DWORD value_data_size_w;
1290 GWin32RegistryValueType value_type_g;
1292 g_return_val_if_fail (iter != NULL, FALSE);
1293 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1295 if G_UNLIKELY (iter->counter >= iter->value_count)
1297 g_critical ("g_win32_registry_value_iter_next: must not be called "
1298 "again after FALSE has already been returned.");
1306 if (iter->counter >= iter->value_count)
1309 g_clear_pointer (&iter->value_name_u8, g_free);
1310 g_clear_pointer (&iter->value_data_u8, g_free);
1311 g_clear_pointer (&iter->value_data_expanded_u8, g_free);
1312 /* Including 0-terminator */
1313 value_name_len_w = iter->value_name_size / sizeof (gunichar2);
1314 value_data_size_w = iter->value_data_size;
1315 status = RegEnumValueW (iter->key->priv->handle,
1321 (LPBYTE) iter->value_data,
1322 &value_data_size_w);
1324 if (status != ERROR_SUCCESS && !skip_errors)
1326 g_set_error (error, G_IO_ERROR, g_io_error_from_win32_error (status),
1327 "Failed to enumerate value #%d for key '%S'",
1328 iter->counter, g_win32_registry_key_get_path_w (iter->key));
1329 iter->value_count = 0;
1333 else if (status != ERROR_SUCCESS && skip_errors)
1336 value_type_g = _g_win32_registry_type_w_to_g (value_type_w);
1337 value_data_size_w = ensure_nul_termination (value_type_g,
1340 iter->value_type = value_type_g;
1341 iter->value_expanded_type = value_type_g;
1342 iter->value_actual_data_size = value_data_size_w;
1343 iter->value_name_len = value_name_len_w;
1350 * g_win32_registry_value_iter_get_value_type:
1351 * @iter: (in) (transfer none): a #GWin32RegistryValueIter
1352 * @value_type: (out): Pointer to a location to store the type of
1354 * @error: (nullable): a pointer to %NULL #GError, or %NULL
1356 * Stores the type of the value currently being iterated over in @value_type.
1358 * Returns: %TRUE if value type was retrieved, %FALSE otherwise.
1363 g_win32_registry_value_iter_get_value_type (GWin32RegistryValueIter *iter,
1364 GWin32RegistryValueType *value_type,
1367 g_return_val_if_fail (iter != NULL, FALSE);
1368 g_return_val_if_fail (value_type != NULL, FALSE);
1369 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1371 if G_UNLIKELY (iter->counter >= iter->value_count)
1373 g_critical ("g_win32_registry_value_iter_get_type: must not be called "
1374 "again after NULL has already been returned.");
1378 *value_type = iter->value_type;
1384 * g_win32_registry_value_iter_get_name_w:
1385 * @iter: (in) (transfer none): a #GWin32RegistryValueIter
1386 * @value_name: (out callee-allocates) (transfer none): Pointer to a location
1387 * to store the name of a value (in UTF-16).
1388 * @value_name_len: (out) (optional): Pointer to a location to store the length
1389 * of @value_name, in gunichar2s, excluding NUL-terminator.
1390 * %NULL if length is not needed.
1391 * @error: (nullable): a pointer to %NULL #GError, or %NULL
1393 * Stores the name of the value currently being iterated over in @value_name,
1394 * and its length - in @value_name (if not %NULL).
1396 * Returns: %TRUE if value name was retrieved, %FALSE otherwise.
1401 g_win32_registry_value_iter_get_name_w (GWin32RegistryValueIter *iter,
1402 gunichar2 **value_name,
1403 gsize *value_name_len,
1406 g_return_val_if_fail (iter != NULL, FALSE);
1407 g_return_val_if_fail (value_name != NULL, FALSE);
1408 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1410 if G_UNLIKELY (iter->counter >= iter->value_count)
1412 g_critical ("g_win32_registry_value_iter_get_name_w: must not be called "
1413 "again after NULL has already been returned.");
1417 *value_name = iter->value_name;
1420 *value_name_len = iter->value_name_len;
1426 * g_win32_registry_value_iter_get_name:
1427 * @iter: (in) (transfer none): a #GWin32RegistryValueIter
1428 * @value_name: (out callee-allocates) (transfer none): Pointer to a location
1429 * to store the name of a value (in UTF-8).
1430 * @value_name_len: (out) (optional): Pointer to a location to store the length
1431 * of @value_name, in gchars, excluding NUL-terminator.
1432 * %NULL if length is not needed.
1433 * @error: (nullable): a pointer to %NULL #GError, or %NULL
1435 * Stores the name of the value currently being iterated over in @value_name,
1436 * and its length - in @value_name_len (if not %NULL).
1438 * Returns: %TRUE if value name was retrieved, %FALSE otherwise.
1443 g_win32_registry_value_iter_get_name (GWin32RegistryValueIter *iter,
1445 gsize *value_name_len,
1448 glong value_name_len_glong;
1450 g_return_val_if_fail (iter != NULL, FALSE);
1451 g_return_val_if_fail (value_name != NULL, FALSE);
1452 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1454 if G_UNLIKELY (iter->counter >= iter->value_count)
1456 g_critical ("g_win32_registry_value_iter_get_name: must not be called "
1457 "again after NULL has already been returned.");
1461 if (iter->value_name_u8 == NULL)
1463 iter->value_name_u8 = g_utf16_to_utf8 (iter->value_name, iter->value_name_len, NULL,
1464 &value_name_len_glong, error);
1466 if (iter->value_name_u8 == NULL)
1470 *value_name = iter->value_name_u8;
1473 *value_name_len = iter->value_name_u8_len;
1479 expand_value (gunichar2 *value,
1480 const gunichar2 *value_name,
1481 gpointer *expanded_value,
1482 gsize *expanded_charsize,
1485 DWORD value_data_expanded_charsize_w;
1487 value_data_expanded_charsize_w =
1488 ExpandEnvironmentStringsW (value,
1489 (gunichar2 *) *expanded_value,
1490 *expanded_charsize);
1492 if (value_data_expanded_charsize_w > *expanded_charsize)
1494 *expanded_value = g_realloc (*expanded_value,
1495 value_data_expanded_charsize_w * sizeof (gunichar2));
1496 *expanded_charsize = value_data_expanded_charsize_w;
1497 value_data_expanded_charsize_w =
1498 ExpandEnvironmentStringsW (value,
1499 (gunichar2 *) *expanded_value,
1500 *expanded_charsize);
1503 if (value_data_expanded_charsize_w == 0)
1505 g_set_error (error, G_IO_ERROR,
1506 g_io_error_from_win32_error (GetLastError ()),
1507 "Failed to expand data '%S' of value %S",
1516 * g_win32_registry_value_iter_get_data_w:
1517 * @iter: (in) (transfer none): a #GWin32RegistryValueIter
1518 * @auto_expand: (in): %TRUE to automatically expand G_WIN32_REGISTRY_VALUE_EXPAND_STR to
1519 * G_WIN32_REGISTRY_VALUE_STR
1520 * @value_data: (out callee-allocates) (optional) (transfer none): Pointer to a
1521 * location to store the data of the value (in UTF-16, if it's a string)
1522 * @value_data_size: (out) (optional): Pointer to a location to store the size
1523 * of @value_data, in bytes (including any NUL-terminators, if it's a string).
1524 * %NULL if length is not needed.
1525 * @error: (nullable): a pointer to %NULL #GError, or %NULL
1527 * Stores the data of the value currently being iterated over in @value_data,
1528 * and its length - in @value_data_len (if not %NULL).
1530 * Returns: %TRUE if value data was retrieved, %FALSE otherwise.
1535 g_win32_registry_value_iter_get_data_w (GWin32RegistryValueIter *iter,
1536 gboolean auto_expand,
1537 gpointer *value_data,
1538 gsize *value_data_size,
1541 g_return_val_if_fail (iter != NULL, FALSE);
1542 g_return_val_if_fail (value_data != NULL, FALSE);
1543 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1545 if G_UNLIKELY (iter->counter >= iter->value_count)
1547 g_critical ("g_win32_registry_value_iter_get_data_w: must not be called "
1548 "again after FALSE has already been returned.");
1552 if (!auto_expand || (iter->value_type != G_WIN32_REGISTRY_VALUE_EXPAND_STR))
1554 *value_data = iter->value_data;
1556 if (value_data_size)
1557 *value_data_size = iter->value_actual_data_size;
1562 if (iter->value_type == iter->value_expanded_type)
1564 if (!expand_value ((gunichar2 *) iter->value_data,
1566 (gpointer *) &iter->value_data_expanded,
1567 &iter->value_data_expanded_charsize,
1571 iter->value_expanded_type = G_WIN32_REGISTRY_VALUE_STR;
1574 *value_data = iter->value_data_expanded;
1576 if (value_data_size)
1577 *value_data_size = iter->value_data_expanded_charsize * sizeof (gunichar2);
1583 * g_win32_registry_value_iter_get_data:
1584 * @iter: (in) (transfer none): a #GWin32RegistryValueIter
1585 * @auto_expand: (in): %TRUE to automatically expand G_WIN32_REGISTRY_VALUE_EXPAND_STR to
1586 * G_WIN32_REGISTRY_VALUE_STR
1587 * @value_data: (out callee-allocates) (optional) (transfer none): Pointer to a
1588 * location to store the data of the value (in UTF-8, if it's a string)
1589 * @value_data_size: (out) (optional): Pointer to a location to store the length
1590 * of @value_data, in bytes (including any NUL-terminators, if it's a string).
1591 * %NULL if length is not needed
1592 * @error: (nullable): a pointer to %NULL #GError, or %NULL
1594 * Stores the data of the value currently being iterated over in @value_data,
1595 * and its length - in @value_data_len (if not %NULL).
1597 * Returns: %TRUE if value data was retrieved, %FALSE otherwise.
1602 g_win32_registry_value_iter_get_data (GWin32RegistryValueIter *iter,
1603 gboolean auto_expand,
1604 gpointer *value_data,
1605 gsize *value_data_size,
1608 gsize value_data_len_gsize;
1612 g_return_val_if_fail (iter != NULL, FALSE);
1613 g_return_val_if_fail (value_data != NULL, FALSE);
1614 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1616 if G_UNLIKELY (iter->counter >= iter->value_count)
1618 g_critical ("g_win32_registry_value_iter_get_data: must not be called "
1619 "again after FALSE has already been returned.");
1623 if (iter->value_type != G_WIN32_REGISTRY_VALUE_EXPAND_STR &&
1624 iter->value_type != G_WIN32_REGISTRY_VALUE_LINK &&
1625 iter->value_type != G_WIN32_REGISTRY_VALUE_STR &&
1626 iter->value_type != G_WIN32_REGISTRY_VALUE_MULTI_STR)
1628 *value_data = iter->value_data;
1630 if (value_data_size != NULL)
1631 *value_data_size = iter->value_actual_data_size;
1636 if (!auto_expand || (iter->value_type != G_WIN32_REGISTRY_VALUE_EXPAND_STR))
1638 if (iter->value_data_u8 == NULL)
1640 iter->value_data_u8 = g_convert ((const gchar *) iter->value_data,
1641 iter->value_actual_data_size - sizeof (gunichar2) /* excl. 0 */,
1642 "UTF8", "UTF16", NULL,
1643 &value_data_len_gsize,
1646 if (iter->value_data_u8 == NULL)
1649 iter->value_data_u8_size = value_data_len_gsize + 1; /* incl. 0 */
1652 *value_data = iter->value_data_u8;
1654 if (value_data_size != NULL)
1655 *value_data_size = iter->value_data_u8_size;
1660 if (iter->value_data_expanded_u8 == NULL)
1662 if (!g_win32_registry_value_iter_get_data_w (iter,
1669 iter->value_data_expanded_u8 = g_convert ((const gchar *) iter->value_data_expanded,
1670 iter->value_data_expanded_charsize * sizeof (gunichar2) - sizeof (gunichar2) /* excl. 0 */,
1671 "UTF8", "UTF16", NULL,
1672 &value_data_len_gsize,
1675 if (iter->value_data_expanded_u8 == NULL)
1678 iter->value_data_u8_size = value_data_len_gsize + 1; /* incl. 0 */
1681 *value_data = iter->value_data_expanded_u8;
1683 if (value_data_size != NULL)
1684 *value_data_size = iter->value_data_expanded_u8_size;
1690 _g_win32_registry_key_reread_kernel (GWin32RegistryKey *key,
1691 GWin32RegistryKeyPrivate *buf)
1694 KEY_BASIC_INFORMATION *basic_info;
1695 ULONG basic_info_size;
1698 basic_info_size = 256 * sizeof (gunichar2) + sizeof (KEY_BASIC_INFORMATION);
1699 basic_info = g_malloc (basic_info_size + sizeof (gunichar2));
1700 status = nt_query_key (key->priv->handle,
1701 KeyBasicInformation,
1706 if (status == STATUS_BUFFER_OVERFLOW || status == STATUS_BUFFER_TOO_SMALL)
1708 g_free (basic_info);
1709 basic_info_size = datasize;
1710 /* +1 for 0-terminator */
1711 basic_info = g_malloc (basic_info_size + sizeof (gunichar2));
1712 status = nt_query_key (key->priv->handle,
1713 KeyBasicInformation,
1719 if (status != STATUS_SUCCESS)
1721 g_free (basic_info);
1725 /* Ensure 0-termination */
1726 ((char *) basic_info)[datasize] = 0;
1727 ((char *) basic_info)[datasize + 1] = 0;
1729 buf->absolute_path_w = g_wcsdup (&basic_info->Name[0],
1730 basic_info->NameLength + sizeof (gunichar2));
1731 g_free (basic_info);
1735 _g_win32_registry_key_reread_user (GWin32RegistryKey *key,
1736 GWin32RegistryKeyPrivate *buf)
1738 /* Use RegQueryInfoKey(). It's just like NtQueryKey(), but can't query
1740 * Since right now we only need the name, this function is a noop.
1745 _g_win32_registry_key_reread (GWin32RegistryKey *key,
1746 GWin32RegistryKeyPrivate *buf)
1748 if (g_once_init_enter (&nt_query_key))
1750 NtQueryKeyFunc func;
1751 HMODULE ntdll = GetModuleHandleW (L"ntdll.dll");
1754 func = (NtQueryKeyFunc) GetProcAddress (ntdll, "NtQueryKey");
1758 g_once_init_leave (&nt_query_key, func);
1761 /* Assume that predefined keys never get renamed. Also, their handles probably
1762 * won't be accepted by NtQueryKey(), i suspect.
1764 if (nt_query_key != NULL && !key->priv->predefined)
1765 _g_win32_registry_key_reread_kernel (key, buf);
1767 _g_win32_registry_key_reread_user (key, buf);
1771 _g_win32_registry_key_update_path (GWin32RegistryKey *key)
1773 GWin32RegistryKeyPrivate tmp;
1775 gint change_indicator;
1777 change_indicator = g_atomic_int_get (&key->priv->change_indicator);
1779 if (change_indicator == G_WIN32_KEY_UNCHANGED)
1782 tmp.absolute_path_w = NULL;
1783 _g_win32_registry_key_reread (key, &tmp);
1786 if (wcscmp (key->priv->absolute_path_w, tmp.absolute_path_w) == 0)
1787 g_free (tmp.absolute_path_w);
1790 g_free (key->priv->absolute_path_w);
1791 key->priv->absolute_path_w = tmp.absolute_path_w;
1799 * g_win32_registry_key_get_path:
1800 * @key: (in) (transfer none): a #GWin32RegistryKey
1802 * Get full path to the key
1804 * Returns: (transfer none): a full path to the key (in UTF-8),
1805 * or %NULL if it can't be converted to UTF-8.
1810 g_win32_registry_key_get_path (GWin32RegistryKey *key)
1812 gint change_indicator;
1814 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), NULL);
1816 change_indicator = g_atomic_int_get (&key->priv->change_indicator);
1818 if (change_indicator == G_WIN32_KEY_CHANGED &&
1819 !(key->priv->update_flags & G_WIN32_REGISTRY_UPDATED_PATH))
1821 _g_win32_registry_key_update_path (key);
1822 key->priv->update_flags |= G_WIN32_REGISTRY_UPDATED_PATH;
1825 if (key->priv->absolute_path == NULL)
1827 g_free (key->priv->absolute_path);
1828 key->priv->absolute_path =
1829 g_utf16_to_utf8 (key->priv->absolute_path_w, -1,
1833 return key->priv->absolute_path;
1837 * g_win32_registry_key_get_path_w:
1838 * @key: (in) (transfer none): a #GWin32RegistryKey
1840 * Get full path to the key
1842 * Returns: (transfer none): a full path to the key (in UTF-16)
1847 g_win32_registry_key_get_path_w (GWin32RegistryKey *key)
1849 gint change_indicator;
1851 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), NULL);
1853 change_indicator = g_atomic_int_get (&key->priv->change_indicator);
1855 if (change_indicator == G_WIN32_KEY_CHANGED)
1856 _g_win32_registry_key_update_path (key);
1858 return key->priv->absolute_path_w;
1862 * g_win32_registry_get_os_dirs_w:
1864 * Returns a list of directories for DLL lookups.
1865 * Can be used with g_win32_registry_key_get_value_w().
1867 * Returns: (array zero-terminated=1) (transfer none): a %NULL-terminated array of UTF-16 strings.
1871 const gunichar2 * const *
1872 g_win32_registry_get_os_dirs_w (void)
1874 static gunichar2 **mui_os_dirs = NULL;
1876 if (g_once_init_enter (&mui_os_dirs))
1878 gunichar2 **new_mui_os_dirs;
1879 gunichar2 *system32 = NULL;
1880 gunichar2 *syswow64 = NULL;
1882 gsize array_index = 0;
1884 buffer_size = GetSystemWow64DirectoryW (NULL, 0);
1886 if (buffer_size > 0)
1889 syswow64 = g_malloc (buffer_size * sizeof (gunichar2));
1890 copied = GetSystemWow64DirectoryW (syswow64, buffer_size);
1892 g_clear_pointer (&syswow64, g_free);
1895 buffer_size = GetSystemDirectoryW (NULL, 0);
1897 if (buffer_size > 0)
1900 system32 = g_malloc (buffer_size * sizeof (gunichar2));
1901 copied = GetSystemDirectoryW (system32, buffer_size);
1903 g_clear_pointer (&system32, g_free);
1906 new_mui_os_dirs = g_new0 (gunichar2 *, 3);
1908 if (system32 != NULL)
1909 new_mui_os_dirs[array_index++] = system32;
1911 if (syswow64 != NULL)
1912 new_mui_os_dirs[array_index++] = syswow64;
1914 new_mui_os_dirs[array_index++] = NULL;
1916 g_once_init_leave (&mui_os_dirs, new_mui_os_dirs);
1919 return (const gunichar2 * const *) mui_os_dirs;
1923 * g_win32_registry_get_os_dirs:
1925 * Returns a list of directories for DLL lookups.
1926 * Can be used with g_win32_registry_key_get_value().
1928 * Returns: (array zero-terminated=1) (transfer none): a %NULL-terminated array of UTF-8 strings.
1932 const gchar * const *
1933 g_win32_registry_get_os_dirs (void)
1935 static gchar **mui_os_dirs = NULL;
1937 if (g_once_init_enter (&mui_os_dirs))
1939 gchar **new_mui_os_dirs;
1941 gsize new_array_index;
1942 const gunichar2 * const *mui_os_dirs_utf16 = g_win32_registry_get_os_dirs_w ();
1944 for (array_index = 0; mui_os_dirs_utf16[array_index] != NULL; array_index++)
1947 new_mui_os_dirs = g_new0 (gchar *, array_index + 1);
1949 for (array_index = 0, new_array_index = 0;
1950 mui_os_dirs_utf16[array_index] != NULL;
1953 new_mui_os_dirs[new_array_index] = g_utf16_to_utf8 (mui_os_dirs_utf16[array_index],
1954 -1, NULL, NULL, NULL);
1955 if (new_mui_os_dirs[new_array_index] != NULL)
1956 new_array_index += 1;
1958 g_critical ("Failed to convert to a system directory #%zu to UTF-8", array_index);
1961 g_once_init_leave (&mui_os_dirs, new_mui_os_dirs);
1964 return (const gchar * const *) mui_os_dirs;
1968 * g_win32_registry_key_get_value:
1969 * @key: (in) (transfer none): a #GWin32RegistryKey
1970 * @mui_dll_dirs: (in) (transfer none) (array zero-terminated=1) (optional): a %NULL-terminated
1971 * array of directory names where the OS
1972 * should look for a DLL indicated in a MUI string, if the
1973 * DLL path in the string is not absolute
1974 * @auto_expand: (in) %TRUE to automatically expand G_WIN32_REGISTRY_VALUE_EXPAND_STR
1975 * to G_WIN32_REGISTRY_VALUE_STR.
1976 * @value_name: (in) (transfer none): name of the value to get (in UTF-8).
1977 * Empty string means the '(Default)' value.
1978 * @value_type: (out) (optional): type of the value retrieved.
1979 * @value_data: (out callee-allocates) (optional): contents of the value.
1980 * @value_data_size: (out) (optional): size of the buffer pointed
1982 * @error: (nullable): a pointer to %NULL #GError, or %NULL
1984 * Get data from a value of a key. String data is guaranteed to be
1985 * appropriately terminated and will be in UTF-8.
1987 * When not %NULL, @mui_dll_dirs indicates that `RegLoadMUIStringW()` API
1988 * should be used instead of the usual `RegQueryValueExW()`. This implies
1989 * that the value being queried is of type `REG_SZ` or `REG_EXPAND_SZ` (if it is not, the function
1990 * falls back to `RegQueryValueExW()`), and that this string must undergo special processing
1991 * (see [`SHLoadIndirectString()` documentation](https://docs.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-shloadindirectstring) for an explanation on what
1992 * kinds of strings are processed) to get the result.
1994 * If no specific MUI DLL directories need to be used, pass
1995 * the return value of g_win32_registry_get_os_dirs() as @mui_dll_dirs
1996 * (as an bonus, the value from g_win32_registry_get_os_dirs()
1997 * does not add any extra UTF8->UTF16 conversion overhead).
1999 * @auto_expand works with @mui_dll_dirs, but only affects the processed
2000 * string, making it somewhat useless. The unprocessed string is always expanded
2001 * internally, if its type is `REG_EXPAND_SZ` - there is no need to enable
2002 * @auto_expand for this to work.
2004 * The API for this function changed in GLib 2.66 to add the @mui_dll_dirs argument.
2006 * Returns: %TRUE on success, %FALSE on failure.
2011 g_win32_registry_key_get_value (GWin32RegistryKey *key,
2012 const gchar * const *mui_dll_dirs,
2013 gboolean auto_expand,
2014 const gchar *value_name,
2015 GWin32RegistryValueType *value_type,
2016 gpointer *value_data,
2017 gsize *value_data_size,
2020 GWin32RegistryValueType value_type_g;
2021 gpointer value_data_w;
2022 gsize value_data_w_size;
2023 gunichar2 *value_name_w;
2024 gchar *value_data_u8;
2025 gsize value_data_u8_len;
2027 gsize mui_dll_dirs_count;
2028 gunichar2 **mui_dll_dirs_utf16;
2029 const gchar * const *mui_os_dirs;
2031 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), FALSE);
2032 g_return_val_if_fail (value_name != NULL, FALSE);
2033 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2035 /* No sense calling this function with all of these set to NULL */
2036 g_return_val_if_fail (value_type != NULL ||
2037 value_data != NULL ||
2038 value_data_size != NULL, FALSE);
2040 value_name_w = g_utf8_to_utf16 (value_name, -1, NULL, NULL, error);
2042 if (value_name_w == NULL)
2045 mui_dll_dirs_utf16 = NULL;
2046 mui_os_dirs = g_win32_registry_get_os_dirs ();
2048 if (mui_dll_dirs != NULL &&
2049 mui_dll_dirs != mui_os_dirs)
2053 mui_dll_dirs_count = g_strv_length ((gchar **) mui_dll_dirs);
2054 mui_dll_dirs_utf16 = g_new0 (gunichar2 *, mui_dll_dirs_count + 1);
2056 for (i = 0; mui_dll_dirs[i] != NULL; i++)
2058 mui_dll_dirs_utf16[i] = g_utf8_to_utf16 (mui_dll_dirs[i], -1, NULL, NULL, error);
2060 if (mui_dll_dirs_utf16[i] == NULL)
2064 if (mui_dll_dirs[i] != NULL)
2066 g_prefix_error (error,
2067 "A mui_dll_dirs string #%zu `%s' failed to convert: ",
2068 i, mui_dll_dirs[i]);
2070 for (i = 0; i < mui_dll_dirs_count; i++)
2071 g_free (mui_dll_dirs_utf16[i]);
2073 g_free (mui_dll_dirs_utf16);
2074 g_free (value_name_w);
2079 else if (mui_dll_dirs != NULL &&
2080 mui_dll_dirs == mui_os_dirs)
2082 mui_dll_dirs_utf16 = (gunichar2 **) g_win32_registry_get_os_dirs_w ();
2085 result = g_win32_registry_key_get_value_w (key,
2086 (const gunichar2 * const *) mui_dll_dirs_utf16,
2094 g_free (value_name_w);
2095 if (mui_dll_dirs_utf16 != NULL &&
2096 mui_dll_dirs != mui_os_dirs)
2099 for (array_index = 0; mui_dll_dirs_utf16[array_index] != NULL; array_index++)
2100 g_free (mui_dll_dirs_utf16[array_index]);
2101 g_free (mui_dll_dirs_utf16);
2107 if (value_type_g == G_WIN32_REGISTRY_VALUE_EXPAND_STR ||
2108 value_type_g == G_WIN32_REGISTRY_VALUE_LINK ||
2109 value_type_g == G_WIN32_REGISTRY_VALUE_STR ||
2110 value_type_g == G_WIN32_REGISTRY_VALUE_MULTI_STR)
2112 value_data_u8 = g_convert ((const gchar *) value_data_w,
2113 value_data_w_size - sizeof (gunichar2) /* excl. 0 */,
2119 g_free (value_data_w);
2121 if (value_data_u8 == NULL)
2125 *value_data = value_data_u8;
2127 g_free (value_data_u8);
2129 if (value_data_size)
2130 *value_data_size = value_data_u8_len + 1;
2135 *value_data = value_data_w;
2137 g_free (value_data_w);
2139 if (value_data_size)
2140 *value_data_size = value_data_w_size;
2144 *value_type = value_type_g;
2149 /* A wrapper that calls either RegQueryValueExW() or
2150 * RegLoadMUIStringW() depending on the value of the
2152 * Apart from the extra argument, the function behaves
2153 * just like RegQueryValueExW(), with a few caveats.
2156 MuiRegQueryValueExW (HKEY hKey,
2157 LPCWSTR lpValueName,
2162 const gunichar2 * const *mui_dll_dirs)
2165 LSTATUS result = ERROR_PATH_NOT_FOUND;
2170 if (mui_dll_dirs == NULL)
2171 return RegQueryValueExW (hKey, lpValueName, lpReserved, lpType, lpData, lpcbData);
2175 if (lpcbData != NULL)
2176 bufsize = *lpcbData;
2178 if (mui_dll_dirs[0] != NULL)
2180 /* Optimization: check that the value actually exists,
2181 * before we start trying different mui dll dirs
2183 result = RegQueryValueExW (hKey, lpValueName, NULL, NULL, NULL, 0);
2185 if (result == ERROR_FILE_NOT_FOUND)
2189 Wow64DisableWow64FsRedirection (&old_value);
2191 /* Try with NULL dir first */
2192 result = RegLoadMUIStringW (hKey,
2200 /* Not a MUI value, load normally */
2201 if (result == ERROR_INVALID_DATA)
2203 Wow64RevertWow64FsRedirection (old_value);
2205 return RegQueryValueExW (hKey, lpValueName, lpReserved, lpType, lpData, lpcbData);
2209 result == ERROR_FILE_NOT_FOUND &&
2210 mui_dll_dirs[dir_index] != NULL;
2212 result = RegLoadMUIStringW (hKey,
2218 mui_dll_dirs[dir_index]);
2220 Wow64RevertWow64FsRedirection (old_value);
2222 if (lpcbData != NULL &&
2223 result == ERROR_MORE_DATA)
2224 *lpcbData = data_size;
2226 if (lpType != NULL &&
2227 result != ERROR_INVALID_DATA &&
2228 result != ERROR_FILE_NOT_FOUND)
2235 * g_win32_registry_key_get_value_w:
2236 * @key: (in) (transfer none): a #GWin32RegistryKey
2237 * @mui_dll_dirs: (in) (transfer none) (array zero-terminated=1) (optional): a %NULL-terminated
2238 * array of directory names where the OS
2239 * should look for a DLL indicated in a MUI string, if the
2240 * DLL path in the string is not absolute
2241 * @auto_expand: (in) %TRUE to automatically expand G_WIN32_REGISTRY_VALUE_EXPAND_STR
2242 * to G_WIN32_REGISTRY_VALUE_STR.
2243 * @value_name: (in) (transfer none): name of the value to get (in UTF-16).
2244 * Empty string means the '(Default)' value.
2245 * @value_type: (out) (optional): type of the value retrieved.
2246 * @value_data: (out callee-allocates) (optional): contents of the value.
2247 * @value_data_size: (out) (optional): size of the buffer pointed
2249 * @error: (nullable): a pointer to %NULL #GError, or %NULL
2251 * Get data from a value of a key. String data is guaranteed to be
2252 * appropriately terminated and will be in UTF-16.
2254 * When calling with value_data == NULL (to get data size without getting
2255 * the data itself) remember that returned size corresponds to possibly
2256 * unterminated string data (if value is some kind of string), because
2257 * termination cannot be checked and fixed unless the data is retrieved
2260 * When not %NULL, @mui_dll_dirs indicates that `RegLoadMUIStringW()` API
2261 * should be used instead of the usual `RegQueryValueExW()`. This implies
2262 * that the value being queried is of type `REG_SZ` or `REG_EXPAND_SZ` (if it is not, the function
2263 * falls back to `RegQueryValueExW()`), and that this string must undergo special processing
2264 * (see [`SHLoadIndirectString()` documentation](https://docs.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-shloadindirectstring) for an explanation on what
2265 * kinds of strings are processed) to get the result.
2267 * If no specific MUI DLL directories need to be used, pass
2268 * the return value of g_win32_registry_get_os_dirs_w() as @mui_dll_dirs.
2270 * @auto_expand works with @mui_dll_dirs, but only affects the processed
2271 * string, making it somewhat useless. The unprocessed string is always expanded
2272 * internally, if its type is `REG_EXPAND_SZ` - there is no need to enable
2273 * @auto_expand for this to work.
2275 * The API for this function changed in GLib 2.66 to add the @mui_dll_dirs argument.
2277 * Returns: %TRUE on success, %FALSE on failure.
2282 g_win32_registry_key_get_value_w (GWin32RegistryKey *key,
2283 const gunichar2 * const *mui_dll_dirs,
2284 gboolean auto_expand,
2285 const gunichar2 *value_name,
2286 GWin32RegistryValueType *value_type,
2287 gpointer *value_data,
2288 gsize *value_data_size,
2293 DWORD value_type_w2;
2294 char *req_value_data;
2295 GWin32RegistryValueType value_type_g;
2296 GWin32RegistryValueType value_type_g2;
2297 DWORD req_value_data_size;
2298 DWORD req_value_data_size2;
2300 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), FALSE);
2301 g_return_val_if_fail (value_name != NULL, FALSE);
2302 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2304 /* No sense calling this functions with all of these set to NULL */
2305 g_return_val_if_fail (value_type != NULL ||
2306 value_data != NULL ||
2307 value_data_size != NULL, FALSE);
2309 req_value_data_size = 0;
2310 status = MuiRegQueryValueExW (key->priv->handle,
2315 &req_value_data_size,
2318 if (status != ERROR_MORE_DATA && status != ERROR_SUCCESS)
2320 g_set_error (error, G_IO_ERROR, g_io_error_from_win32_error (status),
2321 "Failed to query value '%S' for key '%S'",
2322 value_name, g_win32_registry_key_get_path_w (key));
2327 value_type_g = _g_win32_registry_type_w_to_g (value_type_w);
2329 if (value_data == NULL &&
2330 (!auto_expand || value_type_g != G_WIN32_REGISTRY_VALUE_EXPAND_STR))
2333 *value_type = value_type_g;
2335 if (value_data_size)
2336 *value_data_size = req_value_data_size;
2341 req_value_data = g_malloc (req_value_data_size + sizeof (gunichar2) * 2);
2342 req_value_data_size2 = req_value_data_size;
2343 status = MuiRegQueryValueExW (key->priv->handle,
2347 (gpointer) req_value_data,
2348 &req_value_data_size2,
2351 if (status != ERROR_SUCCESS)
2353 g_set_error (error, G_IO_ERROR, g_io_error_from_win32_error (status),
2354 "Failed to query value '%S' of size %lu for key '%S'",
2356 req_value_data_size,
2357 g_win32_registry_key_get_path_w (key));
2358 g_free (req_value_data);
2362 value_type_g2 = _g_win32_registry_type_w_to_g (value_type_w2);
2364 if (value_type_w != value_type_w2)
2366 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
2367 "Type of value '%S' of key '%S' changed from %u to %u"
2370 g_win32_registry_key_get_path_w (key),
2371 value_type_g, value_type_g2);
2372 g_free (req_value_data);
2376 req_value_data_size = ensure_nul_termination (value_type_g,
2377 (guint8 *) req_value_data,
2378 req_value_data_size2);
2380 if (value_type_g == G_WIN32_REGISTRY_VALUE_EXPAND_STR && auto_expand)
2382 gsize value_data_expanded_charsize_w = 0;
2383 gunichar2 *value_data_expanded = NULL;
2385 if (!expand_value ((gunichar2 *) req_value_data,
2387 (gpointer *) &value_data_expanded,
2388 &value_data_expanded_charsize_w,
2392 g_free (req_value_data);
2395 *value_type = G_WIN32_REGISTRY_VALUE_STR;
2398 *value_data = value_data_expanded;
2400 g_free (value_data_expanded);
2402 if (value_data_size)
2403 *value_data_size = value_data_expanded_charsize_w * sizeof (gunichar2);
2409 *value_type = value_type_g;
2411 if (value_data_size)
2412 *value_data_size = req_value_data_size;
2415 *value_data = req_value_data;
2417 g_free (req_value_data);
2423 key_changed (PVOID closure,
2424 PIO_STATUS_BLOCK status_block,
2427 GWin32RegistryKey *key = G_WIN32_REGISTRY_KEY (closure);
2429 GWin32RegistryKeyWatchCallbackFunc callback;
2431 callback = g_steal_pointer (&key->priv->callback);
2432 user_data = g_steal_pointer (&key->priv->user_data);
2434 g_free (status_block);
2435 g_atomic_int_set (&key->priv->change_indicator, G_WIN32_KEY_CHANGED);
2436 g_atomic_int_set (&key->priv->watch_indicator, G_WIN32_KEY_UNWATCHED);
2437 key->priv->update_flags = G_WIN32_REGISTRY_UPDATED_NOTHING;
2440 callback (key, user_data);
2442 g_object_unref (key);
2446 * g_win32_registry_key_watch:
2447 * @key: (in) (transfer none): a #GWin32RegistryKey
2448 * @watch_children: (in) %TRUE also watch the children of the @key, %FALSE
2449 * to watch the key only.
2450 * @watch_flags: (in): specifies the types of changes to watch for.
2451 * @callback: (in) (nullable): a function to invoke when a change occurs.
2452 * @user_data: (in) (nullable): a pointer to pass to @callback on invocation.
2453 * @error: (nullable): a pointer to %NULL #GError, or %NULL
2455 * Puts @key under a watch.
2457 * When the key changes, an APC will be queued in the current thread. The APC
2458 * will run when the current thread enters alertable state (GLib main loop
2459 * should do that; if you are not using it, see MSDN documentation for W32API
2460 * calls that put thread into alertable state). When it runs, it will
2461 * atomically switch an indicator in the @key. If a callback was specified,
2462 * it is invoked at that point. Subsequent calls to
2463 * g_win32_registry_key_has_changed() will return %TRUE, and the callback (if
2464 * it was specified) will not be invoked anymore.
2465 * Calling g_win32_registry_key_erase_change_indicator() will reset the indicator,
2466 * and g_win32_registry_key_has_changed() will start returning %FALSE.
2467 * To resume the watch, call g_win32_registry_key_watch_for_changes() again.
2469 * Calling g_win32_registry_key_watch_for_changes() for a key that is already
2470 * being watched is allowed and affects nothing.
2472 * The fact that the key is being watched will be used internally to update
2473 * key path (if it changes).
2475 * Returns: %TRUE on success, %FALSE on failure.
2480 g_win32_registry_key_watch (GWin32RegistryKey *key,
2481 gboolean watch_children,
2482 GWin32RegistryKeyWatcherFlags watch_flags,
2483 GWin32RegistryKeyWatchCallbackFunc callback,
2488 gboolean started_to_watch;
2490 PIO_STATUS_BLOCK status_block;
2492 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), FALSE);
2494 filter = ((watch_flags & G_WIN32_REGISTRY_WATCH_NAME) ? REG_NOTIFY_CHANGE_NAME : 0) |
2495 ((watch_flags & G_WIN32_REGISTRY_WATCH_ATTRIBUTES) ? REG_NOTIFY_CHANGE_ATTRIBUTES : 0) |
2496 ((watch_flags & G_WIN32_REGISTRY_WATCH_VALUES) ? REG_NOTIFY_CHANGE_LAST_SET : 0) |
2497 ((watch_flags & G_WIN32_REGISTRY_WATCH_SECURITY) ? REG_NOTIFY_CHANGE_SECURITY : 0);
2501 g_critical ("No supported flags specified in watch_flags (%x)", (guint) watch_flags);
2505 if (g_once_init_enter (&nt_notify_change_multiple_keys))
2507 NtNotifyChangeMultipleKeysFunc func;
2508 HMODULE ntdll = GetModuleHandleW (L"ntdll.dll");
2511 func = (NtNotifyChangeMultipleKeysFunc) GetProcAddress (ntdll, "NtNotifyChangeMultipleKeys");
2515 g_once_init_leave (&nt_notify_change_multiple_keys, func);
2518 if (nt_notify_change_multiple_keys== NULL)
2520 g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
2521 "Couldn't get NtNotifyChangeMultipleKeys() from ntdll");
2526 g_atomic_int_compare_and_exchange (&key->priv->watch_indicator,
2527 G_WIN32_KEY_UNWATCHED,
2528 G_WIN32_KEY_WATCHED);
2530 if (!started_to_watch)
2533 key->priv->callback = callback;
2534 key->priv->user_data = user_data;
2536 g_atomic_int_set (&key->priv->change_indicator, G_WIN32_KEY_UNCHANGED);
2538 /* Keep it alive until APC is called */
2541 status_block = g_malloc (sizeof (IO_STATUS_BLOCK));
2543 status = nt_notify_change_multiple_keys (key->priv->handle,
2556 if (status == STATUS_PENDING || status == STATUS_SUCCESS)
2559 g_atomic_int_set (&key->priv->change_indicator, G_WIN32_KEY_UNKNOWN);
2560 g_atomic_int_set (&key->priv->watch_indicator, G_WIN32_KEY_UNWATCHED);
2561 g_object_unref (key);
2562 g_free (status_block);
2568 * g_win32_registry_key_erase_change_indicator:
2569 * @key: (in) (transfer none): a #GWin32RegistryKey
2571 * Erases change indicator of the @key.
2573 * Subsequent calls to g_win32_registry_key_has_changed() will return %FALSE
2574 * until the key is put on watch again by calling
2575 * g_win32_registry_key_watch() again.
2580 g_win32_registry_key_erase_change_indicator (GWin32RegistryKey *key)
2582 g_return_if_fail (G_IS_WIN32_REGISTRY_KEY (key));
2584 g_atomic_int_set (&key->priv->change_indicator, G_WIN32_KEY_UNKNOWN);
2588 * g_win32_registry_key_has_changed:
2589 * @key: (in) (transfer none): a #GWin32RegistryKey
2591 * Check the @key's status indicator.
2593 * Returns: %TRUE if the @key was put under watch at some point and has changed
2594 * since then, %FALSE if it either wasn't changed or wasn't watched at all.
2599 g_win32_registry_key_has_changed (GWin32RegistryKey *key)
2603 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), FALSE);
2605 changed = g_atomic_int_get (&key->priv->change_indicator);
2607 return (changed == G_WIN32_KEY_CHANGED ? TRUE : FALSE);
2611 g_win32_registry_key_get_property (GObject *object,
2616 GWin32RegistryKey *key = G_WIN32_REGISTRY_KEY (object);
2621 g_value_set_string (value, g_win32_registry_key_get_path (key));
2624 case PROP_PATH_UTF16:
2625 g_value_set_pointer (value, (gpointer) g_win32_registry_key_get_path_w (key));
2629 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2634 g_win32_registry_key_set_property (GObject *object,
2636 const GValue *value,
2639 GWin32RegistryKey *key = G_WIN32_REGISTRY_KEY (object);
2640 GWin32RegistryKeyPrivate *priv = key->priv;
2647 path = g_value_get_string (value);
2652 path_w = g_utf8_to_utf16 (path, -1, NULL, NULL, NULL);
2657 /* Construct only */
2658 g_assert (priv->absolute_path_w == NULL);
2659 g_assert (priv->absolute_path == NULL);
2660 priv->absolute_path_w = path_w;
2661 priv->absolute_path = g_value_dup_string (value);
2664 case PROP_PATH_UTF16:
2665 path_w = (gunichar2 *) g_value_get_pointer (value);
2670 /* Construct only */
2671 g_assert (priv->absolute_path_w == NULL);
2672 priv->absolute_path_w = g_wcsdup (path_w, -1);
2676 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2681 g_win32_registry_key_class_init (GWin32RegistryKeyClass *klass)
2683 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
2685 gobject_class->dispose = g_win32_registry_key_dispose;
2686 gobject_class->set_property = g_win32_registry_key_set_property;
2687 gobject_class->get_property = g_win32_registry_key_get_property;
2690 * GWin32RegistryKey:path:
2692 * A path to the key in the registry, in UTF-8.
2696 g_object_class_install_property (gobject_class,
2698 g_param_spec_string ("path",
2700 "Path to the key in the registry",
2703 G_PARAM_CONSTRUCT_ONLY |
2704 G_PARAM_STATIC_STRINGS));
2707 * GWin32RegistryKey:path-utf16:
2709 * A path to the key in the registry, in UTF-16.
2713 g_object_class_install_property (gobject_class,
2715 g_param_spec_pointer ("path-utf16",
2717 "Path to the key in the registry, in UTF-16",
2719 G_PARAM_CONSTRUCT_ONLY |
2720 G_PARAM_STATIC_STRINGS));
2724 g_win32_registry_key_init (GWin32RegistryKey *key)
2726 key->priv = g_win32_registry_key_get_instance_private (key);
2727 key->priv->change_indicator = G_WIN32_KEY_UNKNOWN;