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 (* 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_wcsdup (const gunichar2
*str
,
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:
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 ()
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
;
170 new_iter
->subkey_name_u8
= NULL
;
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.
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
);
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.
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
);
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:
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 ().
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
;
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.
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
);
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.
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
);
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
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
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
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.
374 GWin32RegistryKey
*ancestor
;
376 /* Handle to the key */
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).
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
;
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
,
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
));
428 g_win32_registry_key_dispose (GObject
*object
)
430 GWin32RegistryKey
*key
;
431 GWin32RegistryKeyPrivate
*priv
;
433 key
= G_WIN32_REGISTRY_KEY (object
);
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
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().
471 g_win32_registry_key_new (const gchar
*path
,
474 g_return_val_if_fail (path
!= NULL
, NULL
);
476 return g_initable_new (G_TYPE_WIN32_REGISTRY_KEY
,
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) (optional) (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
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().
506 g_win32_registry_key_new_w (const gunichar2
*path
,
511 g_return_val_if_fail (path
!= NULL
, NULL
);
513 result
= g_initable_new (G_TYPE_WIN32_REGISTRY_KEY
,
520 return result
? G_WIN32_REGISTRY_KEY (result
) : NULL
;
524 g_win32_registry_key_initable_iface_init (GInitableIface
*iface
)
526 iface
->init
= g_win32_registry_key_initable_init
;
530 g_win32_registry_key_initable_init (GInitable
*initable
,
531 GCancellable
*cancellable
,
534 GWin32RegistryKey
*key
;
535 GWin32RegistryKeyPrivate
*priv
;
537 gunichar2
*first_chunk_end
;
538 gsize first_chunk_len
;
539 gunichar2
*second_chunk_begin
;
540 gunichar2
*first_chunk
;
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
);
551 if (priv
->absolute_path_w
== NULL
)
553 priv
->absolute_path_w
= g_utf8_to_utf16 (priv
->absolute_path
,
559 if (priv
->absolute_path_w
== NULL
)
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
;
593 g_critical ("Root key '%S' is not a pre-defined key", first_chunk
);
594 g_free (first_chunk
);
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
);
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
);
620 priv
->ancestor
= NULL
;
621 priv
->handle
= key_handle
;
622 priv
->predefined
= (second_chunk_begin
[0] == L
'\0');
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) (optional) (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().
639 g_win32_registry_key_get_child (GWin32RegistryKey
*key
,
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
);
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) (optional) (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().
673 g_win32_registry_key_get_child_w (GWin32RegistryKey
*key
,
674 const gunichar2
*subkey
,
679 const gunichar2
*end_of_subkey
;
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
);
694 subkey_len
= wcslen (subkey
);
695 end_of_subkey
= &subkey
[subkey_len
];
698 end_of_subkey
= subkey
;
700 if (end_of_subkey
[0] == L
'\\')
702 g_critical ("Subkey name '%S' ends with '\\'", subkey
);
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'",
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
);
731 result
->priv
->ancestor
= NULL
;
733 result
->priv
->change_indicator
= G_WIN32_KEY_UNKNOWN
;
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) (optional) (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
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.
757 g_win32_registry_subkey_iter_init (GWin32RegistrySubkeyIter
*iter
,
758 GWin32RegistryKey
*key
,
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
,
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
));
782 iter
->key
= g_object_ref (key
);
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
;
793 * g_win32_registry_subkey_iter_clear:
794 * @iter: (in) (transfer none): a #GWin32RegistrySubkeyIter
796 * Frees internal buffers of a #GWin32RegistrySubkeyIter.
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
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
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
848 * iterate_key_recursive (GWin32RegistryKey *key)
850 * GWin32RegistrySubkeyIter iter;
852 * GWin32RegistryKey *child;
854 * if (!g_win32_registry_subkey_iter_init (&iter, key, NULL))
857 * while (g_win32_registry_subkey_iter_next (&iter, TRUE, NULL))
859 * if (!g_win32_registry_subkey_iter_get_name (&iter, &name, NULL, NULL))
862 * g_print ("subkey '%s'\n", name);
863 * child = g_win32_registry_key_get_child (key, name, NULL);
866 * iterate_key_recursive (child);
869 * g_win32_registry_subkey_iter_clear (&iter);
873 * Returns: %TRUE if next subkey info was retrieved, %FALSE otherwise.
878 g_win32_registry_subkey_iter_next (GWin32RegistrySubkeyIter
*iter
,
879 gboolean skip_errors
,
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.");
899 if (iter
->counter
>= iter
->subkey_count
)
902 /* Including 0-terminator */
903 subkey_len
= iter
->subkey_name_size
;
904 status
= RegEnumKeyExW (iter
->key
->priv
->handle
,
908 NULL
, NULL
, NULL
, NULL
);
910 if (status
== ERROR_SUCCESS
)
912 iter
->subkey_name_len
= subkey_len
;
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;
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
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.
948 g_win32_registry_subkey_iter_get_name_w (GWin32RegistrySubkeyIter
*iter
,
949 gunichar2
**subkey_name
,
950 gsize
*subkey_name_len
,
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.");
965 *subkey_name
= iter
->subkey_name
;
968 *subkey_name_len
= iter
->subkey_name_len
;
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.
990 g_win32_registry_subkey_iter_get_name (GWin32RegistrySubkeyIter
*iter
,
992 gsize
*subkey_name_len
,
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.");
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
,
1013 &subkey_name_len_glong
,
1016 if (iter
->subkey_name_u8
!= NULL
)
1018 *subkey_name_len
= subkey_name_len_glong
;
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
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.
1044 g_win32_registry_value_iter_init (GWin32RegistryValueIter
*iter
,
1045 GWin32RegistryKey
*key
,
1050 DWORD max_value_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
));
1070 iter
->key
= g_object_ref (key
);
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;
1095 * g_win32_registry_value_iter_clear:
1096 * @iter: (in) (transfer none): a #GWin32RegistryValueIter
1098 * Frees internal buffers of a #GWin32RegistryValueIter.
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
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
)
1145 return G_WIN32_REGISTRY_VALUE_BINARY
;
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
;
1152 case REG_DWORD_BIG_ENDIAN
:
1153 return G_WIN32_REGISTRY_VALUE_UINT32BE
;
1156 return G_WIN32_REGISTRY_VALUE_EXPAND_STR
;
1158 return G_WIN32_REGISTRY_VALUE_LINK
;
1160 return G_WIN32_REGISTRY_VALUE_MULTI_STR
;
1162 return G_WIN32_REGISTRY_VALUE_NONE
;
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
;
1170 return G_WIN32_REGISTRY_VALUE_STR
;
1172 return G_WIN32_REGISTRY_VALUE_NONE
;
1177 ensure_nul_termination (GWin32RegistryValueType value_type
,
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;
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;
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
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
1231 * iterate_values_recursive (GWin32RegistryKey *key)
1233 * GWin32RegistryValueIter iter;
1235 * GWin32RegistryValueType val_type;
1238 * if (!g_win32_registry_value_iter_init (&iter, key, NULL))
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)))
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);
1257 * Returns: %TRUE if next value info was retrieved, %FALSE otherwise.
1262 g_win32_registry_value_iter_next (GWin32RegistryValueIter
*iter
,
1263 gboolean skip_errors
,
1267 DWORD value_name_len_w
;
1268 DWORD value_data_size_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.");
1286 if (iter
->counter
>= iter
->value_count
)
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
,
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;
1313 else if (status
!= ERROR_SUCCESS
&& skip_errors
)
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
,
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
;
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
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.
1343 g_win32_registry_value_iter_get_value_type (GWin32RegistryValueIter
*iter
,
1344 GWin32RegistryValueType
*value_type
,
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.");
1358 *value_type
= iter
->value_type
;
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.
1381 g_win32_registry_value_iter_get_name_w (GWin32RegistryValueIter
*iter
,
1382 gunichar2
**value_name
,
1383 gsize
*value_name_len
,
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.");
1397 *value_name
= iter
->value_name
;
1400 *value_name_len
= iter
->value_name_len
;
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.
1423 g_win32_registry_value_iter_get_name (GWin32RegistryValueIter
*iter
,
1425 gsize
*value_name_len
,
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.");
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
)
1450 *value_name
= iter
->value_name_u8
;
1453 *value_name_len
= iter
->value_name_u8_len
;
1459 expand_value (gunichar2
*value
,
1460 const gunichar2
*value_name
,
1461 gpointer
*expanded_value
,
1462 gsize
*expanded_charsize
,
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",
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.
1515 g_win32_registry_value_iter_get_data_w (GWin32RegistryValueIter
*iter
,
1516 gboolean auto_expand
,
1517 gpointer
*value_data
,
1518 gsize
*value_data_size
,
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.");
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
;
1542 if (iter
->value_type
== iter
->value_expanded_type
)
1544 if (!expand_value ((gunichar2
*) iter
->value_data
,
1546 (gpointer
*) &iter
->value_data_expanded
,
1547 &iter
->value_data_expanded_charsize
,
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
);
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.
1582 g_win32_registry_value_iter_get_data (GWin32RegistryValueIter
*iter
,
1583 gboolean auto_expand
,
1584 gpointer
*value_data
,
1585 gsize
*value_data_size
,
1588 gsize value_data_len_gsize
;
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.");
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
;
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
,
1626 if (iter
->value_data_u8
== NULL
)
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
;
1640 if (iter
->value_data_expanded_u8
== NULL
)
1642 if (!g_win32_registry_value_iter_get_data_w (iter
,
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
,
1655 if (iter
->value_data_expanded_u8
== NULL
)
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
;
1670 _g_win32_registry_key_reread_kernel (GWin32RegistryKey
*key
,
1671 GWin32RegistryKeyPrivate
*buf
)
1674 KEY_BASIC_INFORMATION
*basic_info
;
1675 ULONG basic_info_size
;
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
,
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
,
1699 if (status
!= STATUS_SUCCESS
)
1701 g_free (basic_info
);
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
);
1715 _g_win32_registry_key_reread_user (GWin32RegistryKey
*key
,
1716 GWin32RegistryKeyPrivate
*buf
)
1718 /* Use RegQueryInfoKey(). It's just like NtQueryKey(), but can't query
1720 * Since right now we only need the name, this function is a noop.
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");
1734 func
= (NtQueryKeyFunc
) GetProcAddress (ntdll
, "NtQueryKey");
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
);
1747 _g_win32_registry_key_reread_user (key
, buf
);
1751 _g_win32_registry_key_update_path (GWin32RegistryKey
*key
)
1753 GWin32RegistryKeyPrivate tmp
;
1755 gint change_indicator
;
1757 change_indicator
= g_atomic_int_get (&key
->priv
->change_indicator
);
1759 if (change_indicator
== G_WIN32_KEY_UNCHANGED
)
1762 tmp
.absolute_path_w
= NULL
;
1763 _g_win32_registry_key_reread (key
, &tmp
);
1766 if (wcscmp (key
->priv
->absolute_path_w
, tmp
.absolute_path_w
) == 0)
1767 g_free (tmp
.absolute_path_w
);
1770 g_free (key
->priv
->absolute_path_w
);
1771 key
->priv
->absolute_path_w
= tmp
.absolute_path_w
;
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.
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,
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)
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
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.
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
,
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
;
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
)
1892 result
= g_win32_registry_key_get_value_w (key
,
1900 g_free (value_name_w
);
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 */,
1917 g_free (value_data_w
);
1919 if (value_data_u8
== NULL
)
1923 *value_data
= value_data_u8
;
1925 g_free (value_data_u8
);
1927 if (value_data_size
)
1928 *value_data_size
= value_data_u8_len
+ 1;
1933 *value_data
= value_data_w
;
1935 g_free (value_data_w
);
1937 if (value_data_size
)
1938 *value_data_size
= value_data_w_size
;
1942 *value_type
= value_type_g
;
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
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
1971 * Returns: %TRUE on success, %FALSE on failure.
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
,
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
,
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
));
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
))
2025 *value_type
= value_type_g
;
2027 if (value_data_size
)
2028 *value_data_size
= req_value_data_size
;
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
,
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'",
2047 req_value_data_size
,
2048 g_win32_registry_key_get_path_w (key
));
2049 g_free (req_value_data
);
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"
2061 g_win32_registry_key_get_path_w (key
),
2062 value_type_g
, value_type_g2
);
2063 g_free (req_value_data
);
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
,
2078 (gpointer
*) &value_data_expanded
,
2079 &value_data_expanded_charsize_w
,
2083 g_free (req_value_data
);
2086 *value_type
= G_WIN32_REGISTRY_VALUE_STR
;
2089 *value_data
= value_data_expanded
;
2091 g_free (value_data_expanded
);
2093 if (value_data_size
)
2094 *value_data_size
= value_data_expanded_charsize_w
* sizeof (gunichar2
);
2100 *value_type
= value_type_g
;
2102 if (value_data_size
)
2103 *value_data_size
= req_value_data_size
;
2106 *value_data
= req_value_data
;
2108 g_free (req_value_data
);
2114 key_changed (PVOID closure
,
2115 PIO_STATUS_BLOCK status_block
,
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.
2168 g_win32_registry_key_watch (GWin32RegistryKey
*key
,
2169 gboolean watch_children
,
2170 GWin32RegistryKeyWatcherFlags watch_flags
,
2171 GWin32RegistryKeyWatchCallbackFunc callback
,
2176 gboolean started_to_watch
;
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);
2189 g_critical ("No supported flags specified in watch_flags (%x)", (guint
) watch_flags
);
2193 if (g_once_init_enter (&nt_notify_change_multiple_keys
))
2195 NtNotifyChangeMultipleKeysFunc func
;
2196 HMODULE ntdll
= GetModuleHandle ("ntdll.dll");
2199 func
= (NtNotifyChangeMultipleKeysFunc
) GetProcAddress (ntdll
, "NtNotifyChangeMultipleKeys");
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");
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
)
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 */
2229 status_block
= g_malloc (sizeof (IO_STATUS_BLOCK
));
2231 status
= nt_notify_change_multiple_keys (key
->priv
->handle
,
2244 g_assert (status
!= STATUS_SUCCESS
);
2246 if (status
== STATUS_PENDING
)
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
);
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.
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.
2289 g_win32_registry_key_has_changed (GWin32RegistryKey
*key
)
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
);
2301 g_win32_registry_key_get_property (GObject
*object
,
2306 GWin32RegistryKey
*key
= G_WIN32_REGISTRY_KEY (object
);
2311 g_value_set_string (value
, g_win32_registry_key_get_path (key
));
2314 case PROP_PATH_UTF16
:
2315 g_value_set_pointer (value
, (gpointer
) g_win32_registry_key_get_path_w (key
));
2319 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
2324 g_win32_registry_key_set_property (GObject
*object
,
2326 const GValue
*value
,
2329 GWin32RegistryKey
*key
= G_WIN32_REGISTRY_KEY (object
);
2330 GWin32RegistryKeyPrivate
*priv
= key
->priv
;
2337 g_assert (priv
->absolute_path_w
== NULL
);
2338 g_assert (priv
->absolute_path
== NULL
);
2339 path
= g_value_get_string (value
);
2344 path_w
= g_utf8_to_utf16 (path
, -1, NULL
, NULL
, NULL
);
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
);
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
);
2363 priv
->absolute_path_w
= g_wcsdup (path_w
, -1);
2367 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
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.
2387 g_object_class_install_property (gobject_class
,
2389 g_param_spec_string ("path",
2391 "Path to the key in the registry",
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.
2404 g_object_class_install_property (gobject_class
,
2406 g_param_spec_pointer ("path-utf16",
2408 "Path to the key in the registry, in UTF-16",
2410 G_PARAM_CONSTRUCT_ONLY
|
2411 G_PARAM_STATIC_STRINGS
));
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
;