Partly revert "gio: Add filename type annotations"
[glib.git] / gio / gwin32registrykey.c
blob69cd9ed47a9b83ea8c106eb8c793c06409626ed1
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 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/>.
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>
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;
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
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
70 #ifndef HKEY_CURRENT_USER_LOCAL_SETTINGS
71 #define HKEY_CURRENT_USER_LOCAL_SETTINGS ((HKEY) (ULONG_PTR)((LONG)0x80000007))
72 #endif
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;
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);
91 typedef NTSTATUS
92 (* 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);
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
114 enum
116 PROP_0,
117 PROP_PATH,
118 PROP_PATH_UTF16,
119 PROP_MAX,
122 typedef enum
124 G_WIN32_REGISTRY_UPDATED_NOTHING = 0,
125 G_WIN32_REGISTRY_UPDATED_PATH = 1,
126 } GWin32RegistryKeyUpdateFlag;
128 static gunichar2 *
129 g_wcsdup (const gunichar2 *str,
130 gssize str_size)
132 if (str_size == -1)
134 str_size = wcslen (str) + 1;
135 str_size *= sizeof (gunichar2);
137 return g_memdup (str, str_size);
141 * g_win32_registry_subkey_iter_copy:
142 * @iter: an iterator
144 * Creates a dynamically-allocated copy of an iterator. Dynamically-allocated
145 * state of the iterator is duplicated too.
147 * Returns: (transfer full): a copy of the @iter,
148 * free with g_win32_registry_subkey_iter_free ()
150 * Since: 2.46
152 GWin32RegistrySubkeyIter *
153 g_win32_registry_subkey_iter_copy (const GWin32RegistrySubkeyIter *iter)
155 GWin32RegistrySubkeyIter *new_iter;
157 g_return_val_if_fail (iter != NULL, NULL);
159 new_iter = g_new0 (GWin32RegistrySubkeyIter, 1);
161 new_iter->key = g_object_ref (iter->key);
162 new_iter->counter = iter->counter;
163 new_iter->subkey_count = iter->subkey_count;
164 new_iter->subkey_name = g_wcsdup (iter->subkey_name, iter->subkey_name_size);
165 new_iter->subkey_name_size = iter->subkey_name_size;
167 if (iter->subkey_name_u8)
168 new_iter->subkey_name_u8 = iter->subkey_name_u8;
169 else
170 new_iter->subkey_name_u8 = NULL;
172 return new_iter;
176 * g_win32_registry_subkey_iter_free:
177 * @iter: a dynamically-allocated iterator
179 * Free an iterator allocated on the heap. For iterators that are allocated
180 * on the stack use g_win32_registry_subkey_iter_clear () instead.
182 * Since: 2.46
184 void
185 g_win32_registry_subkey_iter_free (GWin32RegistrySubkeyIter *iter)
187 g_return_if_fail (iter != NULL);
189 g_object_unref (iter->key);
190 g_free (iter->subkey_name);
191 g_free (iter->subkey_name_u8);
192 g_free (iter);
196 * g_win32_registry_subkey_iter_assign:
197 * @iter: a #GWin32RegistrySubkeyIter
198 * @other: another #GWin32RegistrySubkeyIter
200 * Assigns the value of @other to @iter. This function
201 * is not useful in applications, because iterators can be assigned
202 * with `GWin32RegistrySubkeyIter i = j;`. The
203 * function is used by language bindings.
205 * Since: 2.46
207 void
208 g_win32_registry_subkey_iter_assign (GWin32RegistrySubkeyIter *iter,
209 const GWin32RegistrySubkeyIter *other)
211 g_return_if_fail (iter != NULL);
212 g_return_if_fail (other != NULL);
214 *iter = *other;
218 G_DEFINE_BOXED_TYPE (GWin32RegistrySubkeyIter, g_win32_registry_subkey_iter,
219 g_win32_registry_subkey_iter_copy,
220 g_win32_registry_subkey_iter_free)
223 * g_win32_registry_value_iter_copy:
224 * @iter: an iterator
226 * Creates a dynamically-allocated copy of an iterator. Dynamically-allocated
227 * state of the iterator is duplicated too.
229 * Returns: (transfer full): a copy of the @iter,
230 * free with g_win32_registry_value_iter_free ().
232 * Since: 2.46
234 GWin32RegistryValueIter *
235 g_win32_registry_value_iter_copy (const GWin32RegistryValueIter *iter)
237 GWin32RegistryValueIter *new_iter;
239 g_return_val_if_fail (iter != NULL, NULL);
241 new_iter = g_new0 (GWin32RegistryValueIter, 1);
243 new_iter->key = g_object_ref (iter->key);
244 new_iter->counter = iter->counter;
245 new_iter->value_count = iter->value_count;
246 new_iter->value_name = g_wcsdup (iter->value_name, iter->value_name_size);
247 new_iter->value_name_size = iter->value_name_size;
249 if (iter->value_data != NULL)
250 new_iter->value_data = g_memdup (iter->value_data, iter->value_data_size);
252 new_iter->value_data_size = iter->value_data_size;
254 if (iter->value_name_u8 != NULL)
255 new_iter->value_name_u8 = g_strdup (iter->value_name_u8);
257 new_iter->value_name_u8_len = iter->value_name_u8_len;
259 if (iter->value_data_u8 != NULL)
260 new_iter->value_data_u8 = g_strdup (iter->value_data_u8);
262 new_iter->value_data_u8_size = iter->value_data_u8_size;
264 if (iter->value_data_expanded != NULL)
265 new_iter->value_data_expanded = g_wcsdup ((gunichar2 *) iter->value_data_expanded,
266 iter->value_data_expanded_charsize * sizeof (gunichar2));
268 new_iter->value_data_expanded_charsize = iter->value_data_expanded_charsize;
270 if (iter->value_data_expanded_u8 != NULL)
271 new_iter->value_data_expanded_u8 = g_memdup (iter->value_data_expanded_u8,
272 iter->value_data_expanded_charsize);
274 new_iter->value_data_expanded_u8_size = iter->value_data_expanded_charsize;
276 return new_iter;
280 * g_win32_registry_value_iter_free:
281 * @iter: a dynamically-allocated iterator
283 * Free an iterator allocated on the heap. For iterators that are allocated
284 * on the stack use g_win32_registry_value_iter_clear () instead.
286 * Since: 2.46
288 void
289 g_win32_registry_value_iter_free (GWin32RegistryValueIter *iter)
291 g_return_if_fail (iter != NULL);
293 g_object_unref (iter->key);
294 g_free (iter->value_name);
295 g_free (iter->value_data);
296 g_free (iter->value_data_expanded);
297 g_free (iter->value_name_u8);
298 g_free (iter->value_data_u8);
299 g_free (iter->value_data_expanded_u8);
300 g_free (iter);
304 * g_win32_registry_value_iter_assign:
305 * @iter: a #GWin32RegistryValueIter
306 * @other: another #GWin32RegistryValueIter
308 * Assigns the value of @other to @iter. This function
309 * is not useful in applications, because iterators can be assigned
310 * with `GWin32RegistryValueIter i = j;`. The
311 * function is used by language bindings.
313 * Since: 2.46
315 void
316 g_win32_registry_value_iter_assign (GWin32RegistryValueIter *iter,
317 const GWin32RegistryValueIter *other)
319 g_return_if_fail (iter != NULL);
320 g_return_if_fail (other != NULL);
322 *iter = *other;
325 G_DEFINE_BOXED_TYPE (GWin32RegistryValueIter, g_win32_registry_value_iter,
326 g_win32_registry_value_iter_copy,
327 g_win32_registry_value_iter_free)
330 * SECTION:gwin32registrykey
331 * @title: GWin32RegistryKey
332 * @short_description: W32 registry access helper
333 * @include: gio/win32/gwin32registrykey.h
335 * #GWin32RegistryKey represents a single Windows Registry key.
337 * #GWin32RegistryKey is used by a number of helper functions that read
338 * Windows Registry. All keys are opened with read-only access, and at
339 * the moment there is no API for writing into registry keys or creating
340 * new ones.
342 * #GWin32RegistryKey implements the #GInitable interface, so if it is manually
343 * constructed by e.g. g_object_new() you must call g_initable_init() and check
344 * the results before using the object. This is done automatically
345 * in g_win32_registry_key_new() and g_win32_registry_key_get_child(), so these
346 * functions can return %NULL.
348 * To increase efficiency, a UTF-16 variant is available for all functions
349 * that deal with key or value names in the registry. Use these to perform
350 * deep registry queries or other operations that require querying a name
351 * of a key or a value and then opening it (or querying its data). The use
352 * of UTF-16 functions avoids the overhead of converting names to UTF-8 and
353 * back.
355 * All functions operate in current user's context (it is not possible to
356 * access registry tree of a different user).
358 * Key paths must use '\\' as a separator, '/' is not supported. Key names
359 * must not include '\\', because it's used as a separator. Value names
360 * can include '\\'.
362 * Key and value names are not case sensitive.
364 * Full key name (excluding the pre-defined ancestor's name) can't exceed
365 * 255 UTF-16 characters, give or take. Value name can't exceed 16383 UTF-16
366 * characters. Tree depth is limited to 512 levels.
369 struct _GWin32RegistryKeyPrivate {
370 /* Ancestor of this key. May not be the immediate parent, because
371 * RegOpenKeyEx() allows grand*-children to be opened transitively.
372 * May be NULL.
374 GWin32RegistryKey *ancestor;
376 /* Handle to the key */
377 HKEY handle;
379 /* Full absolute path of the key, in UTF-16. Always allocated.
380 * Can become out of sync if the key is renamed from while we have it
381 * open, check watch_indicator to see if anything changed.
383 gunichar2 *absolute_path_w;
385 /* Full absolute path of the key, in UTF-8. Allocated when needed by
386 * converting the UTF-16 value from absolute_path_w. */
387 gchar *absolute_path;
389 /* TRUE if this object represents one of the pre-defined keys
390 * (and thus must not be closed).
392 gboolean predefined;
394 /* Set to G_WIN32_KEY_UNWATCHED if the key is not being watched.
395 * Set to G_WIN32_KEY_WATCHED when the key is put on watch notification.
397 gint watch_indicator;
399 /* Set to G_WIN32_KEY_UNKNOWN while the key is not being watched.
400 * Set to G_WIN32_KEY_UNCHANGED once the key is put under watch.
401 * Set to G_WIN32_KEY_CHANGED by the watch notification APC on key change.
403 gint change_indicator;
405 /* Unset after the key is changed, individual bits are set when their
406 * respective key parameters are updated from the registry.
407 * This prevents GLib from re-querying things like key name each time
408 * one is requested by the client while key is in G_WIN32_KEY_CHANGED state.
410 GWin32RegistryKeyUpdateFlag update_flags;
412 GWin32RegistryKeyWatchCallbackFunc callback;
414 gpointer user_data;
417 static void g_win32_registry_key_initable_iface_init (GInitableIface *iface);
418 static gboolean g_win32_registry_key_initable_init (GInitable *initable,
419 GCancellable *cancellable,
420 GError **error);
422 G_DEFINE_TYPE_WITH_CODE (GWin32RegistryKey, g_win32_registry_key, G_TYPE_OBJECT,
423 G_ADD_PRIVATE (GWin32RegistryKey)
424 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
425 g_win32_registry_key_initable_iface_init));
427 static void
428 g_win32_registry_key_dispose (GObject *object)
430 GWin32RegistryKey *key;
431 GWin32RegistryKeyPrivate *priv;
433 key = G_WIN32_REGISTRY_KEY (object);
434 priv = key->priv;
436 g_clear_object (&priv->ancestor);
437 g_clear_pointer (&priv->absolute_path_w, g_free);
438 g_clear_pointer (&priv->absolute_path, g_free);
440 if (!priv->predefined && priv->handle != INVALID_HANDLE_VALUE)
442 RegCloseKey (priv->handle);
443 priv->handle = INVALID_HANDLE_VALUE;
446 G_OBJECT_CLASS (g_win32_registry_key_parent_class)->dispose (object);
450 * g_win32_registry_key_new:
451 * @path: absolute full name of a key to open (in UTF-8)
452 * @error: (nullable): a pointer to a %NULL #GError, or %NULL
454 * Creates an object that represents a registry key specified by @path.
455 * @path must start with one of the following pre-defined names:
456 * - HKEY_CLASSES_ROOT
457 * - HKEY_CURRENT_CONFIG
458 * - HKEY_CURRENT_USER
459 * - HKEY_CURRENT_USER_LOCAL_SETTINGS
460 * - HKEY_LOCAL_MACHINE
461 * - HKEY_PERFORMANCE_DATA
462 * - HKEY_PERFORMANCE_NLSTEXT
463 * - HKEY_PERFORMANCE_TEXT
464 * - HKEY_USERS
465 * @path must not end with '\\'.
467 * Returns: (nullable) (transfer full): a #GWin32RegistryKey or %NULL if can't
468 * be opened. Free with g_object_unref().
470 GWin32RegistryKey *
471 g_win32_registry_key_new (const gchar *path,
472 GError **error)
474 g_return_val_if_fail (path != NULL, NULL);
476 return g_initable_new (G_TYPE_WIN32_REGISTRY_KEY,
477 NULL,
478 error,
479 "path",
480 path,
481 NULL);
485 * g_win32_registry_key_new_w:
486 * @path: (in) (transfer none): absolute full name of a key to open (in UTF-16)
487 * @error: (inout) (nullable): a pointer to a %NULL #GError, or %NULL
489 * Creates an object that represents a registry key specified by @path.
490 * @path must start with one of the following pre-defined names:
491 * - HKEY_CLASSES_ROOT
492 * - HKEY_CURRENT_CONFIG
493 * - HKEY_CURRENT_USER
494 * - HKEY_CURRENT_USER_LOCAL_SETTINGS
495 * - HKEY_LOCAL_MACHINE
496 * - HKEY_PERFORMANCE_DATA
497 * - HKEY_PERFORMANCE_NLSTEXT
498 * - HKEY_PERFORMANCE_TEXT
499 * - HKEY_USERS
500 * @path must not end with L'\\'.
502 * Returns: (nullable) (transfer full): a #GWin32RegistryKey or %NULL if can't
503 * be opened. Free with g_object_unref().
505 GWin32RegistryKey *
506 g_win32_registry_key_new_w (const gunichar2 *path,
507 GError **error)
509 GObject *result;
511 g_return_val_if_fail (path != NULL, NULL);
513 result = g_initable_new (G_TYPE_WIN32_REGISTRY_KEY,
514 NULL,
515 error,
516 "path-utf16",
517 g_wcsdup (path, -1),
518 NULL);
520 return result ? G_WIN32_REGISTRY_KEY (result) : NULL;
523 static void
524 g_win32_registry_key_initable_iface_init (GInitableIface *iface)
526 iface->init = g_win32_registry_key_initable_init;
529 static gboolean
530 g_win32_registry_key_initable_init (GInitable *initable,
531 GCancellable *cancellable,
532 GError **error)
534 GWin32RegistryKey *key;
535 GWin32RegistryKeyPrivate *priv;
536 gunichar2 *path;
537 gunichar2 *first_chunk_end;
538 gsize first_chunk_len;
539 gunichar2 *second_chunk_begin;
540 gunichar2 *first_chunk;
541 HKEY ancestor;
542 HKEY key_handle;
543 LONG opened;
545 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (initable), FALSE);
546 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
548 key = G_WIN32_REGISTRY_KEY (initable);
549 priv = key->priv;
551 if (priv->absolute_path_w == NULL)
553 priv->absolute_path_w = g_utf8_to_utf16 (priv->absolute_path,
555 NULL,
556 NULL,
557 error);
559 if (priv->absolute_path_w == NULL)
560 return FALSE;
563 path = priv->absolute_path_w;
565 first_chunk_end = wcschr (path, L'\\');
567 if (first_chunk_end == NULL)
568 first_chunk_end = &path[wcslen (path)];
570 first_chunk_len = first_chunk_end - path;
571 first_chunk = g_wcsdup (path, -1);
572 first_chunk[first_chunk_len] = L'\0';
573 if (wcscmp (first_chunk, L"HKEY_CLASSES_ROOT") == 0)
574 ancestor = HKEY_CLASSES_ROOT;
575 else if (wcscmp (first_chunk, L"HKEY_LOCAL_MACHINE") == 0)
576 ancestor = HKEY_LOCAL_MACHINE;
577 else if (wcscmp (first_chunk, L"HKEY_CURRENT_USER") == 0)
578 ancestor = HKEY_CURRENT_USER;
579 else if (wcscmp (first_chunk, L"HKEY_CURRENT_CONFIG") == 0)
580 ancestor = HKEY_CURRENT_CONFIG;
581 else if (wcscmp (first_chunk, L"HKEY_CURRENT_USER_LOCAL_SETTINGS") == 0)
582 ancestor = HKEY_CURRENT_USER_LOCAL_SETTINGS;
583 else if (wcscmp (first_chunk, L"HKEY_USERS") == 0)
584 ancestor = HKEY_USERS;
585 else if (wcscmp (first_chunk, L"HKEY_PERFORMANCE_DATA") == 0)
586 ancestor = HKEY_PERFORMANCE_DATA;
587 else if (wcscmp (first_chunk, L"HKEY_PERFORMANCE_NLSTEXT") == 0)
588 ancestor = HKEY_PERFORMANCE_NLSTEXT;
589 else if (wcscmp (first_chunk, L"HKEY_PERFORMANCE_TEXT") == 0)
590 ancestor = HKEY_PERFORMANCE_TEXT;
591 else
593 g_critical ("Root key '%S' is not a pre-defined key", first_chunk);
594 g_free (first_chunk);
595 return FALSE;
598 g_free (first_chunk);
600 second_chunk_begin = first_chunk_end;
602 while (second_chunk_begin[0] != L'\0' && second_chunk_begin[0] == L'\\')
603 second_chunk_begin++;
605 if (second_chunk_begin != first_chunk_end && second_chunk_begin[0] == L'\0')
607 g_critical ("Key name '%S' ends with '\\'", path);
608 return FALSE;
611 opened = RegOpenKeyExW (ancestor, second_chunk_begin, 0, KEY_READ, &key_handle);
613 if (opened != ERROR_SUCCESS)
615 g_set_error (error, G_IO_ERROR, g_io_error_from_win32_error (opened),
616 "Failed to open registry key '%S'", path);
617 return FALSE;
620 priv->ancestor = NULL;
621 priv->handle = key_handle;
622 priv->predefined = (second_chunk_begin[0] == L'\0');
624 return TRUE;
628 * g_win32_registry_key_get_child:
629 * @key: (in) (transfer none): a parent #GWin32RegistryKey
630 * @subkey: (in) (transfer none): name of a child key to open (in UTF-8), relative to @key
631 * @error: (inout) (nullable): a pointer to a %NULL #GError, or %NULL
633 * Opens a @subkey of the @key.
635 * Returns: (nullable): a #GWin32RegistryKey or %NULL if can't be opened. Free
636 * with g_object_unref().
638 GWin32RegistryKey *
639 g_win32_registry_key_get_child (GWin32RegistryKey *key,
640 const gchar *subkey,
641 GError **error)
643 gunichar2 *subkey_w;
644 GWin32RegistryKey *result = NULL;
646 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), NULL);
647 g_return_val_if_fail (subkey != NULL, NULL);
648 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
650 subkey_w = g_utf8_to_utf16 (subkey, -1, NULL, NULL, error);
652 if (subkey_w != NULL)
654 result = g_win32_registry_key_get_child_w (key, subkey_w, error);
655 g_free (subkey_w);
658 return result;
662 * g_win32_registry_key_get_child_w:
663 * @key: (in) (transfer none): a parent #GWin32RegistryKey
664 * @subkey: (in) (transfer none): name of a child key to open (in UTF-8), relative to @key
665 * @error: (inout) (nullable): a pointer to a %NULL #GError, or %NULL
667 * Opens a @subkey of the @key.
669 * Returns: (nullable): a #GWin32RegistryKey or %NULL if can't be opened. Free
670 * with g_object_unref().
672 GWin32RegistryKey *
673 g_win32_registry_key_get_child_w (GWin32RegistryKey *key,
674 const gunichar2 *subkey,
675 GError **error)
677 HKEY key_handle;
678 LONG opened;
679 const gunichar2 *end_of_subkey;
680 gsize subkey_len;
681 GWin32RegistryKey *result;
682 const gunichar2 *key_path;
684 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), NULL);
685 g_return_val_if_fail (subkey != NULL, NULL);
686 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
688 if (subkey[0] == L'\\')
690 g_critical ("Subkey name '%S' starts with '\\'", subkey);
691 return NULL;
694 subkey_len = wcslen (subkey);
695 end_of_subkey = &subkey[subkey_len];
697 if (subkey_len == 0)
698 end_of_subkey = subkey;
700 if (end_of_subkey[0] == L'\\')
702 g_critical ("Subkey name '%S' ends with '\\'", subkey);
703 return NULL;
706 key_path = g_win32_registry_key_get_path_w (key);
707 opened = RegOpenKeyExW (key->priv->handle, subkey, 0, KEY_READ, &key_handle);
709 if (opened != ERROR_SUCCESS)
711 g_set_error (error, G_IO_ERROR, g_io_error_from_win32_error (opened),
712 "Failed to open registry subkey '%S' of key '%S'",
713 subkey, key_path);
714 return NULL;
717 result = g_object_new (G_TYPE_WIN32_REGISTRY_KEY, NULL);
719 result->priv->handle = key_handle;
720 result->priv->absolute_path_w =
721 g_malloc ((wcslen (key_path) + 2 + subkey_len) * sizeof (gunichar2));
722 result->priv->absolute_path_w[0] = L'\0';
723 wcscat (&result->priv->absolute_path_w[0], key_path);
724 wcscat (&result->priv->absolute_path_w[wcslen (key_path)], L"\\");
725 wcscat (&result->priv->absolute_path_w[wcslen (key_path) + 1], subkey);
726 result->priv->predefined = (subkey[0] == L'\0' && key->priv->predefined);
728 if (subkey[0] != L'\0')
729 result->priv->ancestor = g_object_ref (key);
730 else
731 result->priv->ancestor = NULL;
733 result->priv->change_indicator = G_WIN32_KEY_UNKNOWN;
735 return result;
739 * g_win32_registry_subkey_iter_init:
740 * @iter: (in) (transfer none): a pointer to a #GWin32RegistrySubkeyIter
741 * @key: (in) (transfer none): a #GWin32RegistryKey to iterate over
742 * @error: (inout) (nullable): a pointer to %NULL #GError, or %NULL
744 * Initialises (without allocating) a #GWin32RegistrySubkeyIter. @iter may be
745 * completely uninitialised prior to this call; its old value is
746 * ignored.
748 * The iterator remains valid for as long as @key exists.
749 * Clean up its internal buffers with a call to
750 * g_win32_registry_subkey_iter_clear() when done.
752 * Returns: %TRUE if iterator was initialized successfully, %FALSE on error.
754 * Since: 2.46
756 gboolean
757 g_win32_registry_subkey_iter_init (GWin32RegistrySubkeyIter *iter,
758 GWin32RegistryKey *key,
759 GError **error)
761 LONG status;
762 DWORD subkey_count;
763 DWORD max_subkey_len;
765 g_return_val_if_fail (iter != NULL, FALSE);
766 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), FALSE);
767 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
769 status = RegQueryInfoKeyW (key->priv->handle,
770 NULL, NULL, NULL,
771 &subkey_count, &max_subkey_len,
772 NULL, NULL, NULL, NULL, NULL, NULL);
774 if (status != ERROR_SUCCESS)
776 g_set_error (error, G_IO_ERROR, g_io_error_from_win32_error (status),
777 "Failed to query info for registry key '%S'",
778 g_win32_registry_key_get_path_w (key));
779 return FALSE;
782 iter->key = g_object_ref (key);
783 iter->counter = -1;
784 iter->subkey_count = subkey_count;
785 iter->subkey_name_size = sizeof (gunichar2) * (max_subkey_len + 1);
786 iter->subkey_name = g_malloc (iter->subkey_name_size);
787 iter->subkey_name_u8 = NULL;
789 return TRUE;
793 * g_win32_registry_subkey_iter_clear:
794 * @iter: (in) (transfer none): a #GWin32RegistrySubkeyIter
796 * Frees internal buffers of a #GWin32RegistrySubkeyIter.
798 * Since: 2.46
800 void
801 g_win32_registry_subkey_iter_clear (GWin32RegistrySubkeyIter *iter)
803 g_return_if_fail (iter != NULL);
805 g_free (iter->subkey_name);
806 g_free (iter->subkey_name_u8);
807 g_clear_object (&iter->key);
811 * g_win32_registry_subkey_iter_n_subkeys:
812 * @iter: (in) (transfer none): a #GWin32RegistrySubkeyIter
814 * Queries the number of subkeys items in the key that we are
815 * iterating over. This is the total number of subkeys -- not the number
816 * of items remaining.
818 * This information is accurate at the point of iterator initialization,
819 * and may go out of sync with reality even while subkeys are enumerated.
821 * Returns: the number of subkeys in the key
823 * Since: 2.46
825 gsize
826 g_win32_registry_subkey_iter_n_subkeys (GWin32RegistrySubkeyIter *iter)
828 g_return_val_if_fail (iter != NULL, 0);
830 return iter->subkey_count;
834 * g_win32_registry_subkey_iter_next:
835 * @iter: (in) (transfer none): a #GWin32RegistrySubkeyIter
836 * @skip_errors: (in): %TRUE if iterator should silently ignore errors (such as
837 * the actual number of subkeys being less than expected) and
838 * proceed forward
839 * @error: (nullable): a pointer to %NULL #GError, or %NULL
841 * Moves iterator to the next subkey.
842 * Enumeration errors can be ignored if @skip_errors is %TRUE
844 * Here is an example for iterating with g_win32_registry_subkey_iter_next():
845 * |[<!-- language="C" -->
846 * // recursively iterate a key
847 * void
848 * iterate_key_recursive (GWin32RegistryKey *key)
850 * GWin32RegistrySubkeyIter iter;
851 * gchar *name;
852 * GWin32RegistryKey *child;
854 * if (!g_win32_registry_subkey_iter_init (&iter, key, NULL))
855 * return;
857 * while (g_win32_registry_subkey_iter_next (&iter, TRUE, NULL))
859 * if (!g_win32_registry_subkey_iter_get_name (&iter, &name, NULL, NULL))
860 * continue;
862 * g_print ("subkey '%s'\n", name);
863 * child = g_win32_registry_key_get_child (key, name, NULL);
865 * if (child)
866 * iterate_key_recursive (child);
869 * g_win32_registry_subkey_iter_clear (&iter);
871 * ]|
873 * Returns: %TRUE if next subkey info was retrieved, %FALSE otherwise.
875 * Since: 2.46
877 gboolean
878 g_win32_registry_subkey_iter_next (GWin32RegistrySubkeyIter *iter,
879 gboolean skip_errors,
880 GError **error)
882 LONG status;
883 DWORD subkey_len;
885 g_return_val_if_fail (iter != NULL, FALSE);
886 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
888 if G_UNLIKELY (iter->counter >= iter->subkey_count)
890 g_critical ("g_win32_registry_subkey_iter_get_next_w: must not be called again "
891 "after FALSE has already been returned.");
892 return FALSE;
895 while (TRUE)
897 iter->counter += 1;
899 if (iter->counter >= iter->subkey_count)
900 return FALSE;
902 /* Including 0-terminator */
903 subkey_len = iter->subkey_name_size;
904 status = RegEnumKeyExW (iter->key->priv->handle,
905 iter->counter,
906 iter->subkey_name,
907 &subkey_len,
908 NULL, NULL, NULL, NULL);
910 if (status == ERROR_SUCCESS)
912 iter->subkey_name_len = subkey_len;
914 return TRUE;
917 if (!skip_errors)
919 g_set_error (error, G_IO_ERROR, g_io_error_from_win32_error (status),
920 "Failed to enumerate subkey #%d for key '%S'",
921 iter->counter, g_win32_registry_key_get_path_w (iter->key));
922 iter->subkey_count = 0;
924 return FALSE;
930 * g_win32_registry_subkey_iter_get_name_w:
931 * @iter: (in) (transfer none): a #GWin32RegistrySubkeyIter
932 * @subkey_name: (out callee-allocates) (transfer none): Pointer to a location
933 * to store the name of a subkey (in UTF-16).
934 * @subkey_name_len: (out) (optional) (transfer none): Pointer to a location
935 * to store the length of @subkey_name, in gunichar2s, excluding
936 * NUL-terminator.
937 * %NULL if length is not needed.
938 * @error: (nullable): a pointer to %NULL #GError, or %NULL
940 * Same as g_win32_registry_subkey_iter_get_next(), but outputs UTF-16-encoded
941 * data, without converting it to UTF-8 first.
943 * Returns: %TRUE if the name was retrieved, %FALSE otherwise.
945 * Since: 2.46
947 gboolean
948 g_win32_registry_subkey_iter_get_name_w (GWin32RegistrySubkeyIter *iter,
949 gunichar2 **subkey_name,
950 gsize *subkey_name_len,
951 GError **error)
953 g_return_val_if_fail (iter != NULL, FALSE);
954 g_return_val_if_fail (subkey_name != NULL, FALSE);
955 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
957 if G_UNLIKELY (iter->counter >= iter->subkey_count)
959 g_critical ("g_win32_registry_subkey_iter_get_name_w: must not be called "
960 "after FALSE has already been returned by "
961 "g_win32_registry_subkey_iter_next.");
962 return FALSE;
965 *subkey_name = iter->subkey_name;
967 if (subkey_name_len)
968 *subkey_name_len = iter->subkey_name_len;
970 return TRUE;
974 * g_win32_registry_subkey_iter_get_name:
975 * @iter: (in) (transfer none): a #GWin32RegistrySubkeyIter
976 * @subkey_name: (out callee-allocates) (transfer none): Pointer to a location
977 * to store the name of a subkey (in UTF-8). Free with g_free().
978 * @subkey_name_len: (out) (optional): Pointer to a location to store the
979 * length of @subkey_name, in gchars, excluding NUL-terminator.
980 * %NULL if length is not needed.
981 * @error: (nullable): a pointer to %NULL #GError, or %NULL
983 * Gets the name of the subkey at the @iter potision.
985 * Returns: %TRUE if the name was retrieved, %FALSE otherwise.
987 * Since: 2.46
989 gboolean
990 g_win32_registry_subkey_iter_get_name (GWin32RegistrySubkeyIter *iter,
991 gchar **subkey_name,
992 gsize *subkey_name_len,
993 GError **error)
995 glong subkey_name_len_glong;
997 g_return_val_if_fail (iter != NULL, FALSE);
998 g_return_val_if_fail (subkey_name != NULL, FALSE);
999 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1001 if G_UNLIKELY (iter->counter >= iter->subkey_count)
1003 g_critical ("g_win32_registry_subkey_iter_get_name_w: must not be called "
1004 "after FALSE has already been returned by "
1005 "g_win32_registry_subkey_iter_next.");
1006 return FALSE;
1009 g_clear_pointer (&iter->subkey_name_u8, g_free);
1010 iter->subkey_name_u8 = g_utf16_to_utf8 (iter->subkey_name,
1011 iter->subkey_name_len,
1012 NULL,
1013 &subkey_name_len_glong,
1014 error);
1016 if (iter->subkey_name_u8 != NULL)
1018 *subkey_name_len = subkey_name_len_glong;
1019 return TRUE;
1022 return FALSE;
1026 * g_win32_registry_value_iter_init:
1027 * @iter: (in) (transfer none): a pointer to a #GWin32RegistryValueIter
1028 * @key: (in) (transfer none): a #GWin32RegistryKey to iterate over
1029 * @error: (nullable): a pointer to %NULL #GError, or %NULL
1031 * Initialises (without allocating) a #GWin32RegistryValueIter. @iter may be
1032 * completely uninitialised prior to this call; its old value is
1033 * ignored.
1035 * The iterator remains valid for as long as @key exists.
1036 * Clean up its internal buffers with a call to
1037 * g_win32_registry_value_iter_clear() when done.
1039 * Returns: %TRUE if iterator was initialized successfully, %FALSE on error.
1041 * Since: 2.46
1043 gboolean
1044 g_win32_registry_value_iter_init (GWin32RegistryValueIter *iter,
1045 GWin32RegistryKey *key,
1046 GError **error)
1048 LONG status;
1049 DWORD value_count;
1050 DWORD max_value_len;
1051 DWORD max_data_len;
1053 g_return_val_if_fail (iter != NULL, FALSE);
1054 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), FALSE);
1055 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1057 status = RegQueryInfoKeyW (key->priv->handle,
1058 NULL, NULL, NULL, NULL, NULL, NULL,
1059 &value_count, &max_value_len,
1060 &max_data_len, NULL, NULL);
1062 if (status != ERROR_SUCCESS)
1064 g_set_error (error, G_IO_ERROR, g_io_error_from_win32_error (status),
1065 "Failed to query info for registry key '%S'",
1066 g_win32_registry_key_get_path_w (key));
1067 return FALSE;
1070 iter->key = g_object_ref (key);
1071 iter->counter = -1;
1072 iter->value_count = value_count;
1073 iter->value_name_size = sizeof (gunichar2) * (max_value_len + 1);
1074 iter->value_name = g_malloc (iter->value_name_size);
1075 /* FIXME: max_value_data_len is said to have no size limit in newer W32
1076 * versions (and its size limit in older ones is 1MB!). Consider limiting it
1077 * with a hard-coded value, or by allowing the user to choose a limit.
1079 /* Two extra gunichar2s is for cases when a string was stored in the
1080 * Registry without a 0-terminator (for multiline strings - 00-terminator),
1081 * and we need to terminate it ourselves.
1083 iter->value_data_size = max_data_len + sizeof (gunichar2) * 2;
1084 iter->value_data = g_malloc (iter->value_data_size);
1085 iter->value_name_u8 = NULL;
1086 iter->value_data_u8 = NULL;
1087 iter->value_data_expanded = NULL;
1088 iter->value_data_expanded_charsize = 0;
1089 iter->value_data_expanded_u8 = NULL;
1090 iter->value_data_expanded_u8_size = 0;
1091 return TRUE;
1095 * g_win32_registry_value_iter_clear:
1096 * @iter: (in) (transfer none): a #GWin32RegistryValueIter
1098 * Frees internal buffers of a #GWin32RegistryValueIter.
1100 * Since: 2.46
1102 void
1103 g_win32_registry_value_iter_clear (GWin32RegistryValueIter *iter)
1105 g_return_if_fail (iter != NULL);
1107 g_free (iter->value_name);
1108 g_free (iter->value_data);
1109 g_free (iter->value_name_u8);
1110 g_free (iter->value_data_u8);
1111 g_free (iter->value_data_expanded);
1112 g_free (iter->value_data_expanded_u8);
1113 g_clear_object (&iter->key);
1117 * g_win32_registry_value_iter_n_values:
1118 * @iter: (in) (transfer none): a #GWin32RegistryValueIter
1120 * Queries the number of values items in the key that we are
1121 * iterating over. This is the total number of values -- not the number
1122 * of items remaining.
1124 * This information is accurate at the point of iterator initialization,
1125 * and may go out of sync with reality even while values are enumerated.
1127 * Returns: the number of values in the key
1129 * Since: 2.46
1131 gsize
1132 g_win32_registry_value_iter_n_values (GWin32RegistryValueIter *iter)
1134 g_return_val_if_fail (iter != NULL, 0);
1136 return iter->value_count;
1139 static GWin32RegistryValueType
1140 _g_win32_registry_type_w_to_g (DWORD value_type)
1142 switch (value_type)
1144 case REG_BINARY:
1145 return G_WIN32_REGISTRY_VALUE_BINARY;
1146 case REG_DWORD:
1147 return G_WIN32_REGISTRY_VALUE_UINT32;
1148 #if G_BYTE_ORDER == G_BIG_ENDIAN
1149 case REG_DWORD_LITTLE_ENDIAN:
1150 return G_WIN32_REGISTRY_VALUE_UINT32LE;
1151 #else
1152 case REG_DWORD_BIG_ENDIAN:
1153 return G_WIN32_REGISTRY_VALUE_UINT32BE;
1154 #endif
1155 case REG_EXPAND_SZ:
1156 return G_WIN32_REGISTRY_VALUE_EXPAND_STR;
1157 case REG_LINK:
1158 return G_WIN32_REGISTRY_VALUE_LINK;
1159 case REG_MULTI_SZ:
1160 return G_WIN32_REGISTRY_VALUE_MULTI_STR;
1161 case REG_NONE:
1162 return G_WIN32_REGISTRY_VALUE_NONE;
1163 case REG_QWORD:
1164 return G_WIN32_REGISTRY_VALUE_UINT64;
1165 #if G_BYTE_ORDER == G_BIG_ENDIAN
1166 case REG_QWORD_LITTLE_ENDIAN:
1167 return G_WIN32_REGISTRY_VALUE_UINT64LE;
1168 #endif
1169 case REG_SZ:
1170 return G_WIN32_REGISTRY_VALUE_STR;
1171 default:
1172 return G_WIN32_REGISTRY_VALUE_NONE;
1176 static gsize
1177 ensure_nul_termination (GWin32RegistryValueType value_type,
1178 guint8 *value_data,
1179 gsize value_data_size)
1181 gsize new_size = value_data_size;
1183 if (value_type == G_WIN32_REGISTRY_VALUE_EXPAND_STR ||
1184 value_type == G_WIN32_REGISTRY_VALUE_LINK ||
1185 value_type == G_WIN32_REGISTRY_VALUE_STR)
1187 if ((value_data_size < 2) ||
1188 (value_data[value_data_size - 1] != 0) ||
1189 (value_data[value_data_size - 2] != 0))
1191 value_data[value_data_size] = 0;
1192 value_data[value_data_size + 1] = 0;
1193 new_size += 2;
1196 else if (value_type == G_WIN32_REGISTRY_VALUE_MULTI_STR)
1198 if ((value_data_size < 4) ||
1199 (value_data[value_data_size - 1] != 0) ||
1200 (value_data[value_data_size - 2] != 0) ||
1201 (value_data[value_data_size - 3] != 0) ||
1202 (value_data[value_data_size - 4] != 0))
1204 value_data[value_data_size] = 0;
1205 value_data[value_data_size + 1] = 0;
1206 value_data[value_data_size + 2] = 0;
1207 value_data[value_data_size + 3] = 0;
1208 new_size += 4;
1212 return new_size;
1216 * g_win32_registry_value_iter_next:
1217 * @iter: (in) (transfer none): a #GWin32RegistryValueIter
1218 * @skip_errors: (in): %TRUE if iterator should silently ignore errors (such as
1219 * the actual number of values being less than expected) and
1220 * proceed forward
1221 * @error: (nullable): a pointer to %NULL #GError, or %NULL
1223 * Advances iterator to the next value in the key. If no more values remain then
1224 * FALSE is returned.
1225 * Enumeration errors can be ignored if @skip_errors is %TRUE
1227 * Here is an example for iterating with g_win32_registry_value_iter_next():
1228 * |[<!-- language="C" -->
1229 * // iterate values of a key
1230 * void
1231 * iterate_values_recursive (GWin32RegistryKey *key)
1233 * GWin32RegistryValueIter iter;
1234 * gchar *name;
1235 * GWin32RegistryValueType val_type;
1236 * gchar *val_data;
1238 * if (!g_win32_registry_value_iter_init (&iter, key, NULL))
1239 * return;
1241 * while (g_win32_registry_value_iter_next (&iter, TRUE, NULL))
1243 * if ((!g_win32_registry_value_iter_get_value_type (&iter, &value)) ||
1244 * ((val_type != G_WIN32_REGISTRY_VALUE_STR) &&
1245 * (val_type != G_WIN32_REGISTRY_VALUE_EXPAND_STR)))
1246 * continue;
1248 * if (g_win32_registry_value_iter_get_value (&iter, TRUE, &name, NULL,
1249 * &val_data, NULL, NULL))
1250 * g_print ("value '%s' = '%s'\n", name, val_data);
1253 * g_win32_registry_value_iter_clear (&iter);
1255 * ]|
1257 * Returns: %TRUE if next value info was retrieved, %FALSE otherwise.
1259 * Since: 2.46
1261 gboolean
1262 g_win32_registry_value_iter_next (GWin32RegistryValueIter *iter,
1263 gboolean skip_errors,
1264 GError **error)
1266 LONG status;
1267 DWORD value_name_len_w;
1268 DWORD value_data_size_w;
1269 DWORD value_type_w;
1270 GWin32RegistryValueType value_type_g;
1272 g_return_val_if_fail (iter != NULL, FALSE);
1273 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1275 if G_UNLIKELY (iter->counter >= iter->value_count)
1277 g_critical ("g_win32_registry_value_iter_next: must not be called "
1278 "again after FALSE has already been returned.");
1279 return FALSE;
1282 while (TRUE)
1284 iter->counter += 1;
1286 if (iter->counter >= iter->value_count)
1287 return FALSE;
1289 g_clear_pointer (&iter->value_name_u8, g_free);
1290 g_clear_pointer (&iter->value_data_u8, g_free);
1291 g_clear_pointer (&iter->value_data_expanded_u8, g_free);
1292 /* Including 0-terminator */
1293 value_name_len_w = iter->value_name_size / sizeof (gunichar2);
1294 value_data_size_w = iter->value_data_size;
1295 status = RegEnumValueW (iter->key->priv->handle,
1296 iter->counter,
1297 iter->value_name,
1298 &value_name_len_w,
1299 NULL,
1300 &value_type_w,
1301 (LPBYTE) iter->value_data,
1302 &value_data_size_w);
1304 if (status != ERROR_SUCCESS && !skip_errors)
1306 g_set_error (error, G_IO_ERROR, g_io_error_from_win32_error (status),
1307 "Failed to enumerate value #%d for key '%S'",
1308 iter->counter, g_win32_registry_key_get_path_w (iter->key));
1309 iter->value_count = 0;
1311 return FALSE;
1313 else if (status != ERROR_SUCCESS && skip_errors)
1314 continue;
1316 value_type_g = _g_win32_registry_type_w_to_g (value_type_w);
1317 value_data_size_w = ensure_nul_termination (value_type_g,
1318 iter->value_data,
1319 value_data_size_w);
1320 iter->value_type = value_type_g;
1321 iter->value_expanded_type = value_type_g;
1322 iter->value_actual_data_size = value_data_size_w;
1323 iter->value_name_len = value_name_len_w;
1325 return TRUE;
1330 * g_win32_registry_value_iter_get_value_type:
1331 * @iter: (in) (transfer none): a #GWin32RegistryValueIter
1332 * @value_type: (out): Pointer to a location to store the type of
1333 * the value.
1334 * @error: (nullable): a pointer to %NULL #GError, or %NULL
1336 * Stores the type of the value currently being iterated over in @value_type.
1338 * Returns: %TRUE if value type was retrieved, %FALSE otherwise.
1340 * Since: 2.46
1342 gboolean
1343 g_win32_registry_value_iter_get_value_type (GWin32RegistryValueIter *iter,
1344 GWin32RegistryValueType *value_type,
1345 GError **error)
1347 g_return_val_if_fail (iter != NULL, FALSE);
1348 g_return_val_if_fail (value_type != NULL, FALSE);
1349 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1351 if G_UNLIKELY (iter->counter >= iter->value_count)
1353 g_critical ("g_win32_registry_value_iter_get_type: must not be called "
1354 "again after NULL has already been returned.");
1355 return FALSE;
1358 *value_type = iter->value_type;
1360 return TRUE;
1364 * g_win32_registry_value_iter_get_name_w:
1365 * @iter: (in) (transfer none): a #GWin32RegistryValueIter
1366 * @value_name: (out callee-allocates) (transfer none): Pointer to a location
1367 * to store the name of a value (in UTF-16).
1368 * @value_name_len: (out) (optional): Pointer to a location to store the length
1369 * of @value_name, in gunichar2s, excluding NUL-terminator.
1370 * %NULL if length is not needed.
1371 * @error: (nullable): a pointer to %NULL #GError, or %NULL
1373 * Stores the name of the value currently being iterated over in @value_name,
1374 * and its length - in @value_name (if not %NULL).
1376 * Returns: %TRUE if value name was retrieved, %FALSE otherwise.
1378 * Since: 2.46
1380 gboolean
1381 g_win32_registry_value_iter_get_name_w (GWin32RegistryValueIter *iter,
1382 gunichar2 **value_name,
1383 gsize *value_name_len,
1384 GError **error)
1386 g_return_val_if_fail (iter != NULL, FALSE);
1387 g_return_val_if_fail (value_name != NULL, FALSE);
1388 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1390 if G_UNLIKELY (iter->counter >= iter->value_count)
1392 g_critical ("g_win32_registry_value_iter_get_name_w: must not be called "
1393 "again after NULL has already been returned.");
1394 return FALSE;
1397 *value_name = iter->value_name;
1399 if (value_name_len)
1400 *value_name_len = iter->value_name_len;
1402 return TRUE;
1406 * g_win32_registry_value_iter_get_name:
1407 * @iter: (in) (transfer none): a #GWin32RegistryValueIter
1408 * @value_name: (out callee-allocates) (transfer none): Pointer to a location
1409 * to store the name of a value (in UTF-8).
1410 * @value_name_len: (out) (optional): Pointer to a location to store the length
1411 * of @value_name, in gchars, excluding NUL-terminator.
1412 * %NULL if length is not needed.
1413 * @error: (nullable): a pointer to %NULL #GError, or %NULL
1415 * Stores the name of the value currently being iterated over in @value_name,
1416 * and its length - in @value_name_len (if not %NULL).
1418 * Returns: %TRUE if value name was retrieved, %FALSE otherwise.
1420 * Since: 2.46
1422 gboolean
1423 g_win32_registry_value_iter_get_name (GWin32RegistryValueIter *iter,
1424 gchar **value_name,
1425 gsize *value_name_len,
1426 GError **error)
1428 glong value_name_len_glong;
1430 g_return_val_if_fail (iter != NULL, FALSE);
1431 g_return_val_if_fail (value_name != NULL, FALSE);
1432 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1434 if G_UNLIKELY (iter->counter >= iter->value_count)
1436 g_critical ("g_win32_registry_value_iter_get_name: must not be called "
1437 "again after NULL has already been returned.");
1438 return FALSE;
1441 if (iter->value_name_u8 == NULL)
1443 iter->value_name_u8 = g_utf16_to_utf8 (iter->value_name, iter->value_name_len, NULL,
1444 &value_name_len_glong, error);
1446 if (iter->value_name_u8 == NULL)
1447 return FALSE;
1450 *value_name = iter->value_name_u8;
1452 if (value_name_len)
1453 *value_name_len = iter->value_name_u8_len;
1455 return TRUE;
1458 static gboolean
1459 expand_value (gunichar2 *value,
1460 const gunichar2 *value_name,
1461 gpointer *expanded_value,
1462 gsize *expanded_charsize,
1463 GError **error)
1465 DWORD value_data_expanded_charsize_w;
1467 value_data_expanded_charsize_w =
1468 ExpandEnvironmentStringsW (value,
1469 (gunichar2 *) *expanded_value,
1470 *expanded_charsize);
1472 if (value_data_expanded_charsize_w > *expanded_charsize)
1474 *expanded_value = g_realloc (*expanded_value,
1475 value_data_expanded_charsize_w * sizeof (gunichar2));
1476 *expanded_charsize = value_data_expanded_charsize_w;
1477 value_data_expanded_charsize_w =
1478 ExpandEnvironmentStringsW (value,
1479 (gunichar2 *) *expanded_value,
1480 *expanded_charsize);
1483 if (value_data_expanded_charsize_w == 0)
1485 g_set_error (error, G_IO_ERROR,
1486 g_io_error_from_win32_error (GetLastError ()),
1487 "Failed to expand data '%S' of value %S",
1488 value, value_name);
1489 return FALSE;
1492 return TRUE;
1496 * g_win32_registry_value_iter_get_data_w:
1497 * @iter: (in) (transfer none): a #GWin32RegistryValueIter
1498 * @auto_expand: (in): %TRUE to automatically expand G_WIN32_REGISTRY_VALUE_EXPAND_STR to
1499 * G_WIN32_REGISTRY_VALUE_STR
1500 * @value_data: (out callee-allocates) (optional) (transfer none): Pointer to a
1501 * location to store the data of the value (in UTF-16, if it's a string)
1502 * @value_data_size: (out) (optional): Pointer to a location to store the size
1503 * of @value_data, in bytes (including any NUL-terminators, if it's a string).
1504 * %NULL if length is not needed.
1505 * @error: (nullable): a pointer to %NULL #GError, or %NULL
1507 * Stores the data of the value currently being iterated over in @value_data,
1508 * and its length - in @value_data_len (if not %NULL).
1510 * Returns: %TRUE if value data was retrieved, %FALSE otherwise.
1512 * Since: 2.46
1514 gboolean
1515 g_win32_registry_value_iter_get_data_w (GWin32RegistryValueIter *iter,
1516 gboolean auto_expand,
1517 gpointer *value_data,
1518 gsize *value_data_size,
1519 GError **error)
1521 g_return_val_if_fail (iter != NULL, FALSE);
1522 g_return_val_if_fail (value_data != NULL, FALSE);
1523 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1525 if G_UNLIKELY (iter->counter >= iter->value_count)
1527 g_critical ("g_win32_registry_value_iter_get_data_w: must not be called "
1528 "again after FALSE has already been returned.");
1529 return FALSE;
1532 if (!auto_expand || (iter->value_type != G_WIN32_REGISTRY_VALUE_EXPAND_STR))
1534 *value_data = iter->value_data;
1536 if (value_data_size)
1537 *value_data_size = iter->value_actual_data_size;
1539 return TRUE;
1542 if (iter->value_type == iter->value_expanded_type)
1544 if (!expand_value ((gunichar2 *) iter->value_data,
1545 iter->value_name,
1546 (gpointer *) &iter->value_data_expanded,
1547 &iter->value_data_expanded_charsize,
1548 error))
1549 return FALSE;
1551 iter->value_expanded_type = G_WIN32_REGISTRY_VALUE_STR;
1554 *value_data = iter->value_data_expanded;
1556 if (value_data_size)
1557 *value_data_size = iter->value_data_expanded_charsize * sizeof (gunichar2);
1559 return TRUE;
1563 * g_win32_registry_value_iter_get_data:
1564 * @iter: (in) (transfer none): a #GWin32RegistryValueIter
1565 * @auto_expand: (in): %TRUE to automatically expand G_WIN32_REGISTRY_VALUE_EXPAND_STR to
1566 * G_WIN32_REGISTRY_VALUE_STR
1567 * @value_data: (out callee-allocates) (optional) (transfer none): Pointer to a
1568 * location to store the data of the value (in UTF-8, if it's a string)
1569 * @value_data_size: (out) (optional): Pointer to a location to store the length
1570 * of @value_data, in bytes (including any NUL-terminators, if it's a string).
1571 * %NULL if length is not needed
1572 * @error: (nullable): a pointer to %NULL #GError, or %NULL
1574 * Stores the data of the value currently being iterated over in @value_data,
1575 * and its length - in @value_data_len (if not %NULL).
1577 * Returns: %TRUE if value data was retrieved, %FALSE otherwise.
1579 * Since: 2.46
1581 gboolean
1582 g_win32_registry_value_iter_get_data (GWin32RegistryValueIter *iter,
1583 gboolean auto_expand,
1584 gpointer *value_data,
1585 gsize *value_data_size,
1586 GError **error)
1588 gsize value_data_len_gsize;
1589 gpointer tmp;
1590 gsize tmp_size;
1592 g_return_val_if_fail (iter != NULL, FALSE);
1593 g_return_val_if_fail (value_data != NULL, FALSE);
1594 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1596 if G_UNLIKELY (iter->counter >= iter->value_count)
1598 g_critical ("g_win32_registry_value_iter_get_data: must not be called "
1599 "again after FALSE has already been returned.");
1600 return FALSE;
1603 if (iter->value_type != G_WIN32_REGISTRY_VALUE_EXPAND_STR &&
1604 iter->value_type != G_WIN32_REGISTRY_VALUE_LINK &&
1605 iter->value_type != G_WIN32_REGISTRY_VALUE_STR &&
1606 iter->value_type != G_WIN32_REGISTRY_VALUE_MULTI_STR)
1608 *value_data = iter->value_data;
1610 if (value_data_size != NULL)
1611 *value_data_size = iter->value_actual_data_size;
1613 return TRUE;
1616 if (!auto_expand || (iter->value_type != G_WIN32_REGISTRY_VALUE_EXPAND_STR))
1618 if (iter->value_data_u8 == NULL)
1620 iter->value_data_u8 = g_convert ((const gchar *) iter->value_data,
1621 iter->value_actual_data_size - sizeof (gunichar2) /* excl. 0 */,
1622 "UTF8", "UTF16", NULL,
1623 &value_data_len_gsize,
1624 error);
1626 if (iter->value_data_u8 == NULL)
1627 return FALSE;
1629 iter->value_data_u8_size = value_data_len_gsize + 1; /* incl. 0 */
1632 *value_data = iter->value_data_u8;
1634 if (value_data_size != NULL)
1635 *value_data_size = iter->value_data_u8_size;
1637 return TRUE;
1640 if (iter->value_data_expanded_u8 == NULL)
1642 if (!g_win32_registry_value_iter_get_data_w (iter,
1643 TRUE,
1644 &tmp,
1645 &tmp_size,
1646 error))
1647 return FALSE;
1649 iter->value_data_expanded_u8 = g_convert ((const gchar *) iter->value_data_expanded,
1650 iter->value_data_expanded_charsize * sizeof (gunichar2) - sizeof (gunichar2) /* excl. 0 */,
1651 "UTF8", "UTF16", NULL,
1652 &value_data_len_gsize,
1653 error);
1655 if (iter->value_data_expanded_u8 == NULL)
1656 return FALSE;
1658 iter->value_data_u8_size = value_data_len_gsize + 1; /* incl. 0 */
1661 *value_data = iter->value_data_expanded_u8;
1663 if (value_data_size != NULL)
1664 *value_data_size = iter->value_data_expanded_u8_size;
1666 return TRUE;
1669 static void
1670 _g_win32_registry_key_reread_kernel (GWin32RegistryKey *key,
1671 GWin32RegistryKeyPrivate *buf)
1673 NTSTATUS status;
1674 KEY_BASIC_INFORMATION *basic_info;
1675 ULONG basic_info_size;
1676 ULONG datasize;
1678 basic_info_size = 256 * sizeof (gunichar2) + sizeof (KEY_BASIC_INFORMATION);
1679 basic_info = g_malloc (basic_info_size + sizeof (gunichar2));
1680 status = nt_query_key (key->priv->handle,
1681 KeyBasicInformation,
1682 basic_info,
1683 basic_info_size,
1684 &datasize);
1686 if (status == STATUS_BUFFER_OVERFLOW || status == STATUS_BUFFER_TOO_SMALL)
1688 g_free (basic_info);
1689 basic_info_size = datasize;
1690 /* +1 for 0-terminator */
1691 basic_info = g_malloc (basic_info_size + sizeof (gunichar2));
1692 status = nt_query_key (key->priv->handle,
1693 KeyBasicInformation,
1694 basic_info,
1695 basic_info_size,
1696 &datasize);
1699 if (status != STATUS_SUCCESS)
1701 g_free (basic_info);
1702 return;
1705 /* Ensure 0-termination */
1706 ((char *) basic_info)[datasize] = 0;
1707 ((char *) basic_info)[datasize + 1] = 0;
1709 buf->absolute_path_w = g_wcsdup (&basic_info->Name[0],
1710 basic_info->NameLength + sizeof (gunichar2));
1711 g_free (basic_info);
1714 static void
1715 _g_win32_registry_key_reread_user (GWin32RegistryKey *key,
1716 GWin32RegistryKeyPrivate *buf)
1718 /* Use RegQueryInfoKey(). It's just like NtQueryKey(), but can't query
1719 * key name.
1720 * Since right now we only need the name, this function is a noop.
1724 static void
1725 _g_win32_registry_key_reread (GWin32RegistryKey *key,
1726 GWin32RegistryKeyPrivate *buf)
1728 if (g_once_init_enter (&nt_query_key))
1730 NtQueryKeyFunc func;
1731 HMODULE ntdll = GetModuleHandleW (L"ntdll.dll");
1733 if (ntdll != NULL)
1734 func = (NtQueryKeyFunc) GetProcAddress (ntdll, "NtQueryKey");
1735 else
1736 func = NULL;
1738 g_once_init_leave (&nt_query_key, func);
1741 /* Assume that predefined keys never get renamed. Also, their handles probably
1742 * won't be accepted by NtQueryKey(), i suspect.
1744 if (nt_query_key != NULL && !key->priv->predefined)
1745 _g_win32_registry_key_reread_kernel (key, buf);
1746 else
1747 _g_win32_registry_key_reread_user (key, buf);
1750 static gboolean
1751 _g_win32_registry_key_update_path (GWin32RegistryKey *key)
1753 GWin32RegistryKeyPrivate tmp;
1754 gboolean changed;
1755 gint change_indicator;
1757 change_indicator = g_atomic_int_get (&key->priv->change_indicator);
1759 if (change_indicator == G_WIN32_KEY_UNCHANGED)
1760 return FALSE;
1762 tmp.absolute_path_w = NULL;
1763 _g_win32_registry_key_reread (key, &tmp);
1764 changed = FALSE;
1766 if (wcscmp (key->priv->absolute_path_w, tmp.absolute_path_w) == 0)
1767 g_free (tmp.absolute_path_w);
1768 else
1770 g_free (key->priv->absolute_path_w);
1771 key->priv->absolute_path_w = tmp.absolute_path_w;
1772 changed = TRUE;
1775 return changed;
1779 * g_win32_registry_key_get_path:
1780 * @key: (in) (transfer none): a #GWin32RegistryKey
1782 * Get full path to the key
1784 * Returns: (transfer none): a full path to the key (in UTF-8),
1785 * or %NULL if it can't be converted to UTF-8.
1787 * Since: 2.46
1789 const gchar *
1790 g_win32_registry_key_get_path (GWin32RegistryKey *key)
1792 gint change_indicator;
1794 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), NULL);
1796 change_indicator = g_atomic_int_get (&key->priv->change_indicator);
1798 if (change_indicator == G_WIN32_KEY_CHANGED &&
1799 !(key->priv->update_flags & G_WIN32_REGISTRY_UPDATED_PATH))
1801 _g_win32_registry_key_update_path (key);
1802 key->priv->update_flags |= G_WIN32_REGISTRY_UPDATED_PATH;
1805 if (key->priv->absolute_path == NULL)
1807 g_free (key->priv->absolute_path);
1808 key->priv->absolute_path =
1809 g_utf16_to_utf8 (key->priv->absolute_path_w, -1,
1810 NULL, NULL, NULL);
1813 return key->priv->absolute_path;
1817 * g_win32_registry_key_get_path_w:
1818 * @key: (in) (transfer none): a #GWin32RegistryKey
1820 * Get full path to the key
1822 * Returns: (transfer none): a full path to the key (in UTF-16)
1824 * Since: 2.46
1826 const gunichar2 *
1827 g_win32_registry_key_get_path_w (GWin32RegistryKey *key)
1829 gint change_indicator;
1831 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), NULL);
1833 change_indicator = g_atomic_int_get (&key->priv->change_indicator);
1835 if (change_indicator == G_WIN32_KEY_CHANGED)
1836 _g_win32_registry_key_update_path (key);
1838 return key->priv->absolute_path_w;
1842 * g_win32_registry_key_get_value:
1843 * @key: (in) (transfer none): a #GWin32RegistryKey
1844 * @auto_expand: (in) %TRUE to automatically expand G_WIN32_REGISTRY_VALUE_EXPAND_STR
1845 * to G_WIN32_REGISTRY_VALUE_STR.
1846 * @value_name: (in) (transfer none): name of the value to get (in UTF-8).
1847 * Empty string means the '(Default)' value.
1848 * @value_type: (out) (optional): type of the value retrieved.
1849 * @value_data: (out callee-allocates) (optional): contents of the value.
1850 * @value_data_size: (out) (optional): size of the buffer pointed
1851 * by @value_data.
1852 * @error: (nullable): a pointer to %NULL #GError, or %NULL
1854 * Get data from a value of a key. String data is guaranteed to be
1855 * appropriately terminated and will be in UTF-8.
1857 * Returns: %TRUE on success, %FALSE on failure.
1859 * Since: 2.46
1861 gboolean
1862 g_win32_registry_key_get_value (GWin32RegistryKey *key,
1863 gboolean auto_expand,
1864 const gchar *value_name,
1865 GWin32RegistryValueType *value_type,
1866 gpointer *value_data,
1867 gsize *value_data_size,
1868 GError **error)
1870 GWin32RegistryValueType value_type_g;
1871 gpointer value_data_w;
1872 gsize value_data_w_size;
1873 gunichar2 *value_name_w;
1874 gchar *value_data_u8;
1875 gsize value_data_u8_len;
1876 gboolean result;
1878 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), FALSE);
1879 g_return_val_if_fail (value_name != NULL, FALSE);
1880 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1882 /* No sense calling this function with all of these set to NULL */
1883 g_return_val_if_fail (value_type != NULL ||
1884 value_data != NULL ||
1885 value_data_size != NULL, FALSE);
1887 value_name_w = g_utf8_to_utf16 (value_name, -1, NULL, NULL, error);
1889 if (value_name_w == NULL)
1890 return FALSE;
1892 result = g_win32_registry_key_get_value_w (key,
1893 auto_expand,
1894 value_name_w,
1895 &value_type_g,
1896 &value_data_w,
1897 &value_data_w_size,
1898 error);
1900 g_free (value_name_w);
1902 if (!result)
1903 return FALSE;
1905 if (value_type_g == G_WIN32_REGISTRY_VALUE_EXPAND_STR ||
1906 value_type_g == G_WIN32_REGISTRY_VALUE_LINK ||
1907 value_type_g == G_WIN32_REGISTRY_VALUE_STR ||
1908 value_type_g == G_WIN32_REGISTRY_VALUE_MULTI_STR)
1910 value_data_u8 = g_convert ((const gchar *) value_data_w,
1911 value_data_w_size - sizeof (gunichar2) /* excl. 0 */,
1912 "UTF8",
1913 "UTF16",
1914 NULL,
1915 &value_data_u8_len,
1916 error);
1917 g_free (value_data_w);
1919 if (value_data_u8 == NULL)
1920 return FALSE;
1922 if (value_data)
1923 *value_data = value_data_u8;
1924 else
1925 g_free (value_data_u8);
1927 if (value_data_size)
1928 *value_data_size = value_data_u8_len + 1;
1930 else
1932 if (value_data)
1933 *value_data = value_data_w;
1934 else
1935 g_free (value_data_w);
1937 if (value_data_size)
1938 *value_data_size = value_data_w_size;
1941 if (value_type)
1942 *value_type = value_type_g;
1944 return TRUE;
1948 * g_win32_registry_key_get_value_w:
1949 * @key: (in) (transfer none): a #GWin32RegistryKey
1950 * @auto_expand: (in) %TRUE to automatically expand G_WIN32_REGISTRY_VALUE_EXPAND_STR
1951 * to G_WIN32_REGISTRY_VALUE_STR.
1952 * @value_name: (in) (transfer none): name of the value to get (in UTF-16).
1953 * Empty string means the '(Default)' value.
1954 * @value_type: (out) (optional): type of the value retrieved.
1955 * @value_data: (out callee-allocates) (optional): contents of the value.
1956 * @value_data_size: (out) (optional): size of the buffer pointed
1957 * by @value_data.
1958 * @error: (nullable): a pointer to %NULL #GError, or %NULL
1960 * Get data from a value of a key.
1962 * Get data from a value of a key. String data is guaranteed to be
1963 * appropriately terminated and will be in UTF-16.
1965 * When calling with value_data == NULL (to get data size without getting
1966 * the data itself) remember that returned size corresponds to possibly
1967 * unterminated string data (if value is some kind of string), because
1968 * termination cannot be checked and fixed unless the data is retreived
1969 * too.
1971 * Returns: %TRUE on success, %FALSE on failure.
1973 * Since: 2.46
1975 gboolean
1976 g_win32_registry_key_get_value_w (GWin32RegistryKey *key,
1977 gboolean auto_expand,
1978 const gunichar2 *value_name,
1979 GWin32RegistryValueType *value_type,
1980 gpointer *value_data,
1981 gsize *value_data_size,
1982 GError **error)
1984 LONG status;
1985 DWORD value_type_w;
1986 DWORD value_type_w2;
1987 char *req_value_data;
1988 GWin32RegistryValueType value_type_g;
1989 GWin32RegistryValueType value_type_g2;
1990 DWORD req_value_data_size;
1991 DWORD req_value_data_size2;
1993 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), FALSE);
1994 g_return_val_if_fail (value_name != NULL, FALSE);
1995 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1997 /* No sense calling this functions with all of these set to NULL */
1998 g_return_val_if_fail (value_type != NULL ||
1999 value_data != NULL ||
2000 value_data_size != NULL, FALSE);
2002 req_value_data_size = 0;
2003 status = RegQueryValueExW (key->priv->handle,
2004 value_name,
2005 NULL,
2006 &value_type_w,
2007 NULL,
2008 &req_value_data_size);
2010 if (status != ERROR_MORE_DATA && status != ERROR_SUCCESS)
2012 g_set_error (error, G_IO_ERROR, g_io_error_from_win32_error (status),
2013 "Failed to query value '%S' for key '%S'",
2014 value_name, g_win32_registry_key_get_path_w (key));
2016 return FALSE;
2019 value_type_g = _g_win32_registry_type_w_to_g (value_type_w);
2021 if (value_data == NULL &&
2022 (!auto_expand || value_type_g != G_WIN32_REGISTRY_VALUE_EXPAND_STR))
2024 if (value_type)
2025 *value_type = value_type_g;
2027 if (value_data_size)
2028 *value_data_size = req_value_data_size;
2030 return TRUE;
2033 req_value_data = g_malloc (req_value_data_size + sizeof (gunichar2) * 2);
2034 req_value_data_size2 = req_value_data_size;
2035 status = RegQueryValueExW (key->priv->handle,
2036 value_name,
2037 NULL,
2038 &value_type_w2,
2039 (gpointer) req_value_data,
2040 &req_value_data_size2);
2042 if (status != ERROR_SUCCESS)
2044 g_set_error (error, G_IO_ERROR, g_io_error_from_win32_error (status),
2045 "Failed to query value '%S' of size %lu for key '%S'",
2046 value_name,
2047 req_value_data_size,
2048 g_win32_registry_key_get_path_w (key));
2049 g_free (req_value_data);
2050 return FALSE;
2053 value_type_g2 = _g_win32_registry_type_w_to_g (value_type_w2);
2055 if (value_type_w != value_type_w2)
2057 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
2058 "Type of value '%S' of key '%S' changed from %u to %u"
2059 " between calls",
2060 value_name,
2061 g_win32_registry_key_get_path_w (key),
2062 value_type_g, value_type_g2);
2063 g_free (req_value_data);
2064 return FALSE;
2067 req_value_data_size = ensure_nul_termination (value_type_g,
2068 (guint8 *) req_value_data,
2069 req_value_data_size2);
2071 if (value_type_g == G_WIN32_REGISTRY_VALUE_EXPAND_STR && auto_expand)
2073 gsize value_data_expanded_charsize_w = 0;
2074 gunichar2 *value_data_expanded = NULL;
2076 if (!expand_value ((gunichar2 *) req_value_data,
2077 value_name,
2078 (gpointer *) &value_data_expanded,
2079 &value_data_expanded_charsize_w,
2080 error))
2081 return FALSE;
2083 g_free (req_value_data);
2085 if (value_type)
2086 *value_type = G_WIN32_REGISTRY_VALUE_STR;
2088 if (value_data)
2089 *value_data = value_data_expanded;
2090 else
2091 g_free (value_data_expanded);
2093 if (value_data_size)
2094 *value_data_size = value_data_expanded_charsize_w * sizeof (gunichar2);
2096 return TRUE;
2099 if (value_type)
2100 *value_type = value_type_g;
2102 if (value_data_size)
2103 *value_data_size = req_value_data_size;
2105 if (value_data)
2106 *value_data = req_value_data;
2107 else
2108 g_free (req_value_data);
2110 return TRUE;
2113 static VOID NTAPI
2114 key_changed (PVOID closure,
2115 PIO_STATUS_BLOCK status_block,
2116 ULONG reserved)
2118 GWin32RegistryKey *key = G_WIN32_REGISTRY_KEY (closure);
2120 g_free (status_block);
2121 g_atomic_int_set (&key->priv->change_indicator, G_WIN32_KEY_CHANGED);
2122 g_atomic_int_set (&key->priv->watch_indicator, G_WIN32_KEY_UNWATCHED);
2123 key->priv->update_flags = G_WIN32_REGISTRY_UPDATED_NOTHING;
2125 if (key->priv->callback)
2126 key->priv->callback (key, key->priv->user_data);
2128 key->priv->callback = NULL;
2129 key->priv->user_data = NULL;
2130 g_object_unref (key);
2134 * g_win32_registry_key_watch:
2135 * @key: (in) (transfer none): a #GWin32RegistryKey
2136 * @watch_children: (in) %TRUE also watch the children of the @key, %FALSE
2137 * to watch the key only.
2138 * @watch_flags: (in): specifies the types of changes to watch for.
2139 * @callback: (in) (nullable): a function to invoke when a change occurs.
2140 * @user_data: (in) (nullable): a pointer to pass to @callback on invocation.
2141 * @error: (nullable): a pointer to %NULL #GError, or %NULL
2143 * Puts @key under a watch.
2145 * When the key changes, an APC will be queued in the current thread. The APC
2146 * will run when the current thread enters alertable state (GLib main loop
2147 * should do that; if you are not using it, see MSDN documentation for W32API
2148 * calls that put thread into alertable state). When it runs, it will
2149 * atomically switch an indicator in the @key. If a callback was specified,
2150 * it is invoked at that point. Subsequent calls to
2151 * g_win32_registry_key_has_changed() will return %TRUE, and the callback (if
2152 * it was specified) will not be invoked anymore.
2153 * Calling g_win32_registry_key_erase_change_indicator() will reset the indicator,
2154 * and g_win32_registry_key_has_changed() will start returning %FALSE.
2155 * To resume the watch, call g_win32_registry_key_watch_for_changes() again.
2157 * Calling g_win32_registry_key_watch_for_changes() for a key that is already
2158 * being watched is allowed and affects nothing.
2160 * The fact that the key is being watched will be used internally to update
2161 * key path (if it changes).
2163 * Returns: %TRUE on success, %FALSE on failure.
2165 * Since: 2.46
2167 gboolean
2168 g_win32_registry_key_watch (GWin32RegistryKey *key,
2169 gboolean watch_children,
2170 GWin32RegistryKeyWatcherFlags watch_flags,
2171 GWin32RegistryKeyWatchCallbackFunc callback,
2172 gpointer user_data,
2173 GError **error)
2175 ULONG filter;
2176 gboolean started_to_watch;
2177 NTSTATUS status;
2178 PIO_STATUS_BLOCK status_block;
2180 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), FALSE);
2182 filter = ((watch_flags & G_WIN32_REGISTRY_WATCH_NAME) ? REG_NOTIFY_CHANGE_NAME : 0) |
2183 ((watch_flags & G_WIN32_REGISTRY_WATCH_ATTRIBUTES) ? REG_NOTIFY_CHANGE_ATTRIBUTES : 0) |
2184 ((watch_flags & G_WIN32_REGISTRY_WATCH_VALUES) ? REG_NOTIFY_CHANGE_LAST_SET : 0) |
2185 ((watch_flags & G_WIN32_REGISTRY_WATCH_SECURITY) ? REG_NOTIFY_CHANGE_SECURITY : 0);
2187 if (filter == 0)
2189 g_critical ("No supported flags specified in watch_flags (%x)", (guint) watch_flags);
2190 return FALSE;
2193 if (g_once_init_enter (&nt_notify_change_multiple_keys))
2195 NtNotifyChangeMultipleKeysFunc func;
2196 HMODULE ntdll = GetModuleHandle ("ntdll.dll");
2198 if (ntdll != NULL)
2199 func = (NtNotifyChangeMultipleKeysFunc) GetProcAddress (ntdll, "NtNotifyChangeMultipleKeys");
2200 else
2201 func = NULL;
2203 g_once_init_leave (&nt_notify_change_multiple_keys, func);
2206 if (nt_notify_change_multiple_keys== NULL)
2208 g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
2209 "Couldn't get NtNotifyChangeMultipleKeys() from ntdll");
2210 return FALSE;
2213 started_to_watch =
2214 g_atomic_int_compare_and_exchange (&key->priv->watch_indicator,
2215 G_WIN32_KEY_UNWATCHED,
2216 G_WIN32_KEY_WATCHED);
2218 if (!started_to_watch)
2219 return TRUE;
2221 key->priv->callback = callback;
2222 key->priv->user_data = user_data;
2224 g_atomic_int_set (&key->priv->change_indicator, G_WIN32_KEY_UNCHANGED);
2226 /* Keep it alive until APC is called */
2227 g_object_ref (key);
2229 status_block = g_malloc (sizeof (IO_STATUS_BLOCK));
2231 status = nt_notify_change_multiple_keys (key->priv->handle,
2233 NULL,
2234 NULL,
2235 key_changed,
2236 (PVOID) key,
2237 status_block,
2238 filter,
2239 watch_children,
2240 NULL,
2242 TRUE);
2244 g_assert (status != STATUS_SUCCESS);
2246 if (status == STATUS_PENDING)
2247 return TRUE;
2249 g_atomic_int_set (&key->priv->change_indicator, G_WIN32_KEY_UNKNOWN);
2250 g_atomic_int_set (&key->priv->watch_indicator, G_WIN32_KEY_UNWATCHED);
2251 g_object_unref (key);
2252 g_free (status_block);
2254 return FALSE;
2258 * g_win32_registry_key_erase_change_indicator:
2259 * @key: (in) (transfer none): a #GWin32RegistryKey
2261 * Erases change indicator of the @key.
2263 * Subsequent calls to g_win32_registry_key_has_changed() will return %FALSE
2264 * until the key is put on watch again by calling
2265 * g_win32_registry_key_watch() again.
2267 * Since: 2.46
2269 void
2270 g_win32_registry_key_erase_change_indicator (GWin32RegistryKey *key)
2272 g_return_if_fail (G_IS_WIN32_REGISTRY_KEY (key));
2274 g_atomic_int_set (&key->priv->change_indicator, G_WIN32_KEY_UNKNOWN);
2278 * g_win32_registry_key_has_changed:
2279 * @key: (in) (transfer none): a #GWin32RegistryKey
2281 * Check the @key's status indicator.
2283 * Returns: %TRUE if the @key was put under watch at some point and has changed
2284 * since then, %FALSE if it either wasn't changed or wasn't watched at all.
2286 * Since: 2.46
2288 gboolean
2289 g_win32_registry_key_has_changed (GWin32RegistryKey *key)
2291 gint changed;
2293 g_return_val_if_fail (G_IS_WIN32_REGISTRY_KEY (key), FALSE);
2295 changed = g_atomic_int_get (&key->priv->change_indicator);
2297 return (changed == G_WIN32_KEY_CHANGED ? TRUE : FALSE);
2300 static void
2301 g_win32_registry_key_get_property (GObject *object,
2302 guint prop_id,
2303 GValue *value,
2304 GParamSpec *pspec)
2306 GWin32RegistryKey *key = G_WIN32_REGISTRY_KEY (object);
2308 switch (prop_id)
2310 case PROP_PATH:
2311 g_value_set_string (value, g_win32_registry_key_get_path (key));
2312 break;
2314 case PROP_PATH_UTF16:
2315 g_value_set_pointer (value, (gpointer) g_win32_registry_key_get_path_w (key));
2316 break;
2318 default:
2319 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2323 static void
2324 g_win32_registry_key_set_property (GObject *object,
2325 guint prop_id,
2326 const GValue *value,
2327 GParamSpec *pspec)
2329 GWin32RegistryKey *key = G_WIN32_REGISTRY_KEY (object);
2330 GWin32RegistryKeyPrivate *priv = key->priv;
2331 const gchar *path;
2332 gunichar2 *path_w;
2334 switch (prop_id)
2336 case PROP_PATH:
2337 g_assert (priv->absolute_path_w == NULL);
2338 g_assert (priv->absolute_path == NULL);
2339 path = g_value_get_string (value);
2341 if (path == NULL)
2342 break;
2344 path_w = g_utf8_to_utf16 (path, -1, NULL, NULL, NULL);
2346 if (path_w == NULL)
2347 break;
2349 g_free (priv->absolute_path_w);
2350 g_free (priv->absolute_path);
2351 priv->absolute_path_w = path_w;
2352 priv->absolute_path = g_value_dup_string (value);
2353 break;
2355 case PROP_PATH_UTF16:
2356 g_assert (priv->absolute_path_w == NULL);
2357 g_assert (priv->absolute_path == NULL);
2358 path_w = (gunichar2 *) g_value_get_pointer (value);
2360 if (path_w == NULL)
2361 break;
2363 priv->absolute_path_w = g_wcsdup (path_w, -1);
2364 break;
2366 default:
2367 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2371 static void
2372 g_win32_registry_key_class_init (GWin32RegistryKeyClass *klass)
2374 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
2376 gobject_class->dispose = g_win32_registry_key_dispose;
2377 gobject_class->set_property = g_win32_registry_key_set_property;
2378 gobject_class->get_property = g_win32_registry_key_get_property;
2381 * GWin32RegistryKey:path:
2383 * A path to the key in the registry, in UTF-8.
2385 * Since: 2.46
2387 g_object_class_install_property (gobject_class,
2388 PROP_PATH,
2389 g_param_spec_string ("path",
2390 "Path",
2391 "Path to the key in the registry",
2392 NULL,
2393 G_PARAM_READWRITE |
2394 G_PARAM_CONSTRUCT_ONLY |
2395 G_PARAM_STATIC_STRINGS));
2398 * GWin32RegistryKey:path-utf16:
2400 * A path to the key in the registry, in UTF-16.
2402 * Since: 2.46
2404 g_object_class_install_property (gobject_class,
2405 PROP_PATH_UTF16,
2406 g_param_spec_pointer ("path-utf16",
2407 "Path (UTF-16)",
2408 "Path to the key in the registry, in UTF-16",
2409 G_PARAM_READWRITE |
2410 G_PARAM_CONSTRUCT_ONLY |
2411 G_PARAM_STATIC_STRINGS));
2414 static void
2415 g_win32_registry_key_init (GWin32RegistryKey *key)
2417 key->priv = g_win32_registry_key_get_instance_private (key);
2418 key->priv->change_indicator = G_WIN32_KEY_UNKNOWN;