ReactOS 0.4.16-dev-1408-gbc64f3a
registry.c
Go to the documentation of this file.
1/*
2 * Registry management
3 *
4 * Copyright 1996 Marcus Meissner
5 * Copyright 1998 Matthew Becker
6 * Copyright 1999 Sylvain St-Germain
7 * Copyright 1999 Alexandre Julliard
8 * Copyright 2017 Dmitry Timoshkov
9 * Copyright 2019 Nikolay Sivov for CodeWeavers
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#include <stdlib.h>
27#include <stdarg.h>
28#include <stdio.h>
29
30#include "ntstatus.h"
31#define WIN32_NO_STATUS
32#include "windef.h"
33#include "winbase.h"
34#include "winreg.h"
35#include "winerror.h"
36#include "winternl.h"
37#include "winperf.h"
38#include "winuser.h"
39#include "shlwapi.h"
40#include "sddl.h"
41
42#include "kernelbase.h"
43#include "wine/debug.h"
44#include "wine/exception.h"
45#include "wine/heap.h"
46#include "wine/list.h"
47
49
50#define HKEY_SPECIAL_ROOT_FIRST HKEY_CLASSES_ROOT
51#define HKEY_SPECIAL_ROOT_LAST HKEY_DYN_DATA
52
53static const WCHAR * const root_key_names[] =
54{
55 L"\\Registry\\Machine\\Software\\Classes",
56 NULL, /* HKEY_CURRENT_USER is determined dynamically */
57 L"\\Registry\\Machine",
58 L"\\Registry\\User",
59 NULL, /* HKEY_PERFORMANCE_DATA is not a real key */
60 L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current",
61 L"\\Registry\\DynData"
62};
63
66
69{
70 0, 0, &reg_mui_cs,
73 0, 0, { (DWORD_PTR)(__FILE__ ": reg_mui_cs") }
74};
75static CRITICAL_SECTION reg_mui_cs = { &reg_mui_cs_debug, -1, 0, 0, 0, 0 };
77 struct list entry;
78 WCHAR *file_name; /* full path name */
82};
83static struct list reg_mui_cache = LIST_INIT(reg_mui_cache); /* MRU */
84static unsigned int reg_mui_cache_count;
85#define REG_MUI_CACHE_SIZE 8
86
87#define IS_OPTION_TRUE(ch) ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
88
89/* check if value type needs string conversion (Ansi<->Unicode) */
90static inline BOOL is_string( DWORD type )
91{
92 return (type == REG_SZ) || (type == REG_EXPAND_SZ) || (type == REG_MULTI_SZ);
93}
94
95/* check if current version is NT or Win95 */
96static inline BOOL is_version_nt(void)
97{
98 return !(GetVersion() & 0x80000000);
99}
100
102{
103 DWORD len = name->Length / sizeof(WCHAR);
104 return (len >= 11 && !wcsnicmp( name->Buffer, L"Wow6432Node\\", min( len, 12 ) ));
105}
106
108{
109 static const WCHAR classes_root[] = L"\\Registry\\Machine\\Software\\Classes\\";
110 DWORD classes_root_len = ARRAY_SIZE( classes_root ) - 1;
111 DWORD len = name->Length / sizeof(WCHAR);
112 return (len >= classes_root_len - 1 && !wcsnicmp( name->Buffer, classes_root, min( len, classes_root_len ) ));
113}
114
116{
117 char buffer[256], *buf_ptr = buffer;
119 DWORD len = sizeof(buffer);
122 BOOL ret = FALSE;
123
124 /* Obtain the name of the root key */
126 if (status && status != STATUS_BUFFER_OVERFLOW) return FALSE;
127
128 /* Retry with a dynamically allocated buffer */
130 {
131 if (buf_ptr != buffer) heap_free( buf_ptr );
132 if (!(buf_ptr = heap_alloc( len ))) return FALSE;
133 info = (KEY_NAME_INFORMATION *)buf_ptr;
135 }
136
137 /* Check if the key ends in Wow6432Node and if the root is the Classes key*/
138 if (!status && info->NameLength / sizeof(WCHAR) >= 11)
139 {
140 name.Buffer = info->Name + info->NameLength / sizeof(WCHAR) - 11;
141 name.Length = 11 * sizeof(WCHAR);
142 if (is_wow6432node( &name ))
143 {
144 name.Buffer = info->Name;
145 name.Length = info->NameLength;
147 }
148 }
149
150 if (buf_ptr != buffer) heap_free( buf_ptr );
151
152 return ret;
153}
154
155/* Open the Wow6432Node subkey of the specified key */
157{
158 UNICODE_STRING nameW = RTL_CONSTANT_STRING( L"Wow6432Node" );
160 HANDLE ret;
161
162 attr.Length = sizeof(attr);
163 attr.RootDirectory = key;
164 attr.ObjectName = &nameW;
165 attr.Attributes = 0;
166 attr.SecurityDescriptor = NULL;
167 attr.SecurityQualityOfService = NULL;
168 if (NtOpenKeyEx( &ret, MAXIMUM_ALLOWED | KEY_WOW64_64KEY, &attr, 0 )) return key;
169 return ret;
170}
171
172/* Open HKCR, which should already exist because it's used when we're in its Wow6432Node child */
174{
177 HANDLE ret = 0;
178
179 attr.Length = sizeof(attr);
180 attr.RootDirectory = 0;
181 attr.ObjectName = &nameW;
182 attr.Attributes = 0;
183 attr.SecurityDescriptor = NULL;
184 attr.SecurityQualityOfService = NULL;
187 return ret;
188}
189
191{
192 static const WCHAR performance_text[] =
193 L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Perflib\\009";
194 char buffer[200];
196
198 {
199 if (!wcsicmp( info->Name.Buffer, performance_text ))
200 {
201 NtClose( key );
203 }
204 }
205
206 return key;
207}
208
210
212{
213 BOOL is_wow64_key = (is_win64 && (access & KEY_WOW64_32KEY)) || (is_wow64 && !(access & KEY_WOW64_64KEY));
214 ACCESS_MASK access_64 = (access & ~KEY_WOW64_32KEY) | KEY_WOW64_64KEY;
215 DWORD i = 0, len = name->Length / sizeof(WCHAR);
216 WCHAR *buffer = name->Buffer;
219
220 if (!root && len > 10 && !wcsnicmp( buffer, L"\\Registry\\", 10 )) i += 10;
221 if (i < len && buffer[i] == '\\') return STATUS_OBJECT_PATH_INVALID;
222 while (i < len && buffer[i] != '\\') i++;
223
224 str.Buffer = name->Buffer;
225 str.Length = i * sizeof(WCHAR);
226
227 if (i < len)
228 options &= ~REG_OPTION_OPEN_LINK;
229
230 status = open_key( subkey, root, &str, options, access_64, FALSE );
231 if (status == STATUS_OBJECT_NAME_NOT_FOUND && root && is_wow64_key)
232 {
233 /* Try to open the shared parent if we can't find the key in the Wow6432Node */
236
238 status = open_key( subkey, root, &str, options, access_64, FALSE );
239
240 if (!status)
241 NtClose( root );
242 else
243 *subkey = root;
244 }
245
246 if (!status)
247 {
248 while (i < len && buffer[i] == '\\') i++;
249
250 name->Buffer += i;
251 name->Length -= i * sizeof(WCHAR);
252
253 if (is_wow64_key && !is_wow6432node( name ))
254 {
255 HKEY wow6432node = open_wow6432node( *subkey );
256 if (wow6432node != *subkey)
257 {
258 NtClose( *subkey );
259 *subkey = wow6432node;
260 }
261 }
262 }
263
264 return status;
265}
266
268{
269 char buffer[256], *buf_ptr = buffer;
271 DWORD len = sizeof(buffer);
274
275 /* Obtain the name of the root key */
277 if (status && status != STATUS_BUFFER_OVERFLOW) return status;
278
279 /* Retry with a dynamically allocated buffer */
281 {
282 if (buf_ptr != buffer) heap_free( buf_ptr );
283 if (!(buf_ptr = heap_alloc( len )))
284 return STATUS_NO_MEMORY;
285 info = (KEY_NAME_INFORMATION *)buf_ptr;
287 }
288
289 if (status)
290 {
291 if (buf_ptr != buffer) heap_free( buf_ptr );
292 return status;
293 }
294
295 name.Buffer = info->Name;
296 name.Length = info->NameLength;
297 root = 0;
298
299 /* Obtain the parent Wow6432Node if it exists */
300 while (!status && name.Length)
301 {
303 if (root) NtClose( root );
304 root = *retkey;
305 }
306
307 if (buf_ptr != buffer) heap_free( buf_ptr );
308
309 return status;
310}
311
312/* wrapper for NtOpenKeyEx to handle Wow6432 nodes */
314{
315 BOOL is_wow64_key = (is_win64 && (access & KEY_WOW64_32KEY)) || (is_wow64 && !(access & KEY_WOW64_64KEY));
316 HKEY subkey = 0, subkey_root = root;
318 BOOL was_wow6432node = TRUE;
319
320 *retkey = NULL;
321
322 if (!(is_win64 && (access & KEY_WOW64_32KEY)) && !create)
323 {
325
326 attr.Length = sizeof(attr);
327 attr.RootDirectory = root;
328 attr.ObjectName = name;
329 attr.Attributes = 0;
330 attr.SecurityDescriptor = NULL;
331 attr.SecurityQualityOfService = NULL;
332
333 if (options & REG_OPTION_OPEN_LINK) attr.Attributes |= OBJ_OPENLINK;
334 status = NtOpenKeyEx( (HANDLE *)retkey, access, &attr, options );
336 {
337 *retkey = get_perflib_key( *retkey );
339 }
340 return status;
341 }
342
344 status = open_wow6432node_parent( &subkey_root, root, options, access );
345 else if (root && is_wow64 && !(access & KEY_WOW64_64KEY) && !is_wow6432node( name ))
346 {
347 subkey_root = open_wow6432node( root );
348 if (!is_classes_wow6432node( subkey_root ) && subkey_root != root)
349 {
350 NtClose( subkey_root );
351 subkey_root = root;
352 }
353 }
354
355 while (!status && (name->Length || !subkey))
356 {
357 was_wow6432node = is_wow6432node( name );
358 status = open_subkey( &subkey, subkey_root, name, options, access );
359 if (subkey && subkey_root && subkey_root != root) NtClose( subkey_root );
360 if (subkey) subkey_root = subkey;
361 }
362
363 /* Return the shared parent if we didn't explicitly look for the Wow6432Node */
364 if (!status && !was_wow6432node && is_wow64_key && is_classes_wow6432node( subkey_root ))
365 {
366 if (subkey_root && subkey_root != root) NtClose( subkey_root );
367 subkey_root = open_classes_root();
368 }
369
371 *retkey = subkey_root;
372 else if (subkey_root && subkey_root != root)
373 NtClose( subkey_root );
374
375 return status;
376}
377
379 const UNICODE_STRING *class, PULONG dispos );
380
382 const UNICODE_STRING *class, PULONG dispos )
383{
384 ACCESS_MASK access_64 = access & ~KEY_WOW64_32KEY;
385 DWORD i = 0, len = name->Length / sizeof(WCHAR);
386 WCHAR *buffer = name->Buffer;
389
390 if (i < len && buffer[i] == '\\') return STATUS_OBJECT_PATH_INVALID;
391 while (i < len && buffer[i] != '\\') i++;
392
393 str.Buffer = name->Buffer;
394 str.Length = i * sizeof(WCHAR);
395
396 if (i < len)
397 options &= ~REG_OPTION_CREATE_LINK;
398
399 status = create_key( subkey, root, str, options, access_64, class, dispos );
400 if (!status)
401 {
402 while (i < len && buffer[i] == '\\') i++;
403
404 name->Buffer += i;
405 name->Length -= i * sizeof(WCHAR);
406 }
407
408 return status;
409}
410
411/* wrapper for NtCreateKey that creates the key recursively if necessary */
413 const UNICODE_STRING *class, PULONG dispos )
414{
416 HKEY subkey, subkey_root = root;
417
418 *retkey = NULL;
419
420 if (!(is_win64 && (access & KEY_WOW64_32KEY)))
421 {
423
424 attr.Length = sizeof(attr);
425 attr.RootDirectory = root;
426 attr.ObjectName = &name;
427 attr.Attributes = 0;
428 attr.SecurityDescriptor = NULL;
429 attr.SecurityQualityOfService = NULL;
430 if (options & REG_OPTION_OPEN_LINK) attr.Attributes |= OBJ_OPENLINK;
431
432 status = NtCreateKey( (HANDLE *)retkey, access, &attr, 0, class, options, dispos );
434 {
435 *retkey = get_perflib_key( *retkey );
437 }
438
440 return status;
441 }
442
445 {
446 NtClose( subkey_root );
448 }
449
450 if (!status)
452
454 {
456 while (!status && name.Length)
457 {
458 status = create_subkey( &subkey, subkey_root, &name, options, access, class, dispos );
459 if (subkey_root && subkey_root != root) NtClose( subkey_root );
460 subkey_root = subkey;
461 }
462 }
463
464 if (!status)
465 *retkey = subkey_root;
466
467 return status;
468}
469
470/* create one of the HKEY_* special root keys */
472{
473 HKEY ret = 0;
475
477 {
478 if (RtlOpenCurrentUser( access, (HANDLE *)&hkey )) return 0;
479 TRACE( "HKEY_CURRENT_USER -> %p\n", hkey );
480 }
481 else
482 {
484
486 if (create_key( &hkey, 0, name, 0, access, NULL, NULL )) return 0;
487 TRACE( "%s -> %p\n", debugstr_w(name.Buffer), hkey );
488 }
489
490 if (!cache_disabled[idx])
491 {
492 if (!(ret = InterlockedCompareExchangePointer( (void **)&special_root_keys[idx], hkey, 0 )))
493 ret = hkey;
494 else
495 NtClose( hkey ); /* somebody beat us to it */
496 }
497 else
498 ret = hkey;
499 return ret;
500}
501
502/* map the hkey from special root to normal key if necessary */
503static inline HKEY get_special_root_hkey( HKEY hkey )
504{
506
507 switch (HandleToUlong(hkey))
508 {
512 case (LONG)(LONG_PTR)HKEY_USERS:
516 return special_root_keys[index];
518
519 default:
520 return hkey;
521 }
522}
523
525{
529}
530
531
532/******************************************************************************
533 * RemapPredefinedHandleInternal (kernelbase.@)
534 */
536{
537 HKEY old_key;
538 int idx;
539
540 TRACE("(%p %p)\n", hkey, override);
541
546
547 if (override)
548 {
550 GetCurrentProcess(), (HANDLE *)&override,
551 0, 0, DUPLICATE_SAME_ACCESS );
552 if (status) return status;
553 }
554
555 old_key = InterlockedExchangePointer( (void **)&special_root_keys[idx], override );
556 if (old_key) NtClose( old_key );
557 return STATUS_SUCCESS;
558}
559
560
561/******************************************************************************
562 * DisablePredefinedHandleTableInternal (kernelbase.@)
563 */
565{
566 HKEY old_key;
567 int idx;
568
569 TRACE("(%p)\n", hkey);
570
575
577
578 old_key = InterlockedExchangePointer( (void **)&special_root_keys[idx], NULL );
579 if (old_key) NtClose( old_key );
580 return STATUS_SUCCESS;
581}
582
583
584/******************************************************************************
585 * RegCreateKeyExW (kernelbase.@)
586 *
587 * See RegCreateKeyExA.
588 */
591 PHKEY retkey, LPDWORD dispos )
592{
594
595 if (!retkey) return ERROR_BADKEY;
597 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
598
600 RtlInitUnicodeString( &classW, class );
601
602 return RtlNtStatusToDosError( create_key( retkey, hkey, nameW, options, access, &classW, dispos ) );
603}
604
605
606/******************************************************************************
607 * RegCreateKeyExA (kernelbase.@)
608 *
609 * Open a registry key, creating it if it doesn't exist.
610 *
611 * PARAMS
612 * hkey [I] Handle of the parent registry key
613 * name [I] Name of the new key to open or create
614 * reserved [I] Reserved, pass 0
615 * class [I] The object type of the new key
616 * options [I] Flags controlling the key creation (REG_OPTION_* flags from "winnt.h")
617 * access [I] Access level desired
618 * sa [I] Security attributes for the key
619 * retkey [O] Destination for the resulting handle
620 * dispos [O] Receives REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY
621 *
622 * RETURNS
623 * Success: ERROR_SUCCESS.
624 * Failure: A standard Win32 error code. retkey remains untouched.
625 *
626 * FIXME
627 * MAXIMUM_ALLOWED in access mask not supported by server
628 */
631 PHKEY retkey, LPDWORD dispos )
632{
634 ANSI_STRING nameA, classA;
636
637 if (!retkey) return ERROR_BADKEY;
639 if (!is_version_nt())
640 {
641 access = MAXIMUM_ALLOWED; /* Win95 ignores the access mask */
642 if (name && *name == '\\') name++; /* win9x,ME ignores one (and only one) beginning backslash */
643 }
644 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
645
646 RtlInitAnsiString( &nameA, name );
647 RtlInitAnsiString( &classA, class );
648
649 if (!(status = RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString,
650 &nameA, FALSE )))
651 {
652 if (!(status = RtlAnsiStringToUnicodeString( &classW, &classA, TRUE )))
653 {
654 status = create_key( retkey, hkey, NtCurrentTeb()->StaticUnicodeString, options, access, &classW, dispos );
656 }
657 }
659}
660
661
662/******************************************************************************
663 * RegOpenKeyExW (kernelbase.@)
664 *
665 * See RegOpenKeyExA.
666 */
668{
670
671 if (retkey && (!name || !name[0]) &&
674 {
675 *retkey = hkey;
676 return ERROR_SUCCESS;
677 }
678
679 /* NT+ allows beginning backslash for HKEY_CLASSES_ROOT */
680 if (HandleToUlong(hkey) == HandleToUlong(HKEY_CLASSES_ROOT) && name && *name == '\\') name++;
681
682 if (!retkey) return ERROR_INVALID_PARAMETER;
683 *retkey = NULL;
684 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
685
687 return RtlNtStatusToDosError( open_key( retkey, hkey, &nameW, options, access, FALSE ) );
688}
689
690
691/******************************************************************************
692 * RegOpenKeyExA (kernelbase.@)
693 *
694 * Open a registry key.
695 *
696 * PARAMS
697 * hkey [I] Handle of open key
698 * name [I] Name of subkey to open
699 * options [I] Open options (can be set to REG_OPTION_OPEN_LINK)
700 * access [I] Security access mask
701 * retkey [O] Handle to open key
702 *
703 * RETURNS
704 * Success: ERROR_SUCCESS
705 * Failure: A standard Win32 error code. retkey is set to 0.
706 *
707 * NOTES
708 * Unlike RegCreateKeyExA(), this function will not create the key if it
709 * does not exist.
710 */
712{
713 STRING nameA;
715
716 if (retkey && (!name || !name[0]) &&
719 {
720 *retkey = hkey;
721 return ERROR_SUCCESS;
722 }
723
724 if (!is_version_nt()) access = MAXIMUM_ALLOWED; /* Win95 ignores the access mask */
725 else
726 {
727 /* NT+ allows beginning backslash for HKEY_CLASSES_ROOT */
728 if (HandleToUlong(hkey) == HandleToUlong(HKEY_CLASSES_ROOT) && name && *name == '\\') name++;
729 }
730
731 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
732
733 RtlInitAnsiString( &nameA, name );
734 if (!(status = RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString,
735 &nameA, FALSE )))
736 {
737 UNICODE_STRING nameW = NtCurrentTeb()->StaticUnicodeString;
738 status = open_key( retkey, hkey, &nameW, options, access, FALSE );
739 }
741}
742
743
744/******************************************************************************
745 * RegOpenCurrentUser (kernelbase.@)
746 *
747 * Get a handle to the HKEY_CURRENT_USER key for the user
748 * the current thread is impersonating.
749 *
750 * PARAMS
751 * access [I] Desired access rights to the key
752 * retkey [O] Handle to the opened key
753 *
754 * RETURNS
755 * Success: ERROR_SUCCESS
756 * Failure: nonzero error code from Winerror.h
757 *
758 * FIXME
759 * This function is supposed to retrieve a handle to the
760 * HKEY_CURRENT_USER for the user the current thread is impersonating.
761 * Since Wine does not currently allow threads to impersonate other users,
762 * this stub should work fine.
763 */
765{
766 void *data[20];
769 DWORD len = 0;
770
771 /* get current user SID */
773 {
774 len = sizeof(data);
777 }
778 if (!len)
779 {
782 {
783 len = sizeof(data);
786 }
787 RevertToSelf();
788 }
789
790 if (len)
791 {
792 WCHAR buffer[200];
793 UNICODE_STRING string = { 0, sizeof(buffer), buffer };
794
795 RtlConvertSidToUnicodeString( &string, info->User.Sid, FALSE );
796 return RegOpenKeyExW( HKEY_USERS, string.Buffer, 0, access, retkey );
797 }
798
799 return RegOpenKeyExA( HKEY_CURRENT_USER, "", 0, access, retkey );
800}
801
802
803
804/******************************************************************************
805 * RegEnumKeyExW (kernelbase.@)
806 *
807 * Enumerate subkeys of the specified open registry key.
808 *
809 * PARAMS
810 * hkey [I] Handle to key to enumerate
811 * index [I] Index of subkey to enumerate
812 * name [O] Buffer for subkey name
813 * name_len [O] Size of subkey buffer
814 * reserved [I] Reserved
815 * class [O] Buffer for class string
816 * class_len [O] Size of class buffer
817 * ft [O] Time key last written to
818 *
819 * RETURNS
820 * Success: ERROR_SUCCESS
821 * Failure: System error code. If there are no more subkeys available, the
822 * function returns ERROR_NO_MORE_ITEMS.
823 */
825 LPDWORD reserved, LPWSTR class, LPDWORD class_len, FILETIME *ft )
826{
828 char buffer[256], *buf_ptr = buffer;
830 DWORD total_size;
831
832 TRACE( "(%p,%ld,%p,%p(%lu),%p,%p,%p,%p)\n", hkey, index, name, name_len,
833 name_len ? *name_len : 0, reserved, class, class_len, ft );
834
836 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
837
839 buffer, sizeof(buffer), &total_size );
840
842 {
843 /* retry with a dynamically allocated buffer */
844 if (buf_ptr != buffer) heap_free( buf_ptr );
845 if (!(buf_ptr = heap_alloc( total_size )))
847 info = (KEY_NODE_INFORMATION *)buf_ptr;
849 buf_ptr, total_size, &total_size );
850 }
851
852 if (!status)
853 {
854 DWORD len = info->NameLength / sizeof(WCHAR);
855 DWORD cls_len = info->ClassLength / sizeof(WCHAR);
856
857 if (ft) *ft = *(FILETIME *)&info->LastWriteTime;
858
859 if (len >= *name_len || (class && class_len && (cls_len >= *class_len)))
861 else
862 {
863 *name_len = len;
864 memcpy( name, info->Name, info->NameLength );
865 name[len] = 0;
866 if (class_len)
867 {
868 *class_len = cls_len;
869 if (class)
870 {
871 memcpy( class, buf_ptr + info->ClassOffset, info->ClassLength );
872 class[cls_len] = 0;
873 }
874 }
875 }
876 }
877
878 if (buf_ptr != buffer) heap_free( buf_ptr );
880}
881
882
883/******************************************************************************
884 * RegEnumKeyExA (kernelbase.@)
885 *
886 * See RegEnumKeyExW.
887 */
889 LPDWORD reserved, LPSTR class, LPDWORD class_len, FILETIME *ft )
890{
892 char buffer[256], *buf_ptr = buffer;
894 DWORD total_size;
895
896 TRACE( "(%p,%ld,%p,%p(%lu),%p,%p,%p,%p)\n", hkey, index, name, name_len,
897 name_len ? *name_len : 0, reserved, class, class_len, ft );
898
900 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
901
903 buffer, sizeof(buffer), &total_size );
904
906 {
907 /* retry with a dynamically allocated buffer */
908 if (buf_ptr != buffer) heap_free( buf_ptr );
909 if (!(buf_ptr = heap_alloc( total_size )))
911 info = (KEY_NODE_INFORMATION *)buf_ptr;
913 buf_ptr, total_size, &total_size );
914 }
915
916 if (!status)
917 {
918 DWORD len, cls_len;
919
920 RtlUnicodeToMultiByteSize( &len, info->Name, info->NameLength );
921 RtlUnicodeToMultiByteSize( &cls_len, (WCHAR *)(buf_ptr + info->ClassOffset),
922 info->ClassLength );
923 if (ft) *ft = *(FILETIME *)&info->LastWriteTime;
924
925 if (len >= *name_len || (class && class_len && (cls_len >= *class_len)))
927 else
928 {
929 *name_len = len;
930 RtlUnicodeToMultiByteN( name, len, NULL, info->Name, info->NameLength );
931 name[len] = 0;
932 if (class_len)
933 {
934 *class_len = cls_len;
935 if (class)
936 {
937 RtlUnicodeToMultiByteN( class, cls_len, NULL,
938 (WCHAR *)(buf_ptr + info->ClassOffset),
939 info->ClassLength );
940 class[cls_len] = 0;
941 }
942 }
943 }
944 }
945
946 if (buf_ptr != buffer) heap_free( buf_ptr );
948}
949
950
951/******************************************************************************
952 * RegQueryInfoKeyW (kernelbase.@)
953 *
954 * Retrieves information about the specified registry key.
955 *
956 * PARAMS
957 * hkey [I] Handle to key to query
958 * class [O] Buffer for class string
959 * class_len [O] Size of class string buffer
960 * reserved [I] Reserved
961 * subkeys [O] Buffer for number of subkeys
962 * max_subkey [O] Buffer for longest subkey name length
963 * max_class [O] Buffer for longest class string length
964 * values [O] Buffer for number of value entries
965 * max_value [O] Buffer for longest value name length
966 * max_data [O] Buffer for longest value data length
967 * security [O] Buffer for security descriptor length
968 * modif [O] Modification time
969 *
970 * RETURNS
971 * Success: ERROR_SUCCESS
972 * Failure: system error code.
973 *
974 * NOTES
975 * - win95 allows class to be valid and class_len to be NULL
976 * - winnt returns ERROR_INVALID_PARAMETER if class is valid and class_len is NULL
977 * - both allow class to be NULL and class_len to be NULL
978 * (it's hard to test validity, so test !NULL instead)
979 */
981 LPDWORD subkeys, LPDWORD max_subkey, LPDWORD max_class,
982 LPDWORD values, LPDWORD max_value, LPDWORD max_data,
983 LPDWORD security, FILETIME *modif )
984{
986 char buffer[256], *buf_ptr = buffer;
988 DWORD total_size;
989
990 TRACE( "(%p,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey, class, class_len ? *class_len : 0,
991 reserved, subkeys, max_subkey, values, max_value, max_data, security, modif );
992
993 if (class && !class_len && is_version_nt()) return ERROR_INVALID_PARAMETER;
994 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
995
996 status = NtQueryKey( hkey, KeyFullInformation, buffer, sizeof(buffer), &total_size );
997 if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
998
999 if (class && class_len && *class_len)
1000 {
1001 /* retry with a dynamically allocated buffer */
1003 {
1004 if (buf_ptr != buffer) heap_free( buf_ptr );
1005 if (!(buf_ptr = heap_alloc( total_size )))
1007 info = (KEY_FULL_INFORMATION *)buf_ptr;
1008 status = NtQueryKey( hkey, KeyFullInformation, buf_ptr, total_size, &total_size );
1009 }
1010
1011 if (status) goto done;
1012
1013 if (class_len && (info->ClassLength/sizeof(WCHAR) + 1 > *class_len))
1014 {
1016 }
1017 else
1018 {
1019 memcpy( class, buf_ptr + info->ClassOffset, info->ClassLength );
1020 class[info->ClassLength/sizeof(WCHAR)] = 0;
1021 }
1022 }
1023 else status = STATUS_SUCCESS;
1024
1025 if (class_len) *class_len = info->ClassLength / sizeof(WCHAR);
1026 if (subkeys) *subkeys = info->SubKeys;
1027 if (max_subkey) *max_subkey = info->MaxNameLen / sizeof(WCHAR);
1028 if (max_class) *max_class = info->MaxClassLen / sizeof(WCHAR);
1029 if (values) *values = info->Values;
1030 if (max_value) *max_value = info->MaxValueNameLen / sizeof(WCHAR);
1031 if (max_data) *max_data = info->MaxValueDataLen;
1032 if (modif) *modif = *(FILETIME *)&info->LastWriteTime;
1033
1034 if (security)
1035 {
1036 FIXME( "security argument not supported.\n");
1037 *security = 0;
1038 }
1039
1040 done:
1041 if (buf_ptr != buffer) heap_free( buf_ptr );
1042 return RtlNtStatusToDosError( status );
1043}
1044
1045
1046/******************************************************************************
1047 * RegQueryInfoKeyA (kernelbase.@)
1048 *
1049 * Retrieves information about a registry key.
1050 *
1051 * PARAMS
1052 * hKey [I] Handle to an open key.
1053 * lpClass [O] Class string of the key.
1054 * lpcClass [I/O] size of lpClass.
1055 * lpReserved [I] Reserved; must be NULL.
1056 * lpcSubKeys [O] Number of subkeys contained by the key.
1057 * lpcMaxSubKeyLen [O] Size of the key's subkey with the longest name.
1058 * lpcMaxClassLen [O] Size of the longest string specifying a subkey
1059 * class in TCHARS.
1060 * lpcValues [O] Number of values associated with the key.
1061 * lpcMaxValueNameLen [O] Size of the key's longest value name in TCHARS.
1062 * lpcMaxValueLen [O] Longest data component among the key's values
1063 * lpcbSecurityDescriptor [O] Size of the key's security descriptor.
1064 * lpftLastWriteTime [O] FILETIME structure that is the last write time.
1065 *
1066 * RETURNS
1067 * Success: ERROR_SUCCESS
1068 * Failure: nonzero error code from Winerror.h
1069 */
1071 LPDWORD subkeys, LPDWORD max_subkey, LPDWORD max_class,
1072 LPDWORD values, LPDWORD max_value, LPDWORD max_data,
1073 LPDWORD security, FILETIME *modif )
1074{
1076 char buffer[256], *buf_ptr = buffer;
1078 DWORD total_size;
1079
1080 TRACE( "(%p,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey, class, class_len ? *class_len : 0,
1081 reserved, subkeys, max_subkey, values, max_value, max_data, security, modif );
1082
1083 if (class && !class_len && is_version_nt()) return ERROR_INVALID_PARAMETER;
1084 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
1085
1086 status = NtQueryKey( hkey, KeyFullInformation, buffer, sizeof(buffer), &total_size );
1087 if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
1088
1089 if (class || class_len)
1090 {
1091 /* retry with a dynamically allocated buffer */
1093 {
1094 if (buf_ptr != buffer) heap_free( buf_ptr );
1095 if (!(buf_ptr = heap_alloc( total_size )))
1097 info = (KEY_FULL_INFORMATION *)buf_ptr;
1098 status = NtQueryKey( hkey, KeyFullInformation, buf_ptr, total_size, &total_size );
1099 }
1100
1101 if (status) goto done;
1102
1103 if (class && class_len && *class_len)
1104 {
1105 DWORD len = *class_len;
1106 RtlUnicodeToMultiByteN( class, len, class_len,
1107 (WCHAR *)(buf_ptr + info->ClassOffset), info->ClassLength );
1108 if (*class_len == len)
1109 {
1111 *class_len -= 1;
1112 }
1113 class[*class_len] = 0;
1114 }
1115 else if (class_len)
1116 RtlUnicodeToMultiByteSize( class_len,
1117 (WCHAR *)(buf_ptr + info->ClassOffset), info->ClassLength );
1118 }
1119 else status = STATUS_SUCCESS;
1120
1121 if (subkeys) *subkeys = info->SubKeys;
1122 if (max_subkey) *max_subkey = info->MaxNameLen / sizeof(WCHAR);
1123 if (max_class) *max_class = info->MaxClassLen / sizeof(WCHAR);
1124 if (values) *values = info->Values;
1125 if (max_value) *max_value = info->MaxValueNameLen / sizeof(WCHAR);
1126 if (max_data) *max_data = info->MaxValueDataLen;
1127 if (modif) *modif = *(FILETIME *)&info->LastWriteTime;
1128
1129 if (security)
1130 {
1131 FIXME( "security argument not supported.\n");
1132 *security = 0;
1133 }
1134
1135 done:
1136 if (buf_ptr != buffer) heap_free( buf_ptr );
1137 return RtlNtStatusToDosError( status );
1138}
1139
1140/******************************************************************************
1141 * RegCloseKey (kernelbase.@)
1142 *
1143 * Close an open registry key.
1144 *
1145 * PARAMS
1146 * hkey [I] Handle of key to close
1147 *
1148 * RETURNS
1149 * Success: ERROR_SUCCESS
1150 * Failure: Error code
1151 */
1153{
1154 if (!hkey) return ERROR_INVALID_HANDLE;
1155 if (hkey >= (HKEY)0x80000000) return ERROR_SUCCESS;
1156 return RtlNtStatusToDosError( NtClose( hkey ) );
1157}
1158
1159
1160/******************************************************************************
1161 * RegDeleteKeyExW (kernelbase.@)
1162 */
1164{
1165 DWORD ret;
1166 HKEY tmp;
1167
1168 if (!name) return ERROR_INVALID_PARAMETER;
1169
1170 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
1171
1173 if (!(ret = RegOpenKeyExW( hkey, name, 0, access | DELETE, &tmp )))
1174 {
1176 RegCloseKey( tmp );
1177 }
1178 TRACE("%s ret=%08lx\n", debugstr_w(name), ret);
1179 return ret;
1180}
1181
1182
1183/******************************************************************************
1184 * RegDeleteKeyExA (kernelbase.@)
1185 */
1187{
1188 DWORD ret;
1189 HKEY tmp;
1190
1191 if (!name) return ERROR_INVALID_PARAMETER;
1192
1193 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
1194
1196 if (!(ret = RegOpenKeyExA( hkey, name, 0, access | DELETE, &tmp )))
1197 {
1198 if (!is_version_nt()) /* win95 does recursive key deletes */
1199 {
1200 CHAR sub[MAX_PATH];
1201 DWORD len = sizeof(sub);
1202 while(!RegEnumKeyExA(tmp, 0, sub, &len, NULL, NULL, NULL, NULL))
1203 {
1204 if(RegDeleteKeyExA(tmp, sub, access, reserved)) /* recurse */
1205 break;
1206 }
1207 }
1209 RegCloseKey( tmp );
1210 }
1211 TRACE("%s ret=%08lx\n", debugstr_a(name), ret);
1212 return ret;
1213}
1214
1215/******************************************************************************
1216 * RegSetValueExW (kernelbase.@)
1217 *
1218 * Set the data and contents of a registry value.
1219 *
1220 * PARAMS
1221 * hkey [I] Handle of key to set value for
1222 * name [I] Name of value to set
1223 * reserved [I] Reserved, must be zero
1224 * type [I] Type of the value being set
1225 * data [I] The new contents of the value to set
1226 * count [I] Size of data
1227 *
1228 * RETURNS
1229 * Success: ERROR_SUCCESS
1230 * Failure: Error code
1231 */
1233 DWORD type, const BYTE *data, DWORD count )
1234{
1236
1237 /* no need for version check, not implemented on win9x anyway */
1238
1239 if ((data && ((ULONG_PTR)data >> 16) == 0) || (!data && count)) return ERROR_NOACCESS;
1240
1241 if (count && is_string(type))
1242 {
1244 /* if user forgot to count terminating null, add it (yes NT does this) */
1245 if (str[count / sizeof(WCHAR) - 1] && !str[count / sizeof(WCHAR)])
1246 count += sizeof(WCHAR);
1247 }
1248 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
1249
1251 return RtlNtStatusToDosError( NtSetValueKey( hkey, &nameW, 0, type, data, count ) );
1252}
1253
1254
1255/******************************************************************************
1256 * RegSetValueExA (kernelbase.@)
1257 *
1258 * See RegSetValueExW.
1259 *
1260 * NOTES
1261 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
1262 * NT does definitely care (aj)
1263 */
1265 const BYTE *data, DWORD count )
1266{
1267 ANSI_STRING nameA;
1269 WCHAR *dataW = NULL;
1271
1272 if (!is_version_nt()) /* win95 */
1273 {
1274 if (type == REG_SZ)
1275 {
1276 if (!data) return ERROR_INVALID_PARAMETER;
1277 count = strlen((const char *)data) + 1;
1278 }
1279 }
1280 else if (count && is_string(type))
1281 {
1282 /* if user forgot to count terminating null, add it (yes NT does this) */
1283 if (data[count-1] && !data[count]) count++;
1284 }
1285
1286 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
1287
1288 if (is_string( type )) /* need to convert to Unicode */
1289 {
1290 DWORD lenW;
1291 RtlMultiByteToUnicodeSize( &lenW, (const char *)data, count );
1292 if (!(dataW = heap_alloc( lenW ))) return ERROR_OUTOFMEMORY;
1293 RtlMultiByteToUnicodeN( dataW, lenW, NULL, (const char *)data, count );
1294 count = lenW;
1295 data = (BYTE *)dataW;
1296 }
1297
1298 RtlInitAnsiString( &nameA, name );
1299 if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
1300 {
1301 status = NtSetValueKey( hkey, &nameW, 0, type, data, count );
1303 }
1304 heap_free( dataW );
1305 return RtlNtStatusToDosError( status );
1306}
1307
1308
1309/******************************************************************************
1310 * RegSetKeyValueW (kernelbase.@)
1311 */
1313{
1314 HKEY hsubkey = NULL;
1315 DWORD ret;
1316
1317 TRACE("(%p,%s,%s,%ld,%p,%ld)\n", hkey, debugstr_w(subkey), debugstr_w(name), type, data, len );
1318
1319 if (subkey && subkey[0]) /* need to create the subkey */
1320 {
1321 if ((ret = RegCreateKeyExW( hkey, subkey, 0, NULL, REG_OPTION_NON_VOLATILE,
1322 KEY_SET_VALUE, NULL, &hsubkey, NULL )) != ERROR_SUCCESS) return ret;
1323 hkey = hsubkey;
1324 }
1325
1326 ret = RegSetValueExW( hkey, name, 0, type, (const BYTE*)data, len );
1327 if (hsubkey) RegCloseKey( hsubkey );
1328 return ret;
1329}
1330
1331/******************************************************************************
1332 * RegSetKeyValueA (kernelbase.@)
1333 */
1335{
1336 HKEY hsubkey = NULL;
1337 DWORD ret;
1338
1339 TRACE("(%p,%s,%s,%ld,%p,%ld)\n", hkey, debugstr_a(subkey), debugstr_a(name), type, data, len );
1340
1341 if (subkey && subkey[0]) /* need to create the subkey */
1342 {
1343 if ((ret = RegCreateKeyExA( hkey, subkey, 0, NULL, REG_OPTION_NON_VOLATILE,
1344 KEY_SET_VALUE, NULL, &hsubkey, NULL )) != ERROR_SUCCESS) return ret;
1345 hkey = hsubkey;
1346 }
1347
1348 ret = RegSetValueExA( hkey, name, 0, type, (const BYTE*)data, len );
1349 if (hsubkey) RegCloseKey( hsubkey );
1350 return ret;
1351}
1352
1353/* FIXME: we should read data from system32/perf009c.dat (or perf###c depending
1354 * on locale) instead */
1355static DWORD query_perf_names( DWORD *type, void *data, DWORD *ret_size, BOOL unicode )
1356{
1357 static const WCHAR names[] = L"1\0" "1847\0" "1846\0End Marker\0";
1358 DWORD size = *ret_size;
1359
1360 if (type) *type = REG_MULTI_SZ;
1361 *ret_size = sizeof(names);
1362 if (!unicode) *ret_size /= sizeof(WCHAR);
1363
1364 if (!data) return ERROR_SUCCESS;
1365 if (size < *ret_size) return ERROR_MORE_DATA;
1366
1367 if (unicode)
1368 memcpy( data, names, sizeof(names) );
1369 else
1371 return ERROR_SUCCESS;
1372}
1373
1374/* FIXME: we should read data from system32/perf009h.dat (or perf###h depending
1375 * on locale) instead */
1376static DWORD query_perf_help( DWORD *type, void *data, DWORD *ret_size, BOOL unicode )
1377{
1378 static const WCHAR names[] = L"1847\0End Marker\0";
1379 DWORD size = *ret_size;
1380
1381 if (type) *type = REG_MULTI_SZ;
1382 *ret_size = sizeof(names);
1383 if (!unicode) *ret_size /= sizeof(WCHAR);
1384
1385 if (!data) return ERROR_SUCCESS;
1386 if (size < *ret_size) return ERROR_MORE_DATA;
1387
1388 if (unicode)
1389 memcpy( data, names, sizeof(names) );
1390 else
1392 return ERROR_SUCCESS;
1393}
1394
1395struct perf_provider
1396{
1400 PM_OPEN_PROC *pOpen;
1401 PM_CLOSE_PROC *pClose;
1402 PM_COLLECT_PROC *pCollect;
1403};
1404
1405static void *get_provider_entry(HKEY perf, HMODULE perflib, const char *name)
1406{
1407 char buf[MAX_PATH];
1408 DWORD err, type, len;
1409
1410 len = sizeof(buf) - 1;
1411 err = RegQueryValueExA(perf, name, NULL, &type, (BYTE *)buf, &len);
1412 if (err != ERROR_SUCCESS || type != REG_SZ)
1413 return NULL;
1414
1415 buf[len] = 0;
1416 TRACE("Loading function pointer for %s: %s\n", name, debugstr_a(buf));
1417
1418 return GetProcAddress(perflib, buf);
1419}
1420
1421static BOOL load_provider(HKEY root, const WCHAR *name, struct perf_provider *provider)
1422{
1423 WCHAR buf[MAX_PATH], buf2[MAX_PATH];
1424 DWORD err, type, len;
1425 HKEY service, perf;
1426
1427 err = RegOpenKeyExW(root, name, 0, KEY_READ, &service);
1428 if (err != ERROR_SUCCESS)
1429 return FALSE;
1430
1431 provider->linkage[0] = 0;
1432 err = RegOpenKeyExW(service, L"Linkage", 0, KEY_READ, &perf);
1433 if (err == ERROR_SUCCESS)
1434 {
1435 len = sizeof(buf) - sizeof(WCHAR);
1436 err = RegQueryValueExW(perf, L"Export", NULL, &type, (BYTE *)buf, &len);
1437 if (err == ERROR_SUCCESS && (type == REG_SZ || type == REG_MULTI_SZ))
1438 {
1439 memcpy(provider->linkage, buf, len);
1440 provider->linkage[len / sizeof(WCHAR)] = 0;
1441 TRACE("Export: %s\n", debugstr_w(provider->linkage));
1442 }
1443 RegCloseKey(perf);
1444 }
1445
1446 err = RegOpenKeyExW(service, L"Performance", 0, KEY_READ, &perf);
1447 RegCloseKey(service);
1448 if (err != ERROR_SUCCESS)
1449 return FALSE;
1450
1451 provider->objects[0] = 0;
1452 len = sizeof(buf) - sizeof(WCHAR);
1453 err = RegQueryValueExW(perf, L"Object List", NULL, &type, (BYTE *)buf, &len);
1454 if (err == ERROR_SUCCESS && (type == REG_SZ || type == REG_MULTI_SZ))
1455 {
1456 memcpy(provider->objects, buf, len);
1457 provider->objects[len / sizeof(WCHAR)] = 0;
1458 TRACE("Object List: %s\n", debugstr_w(provider->objects));
1459 }
1460
1461 len = sizeof(buf) - sizeof(WCHAR);
1462 err = RegQueryValueExW(perf, L"Library", NULL, &type, (BYTE *)buf, &len);
1463 if (err != ERROR_SUCCESS || !(type == REG_SZ || type == REG_EXPAND_SZ))
1464 goto error;
1465
1466 buf[len / sizeof(WCHAR)] = 0;
1467 if (type == REG_EXPAND_SZ)
1468 {
1470 if (!len || len > MAX_PATH) goto error;
1471 lstrcpyW(buf, buf2);
1472 }
1473
1474 if (!(provider->perflib = LoadLibraryW(buf)))
1475 {
1476 WARN("Failed to load %s\n", debugstr_w(buf));
1477 goto error;
1478 }
1479
1481 TRACE("Loaded provider %s\n", wine_dbgstr_w(buf));
1482
1483 provider->pOpen = get_provider_entry(perf, provider->perflib, "Open");
1484 provider->pClose = get_provider_entry(perf, provider->perflib, "Close");
1485 provider->pCollect = get_provider_entry(perf, provider->perflib, "Collect");
1486 if (provider->pOpen && provider->pClose && provider->pCollect)
1487 {
1488 RegCloseKey(perf);
1489 return TRUE;
1490 }
1491
1492 TRACE("Provider is missing required exports\n");
1493 FreeLibrary(provider->perflib);
1494
1495error:
1496 RegCloseKey(perf);
1497 return FALSE;
1498}
1499
1500static DWORD collect_data(struct perf_provider *provider, const WCHAR *query, void **data, DWORD *size, DWORD *obj_count)
1501{
1502 WCHAR *linkage = provider->linkage[0] ? provider->linkage : NULL;
1503 DWORD err;
1504
1505 if (!query || !query[0])
1506 query = L"Global";
1507
1508 err = provider->pOpen(linkage);
1509 if (err != ERROR_SUCCESS)
1510 {
1511 TRACE("Open(%s) error %lu (%#lx)\n", debugstr_w(linkage), err, err);
1512 return err;
1513 }
1514
1515 *obj_count = 0;
1516 err = provider->pCollect((WCHAR *)query, data, size, obj_count);
1517 if (err != ERROR_SUCCESS)
1518 {
1519 TRACE("Collect error %lu (%#lx)\n", err, err);
1520 *obj_count = 0;
1521 }
1522
1523 provider->pClose();
1524 return err;
1525}
1526
1527#define MAX_SERVICE_NAME 260
1528
1529static DWORD query_perf_data( const WCHAR *query, DWORD *type, void *data, DWORD *ret_size, BOOL unicode )
1530{
1531 DWORD err, i, data_size;
1532 HKEY root;
1534
1535 if (!ret_size)
1537
1538 if (!wcsnicmp( query, L"counter", 7 ))
1539 return query_perf_names( type, data, ret_size, unicode );
1540 if (!wcsnicmp( query, L"help", 4 ))
1541 return query_perf_help( type, data, ret_size, unicode );
1542
1543 data_size = *ret_size;
1544 *ret_size = 0;
1545
1546 if (type)
1547 *type = REG_BINARY;
1548
1549 if (!data || data_size < sizeof(*pdb))
1550 return ERROR_MORE_DATA;
1551
1552 pdb = data;
1553
1554 pdb->Signature[0] = 'P';
1555 pdb->Signature[1] = 'E';
1556 pdb->Signature[2] = 'R';
1557 pdb->Signature[3] = 'F';
1558#ifdef WORDS_BIGENDIAN
1559 pdb->LittleEndian = FALSE;
1560#else
1561 pdb->LittleEndian = TRUE;
1562#endif
1563 pdb->Version = PERF_DATA_VERSION;
1564 pdb->Revision = PERF_DATA_REVISION;
1565 pdb->TotalByteLength = 0;
1566 pdb->HeaderLength = sizeof(*pdb);
1567 pdb->NumObjectTypes = 0;
1568 pdb->DefaultObject = 0;
1569 NtQueryPerformanceCounter( &pdb->PerfTime, &pdb->PerfFreq );
1570
1571 data = pdb + 1;
1572 pdb->SystemNameOffset = sizeof(*pdb);
1573 pdb->SystemNameLength = (data_size - sizeof(*pdb)) / sizeof(WCHAR);
1574 if (!GetComputerNameExW(ComputerNameNetBIOS, data, &pdb->SystemNameLength))
1575 return ERROR_MORE_DATA;
1576
1577 pdb->SystemNameLength++;
1578 pdb->SystemNameLength *= sizeof(WCHAR);
1579
1580 pdb->HeaderLength += pdb->SystemNameLength;
1581
1582 /* align to 8 bytes */
1583 if (pdb->SystemNameLength & 7)
1584 pdb->HeaderLength += 8 - (pdb->SystemNameLength & 7);
1585
1586 if (data_size < pdb->HeaderLength)
1587 return ERROR_MORE_DATA;
1588
1589 pdb->TotalByteLength = pdb->HeaderLength;
1590
1591 data_size -= pdb->HeaderLength;
1592 data = (char *)data + pdb->HeaderLength;
1593
1594 err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Services", 0, KEY_READ, &root);
1595 if (err != ERROR_SUCCESS)
1596 return err;
1597
1598 i = 0;
1599 for (;;)
1600 {
1601 DWORD collected_size = data_size, obj_count = 0;
1602 struct perf_provider provider;
1604 DWORD len = ARRAY_SIZE( name );
1605 void *collected_data = data;
1606
1608 if (err == ERROR_NO_MORE_ITEMS)
1609 {
1611 break;
1612 }
1613
1614 if (err != ERROR_SUCCESS)
1615 continue;
1616
1617 if (!load_provider(root, name, &provider))
1618 continue;
1619
1620 err = collect_data(&provider, query, &collected_data, &collected_size, &obj_count);
1621 FreeLibrary(provider.perflib);
1622
1623 if (err == ERROR_MORE_DATA)
1624 break;
1625
1626 if (err == ERROR_SUCCESS)
1627 {
1629
1630 TRACE("Collect: obj->TotalByteLength %lu, collected_size %lu\n",
1631 obj->TotalByteLength, collected_size);
1632
1633 data_size -= collected_size;
1634 data = collected_data;
1635
1636 pdb->TotalByteLength += collected_size;
1637 pdb->NumObjectTypes += obj_count;
1638 }
1639 }
1640
1642
1643 if (err == ERROR_SUCCESS)
1644 {
1645 *ret_size = pdb->TotalByteLength;
1646
1647 GetSystemTime(&pdb->SystemTime);
1648 GetSystemTimeAsFileTime((FILETIME *)&pdb->PerfTime100nSec);
1649 }
1650
1651 return err;
1652}
1653
1654/******************************************************************************
1655 * RegQueryValueExW (kernelbase.@)
1656 *
1657 * See RegQueryValueExA.
1658 */
1661{
1663 UNICODE_STRING name_str;
1664 DWORD total_size;
1665 char buffer[256], *buf_ptr = buffer;
1667 static const int info_size = offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data );
1668
1669 TRACE("(%p,%s,%p,%p,%p,%p=%ld)\n",
1671 (count && data) ? *count : 0 );
1672
1673 if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
1674
1675 if (is_perf_key( hkey ))
1676 return query_perf_data( name, type, data, count, TRUE );
1677
1678 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
1679
1680 RtlInitUnicodeString( &name_str, name );
1681
1682 if (data) total_size = min( sizeof(buffer), *count + info_size );
1683 else
1684 {
1685 total_size = info_size;
1686 if (count) *count = 0;
1687 }
1688
1690 buffer, total_size, &total_size );
1691 if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
1692
1693 if (data)
1694 {
1695 /* retry with a dynamically allocated buffer */
1696 while (status == STATUS_BUFFER_OVERFLOW && total_size - info_size <= *count)
1697 {
1698 if (buf_ptr != buffer) heap_free( buf_ptr );
1699 if (!(buf_ptr = heap_alloc( total_size )))
1703 buf_ptr, total_size, &total_size );
1704 }
1705
1706 if (!status)
1707 {
1708 memcpy( data, buf_ptr + info_size, total_size - info_size );
1709 /* if the type is REG_SZ and data is not 0-terminated
1710 * and there is enough space in the buffer NT appends a \0 */
1711 if (total_size - info_size <= *count-sizeof(WCHAR) && is_string(info->Type))
1712 {
1713 WCHAR *ptr = (WCHAR *)(data + total_size - info_size);
1714 if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
1715 }
1716 }
1717 else if (status != STATUS_BUFFER_OVERFLOW) goto done;
1718 }
1719 else status = STATUS_SUCCESS;
1720
1721 if (type) *type = info->Type;
1722 if (count) *count = total_size - info_size;
1723
1724 done:
1725 if (buf_ptr != buffer) heap_free( buf_ptr );
1727}
1728
1729
1730/******************************************************************************
1731 * RegQueryValueExA (kernelbase.@)
1732 *
1733 * Get the type and contents of a specified value under with a key.
1734 *
1735 * PARAMS
1736 * hkey [I] Handle of the key to query
1737 * name [I] Name of value under hkey to query
1738 * reserved [I] Reserved - must be NULL
1739 * type [O] Destination for the value type, or NULL if not required
1740 * data [O] Destination for the values contents, or NULL if not required
1741 * count [I/O] Size of data, updated with the number of bytes returned
1742 *
1743 * RETURNS
1744 * Success: ERROR_SUCCESS. *count is updated with the number of bytes copied to data.
1745 * Failure: ERROR_INVALID_HANDLE, if hkey is invalid.
1746 * ERROR_INVALID_PARAMETER, if any other parameter is invalid.
1747 * ERROR_MORE_DATA, if on input *count is too small to hold the contents.
1748 *
1749 * NOTES
1750 * MSDN states that if data is too small it is partially filled. In reality
1751 * it remains untouched.
1752 */
1755{
1757 ANSI_STRING nameA;
1759 DWORD total_size, datalen = 0;
1760 char buffer[256], *buf_ptr = buffer;
1762 static const int info_size = offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data );
1763
1764 TRACE("(%p,%s,%p,%p,%p,%p=%ld)\n",
1765 hkey, debugstr_a(name), reserved, type, data, count, count ? *count : 0 );
1766
1767 if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
1768 if (!(hkey = get_special_root_hkey( hkey )))
1769 return ERROR_INVALID_HANDLE;
1770
1771 if (count) datalen = *count;
1772 if (!data && count) *count = 0;
1773
1774 /* this matches Win9x behaviour - NT sets *type to a random value */
1775 if (type) *type = REG_NONE;
1776
1777 RtlInitAnsiString( &nameA, name );
1778 if ((status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
1780
1781 if (is_perf_key( hkey ))
1782 {
1785 return ret;
1786 }
1787
1789 buffer, sizeof(buffer), &total_size );
1790 if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
1791
1792 /* we need to fetch the contents for a string type even if not requested,
1793 * because we need to compute the length of the ANSI string. */
1794 if (data || is_string(info->Type))
1795 {
1796 /* retry with a dynamically allocated buffer */
1798 {
1799 if (buf_ptr != buffer) heap_free( buf_ptr );
1800 if (!(buf_ptr = heap_alloc( total_size )))
1801 {
1803 goto done;
1804 }
1807 buf_ptr, total_size, &total_size );
1808 }
1809
1810 if (status) goto done;
1811
1812 if (is_string(info->Type))
1813 {
1814 DWORD len;
1815
1816 RtlUnicodeToMultiByteSize( &len, (WCHAR *)(buf_ptr + info_size),
1817 total_size - info_size );
1818 if (data && len)
1819 {
1821 else
1822 {
1823 RtlUnicodeToMultiByteN( (char*)data, len, NULL, (WCHAR *)(buf_ptr + info_size),
1824 total_size - info_size );
1825 /* if the type is REG_SZ and data is not 0-terminated
1826 * and there is enough space in the buffer NT appends a \0 */
1827 if (len < datalen && data[len-1]) data[len] = 0;
1828 }
1829 }
1830 total_size = len + info_size;
1831 }
1832 else if (data)
1833 {
1834 if (total_size - info_size > datalen) status = STATUS_BUFFER_OVERFLOW;
1835 else memcpy( data, buf_ptr + info_size, total_size - info_size );
1836 }
1837 }
1838 else status = STATUS_SUCCESS;
1839
1840 if (type) *type = info->Type;
1841 if (count) *count = total_size - info_size;
1842
1843 done:
1844 if (buf_ptr != buffer) heap_free( buf_ptr );
1847}
1848
1849
1850/******************************************************************************
1851 * apply_restrictions [internal]
1852 *
1853 * Helper function for RegGetValueA/W.
1854 */
1855static void apply_restrictions( DWORD dwFlags, DWORD dwType, DWORD cbData, PLONG ret )
1856{
1857 /* Check if the type is restricted by the passed flags */
1858 if (*ret == ERROR_SUCCESS || *ret == ERROR_MORE_DATA)
1859 {
1860 DWORD dwMask = 0;
1861
1862 switch (dwType)
1863 {
1864 case REG_NONE: dwMask = RRF_RT_REG_NONE; break;
1865 case REG_SZ: dwMask = RRF_RT_REG_SZ; break;
1866 case REG_EXPAND_SZ: dwMask = RRF_RT_REG_EXPAND_SZ; break;
1867 case REG_MULTI_SZ: dwMask = RRF_RT_REG_MULTI_SZ; break;
1868 case REG_BINARY: dwMask = RRF_RT_REG_BINARY; break;
1869 case REG_DWORD: dwMask = RRF_RT_REG_DWORD; break;
1870 case REG_QWORD: dwMask = RRF_RT_REG_QWORD; break;
1871 }
1872
1873 if (dwFlags & dwMask)
1874 {
1875 /* Type is not restricted, check for size mismatch */
1876 if (dwType == REG_BINARY)
1877 {
1878 DWORD cbExpect = 0;
1879
1880 if ((dwFlags & RRF_RT_ANY) == RRF_RT_DWORD)
1881 cbExpect = 4;
1882 else if ((dwFlags & RRF_RT_ANY) == RRF_RT_QWORD)
1883 cbExpect = 8;
1884
1885 if (cbExpect && cbData != cbExpect)
1887 }
1888 }
1890 }
1891}
1892
1893
1894/******************************************************************************
1895 * RegGetValueW (kernelbase.@)
1896 *
1897 * Retrieves the type and data for a value name associated with a key,
1898 * optionally expanding its content and restricting its type.
1899 *
1900 * PARAMS
1901 * hKey [I] Handle to an open key.
1902 * pszSubKey [I] Name of the subkey of hKey.
1903 * pszValue [I] Name of value under hKey/szSubKey to query.
1904 * dwFlags [I] Flags restricting the value type to retrieve.
1905 * pdwType [O] Destination for the values type, may be NULL.
1906 * pvData [O] Destination for the values content, may be NULL.
1907 * pcbData [I/O] Size of pvData, updated with the size in bytes required to
1908 * retrieve the whole content, including the trailing '\0'
1909 * for strings.
1910 *
1911 * RETURNS
1912 * Success: ERROR_SUCCESS
1913 * Failure: nonzero error code from Winerror.h
1914 *
1915 * NOTES
1916 * - Unless RRF_NOEXPAND is specified, REG_EXPAND_SZ values are automatically
1917 * expanded and pdwType is set to REG_SZ instead.
1918 * - Restrictions are applied after expanding, using RRF_RT_REG_EXPAND_SZ
1919 * without RRF_NOEXPAND is thus not allowed.
1920 * An exception is the case where RRF_RT_ANY is specified, because then
1921 * RRF_NOEXPAND is allowed.
1922 */
1924 DWORD dwFlags, LPDWORD pdwType, PVOID pvData,
1926{
1927 DWORD dwType, cbData = (pvData && pcbData) ? *pcbData : 0;
1928 PVOID pvBuf = NULL;
1929 LONG ret;
1930
1931 TRACE("(%p,%s,%s,%ld,%p,%p,%p=%ld)\n",
1932 hKey, debugstr_w(pszSubKey), debugstr_w(pszValue), dwFlags, pdwType,
1933 pvData, pcbData, cbData);
1934
1935 if (pvData && !pcbData)
1937
1939 ((dwFlags & RRF_RT_ANY) != RRF_RT_ANY))
1941
1942 if ((dwFlags & RRF_WOW64_MASK) == RRF_WOW64_MASK)
1944
1945 if (pszSubKey && pszSubKey[0])
1946 {
1947 REGSAM samDesired = KEY_QUERY_VALUE;
1948
1949 if (dwFlags & RRF_WOW64_MASK)
1950 samDesired |= (dwFlags & RRF_SUBKEY_WOW6432KEY) ? KEY_WOW64_32KEY : KEY_WOW64_64KEY;
1951
1952 ret = RegOpenKeyExW(hKey, pszSubKey, 0, samDesired, &hKey);
1953 if (ret != ERROR_SUCCESS) return ret;
1954 }
1955
1956 ret = RegQueryValueExW(hKey, pszValue, NULL, &dwType, pvData, &cbData);
1957
1958 /* If the value is a string, we need to read in the whole value to be able
1959 * to know exactly how many bytes are needed after expanding the string and
1960 * ensuring that it is null-terminated. */
1961 if (is_string(dwType) &&
1962 (ret == ERROR_MORE_DATA ||
1963 (ret == ERROR_SUCCESS && dwType == REG_EXPAND_SZ && !(dwFlags & RRF_NOEXPAND)) ||
1964 (ret == ERROR_SUCCESS && (cbData < sizeof(WCHAR) || (pvData && *((WCHAR *)pvData + cbData / sizeof(WCHAR) - 1))))))
1965 {
1966 do {
1967 heap_free(pvBuf);
1968
1969 pvBuf = heap_alloc(cbData + sizeof(WCHAR));
1970 if (!pvBuf)
1971 {
1973 break;
1974 }
1975
1976 if (ret == ERROR_MORE_DATA || !pvData)
1977 ret = RegQueryValueExW(hKey, pszValue, NULL,
1978 &dwType, pvBuf, &cbData);
1979 else
1980 {
1981 /* Even if cbData was large enough we have to copy the
1982 * string since ExpandEnvironmentStrings can't handle
1983 * overlapping buffers. */
1984 CopyMemory(pvBuf, pvData, cbData);
1985 }
1986 } while (ret == ERROR_MORE_DATA);
1987
1988 if (ret == ERROR_SUCCESS)
1989 {
1990 /* Ensure null termination */
1991 if (cbData < sizeof(WCHAR) || *((WCHAR *)pvBuf + cbData / sizeof(WCHAR) - 1))
1992 {
1993 *((WCHAR *)pvBuf + cbData / sizeof(WCHAR)) = 0;
1994 cbData += sizeof(WCHAR);
1995 }
1996
1997 /* Recheck dwType in case it changed since the first call */
1998 if (dwType == REG_EXPAND_SZ && !(dwFlags & RRF_NOEXPAND))
1999 {
2000 cbData = ExpandEnvironmentStringsW(pvBuf, pvData,
2001 pcbData ? *pcbData : 0) * sizeof(WCHAR);
2002 dwType = REG_SZ;
2003 if (pvData && cbData > *pcbData)
2005 }
2006 else if (pvData)
2007 {
2008 if (cbData > *pcbData)
2010 else
2011 CopyMemory(pvData, pvBuf, cbData);
2012 }
2013 }
2014
2015 heap_free(pvBuf);
2016 }
2017
2018 if (pszSubKey && pszSubKey[0])
2020
2021 apply_restrictions(dwFlags, dwType, cbData, &ret);
2022
2025
2026 if (pdwType) *pdwType = dwType;
2027 if (pcbData) *pcbData = cbData;
2028
2029 return ret;
2030}
2031
2032
2033/******************************************************************************
2034 * RegGetValueA (kernelbase.@)
2035 *
2036 * See RegGetValueW.
2037 */
2039 DWORD dwFlags, LPDWORD pdwType, PVOID pvData,
2041{
2042 DWORD dwType, cbData = (pvData && pcbData) ? *pcbData : 0;
2043 PVOID pvBuf = NULL;
2044 LONG ret;
2045
2046 TRACE("(%p,%s,%s,%ld,%p,%p,%p=%ld)\n",
2047 hKey, debugstr_a(pszSubKey), debugstr_a(pszValue), dwFlags,
2048 pdwType, pvData, pcbData, cbData);
2049
2050 if (pvData && !pcbData)
2052
2054 ((dwFlags & RRF_RT_ANY) != RRF_RT_ANY))
2056
2057 if ((dwFlags & RRF_WOW64_MASK) == RRF_WOW64_MASK)
2059
2060 if (pszSubKey && pszSubKey[0])
2061 {
2062 REGSAM samDesired = KEY_QUERY_VALUE;
2063
2064 if (dwFlags & RRF_WOW64_MASK)
2065 samDesired |= (dwFlags & RRF_SUBKEY_WOW6432KEY) ? KEY_WOW64_32KEY : KEY_WOW64_64KEY;
2066
2067 ret = RegOpenKeyExA(hKey, pszSubKey, 0, samDesired, &hKey);
2068 if (ret != ERROR_SUCCESS) return ret;
2069 }
2070
2071 ret = RegQueryValueExA(hKey, pszValue, NULL, &dwType, pvData, &cbData);
2072
2073 /* If the value is a string, we need to read in the whole value to be able
2074 * to know exactly how many bytes are needed after expanding the string and
2075 * ensuring that it is null-terminated. */
2076 if (is_string(dwType) &&
2077 (ret == ERROR_MORE_DATA ||
2078 (ret == ERROR_SUCCESS && dwType == REG_EXPAND_SZ && !(dwFlags & RRF_NOEXPAND)) ||
2079 (ret == ERROR_SUCCESS && (!cbData || (pvData && *((char *)pvData + cbData - 1))))))
2080 {
2081 do {
2082 heap_free(pvBuf);
2083
2084 pvBuf = heap_alloc(cbData + 1);
2085 if (!pvBuf)
2086 {
2088 break;
2089 }
2090
2091 if (ret == ERROR_MORE_DATA || !pvData)
2092 ret = RegQueryValueExA(hKey, pszValue, NULL,
2093 &dwType, pvBuf, &cbData);
2094 else
2095 {
2096 /* Even if cbData was large enough we have to copy the
2097 * string since ExpandEnvironmentStrings can't handle
2098 * overlapping buffers. */
2099 CopyMemory(pvBuf, pvData, cbData);
2100 }
2101 } while (ret == ERROR_MORE_DATA);
2102
2103 if (ret == ERROR_SUCCESS)
2104 {
2105 /* Ensure null termination */
2106 if (!cbData || *((char *)pvBuf + cbData - 1))
2107 {
2108 *((char *)pvBuf + cbData) = 0;
2109 cbData++;
2110 }
2111
2112 /* Recheck dwType in case it changed since the first call */
2113 if (dwType == REG_EXPAND_SZ && !(dwFlags & RRF_NOEXPAND))
2114 {
2115 cbData = ExpandEnvironmentStringsA(pvBuf, pvData,
2116 pcbData ? *pcbData : 0);
2117 dwType = REG_SZ;
2118 if (pvData && cbData > *pcbData)
2120 }
2121 else if (pvData)
2122 {
2123 if (cbData > *pcbData)
2125 else
2126 CopyMemory(pvData, pvBuf, cbData);
2127 }
2128 }
2129
2130 heap_free(pvBuf);
2131 }
2132
2133 if (pszSubKey && pszSubKey[0])
2135
2136 apply_restrictions(dwFlags, dwType, cbData, &ret);
2137
2140
2141 if (pdwType) *pdwType = dwType;
2142 if (pcbData) *pcbData = cbData;
2143
2144 return ret;
2145}
2146
2147
2148/******************************************************************************
2149 * RegEnumValueW (kernelbase.@)
2150 *
2151 * Enumerates the values for the specified open registry key.
2152 *
2153 * PARAMS
2154 * hkey [I] Handle to key to query
2155 * index [I] Index of value to query
2156 * value [O] Value string
2157 * val_count [I/O] Size of value buffer (in wchars)
2158 * reserved [I] Reserved
2159 * type [O] Type code
2160 * data [O] Value data
2161 * count [I/O] Size of data buffer (in bytes)
2162 *
2163 * RETURNS
2164 * Success: ERROR_SUCCESS
2165 * Failure: nonzero error code from Winerror.h
2166 */
2169{
2171 DWORD total_size;
2172 char buffer[256], *buf_ptr = buffer;
2174 static const int info_size = offsetof( KEY_VALUE_FULL_INFORMATION, Name );
2175
2176 TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
2177 hkey, index, value, val_count, reserved, type, data, count );
2178
2179 if ((data && !count) || reserved || !value || !val_count)
2181 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
2182
2183 total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR);
2184 if (data) total_size += *count;
2185 total_size = min( sizeof(buffer), total_size );
2186
2188 buffer, total_size, &total_size );
2189
2190 /* retry with a dynamically allocated buffer */
2192 {
2193 if (buf_ptr != buffer) heap_free( buf_ptr );
2194 if (!(buf_ptr = heap_alloc( total_size )))
2196 info = (KEY_VALUE_FULL_INFORMATION *)buf_ptr;
2198 buf_ptr, total_size, &total_size );
2199 }
2200
2201 if (status) goto done;
2202
2203 if (info->NameLength/sizeof(WCHAR) >= *val_count)
2204 {
2206 goto overflow;
2207 }
2208 memcpy( value, info->Name, info->NameLength );
2209 *val_count = info->NameLength / sizeof(WCHAR);
2210 value[*val_count] = 0;
2211
2212 if (data)
2213 {
2214 if (total_size - info->DataOffset > *count)
2215 {
2217 goto overflow;
2218 }
2219 memcpy( data, buf_ptr + info->DataOffset, total_size - info->DataOffset );
2220 if (total_size - info->DataOffset <= *count-sizeof(WCHAR) && is_string(info->Type))
2221 {
2222 /* if the type is REG_SZ and data is not 0-terminated
2223 * and there is enough space in the buffer NT appends a \0 */
2224 WCHAR *ptr = (WCHAR *)(data + total_size - info->DataOffset);
2225 if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
2226 }
2227 }
2228
2229 overflow:
2230 if (type) *type = info->Type;
2231 if (count) *count = info->DataLength;
2232
2233 done:
2234 if (buf_ptr != buffer) heap_free( buf_ptr );
2236}
2237
2238
2239/******************************************************************************
2240 * RegEnumValueA (kernelbase.@)
2241 *
2242 * See RegEnumValueW.
2243 */
2246{
2248 DWORD total_size;
2249 char buffer[256], *buf_ptr = buffer;
2251 static const int info_size = offsetof( KEY_VALUE_FULL_INFORMATION, Name );
2252
2253 TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
2254 hkey, index, value, val_count, reserved, type, data, count );
2255
2256 if ((data && !count) || reserved || !value || !val_count)
2258 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
2259
2260 total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR);
2261 if (data) total_size += *count;
2262 total_size = min( sizeof(buffer), total_size );
2263
2265 buffer, total_size, &total_size );
2266
2267 /* we need to fetch the contents for a string type even if not requested,
2268 * because we need to compute the length of the ANSI string. */
2269
2270 /* retry with a dynamically allocated buffer */
2272 {
2273 if (buf_ptr != buffer) heap_free( buf_ptr );
2274 if (!(buf_ptr = heap_alloc( total_size )))
2276 info = (KEY_VALUE_FULL_INFORMATION *)buf_ptr;
2278 buf_ptr, total_size, &total_size );
2279 }
2280
2281 if (status) goto done;
2282
2283 if (is_string(info->Type))
2284 {
2285 DWORD len;
2286 RtlUnicodeToMultiByteSize( &len, (WCHAR *)(buf_ptr + info->DataOffset),
2287 total_size - info->DataOffset );
2288 if (data && len)
2289 {
2291 else
2292 {
2293 RtlUnicodeToMultiByteN( (char*)data, len, NULL, (WCHAR *)(buf_ptr + info->DataOffset),
2294 total_size - info->DataOffset );
2295 /* if the type is REG_SZ and data is not 0-terminated
2296 * and there is enough space in the buffer NT appends a \0 */
2297 if (len < *count && data[len-1]) data[len] = 0;
2298 }
2299 }
2300 info->DataLength = len;
2301 }
2302 else if (data)
2303 {
2304 if (total_size - info->DataOffset > *count) status = STATUS_BUFFER_OVERFLOW;
2305 else memcpy( data, buf_ptr + info->DataOffset, total_size - info->DataOffset );
2306 }
2307
2308 if (!status)
2309 {
2310 DWORD len;
2311
2312 RtlUnicodeToMultiByteSize( &len, info->Name, info->NameLength );
2313 if (len >= *val_count)
2314 {
2316 if (*val_count)
2317 {
2318 len = *val_count - 1;
2319 RtlUnicodeToMultiByteN( value, len, NULL, info->Name, info->NameLength );
2320 value[len] = 0;
2321 }
2322 }
2323 else
2324 {
2325 RtlUnicodeToMultiByteN( value, len, NULL, info->Name, info->NameLength );
2326 value[len] = 0;
2327 *val_count = len;
2328 }
2329 }
2330
2331 if (type) *type = info->Type;
2332 if (count) *count = info->DataLength;
2333
2334 done:
2335 if (buf_ptr != buffer) heap_free( buf_ptr );
2337}
2338
2339/******************************************************************************
2340 * RegDeleteValueW (kernelbase.@)
2341 *
2342 * See RegDeleteValueA.
2343 */
2345{
2346 return RegDeleteKeyValueW( hkey, NULL, name );
2347}
2348
2349/******************************************************************************
2350 * RegDeleteValueA (kernelbase.@)
2351 *
2352 * Delete a value from the registry.
2353 *
2354 * PARAMS
2355 * hkey [I] Registry handle of the key holding the value
2356 * name [I] Name of the value under hkey to delete
2357 *
2358 * RETURNS
2359 * Success: ERROR_SUCCESS
2360 * Failure: nonzero error code from Winerror.h
2361 */
2363{
2364 return RegDeleteKeyValueA( hkey, NULL, name );
2365}
2366
2367/******************************************************************************
2368 * RegDeleteKeyValueW (kernelbase.@)
2369 */
2371{
2373 HKEY hsubkey = 0;
2374 LONG ret;
2375
2376 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
2377
2378 if (subkey)
2379 {
2380 if ((ret = RegOpenKeyExW( hkey, subkey, 0, KEY_SET_VALUE, &hsubkey )))
2381 return ret;
2382 hkey = hsubkey;
2383 }
2384
2387 if (hsubkey) RegCloseKey( hsubkey );
2388 return ret;
2389}
2390
2391/******************************************************************************
2392 * RegDeleteKeyValueA (kernelbase.@)
2393 */
2395{
2397 HKEY hsubkey = 0;
2398 ANSI_STRING nameA;
2400
2401 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
2402
2403 if (subkey)
2404 {
2405 LONG ret = RegOpenKeyExA( hkey, subkey, 0, KEY_SET_VALUE, &hsubkey );
2406 if (ret)
2407 return ret;
2408 hkey = hsubkey;
2409 }
2410
2411 RtlInitAnsiString( &nameA, name );
2412 if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
2413 {
2414 status = NtDeleteValueKey( hkey, &nameW );
2416 }
2417
2418 if (hsubkey) RegCloseKey( hsubkey );
2419 return RtlNtStatusToDosError( status );
2420}
2421
2422/******************************************************************************
2423 * RegLoadKeyW (kernelbase.@)
2424 *
2425 * Create a subkey under HKEY_USERS or HKEY_LOCAL_MACHINE and store
2426 * registration information from a specified file into that subkey.
2427 *
2428 * PARAMS
2429 * hkey [I] Handle of open key
2430 * subkey [I] Address of name of subkey
2431 * filename [I] Address of filename for registry information
2432 *
2433 * RETURNS
2434 * Success: ERROR_SUCCESS
2435 * Failure: nonzero error code from Winerror.h
2436 */
2438{
2439 OBJECT_ATTRIBUTES destkey, file;
2440 UNICODE_STRING subkeyW, filenameW;
2442
2443 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
2444
2445 destkey.Length = sizeof(destkey);
2446 destkey.RootDirectory = hkey; /* root key: HKLM or HKU */
2447 destkey.ObjectName = &subkeyW; /* name of the key */
2448 destkey.Attributes = 0;
2449 destkey.SecurityDescriptor = NULL;
2451 RtlInitUnicodeString(&subkeyW, subkey);
2452
2453 file.Length = sizeof(file);
2454 file.RootDirectory = NULL;
2455 file.ObjectName = &filenameW; /* file containing the hive */
2456 file.Attributes = OBJ_CASE_INSENSITIVE;
2457 file.SecurityDescriptor = NULL;
2458 file.SecurityQualityOfService = NULL;
2461
2462 status = NtLoadKey(&destkey, &file);
2464 return RtlNtStatusToDosError( status );
2465}
2466
2467
2468/******************************************************************************
2469 * RegLoadKeyA (kernelbase.@)
2470 *
2471 * See RegLoadKeyW.
2472 */
2474{
2475 UNICODE_STRING subkeyW = { 0, 0, NULL }, filenameW = { 0, 0, NULL };
2476 STRING subkeyA, filenameA;
2478 LONG ret;
2479
2480 RtlInitAnsiString(&subkeyA, subkey);
2482
2483 if (!(status = RtlAnsiStringToUnicodeString(&subkeyW, &subkeyA, TRUE)) &&
2485 {
2486 ret = RegLoadKeyW(hkey, subkeyW.Buffer, filenameW.Buffer);
2487 }
2489 RtlFreeUnicodeString(&subkeyW);
2491 return ret;
2492}
2493
2494
2495/******************************************************************************
2496 * RegSaveKeyExW (kernelbase.@)
2497 */
2499{
2504 HANDLE handle;
2505
2506 TRACE( "(%p,%s,%p)\n", hkey, debugstr_w(file), sa );
2507
2508 if (!file || !*file) return ERROR_INVALID_PARAMETER;
2509 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
2510
2512 return RtlNtStatusToDosError( status );
2513
2519 if (!status)
2520 {
2521 status = NtSaveKey( hkey, handle );
2523 }
2524 return RtlNtStatusToDosError( status );
2525}
2526
2527
2528/******************************************************************************
2529 * RegSaveKeyExA (kernelbase.@)
2530 */
2532{
2533 UNICODE_STRING *fileW = &NtCurrentTeb()->StaticUnicodeString;
2535 STRING fileA;
2536
2537 RtlInitAnsiString(&fileA, file);
2539 return RtlNtStatusToDosError( status );
2540 return RegSaveKeyExW(hkey, fileW->Buffer, sa, flags);
2541}
2542
2543
2544/******************************************************************************
2545 * RegRestoreKeyW (kernelbase.@)
2546 *
2547 * Read the registry information from a file and copy it over a key.
2548 *
2549 * PARAMS
2550 * hkey [I] Handle of key where restore begins
2551 * lpFile [I] Address of filename containing saved tree
2552 * dwFlags [I] Optional flags
2553 *
2554 * RETURNS
2555 * Success: ERROR_SUCCESS
2556 * Failure: nonzero error code from Winerror.h
2557 */
2559{
2560 TRACE("(%p,%s,%ld)\n",hkey,debugstr_w(lpFile),dwFlags);
2561
2562 /* It seems to do this check before the hkey check */
2563 if (!lpFile || !*lpFile)
2565
2566 FIXME("(%p,%s,%ld): stub\n",hkey,debugstr_w(lpFile),dwFlags);
2567
2568 /* Check for file existence */
2569
2570 return ERROR_SUCCESS;
2571}
2572
2573
2574/******************************************************************************
2575 * RegRestoreKeyA (kernelbase.@)
2576 *
2577 * See RegRestoreKeyW.
2578 */
2580{
2581 UNICODE_STRING lpFileW;
2582 LONG ret;
2583
2584 RtlCreateUnicodeStringFromAsciiz( &lpFileW, lpFile );
2585 ret = RegRestoreKeyW( hkey, lpFileW.Buffer, dwFlags );
2586 RtlFreeUnicodeString( &lpFileW );
2587 return ret;
2588}
2589
2590
2591/******************************************************************************
2592 * RegUnLoadKeyW (kernelbase.@)
2593 *
2594 * Unload a registry key and its subkeys from the registry.
2595 *
2596 * PARAMS
2597 * hkey [I] Handle of open key
2598 * lpSubKey [I] Address of name of subkey to unload
2599 *
2600 * RETURNS
2601 * Success: ERROR_SUCCESS
2602 * Failure: nonzero error code from Winerror.h
2603 */
2605{
2607 UNICODE_STRING subkey;
2608
2609 TRACE("(%p,%s)\n",hkey, debugstr_w(lpSubKey));
2610
2611 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
2612
2613 RtlInitUnicodeString(&subkey, lpSubKey);
2616}
2617
2618
2619/******************************************************************************
2620 * RegUnLoadKeyA (kernelbase.@)
2621 *
2622 * See RegUnLoadKeyW.
2623 */
2625{
2626 UNICODE_STRING lpSubKeyW;
2627 LONG ret;
2628
2629 RtlCreateUnicodeStringFromAsciiz( &lpSubKeyW, lpSubKey );
2630 ret = RegUnLoadKeyW( hkey, lpSubKeyW.Buffer );
2631 RtlFreeUnicodeString( &lpSubKeyW );
2632 return ret;
2633}
2634
2635
2636/******************************************************************************
2637 * RegSetKeySecurity (kernelbase.@)
2638 *
2639 * Set the security of an open registry key.
2640 *
2641 * PARAMS
2642 * hkey [I] Open handle of key to set
2643 * SecurityInfo [I] Descriptor contents
2644 * pSecurityDesc [I] Address of descriptor for key
2645 *
2646 * RETURNS
2647 * Success: ERROR_SUCCESS
2648 * Failure: nonzero error code from Winerror.h
2649 */
2651 PSECURITY_DESCRIPTOR pSecurityDesc )
2652{
2653 TRACE("(%p,%ld,%p)\n",hkey,SecurityInfo,pSecurityDesc);
2654
2655 /* It seems to perform this check before the hkey check */
2656 if ((SecurityInfo & OWNER_SECURITY_INFORMATION) ||
2657 (SecurityInfo & GROUP_SECURITY_INFORMATION) ||
2658 (SecurityInfo & DACL_SECURITY_INFORMATION) ||
2659 (SecurityInfo & SACL_SECURITY_INFORMATION)) {
2660 /* Param OK */
2661 } else
2663
2664 if (!pSecurityDesc)
2666
2667 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
2668
2669 return RtlNtStatusToDosError( NtSetSecurityObject( hkey, SecurityInfo, pSecurityDesc ) );
2670}
2671
2672
2673/******************************************************************************
2674 * RegGetKeySecurity (kernelbase.@)
2675 *
2676 * Get a copy of the security descriptor for a given registry key.
2677 *
2678 * PARAMS
2679 * hkey [I] Open handle of key to set
2680 * SecurityInformation [I] Descriptor contents
2681 * pSecurityDescriptor [O] Address of descriptor for key
2682 * lpcbSecurityDescriptor [I/O] Address of size of buffer and description
2683 *
2684 * RETURNS
2685 * Success: ERROR_SUCCESS
2686 * Failure: Error code
2687 */
2689 PSECURITY_DESCRIPTOR pSecurityDescriptor,
2690 LPDWORD lpcbSecurityDescriptor )
2691{
2692 TRACE("(%p,%ld,%p,%ld)\n",hkey,SecurityInformation,pSecurityDescriptor,
2693 *lpcbSecurityDescriptor);
2694
2695 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
2696
2698 SecurityInformation, pSecurityDescriptor,
2699 *lpcbSecurityDescriptor, lpcbSecurityDescriptor ) );
2700}
2701
2702
2703/******************************************************************************
2704 * RegFlushKey (kernelbase.@)
2705 *
2706 * Immediately write a registry key to registry.
2707 *
2708 * PARAMS
2709 * hkey [I] Handle of key to write
2710 *
2711 * RETURNS
2712 * Success: ERROR_SUCCESS
2713 * Failure: Error code
2714 */
2716{
2717 hkey = get_special_root_hkey( hkey );
2718 if (!hkey) return ERROR_INVALID_HANDLE;
2719
2720 return RtlNtStatusToDosError( NtFlushKey( hkey ) );
2721}
2722
2723
2724/******************************************************************************
2725 * RegNotifyChangeKeyValue (kernelbase.@)
2726 *
2727 * Notify the caller about changes to the attributes or contents of a registry key.
2728 *
2729 * PARAMS
2730 * hkey [I] Handle of key to watch
2731 * fWatchSubTree [I] Flag for subkey notification
2732 * fdwNotifyFilter [I] Changes to be reported
2733 * hEvent [I] Handle of signaled event
2734 * fAsync [I] Flag for asynchronous reporting
2735 *
2736 * RETURNS
2737 * Success: ERROR_SUCCESS
2738 * Failure: nonzero error code from Winerror.h
2739 */
2741 DWORD fdwNotifyFilter, HANDLE hEvent,
2742 BOOL fAsync )
2743{
2746
2747 hkey = get_special_root_hkey( hkey );
2748 if (!hkey) return ERROR_INVALID_HANDLE;
2749
2750 TRACE("(%p,%i,%ld,%p,%i)\n", hkey, fWatchSubTree, fdwNotifyFilter,
2751 hEvent, fAsync);
2752
2754 fdwNotifyFilter, fWatchSubTree, NULL, 0,
2755 fAsync);
2756
2757 if (status && status != STATUS_PENDING)
2758 return RtlNtStatusToDosError( status );
2759
2760 return ERROR_SUCCESS;
2761}
2762
2763/******************************************************************************
2764 * RegOpenUserClassesRoot (kernelbase.@)
2765 *
2766 * Open the HKEY_CLASSES_ROOT key for a user.
2767 *
2768 * PARAMS
2769 * hToken [I] Handle of token representing the user
2770 * dwOptions [I] Reserved, must be 0
2771 * samDesired [I] Desired access rights
2772 * phkResult [O] Destination for the resulting key handle
2773 *
2774 * RETURNS
2775 * Success: ERROR_SUCCESS
2776 * Failure: nonzero error code from Winerror.h
2777 *
2778 * NOTES
2779 * On Windows 2000 and upwards the HKEY_CLASSES_ROOT key is a view of the
2780 * "HKEY_LOCAL_MACHINE\Software\Classes" and the
2781 * "HKEY_CURRENT_USER\Software\Classes" keys merged together.
2782 */
2784{
2785 FIXME("(%p, 0x%lx, 0x%lx, %p) semi-stub\n", hToken, dwOptions, samDesired, phkResult);
2786
2787 *phkResult = HKEY_CLASSES_ROOT;
2788 return ERROR_SUCCESS;
2789}
2790
2791
2792static void dump_mui_cache(void)
2793{
2794 struct mui_cache_entry *ent;
2795
2796 TRACE("---------- MUI Cache ----------\n");
2798 TRACE("entry=%p, %s,-%lu [%#lx] => %s\n",
2799 ent, wine_dbgstr_w(ent->file_name), ent->index, ent->locale, wine_dbgstr_w(ent->text));
2800}
2801
2802static inline void free_mui_cache_entry(struct mui_cache_entry *ent)
2803{
2804 heap_free(ent->file_name);
2805 heap_free(ent->text);
2806 heap_free(ent);
2807}
2808
2809/* critical section must be held */
2811{
2812 struct mui_cache_entry *ent;
2813
2814 TRACE("(%s %u %p)\n", wine_dbgstr_w(file_name), index, buffer);
2815
2817 {
2818 if (ent->index == index && ent->locale == GetThreadLocale() &&
2820 goto found;
2821 }
2822 return 0;
2823
2824found:
2825 /* move to the list head */
2826 if (list_prev(&reg_mui_cache, &ent->entry)) {
2827 list_remove(&ent->entry);
2829 }
2830
2831 TRACE("=> %s\n", wine_dbgstr_w(ent->text));
2832 *buffer = ent->text;
2833 return lstrlenW(ent->text);
2834}
2835
2836/* critical section must be held */
2838{
2839 struct mui_cache_entry *ent;
2840 TRACE("(%s %u %s %d)\n", wine_dbgstr_w(file_name), index, wine_dbgstr_wn(buffer, size), size);
2841
2842 ent = heap_calloc(sizeof(*ent), 1);
2843 if (!ent)
2844 return;
2845 ent->file_name = heap_alloc((lstrlenW(file_name) + 1) * sizeof(WCHAR));
2846 if (!ent->file_name) {
2848 return;
2849 }
2851 ent->index = index;
2852 ent->locale = GetThreadLocale();
2853 ent->text = heap_alloc((size + 1) * sizeof(WCHAR));
2854 if (!ent->text) {
2856 return;
2857 }
2858 memcpy(ent->text, buffer, size * sizeof(WCHAR));
2859 ent->text[size] = '\0';
2860
2861 TRACE("add %p\n", ent);
2865 TRACE("freeing %p\n", ent);
2866 list_remove(&ent->entry);
2868 }
2869 else
2871
2872 if (TRACE_ON(reg))
2874 return;
2875}
2876
2877static LONG load_mui_string(const WCHAR *file_name, UINT res_id, WCHAR *buffer, INT max_chars, INT *req_chars, DWORD flags)
2878{
2880 WCHAR *string = NULL, *full_name;
2881 int size;
2882 LONG result;
2883
2884 /* Verify the file existence. i.e. We don't rely on PATH variable */
2886 return ERROR_FILE_NOT_FOUND;
2887
2889 if (!size)
2890 return GetLastError();
2891 full_name = heap_alloc(size * sizeof(WCHAR));
2892 if (!full_name)
2894 GetFullPathNameW(file_name, size, full_name, NULL);
2895
2897 size = reg_mui_cache_get(full_name, res_id, &string);
2898 if (!size) {
2900
2901 /* Load the file */
2902 hModule = LoadLibraryExW(full_name, NULL,
2904 if (!hModule)
2905 return GetLastError();
2906
2907 size = LoadStringW(hModule, res_id, (WCHAR *)&string, 0);
2908 if (!size) {
2909 if (string) result = ERROR_NOT_FOUND;
2910 else result = GetLastError();
2911 goto cleanup;
2912 }
2913
2915 reg_mui_cache_put(full_name, res_id, string, size);
2917 }
2918 *req_chars = size + 1;
2919
2920 /* If no buffer is given, skip copying. */
2921 if (!buffer) {
2923 goto cleanup;
2924 }
2925
2926 /* Else copy over the string, respecting the buffer size. */
2927 if (size < max_chars)
2928 max_chars = size;
2929 else {
2930 if (flags & REG_MUI_STRING_TRUNCATE)
2931 max_chars--;
2932 else {
2934 goto cleanup;
2935 }
2936 }
2937 if (max_chars >= 0) {
2938 memcpy(buffer, string, max_chars * sizeof(WCHAR));
2939 buffer[max_chars] = '\0';
2940 }
2941
2943
2944cleanup:
2945 if (hModule)
2947 else
2949 heap_free(full_name);
2950 return result;
2951}
2952
2953/******************************************************************************
2954 * RegLoadMUIStringW (kernelbase.@)
2955 *
2956 * Load the localized version of a string resource from some PE, respective
2957 * id and path of which are given in the registry value in the format
2958 * @[path]\dllname,-resourceId
2959 *
2960 * PARAMS
2961 * hKey [I] Key, of which to load the string value from.
2962 * pszValue [I] The value to be loaded (Has to be of REG_EXPAND_SZ or REG_SZ type).
2963 * pszBuffer [O] Buffer to store the localized string in.
2964 * cbBuffer [I] Size of the destination buffer in bytes.
2965 * pcbData [O] Number of bytes written to pszBuffer (optional, may be NULL).
2966 * dwFlags [I] Truncate output to fit the buffer if REG_MUI_STRING_TRUNCATE.
2967 * pszBaseDir [I] Base directory of loading path. If NULL, use the current directory.
2968 *
2969 * RETURNS
2970 * Success: ERROR_SUCCESS,
2971 * Failure: nonzero error code from winerror.h
2972 */
2973LSTATUS WINAPI RegLoadMUIStringW(HKEY hKey, LPCWSTR pwszValue, LPWSTR pwszBuffer, DWORD cbBuffer,
2974 LPDWORD pcbData, DWORD dwFlags, LPCWSTR pwszBaseDir)
2975{
2976 DWORD dwValueType, cbData;
2977 LPWSTR pwszTempBuffer = NULL, pwszExpandedBuffer = NULL;
2978 LONG result;
2979
2980 TRACE("(hKey = %p, pwszValue = %s, pwszBuffer = %p, cbBuffer = %ld, pcbData = %p, "
2981 "dwFlags = %lu, pwszBaseDir = %s)\n", hKey, debugstr_w(pwszValue), pwszBuffer,
2982 cbBuffer, pcbData, dwFlags, debugstr_w(pwszBaseDir));
2983
2984 /* Parameter sanity checks. */
2985 if (!hKey || (!pwszBuffer && cbBuffer) || (cbBuffer % sizeof(WCHAR))
2986 || ((dwFlags & REG_MUI_STRING_TRUNCATE) && pcbData)
2987 || (dwFlags & ~REG_MUI_STRING_TRUNCATE))
2989
2990 /* Check for value existence and correctness of its type, allocate a buffer and load it. */
2991 result = RegQueryValueExW(hKey, pwszValue, NULL, &dwValueType, NULL, &cbData);
2992 if (result != ERROR_SUCCESS) goto cleanup;
2993 if (!(dwValueType == REG_SZ || dwValueType == REG_EXPAND_SZ) || !cbData) {
2995 goto cleanup;
2996 }
2997 pwszTempBuffer = heap_alloc(cbData);
2998 if (!pwszTempBuffer) {
3000 goto cleanup;
3001 }
3002 result = RegQueryValueExW(hKey, pwszValue, NULL, &dwValueType, (LPBYTE)pwszTempBuffer, &cbData);
3003 if (result != ERROR_SUCCESS) goto cleanup;
3004
3005 /* '@' is the prefix for resource based string entries. */
3006 if (*pwszTempBuffer != '@') {
3008 goto cleanup;
3009 }
3010
3011 /* Expand environment variables regardless of the type. */
3012 cbData = ExpandEnvironmentStringsW(pwszTempBuffer, NULL, 0) * sizeof(WCHAR);
3013 if (!cbData) goto cleanup;
3014 pwszExpandedBuffer = heap_alloc(cbData);
3015 if (!pwszExpandedBuffer) {
3017 goto cleanup;
3018 }
3019 ExpandEnvironmentStringsW(pwszTempBuffer, pwszExpandedBuffer, cbData / sizeof(WCHAR));
3020
3021 /* Parse the value and load the string. */
3022 {
3023 WCHAR *pComma = wcsrchr(pwszExpandedBuffer, ','), *pNewBuffer;
3024 UINT uiStringId;
3025 DWORD baseDirLen;
3026 int reqChars;
3027
3028 /* Format of the expanded value is 'path_to_dll,-resId' */
3029 if (!pComma || pComma[1] != '-') {
3031 goto cleanup;
3032 }
3033
3034 uiStringId = wcstol(pComma+2, NULL, 10);
3035 *pComma = '\0';
3036
3037 /* Build a resource dll path. */
3038 baseDirLen = pwszBaseDir ? lstrlenW(pwszBaseDir) : 0;
3039 cbData = (baseDirLen + 1 + lstrlenW(pwszExpandedBuffer + 1) + 1) * sizeof(WCHAR);
3040 pNewBuffer = heap_realloc(pwszTempBuffer, cbData);
3041 if (!pNewBuffer) {
3043 goto cleanup;
3044 }
3045 pwszTempBuffer = pNewBuffer;
3046 pwszTempBuffer[0] = '\0';
3047 if (baseDirLen) {
3048 lstrcpyW(pwszTempBuffer, pwszBaseDir);
3049 if (pwszBaseDir[baseDirLen - 1] != '\\')
3050 lstrcatW(pwszTempBuffer, L"\\");
3051 }
3052 lstrcatW(pwszTempBuffer, pwszExpandedBuffer + 1);
3053
3054 /* Load specified string from the file */
3055 reqChars = 0;
3056 result = load_mui_string(pwszTempBuffer, uiStringId, pwszBuffer, cbBuffer/sizeof(WCHAR), &reqChars, dwFlags);
3058 *pcbData = reqChars * sizeof(WCHAR);
3059 }
3060
3061cleanup:
3062 heap_free(pwszTempBuffer);
3063 heap_free(pwszExpandedBuffer);
3064 return result;
3065}
3066
3067/******************************************************************************
3068 * RegLoadMUIStringA (kernelbase.@)
3069 *
3070 * Not implemented on native.
3071 */
3073 LPDWORD pcbData, DWORD dwFlags, LPCSTR pszBaseDir)
3074{
3076}
3077
3078
3079/******************************************************************************
3080 * RegDeleteTreeW (kernelbase.@)
3081 *
3082 */
3084{
3085 DWORD name_size, max_name, max_subkey;
3086 WCHAR *name_buf = NULL;
3087 LONG ret;
3088
3089 TRACE( "(%p, %s)\n", hkey, debugstr_w(subkey) );
3090
3091 if (subkey && *subkey)
3092 {
3093 ret = RegOpenKeyExW( hkey, subkey, 0, KEY_READ, &hkey );
3094 if (ret) return ret;
3095 }
3096
3097 ret = RegQueryInfoKeyW( hkey, NULL, NULL, NULL, NULL, &max_subkey,
3098 NULL, NULL, &max_name, NULL, NULL, NULL );
3099 if (ret)
3100 goto cleanup;
3101
3102 max_name = max( max_subkey, max_name ) + 1;
3103 if (!(name_buf = heap_alloc( max_name * sizeof(WCHAR) )))
3104 {
3106 goto cleanup;
3107 }
3108
3109 /* Recursively delete subkeys */
3110 for (;;)
3111 {
3112 name_size = max_name;
3113 ret = RegEnumKeyExW( hkey, 0, name_buf, &name_size, NULL, NULL, NULL, NULL );
3114 if (ret == ERROR_NO_MORE_ITEMS) break;
3115 if (ret) goto cleanup;
3116 ret = RegDeleteTreeW( hkey, name_buf );
3117 if (ret) goto cleanup;
3118 }
3119
3120 /* Delete the key itself */
3121 if (subkey && *subkey)
3122 {
3123 ret = RegDeleteKeyExW( hkey, L"", 0, 0 );
3124 goto cleanup;
3125 }
3126
3127 /* Delete values */
3128 for (;;)
3129 {
3130 name_size = max_name;
3131 ret = RegEnumValueW( hkey, 0, name_buf, &name_size, NULL, NULL, NULL, NULL );
3132 if (ret == ERROR_NO_MORE_ITEMS) break;
3133 if (ret) goto cleanup;
3134 ret = RegDeleteValueW( hkey, name_buf );
3135 if (ret) goto cleanup;
3136 }
3137
3139
3140cleanup:
3141 heap_free( name_buf );
3142 if (subkey && *subkey)
3143 RegCloseKey( hkey );
3144 return ret;
3145}
3146
3147
3148/******************************************************************************
3149 * RegDeleteTreeA (kernelbase.@)
3150 *
3151 */
3152LSTATUS WINAPI RegDeleteTreeA( HKEY hkey, const char *subkey )
3153{
3154 UNICODE_STRING subkeyW;
3155 LONG ret;
3156
3157 if (subkey) RtlCreateUnicodeStringFromAsciiz( &subkeyW, subkey );
3158 else subkeyW.Buffer = NULL;
3159 ret = RegDeleteTreeW( hkey, subkeyW.Buffer );
3160 RtlFreeUnicodeString( &subkeyW );
3161 return ret;
3162}
3163
3164
3165/******************************************************************************
3166 * RegCopyTreeW (kernelbase.@)
3167 *
3168 */
3169LSTATUS WINAPI RegCopyTreeW( HKEY hsrc, const WCHAR *subkey, HKEY hdst )
3170{
3171 DWORD name_size, max_name;
3172 DWORD value_size, max_value;
3173 DWORD max_subkey, i, type;
3174 WCHAR *name_buf = NULL;
3175 BYTE *value_buf = NULL;
3176 HKEY hkey;
3177 LONG ret;
3178
3179 TRACE( "(%p, %s, %p)\n", hsrc, debugstr_w(subkey), hdst );
3180
3181 if (subkey)
3182 {
3183 ret = RegOpenKeyExW( hsrc, subkey, 0, KEY_READ, &hsrc );
3184 if (ret) return ret;
3185 }
3186
3187 ret = RegQueryInfoKeyW( hsrc, NULL, NULL, NULL, NULL, &max_subkey,
3188 NULL, NULL, &max_name, &max_value, NULL, NULL );
3189 if (ret)
3190 goto cleanup;
3191
3192 max_name = max( max_subkey, max_name ) + 1;
3193 if (!(name_buf = heap_alloc( max_name * sizeof(WCHAR) )))
3194 {
3196 goto cleanup;
3197 }
3198
3199 if (!(value_buf = heap_alloc( max_value )))
3200 {
3202 goto cleanup;
3203 }
3204
3205 /* Copy values */
3206 for (i = 0;; i++)
3207 {
3208 name_size = max_name;
3209 value_size = max_value;
3210 ret = RegEnumValueW( hsrc, i, name_buf, &name_size, NULL, &type, value_buf, &value_size );
3211 if (ret == ERROR_NO_MORE_ITEMS) break;
3212 if (ret) goto cleanup;
3213 ret = RegSetValueExW( hdst, name_buf, 0, type, value_buf, value_size );
3214 if (ret) goto cleanup;
3215 }
3216
3217 /* Recursively copy subkeys */
3218 for (i = 0;; i++)
3219 {
3220 name_size = max_name;
3221 ret = RegEnumKeyExW( hsrc, i, name_buf, &name_size, NULL, NULL, NULL, NULL );
3222 if (ret == ERROR_NO_MORE_ITEMS) break;
3223 if (ret) goto cleanup;
3224 ret = RegCreateKeyExW( hdst, name_buf, 0, NULL, 0, KEY_WRITE, NULL, &hkey, NULL );
3225 if (ret) goto cleanup;
3226 ret = RegCopyTreeW( hsrc, name_buf, hkey );
3227 RegCloseKey( hkey );
3228 if (ret) goto cleanup;
3229 }
3230
3232
3233cleanup:
3234 heap_free( name_buf );
3235 heap_free( value_buf );
3236 if (subkey)
3237 RegCloseKey( hsrc );
3238 return ret;
3239}
3240
3241
3242/******************************************************************************
3243 * RegLoadAppKeyA (kernelbase.@)
3244 *
3245 */
3247{
3248 FIXME("%s %p %lu %lu %lu: stub\n", wine_dbgstr_a(file), result, sam, options, reserved);
3249
3250 if (!file || reserved)
3252
3253 *result = (HKEY)0xdeadbeef;
3254 return ERROR_SUCCESS;
3255}
3256
3257/******************************************************************************
3258 * RegLoadAppKeyW (kernelbase.@)
3259 *
3260 */
3262{
3263 FIXME("%s %p %lu %lu %lu: stub\n", wine_dbgstr_w(file), result, sam, options, reserved);
3264
3265 if (!file || reserved)
3267
3268 *result = (HKEY)0xdeadbeef;
3269 return ERROR_SUCCESS;
3270}
3271
3272
3273/***********************************************************************
3274 * DnsHostnameToComputerNameExW (kernelbase.@)
3275 *
3276 * FIXME: how is this different from the non-Ex function?
3277 */
3279 DWORD *size )
3280{
3281 static const WCHAR allowed[] = L"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&')(-_{}";
3283 DWORD i, len;
3284
3286 len = lstrlenW( buffer );
3287 if (*size < len + 1)
3288 {
3289 *size = len;
3291 return FALSE;
3292 }
3293 *size = len;
3294 if (!computername) return FALSE;
3295 for (i = 0; i < len; i++)
3296 {
3297 if (buffer[i] >= 'a' && buffer[i] <= 'z') computername[i] = buffer[i] + 'A' - 'a';
3298 else computername[i] = wcschr( allowed, buffer[i] ) ? buffer[i] : '_';
3299 }
3300 computername[len] = 0;
3301 return TRUE;
3302}
3303
3304
3305/***********************************************************************
3306 * GetComputerNameExA (kernelbase.@)
3307 */
3308BOOL WINAPI GetComputerNameExA( COMPUTER_NAME_FORMAT type, char *name, DWORD *len )
3309{
3310 BOOL ret = FALSE;
3311 DWORD lenA, lenW = 0;
3312 WCHAR *buffer;
3313
3314 GetComputerNameExW( type, NULL, &lenW );
3315 if (GetLastError() != ERROR_MORE_DATA) return FALSE;
3316
3317 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, lenW * sizeof(WCHAR) )))
3318 {
3320 return FALSE;
3321 }
3322 if (GetComputerNameExW( type, buffer, &lenW ))
3323 {
3324 lenA = WideCharToMultiByte( CP_ACP, 0, buffer, -1, NULL, 0, NULL, NULL );
3325 if (lenA > *len)
3326 {
3327 *len = lenA;
3329 }
3330 else
3331 {
3333 *len = lenA - 1;
3334 ret = TRUE;
3335 }
3336 }
3338 return ret;
3339}
3340
3341
3342/***********************************************************************
3343 * GetComputerNameExW (kernelbase.@)
3344 */
3346{
3347 const WCHAR *keyname, *valuename;
3348 LRESULT ret;
3349 HKEY key;
3350
3351 switch (type)
3352 {
3353 case ComputerNameNetBIOS:
3354 case ComputerNamePhysicalNetBIOS:
3355 keyname = L"System\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName";
3356 valuename = L"ComputerName";
3357 break;
3358 case ComputerNameDnsHostname:
3359 case ComputerNamePhysicalDnsHostname:
3360 keyname = L"System\\CurrentControlSet\\Services\\Tcpip\\Parameters";
3361 valuename = L"Hostname";
3362 break;
3363 case ComputerNameDnsDomain:
3364 case ComputerNamePhysicalDnsDomain:
3365 keyname = L"System\\CurrentControlSet\\Services\\Tcpip\\Parameters";
3366 valuename = L"Domain";
3367 break;
3368 case ComputerNameDnsFullyQualified:
3369 case ComputerNamePhysicalDnsFullyQualified:
3370 {
3371 WCHAR *domain, buffer[256];
3372 DWORD size = ARRAY_SIZE(buffer) - 1;
3373
3374 if (!GetComputerNameExW( ComputerNameDnsHostname, buffer, &size )) return FALSE;
3376 *domain++ = '.';
3378 if (!GetComputerNameExW( ComputerNameDnsDomain, domain, &size )) return FALSE;
3379 if (!*domain) domain[-1] = 0;
3380 size = lstrlenW(buffer);
3381 if (name && size < *len)
3382 {
3383 if (name) lstrcpyW( name, buffer );
3384 *len = size;
3385 return TRUE;
3386 }
3387 *len = size + 1;
3389 return FALSE;
3390 }
3391 default:
3393 return FALSE;
3394 }
3395
3396 if (!(ret = RegOpenKeyExW( HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &key )))
3397 {
3398 DWORD size = *len * sizeof(WCHAR);
3399 ret = RegQueryValueExW( key, valuename, NULL, NULL, (BYTE *)name, &size );
3400 if (!name) ret = ERROR_MORE_DATA;
3401 else if (!ret) size -= sizeof(WCHAR);
3402 *len = size / sizeof(WCHAR);
3403 RegCloseKey( key );
3404 }
3405 TRACE("-> %Iu %s\n", ret, debugstr_w(name) );
3406 if (ret) SetLastError( ret );
3407 return !ret;
3408}
3409
3410
3411/***********************************************************************
3412 * SetComputerNameA (kernelbase.@)
3413 */
3415{
3416 BOOL ret;
3417 DWORD len = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 );
3418 WCHAR *nameW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
3419
3421 ret = SetComputerNameExW( ComputerNamePhysicalNetBIOS, nameW );
3422 HeapFree( GetProcessHeap(), 0, nameW );
3423 return ret;
3424}
3425
3426
3427/***********************************************************************
3428 * SetComputerNameW (kernelbase.@)
3429 */
3431{
3432 return SetComputerNameExW( ComputerNamePhysicalNetBIOS, name );
3433}
3434
3435
3436/***********************************************************************
3437 * SetComputerNameExA (kernelbase.@)
3438 */
3439BOOL WINAPI DECLSPEC_HOTPATCH SetComputerNameExA( COMPUTER_NAME_FORMAT type, const char *name )
3440{
3441 BOOL ret;
3442 DWORD len = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 );
3443 WCHAR *nameW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
3444
3447 HeapFree( GetProcessHeap(), 0, nameW );
3448 return ret;
3449}
3450
3451
3452/***********************************************************************
3453 * SetComputerNameExW (kernelbase.@)
3454 */
3456{
3458 DWORD size;
3459 HKEY key;
3460 LRESULT ret;
3461
3462 TRACE( "%u %s\n", type, debugstr_w( name ));
3463
3464 switch (type)
3465 {
3466 case ComputerNameDnsHostname:
3467 case ComputerNamePhysicalDnsHostname:
3468 ret = RegCreateKeyExW( HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Services\\Tcpip\\Parameters",
3469 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key, NULL );
3470 if (ret) break;
3471 ret = RegSetValueExW( key, L"Hostname", 0, REG_SZ,
3472 (BYTE *)name, (lstrlenW(name) + 1) * sizeof(WCHAR) );
3473 RegCloseKey( key );
3474 /* fall through */
3475
3476 case ComputerNameNetBIOS:
3477 case ComputerNamePhysicalNetBIOS:
3478 /* @@ Wine registry key: HKCU\Software\Wine\Network */
3479 if (!RegOpenKeyExW( HKEY_CURRENT_USER, L"Software\\Wine\\Network", 0, KEY_READ, &key ))
3480 {
3481 BOOL use_dns = TRUE;
3482 size = sizeof(buffer);
3483 if (!RegQueryValueExW( key, L"UseDnsComputerName", NULL, NULL, (BYTE *)buffer, &size ))
3484 use_dns = IS_OPTION_TRUE( buffer[0] );
3485 RegCloseKey( key );
3486 if (!use_dns)
3487 {
3489 break;
3490 }
3491 }
3492 size = ARRAY_SIZE( buffer );
3494 ret = RegCreateKeyExW( HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Control\\ComputerName\\ComputerName",
3495 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key, NULL );
3496 if (ret) break;
3497 ret = RegSetValueExW( key, L"ComputerName", 0, REG_SZ,
3498 (BYTE *)buffer, (lstrlenW(buffer) + 1) * sizeof(WCHAR) );
3499 RegCloseKey( key );
3500 break;
3501
3502 case ComputerNameDnsDomain:
3503 case ComputerNamePhysicalDnsDomain:
3504 ret = RegCreateKeyExW( HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Services\\Tcpip\\Parameters",
3505 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key, NULL );
3506 if (ret) break;
3507 ret = RegSetValueExW( key, L"Domain", 0, REG_SZ,
3508 (BYTE *)name, (lstrlenW(name) + 1) * sizeof(WCHAR) );
3509 RegCloseKey( key );
3510 break;
3511 default:
3513 break;
3514 }
3515 if (ret) SetLastError( ret );
3516 return !ret;
3517}
3518
3519struct USKEY
3520{
3521 HKEY HKCUstart; /* Start key in CU hive */
3522 HKEY HKCUkey; /* Opened key in CU hive */
3523 HKEY HKLMstart; /* Start key in LM hive */
3524 HKEY HKLMkey; /* Opened key in LM hive */
3526};
3527
3528LONG WINAPI SHRegCreateUSKeyA(LPCSTR path, REGSAM samDesired, HUSKEY relative_key, PHUSKEY new_uskey, DWORD flags)
3529{
3530 WCHAR *pathW;
3531 LONG ret;
3532
3533 TRACE("%s, %#lx, %p, %p, %#lx\n", debugstr_a(path), samDesired, relative_key, new_uskey, flags);
3534
3535 if (path)
3536 {
3537 INT len = MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0);
3538 pathW = heap_alloc(len * sizeof(WCHAR));
3539 if (!pathW)
3541 MultiByteToWideChar(CP_ACP, 0, path, -1, pathW, len);
3542 }
3543 else
3544 pathW = NULL;
3545
3546 ret = SHRegCreateUSKeyW(pathW, samDesired, relative_key, new_uskey, flags);
3547 HeapFree(GetProcessHeap(), 0, pathW);
3548 return ret;
3549}
3550
3552{
3553 HKEY newKey = 0;
3554
3555 RegOpenKeyExW(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
3556 return newKey;
3557}
3558
3560{
3561 struct USKEY *mihk = hUSKey;
3562 HKEY test = hUSKey;
3563
3564 if (test == HKEY_CLASSES_ROOT
3567 || test == HKEY_DYN_DATA
3570 || test == HKEY_USERS)
3571/* FIXME: need to define for Win2k, ME, XP
3572 * (test == HKEY_PERFORMANCE_TEXT) ||
3573 * (test == HKEY_PERFORMANCE_NLSTEXT) ||
3574 */
3575 {
3576 return test;
3577 }
3578
3579 return is_hkcu ? mihk->HKCUkey : mihk->HKLMkey;
3580}
3581
3582LONG WINAPI SHRegCreateUSKeyW(const WCHAR *path, REGSAM samDesired, HUSKEY relative_key, PHUSKEY new_uskey, DWORD flags)
3583{
3585 struct USKEY *ret_key;
3586
3587 TRACE("%s, %#lx, %p, %p, %#lx\n", debugstr_w(path), samDesired, relative_key, new_uskey, flags);
3588
3589 if (!new_uskey)
3591
3592 *new_uskey = NULL;
3593
3595 {
3596 FIXME("unsupported flags 0x%08lx\n", flags);
3597 return ERROR_SUCCESS;
3598 }
3599
3600 ret_key = heap_alloc_zero(sizeof(*ret_key));
3601 lstrcpynW(ret_key->path, path, ARRAY_SIZE(ret_key->path));
3602
3603 if (relative_key)
3604 {
3605 ret_key->HKCUstart = reg_duplicate_hkey(reg_get_hkey_from_huskey(relative_key, TRUE));
3607 }
3608 else
3609 {
3610 ret_key->HKCUstart = HKEY_CURRENT_USER;
3611 ret_key->HKLMstart = HKEY_LOCAL_MACHINE;
3612 }
3613
3615 {
3616 ret = RegCreateKeyExW(ret_key->HKCUstart, path, 0, NULL, 0, samDesired, NULL, &ret_key->HKCUkey, NULL);
3617 if (ret == ERROR_SUCCESS)
3618 *new_uskey = ret_key;
3619 else
3620 heap_free(ret_key);
3621 }
3622
3623 return ret;
3624}
3625
3627{
3628 struct USKEY *key = hUSKey;
3630
3631 if (!key)
3633
3634 if (key->HKCUkey)
3635 ret = RegCloseKey(key->HKCUkey);
3636 if (key->HKCUstart && key->HKCUstart != HKEY_CURRENT_USER)
3637 ret = RegCloseKey(key->HKCUstart);
3638 if (key->HKLMkey)
3639 ret = RegCloseKey(key->HKLMkey);
3640 if (key->HKLMstart && key->HKLMstart != HKEY_LOCAL_MACHINE)
3641 ret = RegCloseKey(key->HKLMstart);
3642
3643 heap_free(key);
3644 return ret;
3645}
3646
3648{
3649 FIXME("%p, %s, %#x\n", hUSKey, debugstr_a(value), flags);
3650 return ERROR_SUCCESS;
3651}
3652
3654{
3655 FIXME("%p, %s, %#x\n", hUSKey, debugstr_w(value), flags);
3656 return ERROR_SUCCESS;
3657}
3658
3660{
3661 FIXME("%p, %s, %#x\n", hUSKey, debugstr_a(value), flags);
3662 return ERROR_SUCCESS;
3663}
3664
3666{
3667 FIXME("%p, %s, %#x\n", hUSKey, debugstr_w(value), flags);
3668 return ERROR_SUCCESS;
3669}
3670
3671LONG WINAPI SHRegEnumUSValueA(HUSKEY hUSKey, DWORD index, char *value_name, DWORD *value_name_len, DWORD *type,
3672 void *data, DWORD *data_len, SHREGENUM_FLAGS flags)
3673{
3674 HKEY dokey;
3675
3676 TRACE("%p, %#lx, %p, %p, %p, %p, %p, %#x\n", hUSKey, index, value_name, value_name_len, type, data, data_len, flags);
3677
3678 if ((flags == SHREGENUM_HKCU || flags == SHREGENUM_DEFAULT) && (dokey = reg_get_hkey_from_huskey(hUSKey, TRUE)))
3679 return RegEnumValueA(dokey, index, value_name, value_name_len, NULL, type, data, data_len);
3680
3681 if ((flags == SHREGENUM_HKLM || flags == SHREGENUM_DEFAULT) && (dokey = reg_get_hkey_from_huskey(hUSKey, FALSE)))
3682 return RegEnumValueA(dokey, index, value_name, value_name_len, NULL, type, data, data_len);
3683
3684 FIXME("no support for SHREGENUM_BOTH\n");
3686}
3687
3688LONG WINAPI SHRegEnumUSValueW(HUSKEY hUSKey, DWORD index, WCHAR *value_name, DWORD *value_name_len, DWORD *type,
3689 void *data, DWORD *data_len, SHREGENUM_FLAGS flags)
3690{
3691 HKEY dokey;
3692
3693 TRACE("%p, %#lx, %p, %p, %p, %p, %p, %#x\n", hUSKey, index, value_name, value_name_len, type, data, data_len, flags);
3694
3695 if ((flags == SHREGENUM_HKCU || flags == SHREGENUM_DEFAULT) && (dokey = reg_get_hkey_from_huskey(hUSKey, TRUE)))
3696 return RegEnumValueW(dokey, index, value_name, value_name_len, NULL, type, data, data_len);
3697
3698 if ((flags == SHREGENUM_HKLM || flags == SHREGENUM_DEFAULT) && (dokey = reg_get_hkey_from_huskey(hUSKey, FALSE)))
3699 return RegEnumValueW(dokey, index, value_name, value_name_len, NULL, type, data, data_len);
3700
3701 FIXME("no support for SHREGENUM_BOTH\n");
3703}
3704
3706{
3707 HKEY dokey;
3708
3709 TRACE("%p, %ld, %p, %p(%ld), %d\n", hUSKey, index, name, name_len, *name_len, flags);
3710
3711 if ((flags == SHREGENUM_HKCU || flags == SHREGENUM_DEFAULT) && (dokey = reg_get_hkey_from_huskey(hUSKey, TRUE)))
3712 return RegEnumKeyExA(dokey, index, name, name_len, 0, 0, 0, 0);
3713
3714 if ((flags == SHREGENUM_HKLM || flags == SHREGENUM_DEFAULT) && (dokey = reg_get_hkey_from_huskey(hUSKey, FALSE)))
3715 return RegEnumKeyExA(dokey, index, name, name_len, 0, 0, 0, 0);
3716
3717 FIXME("no support for SHREGENUM_BOTH\n");
3719}
3720
3722{
3723 HKEY dokey;
3724
3725 TRACE("%p, %ld, %p, %p(%ld), %d\n", hUSKey, index, name, name_len, *name_len, flags);
3726
3727 if ((flags == SHREGENUM_HKCU || flags == SHREGENUM_DEFAULT) && (dokey = reg_get_hkey_from_huskey(hUSKey, TRUE)))
3728 return RegEnumKeyExW(dokey, index, name, name_len, 0, 0, 0, 0);
3729
3730 if ((flags == SHREGENUM_HKLM || flags == SHREGENUM_DEFAULT) && (dokey = reg_get_hkey_from_huskey(hUSKey, FALSE)))
3731 return RegEnumKeyExW(dokey, index, name, name_len, 0, 0, 0, 0);
3732
3733 FIXME("no support for SHREGENUM_BOTH\n");
3735}
3736
3737LONG WINAPI SHRegOpenUSKeyA(const char *path, REGSAM access_mask, HUSKEY relative_key, HUSKEY *uskey, BOOL ignore_hkcu)
3738{
3739 WCHAR pathW[MAX_PATH];
3740
3741 if (path)
3742 MultiByteToWideChar(CP_ACP, 0, path, -1, pathW, ARRAY_SIZE(pathW));
3743
3744 return SHRegOpenUSKeyW(path ? pathW : NULL, access_mask, relative_key, uskey, ignore_hkcu);
3745}
3746
3747LONG WINAPI SHRegOpenUSKeyW(const WCHAR *path, REGSAM access_mask, HUSKEY relative_key, HUSKEY *uskey, BOOL ignore_hkcu)
3748{
3749 LONG ret2, ret1 = ~ERROR_SUCCESS;
3750 struct USKEY *key;
3751
3752 TRACE("%s, %#lx, %p, %p, %d\n", debugstr_w(path), access_mask, relative_key, uskey, ignore_hkcu);
3753
3754 if (uskey)
3755 *uskey = NULL;
3756
3757 /* Create internal HUSKEY */
3758 key = heap_alloc_zero(sizeof(*key));
3760
3761 if (relative_key)
3762 {
3763 key->HKCUstart = reg_duplicate_hkey(reg_get_hkey_from_huskey(relative_key, TRUE));
3764 key->HKLMstart = reg_duplicate_hkey(reg_get_hkey_from_huskey(relative_key, FALSE));
3765
3766 /* FIXME: if either of these keys is NULL, create the start key from
3767 * the relative keys start+path
3768 */
3769 }
3770 else
3771 {
3772 key->HKCUstart = HKEY_CURRENT_USER;
3773 key->HKLMstart = HKEY_LOCAL_MACHINE;
3774 }
3775
3776 if (!ignore_hkcu)
3777 {
3778 ret1 = RegOpenKeyExW(key->HKCUstart, key->path, 0, access_mask, &key->HKCUkey);
3779 if (ret1)
3780 key->HKCUkey = 0;
3781 }
3782
3783 ret2 = RegOpenKeyExW(key->HKLMstart, key->path, 0, access_mask, &key->HKLMkey);
3784 if (ret2)
3785 key->HKLMkey = 0;
3786
3787 if (ret1 || ret2)
3788 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
3789
3790 if (ret1 && ret2)
3791 {
3792 /* Neither open succeeded: fail */
3794 return ret2;
3795 }
3796
3797 TRACE("HUSKEY=%p\n", key);
3798 if (uskey)
3799 *uskey = key;
3800
3801 return ERROR_SUCCESS;
3802}
3803
3804LONG WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, const char *value, DWORD type, void *data, DWORD data_len, DWORD flags)
3805{
3807
3808 if (value)
3810
3811 return SHRegWriteUSValueW(hUSKey, value ? valueW : NULL, type, data, data_len, flags);
3812}
3813
3815{
3816 struct USKEY *hKey = hUSKey;
3818 DWORD dummy;
3819
3820 TRACE("%p, %s, %ld, %p, %ld, %#lx\n", hUSKey, debugstr_w(value), type, data, data_len, flags);
3821
3822 __TRY
3823 {
3824 dummy = hKey->HKCUkey || hKey->HKLMkey;
3825 }
3827 {
3829 }
3830 __ENDTRY
3832
3834 {
3835 if (!hKey->HKCUkey)
3836 {
3837 /* Create the key */
3838 ret = RegCreateKeyExW(hKey->HKCUstart, hKey->path, 0, NULL, REG_OPTION_NON_VOLATILE,
3839 MAXIMUM_ALLOWED, NULL, &hKey->HKCUkey, NULL);
3840 TRACE("Creating HKCU key, ret = %ld\n", ret);
3841 if (ret && (flags & SHREGSET_FORCE_HKCU))
3842 {
3843 hKey->HKCUkey = 0;
3844 return ret;
3845 }
3846 }
3847
3848 if (!ret)
3849 {
3851 {
3852 /* Doesn't exist or we are forcing: Write value */
3853 ret = RegSetValueExW(hKey->HKCUkey, value, 0, type, data, data_len);
3854 TRACE("Writing HKCU value, ret = %ld\n", ret);
3855 }
3856 }
3857 }
3858
3860 {
3861 if (!hKey->HKLMkey)
3862 {
3863 /* Create the key */
3864 ret = RegCreateKeyExW(hKey->HKLMstart, hKey->path, 0, NULL, REG_OPTION_NON_VOLATILE,
3865 MAXIMUM_ALLOWED, NULL, &hKey->HKLMkey, NULL);
3866 TRACE("Creating HKLM key, ret = %ld\n", ret);
3867 if (ret && (flags & (SHREGSET_FORCE_HKLM)))
3868 {
3869 hKey->HKLMkey = 0;
3870 return ret;
3871 }
3872 }
3873
3874 if (!ret)
3875 {
3877 {
3878 /* Doesn't exist or we are forcing: Write value */
3879 ret = RegSetValueExW(hKey->HKLMkey, value, 0, type, data, data_len);
3880 TRACE("Writing HKLM value, ret = %ld\n", ret);
3881 }
3882 }
3883 }
3884
3885 return ret;
3886}
3887
3888LONG WINAPI SHRegSetUSValueA(const char *subkey, const char *value, DWORD type, void *data, DWORD data_len,
3889 DWORD flags)
3890{
3891 BOOL ignore_hkcu;
3892 HUSKEY hkey;
3893 LONG ret;
3894
3895 TRACE("%s, %s, %ld, %p, %ld, %#lx\n", debugstr_a(subkey), debugstr_a(value), type, data, data_len, flags);
3896
3897 if (!data)
3899
3900 ignore_hkcu = !(flags & SHREGSET_HKCU || flags & SHREGSET_FORCE_HKCU);
3901
3902 ret = SHRegOpenUSKeyA(subkey, KEY_ALL_ACCESS, 0, &hkey, ignore_hkcu);
3903 if (ret == ERROR_SUCCESS)
3904 {
3905 ret = SHRegWriteUSValueA(hkey, value, type, data, data_len, flags);
3906 SHRegCloseUSKey(hkey);
3907 }
3908
3909 return ret;
3910}
3911
3912LONG WINAPI SHRegSetUSValueW(const WCHAR *subkey, const WCHAR *value, DWORD type, void *data, DWORD data_len,
3913 DWORD flags)
3914{
3915 BOOL ignore_hkcu;
3916 HUSKEY hkey;
3917 LONG ret;
3918
3919 TRACE("%s, %s, %ld, %p, %ld, %#lx\n", debugstr_w(subkey), debugstr_w(value), type, data, data_len, flags);
3920
3921 if (!data)
3923
3924 ignore_hkcu = !(flags & SHREGSET_HKCU || flags & SHREGSET_FORCE_HKCU);
3925
3926 ret = SHRegOpenUSKeyW(subkey, KEY_ALL_ACCESS, 0, &hkey, ignore_hkcu);
3927 if (ret == ERROR_SUCCESS)
3928 {
3929 ret = SHRegWriteUSValueW(hkey, value, type, data, data_len, flags);
3930 SHRegCloseUSKey(hkey);
3931 }
3932
3933 return ret;
3934}
3935
3936LONG WINAPI SHRegQueryInfoUSKeyA(HUSKEY hUSKey, DWORD *subkeys, DWORD *max_subkey_len, DWORD *values,
3937 DWORD *max_value_name_len, SHREGENUM_FLAGS flags)
3938{
3939 HKEY dokey;
3940 LONG ret;
3941
3942 TRACE("%p, %p, %p, %p, %p, %#x\n", hUSKey, subkeys, max_subkey_len, values, max_value_name_len, flags);
3943
3944 if ((flags == SHREGENUM_HKCU || flags == SHREGENUM_DEFAULT) && (dokey = reg_get_hkey_from_huskey(hUSKey, TRUE)))
3945 {
3946 ret = RegQueryInfoKeyA(dokey, 0, 0, 0, subkeys, max_subkey_len, 0, values, max_value_name_len, 0, 0, 0);
3948 return ret;
3949 }
3950
3951 if ((flags == SHREGENUM_HKLM || flags == SHREGENUM_DEFAULT) && (dokey = reg_get_hkey_from_huskey(hUSKey, FALSE)))
3952 {
3953 return RegQueryInfoKeyA(dokey, 0, 0, 0, subkeys, max_subkey_len, 0, values, max_value_name_len, 0, 0, 0);
3954 }
3955
3957}
3958
3959LONG WINAPI SHRegQueryInfoUSKeyW(HUSKEY hUSKey, DWORD *subkeys, DWORD *max_subkey_len, DWORD *values,
3960 DWORD *max_value_name_len, SHREGENUM_FLAGS flags)
3961{
3962 HKEY dokey;
3963 LONG ret;
3964
3965 TRACE("%p, %p, %p, %p, %p, %#x\n", hUSKey, subkeys, max_subkey_len, values, max_value_name_len, flags);
3966
3967 if ((flags == SHREGENUM_HKCU || flags == SHREGENUM_DEFAULT) && (dokey = reg_get_hkey_from_huskey(hUSKey, TRUE)))
3968 {
3969 ret = RegQueryInfoKeyW(dokey, 0, 0, 0, subkeys, max_subkey_len, 0, values, max_value_name_len, 0, 0, 0);
3971 return ret;
3972 }
3973
3974 if ((flags == SHREGENUM_HKLM || flags == SHREGENUM_DEFAULT) && (dokey = reg_get_hkey_from_huskey(hUSKey, FALSE)))
3975 {
3976 return RegQueryInfoKeyW(dokey, 0, 0, 0, subkeys, max_subkey_len, 0, values, max_value_name_len, 0, 0, 0);
3977 }
3978
3980}
3981
3982LONG WINAPI SHRegQueryUSValueA(HUSKEY hUSKey, const char *value, DWORD *type, void *data, DWORD *data_len,
3983 BOOL ignore_hkcu, void *default_data, DWORD default_data_len)
3984{
3985 LONG ret = ~ERROR_SUCCESS;
3986 DWORD move_len;
3987 HKEY dokey;
3988
3989 /* If user wants HKCU, and it exists, then try it */
3990 if (!ignore_hkcu && (dokey = reg_get_hkey_from_huskey(hUSKey, TRUE)))
3991 {
3992 ret = RegQueryValueExA(dokey, value, 0, type, data, data_len);
3993 TRACE("HKCU RegQueryValue returned %ld\n", ret);
3994 }
3995
3996 /* If HKCU did not work and HKLM exists, then try it */
3997 if ((ret != ERROR_SUCCESS) && (dokey = reg_get_hkey_from_huskey(hUSKey, FALSE)))
3998 {
3999 ret = RegQueryValueExA(dokey, value, 0, type, data, data_len);
4000 TRACE("HKLM RegQueryValue returned %ld\n", ret);
4001 }
4002
4003 /* If neither worked, and default data exists, then use it */
4004 if (ret != ERROR_SUCCESS)
4005 {
4006 if (default_data && default_data_len)
4007 {
4008 move_len = default_data_len >= *data_len ? *data_len : default_data_len;
4009 memmove(data, default_data, move_len);
4010 *data_len = move_len;
4011 TRACE("setting default data\n");
4013 }
4014 }
4015
4016 return ret;
4017}
4018
4019LONG WINAPI SHRegQueryUSValueW(HUSKEY hUSKey, const WCHAR *value, DWORD *type, void *data, DWORD *data_len,
4020 BOOL ignore_hkcu, void *default_data, DWORD default_data_len)
4021{
4022 LONG ret = ~ERROR_SUCCESS;
4023 DWORD move_len;
4024 HKEY dokey;
4025
4026 /* If user wants HKCU, and it exists, then try it */
4027 if (!ignore_hkcu && (dokey = reg_get_hkey_from_huskey(hUSKey, TRUE)))
4028 {
4029 ret = RegQueryValueExW(dokey, value, 0, type, data, data_len);
4030 TRACE("HKCU RegQueryValue returned %ld\n", ret);
4031 }
4032
4033 /* If HKCU did not work and HKLM exists, then try it */
4034 if ((ret != ERROR_SUCCESS) && (dokey = reg_get_hkey_from_huskey(hUSKey, FALSE)))
4035 {
4036 ret = RegQueryValueExW(dokey, value, 0, type, data, data_len);
4037 TRACE("HKLM RegQueryValue returned %ld\n", ret);
4038 }
4039
4040 /* If neither worked, and default data exists, then use it */
4041 if (ret != ERROR_SUCCESS)
4042 {
4043 if (default_data && default_data_len)
4044 {
4045 move_len = default_data_len >= *data_len ? *data_len : default_data_len;
4046 memmove(data, default_data, move_len);
4047 *data_len = move_len;
4048 TRACE("setting default data\n");
4050 }
4051 }
4052
4053 return ret;
4054}
4055
4056LONG WINAPI SHRegGetUSValueA(const char *subkey, const char *value, DWORD *type, void *data, DWORD *data_len,
4057 BOOL ignore_hkcu, void *default_data, DWORD default_data_len)
4058{
4059 HUSKEY myhuskey;
4060 LONG ret;
4061
4062 if (!data || !data_len)
4063 return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
4064
4065 TRACE("%s, %s, %ld\n", debugstr_a(subkey), debugstr_a(value), *data_len);
4066
4067 ret = SHRegOpenUSKeyA(subkey, KEY_QUERY_VALUE, 0, &myhuskey, ignore_hkcu);
4068 if (!ret)
4069 {
4070 ret = SHRegQueryUSValueA(myhuskey, value, type, data, data_len, ignore_hkcu, default_data, default_data_len);
4071 SHRegCloseUSKey(myhuskey);
4072 }
4073
4074 return ret;
4075}
4076
4077LONG WINAPI SHRegGetUSValueW(const WCHAR *subkey, const WCHAR *value, DWORD *type, void *data, DWORD *data_len,
4078 BOOL ignore_hkcu, void *default_data, DWORD default_data_len)
4079{
4080 HUSKEY myhuskey;
4081 LONG ret;
4082
4083 if (!data || !data_len)
4084 return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
4085
4086 TRACE("%s, %s, %ld\n", debugstr_w(subkey), debugstr_w(value), *data_len);
4087
4088 ret = SHRegOpenUSKeyW(subkey, KEY_QUERY_VALUE, 0, &myhuskey, ignore_hkcu);
4089 if (!ret)
4090 {
4091 ret = SHRegQueryUSValueW(myhuskey, value, type, data, data_len, ignore_hkcu, default_data, default_data_len);
4092 SHRegCloseUSKey(myhuskey);
4093 }
4094
4095 return ret;
4096}
4097
4098BOOL WINAPI SHRegGetBoolUSValueA(const char *subkey, const char *value, BOOL ignore_hkcu, BOOL default_value)
4099{
4100 BOOL ret = default_value;
4102 char data[10];
4103
4104 TRACE("%s, %s, %d\n", debugstr_a(subkey), debugstr_a(value), ignore_hkcu);
4105
4106 datalen = ARRAY_SIZE(data) - 1;
4107 if (!SHRegGetUSValueA(subkey, value, &type, data, &datalen, ignore_hkcu, 0, 0))
4108 {
4109 switch (type)
4110 {
4111 case REG_SZ:
4112 data[9] = '\0';
4113 if (!lstrcmpiA(data, "YES") || !lstrcmpiA(data, "TRUE"))
4114 ret = TRUE;
4115 else if (!lstrcmpiA(data, "NO") || !lstrcmpiA(data, "FALSE"))
4116 ret = FALSE;
4117 break;
4118 case REG_DWORD:
4119 ret = *(DWORD *)data != 0;
4120 break;
4121 case REG_BINARY:
4122 if (datalen == 1)
4123 {
4124 ret = !!data[0];
4125 break;
4126 }
4127 default:
4128 FIXME("Unsupported registry data type %ld\n", type);
4129 ret = FALSE;
4130 }
4131 TRACE("got value (type=%ld), returning %d\n", type, ret);
4132 }
4133 else
4134 TRACE("returning default value %d\n", ret);
4135
4136 return ret;
4137}
4138
4139BOOL WINAPI SHRegGetBoolUSValueW(const WCHAR *subkey, const WCHAR *value, BOOL ignore_hkcu, BOOL default_value)
4140{
4141 BOOL ret = default_value;
4143 WCHAR data[10];
4144
4145 TRACE("%s, %s, %d\n", debugstr_w(subkey), debugstr_w(value), ignore_hkcu);
4146
4147 datalen = (ARRAY_SIZE(data) - 1) * sizeof(WCHAR);
4148 if (!SHRegGetUSValueW(subkey, value, &type, data, &datalen, ignore_hkcu, 0, 0))
4149 {
4150 switch (type)
4151 {
4152 case REG_SZ:
4153 data[9] = '\0';
4154 if (!lstrcmpiW(data, L"yes") || !lstrcmpiW(data, L"true"))
4155 ret = TRUE;
4156 else if (!lstrcmpiW(data, L"no") || !lstrcmpiW(data, L"false"))
4157 ret = FALSE;
4158 break;
4159 case REG_DWORD:
4160 ret = *(DWORD *)data != 0;
4161 break;
4162 case REG_BINARY:
4163 if (datalen == 1)
4164 {
4165 ret = !!data[0];
4166 break;
4167 }
4168 default:
4169 FIXME("Unsupported registry data type %ld\n", type);
4170 ret = FALSE;
4171 }
4172 TRACE("got value (type=%ld), returning %d\n", type, ret);
4173 }
4174 else
4175 TRACE("returning default value %d\n", ret);
4176
4177 return ret;
4178}
@ ObjectNameInformation
Definition: DriverTester.h:55
NTSTATUS NtQueryObject(IN HANDLE Handle, IN OBJECT_INFO_CLASS ObjectInformationClass, OUT PVOID ObjectInformation, IN ULONG ObjectInformationLength, OUT PULONG ReturnLength)
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
static struct sockaddr_in sa
Definition: adnsresfilter.c:69
static void * heap_alloc(size_t len)
Definition: appwiz.h:66
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
static void * heap_realloc(void *mem, size_t len)
Definition: appwiz.h:71
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
static REGSAM sam
Definition: query.c:143
LONG NTSTATUS
Definition: precomp.h:26
static const WCHAR nameW[]
Definition: main.c:49
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
#define index(s, c)
Definition: various.h:29
char * hostname
Definition: ftp.c:88
#define ARRAY_SIZE(A)
Definition: main.h:20
static void list_remove(struct list_entry *entry)
Definition: list.h:90
static void list_add_head(struct list_entry *head, struct list_entry *entry)
Definition: list.h:76
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define HandleToUlong(h)
Definition: basetsd.h:79
HANDLE HKEY
Definition: registry.h:26
#define RegCloseKey(hKey)
Definition: registry.h:49
struct _root root
Definition: bufpool.h:45
Definition: list.h:37
#define STATUS_INVALID_HANDLE
Definition: d3dkmdt.h:40
#define STATUS_PENDING
Definition: d3dkmdt.h:43
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
static PDB pdb
Definition: db.cpp:172
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define ERROR_MORE_DATA
Definition: dderror.h:13
#define ERROR_INVALID_FUNCTION
Definition: dderror.h:6
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
#define ERROR_SUCCESS
Definition: deptool.c:10
LPWSTR Name
Definition: desk.c:124
static LSTATUS(WINAPI *pRegDeleteTreeW)(HKEY
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
unsigned int idx
Definition: utils.c:41
LONG WINAPI RegCreateKeyExW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ DWORD Reserved, _In_opt_ LPWSTR lpClass, _In_ DWORD dwOptions, _In_ REGSAM samDesired, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _Out_ PHKEY phkResult, _Out_opt_ LPDWORD lpdwDisposition)
Definition: reg.c:1096
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
LONG WINAPI RegEnumKeyExW(_In_ HKEY hKey, _In_ DWORD dwIndex, _Out_ LPWSTR lpName, _Inout_ LPDWORD lpcbName, _Reserved_ LPDWORD lpReserved, _Out_opt_ LPWSTR lpClass, _Inout_opt_ LPDWORD lpcbClass, _Out_opt_ PFILETIME lpftLastWriteTime)
Definition: reg.c:2504
LONG WINAPI RegSetValueExW(_In_ HKEY hKey, _In_ LPCWSTR lpValueName, _In_ DWORD Reserved, _In_ DWORD dwType, _In_ CONST BYTE *lpData, _In_ DWORD cbData)
Definition: reg.c:4882
LONG WINAPI RegDeleteValueW(HKEY hKey, LPCWSTR lpValueName)
Definition: reg.c:2330
LONG WINAPI RegQueryInfoKeyW(HKEY hKey, LPWSTR lpClass, LPDWORD lpcClass, LPDWORD lpReserved, LPDWORD lpcSubKeys, LPDWORD lpcMaxSubKeyLen, LPDWORD lpcMaxClassLen, LPDWORD lpcValues, LPDWORD lpcMaxValueNameLen, LPDWORD lpcMaxValueLen, LPDWORD lpcbSecurityDescriptor, PFILETIME lpftLastWriteTime)
Definition: reg.c:3662
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
BOOL WINAPI GetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, LPVOID TokenInformation, DWORD TokenInformationLength, PDWORD ReturnLength)
Definition: security.c:411
BOOL WINAPI ImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
Definition: security.c:1631
BOOL WINAPI OpenThreadToken(HANDLE ThreadHandle, DWORD DesiredAccess, BOOL OpenAsSelf, HANDLE *TokenHandle)
Definition: security.c:336
HMODULE hModule
Definition: animate.c:44
#define CloseHandle
Definition: compat.h:739
#define wcschr
Definition: compat.h:17
#define GetProcessHeap()
Definition: compat.h:736
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define wcsnicmp
Definition: compat.h:14
#define wcsrchr
Definition: compat.h:16
#define CP_ACP
Definition: compat.h:109
#define SetLastError(x)
Definition: compat.h:752
#define GetProcAddress(x, y)
Definition: compat.h:753
#define HeapAlloc
Definition: compat.h:733
#define __TRY
Definition: compat.h:80
#define FreeLibrary(x)
Definition: compat.h:748
#define GetCurrentProcess()
Definition: compat.h:759
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
#define TRACE_ON(x)
Definition: compat.h:75
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
#define __ENDTRY
Definition: compat.h:82
#define lstrcpyW
Definition: compat.h:749
#define WideCharToMultiByte
Definition: compat.h:111
#define MultiByteToWideChar
Definition: compat.h:110
#define LoadLibraryW(x)
Definition: compat.h:747
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
#define FILE_SHARE_READ
Definition: compat.h:136
#define __EXCEPT_PAGE_FAULT
Definition: compat.h:81
#define wcsicmp
Definition: compat.h:15
#define lstrcpynW
Definition: compat.h:738
#define lstrlenW
Definition: compat.h:750
static void cleanup(void)
Definition: main.c:1335
static const WCHAR valueW[]
Definition: object.c:48
DWORD WINAPI ExpandEnvironmentStringsA(IN LPCSTR lpSrc, IN LPSTR lpDst, IN DWORD nSize)
Definition: environ.c:399
DWORD WINAPI ExpandEnvironmentStringsW(IN LPCWSTR lpSrc, IN LPWSTR lpDst, IN DWORD nSize)
Definition: environ.c:519
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:652
DWORD WINAPI GetModuleFileNameW(HINSTANCE hModule, LPWSTR lpFilename, DWORD nSize)
Definition: loader.c:600
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
Definition: loader.c:288
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1106
VOID WINAPI GetSystemTimeAsFileTime(OUT PFILETIME lpFileTime)
Definition: time.c:128
VOID WINAPI GetSystemTime(OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:327
LCID WINAPI GetThreadLocale(void)
Definition: locale.c:2803
int WINAPI lstrcmpiW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4265
int WINAPI lstrcmpiA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4227
LONG WINAPI SHRegDeleteEmptyUSKeyW(HUSKEY hUSKey, const WCHAR *value, SHREGDEL_FLAGS flags)
Definition: registry.c:3653
LONG WINAPI SHRegDeleteUSValueA(HUSKEY hUSKey, const char *value, SHREGDEL_FLAGS flags)
Definition: registry.c:3659
static DWORD query_perf_data(const WCHAR *query, DWORD *type, void *data, DWORD *ret_size, BOOL unicode)
Definition: registry.c:1529
#define IS_OPTION_TRUE(ch)
Definition: registry.c:87
LSTATUS WINAPI RegEnumValueW(HKEY hkey, DWORD index, LPWSTR value, LPDWORD val_count, LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count)
Definition: registry.c:2167
static BOOL is_string(DWORD type)
Definition: registry.c:90
static HKEY get_perflib_key(HANDLE key)
Definition: registry.c:190
LSTATUS WINAPI RegDeleteValueA(HKEY hkey, LPCSTR name)
Definition: registry.c:2362
static HANDLE open_wow6432node(HANDLE key)
Definition: registry.c:156
NTSTATUS WINAPI RemapPredefinedHandleInternal(HKEY hkey, HKEY override)
Definition: registry.c:535
static void dump_mui_cache(void)
Definition: registry.c:2792
LONG WINAPI SHRegGetUSValueW(const WCHAR *subkey, const WCHAR *value, DWORD *type, void *data, DWORD *data_len, BOOL ignore_hkcu, void *default_data, DWORD default_data_len)
Definition: registry.c:4077
LONG WINAPI RegDeleteKeyValueW(HKEY hkey, LPCWSTR subkey, LPCWSTR name)
Definition: registry.c:2370
LONG WINAPI SHRegSetUSValueW(const WCHAR *subkey, const WCHAR *value, DWORD type, void *data, DWORD data_len, DWORD flags)
Definition: registry.c:3912
#define REG_MUI_CACHE_SIZE
Definition: registry.c:85
static BOOL is_classes_wow6432node(HKEY key)
Definition: registry.c:115
LONG WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, const char *value, DWORD type, void *data, DWORD data_len, DWORD flags)
Definition: registry.c:3804
LSTATUS WINAPI RegGetKeySecurity(HKEY hkey, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, LPDWORD lpcbSecurityDescriptor)
Definition: registry.c:2688
LONG WINAPI SHRegDeleteEmptyUSKeyA(HUSKEY hUSKey, const char *value, SHREGDEL_FLAGS flags)
Definition: registry.c:3647
static BOOL is_version_nt(void)
Definition: registry.c:96
LSTATUS WINAPI RegGetValueW(HKEY hKey, LPCWSTR pszSubKey, LPCWSTR pszValue, DWORD dwFlags, LPDWORD pdwType, PVOID pvData, LPDWORD pcbData)
Definition: registry.c:1923
static struct list reg_mui_cache
Definition: registry.c:83
LSTATUS WINAPI RegOpenCurrentUser(REGSAM access, PHKEY retkey)
Definition: registry.c:764
static BOOL is_classes_root(const UNICODE_STRING *name)
Definition: registry.c:107
static void reg_mui_cache_put(const WCHAR *file_name, UINT index, const WCHAR *buffer, INT size)
Definition: registry.c:2837
static BOOL is_perf_key(HKEY key)
Definition: registry.c:524
LSTATUS WINAPI RegLoadMUIStringW(HKEY hKey, LPCWSTR pwszValue, LPWSTR pwszBuffer, DWORD cbBuffer, LPDWORD pcbData, DWORD dwFlags, LPCWSTR pwszBaseDir)
Definition: registry.c:2973
LONG WINAPI RegDeleteKeyValueA(HKEY hkey, LPCSTR subkey, LPCSTR name)
Definition: registry.c:2394
LSTATUS WINAPI RegDeleteTreeA(HKEY hkey, const char *subkey)
Definition: registry.c:3152
LSTATUS WINAPI RegRestoreKeyW(HKEY hkey, LPCWSTR lpFile, DWORD dwFlags)
Definition: registry.c:2558
static HKEY reg_duplicate_hkey(HKEY hKey)
Definition: registry.c:3551
LONG WINAPI SHRegQueryInfoUSKeyA(HUSKEY hUSKey, DWORD *subkeys, DWORD *max_subkey_len, DWORD *values, DWORD *max_value_name_len, SHREGENUM_FLAGS flags)
Definition: registry.c:3936
LSTATUS WINAPI RegNotifyChangeKeyValue(HKEY hkey, BOOL fWatchSubTree, DWORD fdwNotifyFilter, HANDLE hEvent, BOOL fAsync)
Definition: registry.c:2740
LSTATUS WINAPI RegUnLoadKeyW(HKEY hkey, LPCWSTR lpSubKey)
Definition: registry.c:2604
#define MAX_SERVICE_NAME
Definition: registry.c:1527
static unsigned int reg_mui_cache_count
Definition: registry.c:84
static void free_mui_cache_entry(struct mui_cache_entry *ent)
Definition: registry.c:2802
LSTATUS WINAPI RegOpenUserClassesRoot(HANDLE hToken, DWORD dwOptions, REGSAM samDesired, PHKEY phkResult)
Definition: registry.c:2783
static const WCHAR *const root_key_names[]
Definition: registry.c:53
NTSTATUS WINAPI DisablePredefinedHandleTableInternal(HKEY hkey)
Definition: registry.c:564
static void * get_provider_entry(HKEY perf, HMODULE perflib, const char *name)
Definition: registry.c:1405
static NTSTATUS open_subkey(HKEY *subkey, HKEY root, UNICODE_STRING *name, DWORD options, ACCESS_MASK access)
Definition: registry.c:211
LONG WINAPI RegSetKeyValueW(HKEY hkey, LPCWSTR subkey, LPCWSTR name, DWORD type, const void *data, DWORD len)
Definition: registry.c:1312
static DWORD query_perf_names(DWORD *type, void *data, DWORD *ret_size, BOOL unicode)
Definition: registry.c:1355
LONG WINAPI SHRegQueryInfoUSKeyW(HUSKEY hUSKey, DWORD *subkeys, DWORD *max_subkey_len, DWORD *values, DWORD *max_value_name_len, SHREGENUM_FLAGS flags)
Definition: registry.c:3959
LONG WINAPI SHRegEnumUSKeyA(HUSKEY hUSKey, DWORD index, char *name, DWORD *name_len, SHREGENUM_FLAGS flags)
Definition: registry.c:3705
LSTATUS WINAPI RegEnumValueA(HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count, LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count)
Definition: registry.c:2244
#define HKEY_SPECIAL_ROOT_LAST
Definition: registry.c:51
LONG WINAPI SHRegGetUSValueA(const char *subkey, const char *value, DWORD *type, void *data, DWORD *data_len, BOOL ignore_hkcu, void *default_data, DWORD default_data_len)
Definition: registry.c:4056
BOOL WINAPI GetComputerNameExW(COMPUTER_NAME_FORMAT type, WCHAR *name, DWORD *len)
Definition: registry.c:3345
LSTATUS WINAPI DECLSPEC_HOTPATCH RegQueryValueExA(HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count)
Definition: registry.c:1753
LSTATUS WINAPI RegEnumKeyExA(HKEY hkey, DWORD index, LPSTR name, LPDWORD name_len, LPDWORD reserved, LPSTR class, LPDWORD class_len, FILETIME *ft)
Definition: registry.c:888
BOOL WINAPI DECLSPEC_HOTPATCH SetComputerNameW(const WCHAR *name)
Definition: registry.c:3430
LSTATUS WINAPI RegDeleteTreeW(HKEY hkey, const WCHAR *subkey)
Definition: registry.c:3083
LSTATUS WINAPI RegSetKeySecurity(HKEY hkey, SECURITY_INFORMATION SecurityInfo, PSECURITY_DESCRIPTOR pSecurityDesc)
Definition: registry.c:2650
LONG WINAPI SHRegOpenUSKeyA(const char *path, REGSAM access_mask, HUSKEY relative_key, HUSKEY *uskey, BOOL ignore_hkcu)
Definition: registry.c:3737
LONG WINAPI SHRegCreateUSKeyA(LPCSTR path, REGSAM samDesired, HUSKEY relative_key, PHUSKEY new_uskey, DWORD flags)
Definition: registry.c:3528
BOOL WINAPI DECLSPEC_HOTPATCH DnsHostnameToComputerNameExW(const WCHAR *hostname, WCHAR *computername, DWORD *size)
Definition: registry.c:3278
BOOL WINAPI DECLSPEC_HOTPATCH SetComputerNameExA(COMPUTER_NAME_FORMAT type, const char *name)
Definition: registry.c:3439
static HKEY get_special_root_hkey(HKEY hkey)
Definition: registry.c:503
static int reg_mui_cache_get(const WCHAR *file_name, UINT index, WCHAR **buffer)
Definition: registry.c:2810
BOOL WINAPI SHRegGetBoolUSValueA(const char *subkey, const char *value, BOOL ignore_hkcu, BOOL default_value)
Definition: registry.c:4098
BOOL WINAPI SHRegGetBoolUSValueW(const WCHAR *subkey, const WCHAR *value, BOOL ignore_hkcu, BOOL default_value)
Definition: registry.c:4139
LONG WINAPI SHRegEnumUSValueA(HUSKEY hUSKey, DWORD index, char *value_name, DWORD *value_name_len, DWORD *type, void *data, DWORD *data_len, SHREGENUM_FLAGS flags)
Definition: registry.c:3671
static BOOL load_provider(HKEY root, const WCHAR *name, struct perf_provider *provider)
Definition: registry.c:1421
#define HKEY_SPECIAL_ROOT_FIRST
Definition: registry.c:50
LONG WINAPI SHRegCloseUSKey(HUSKEY hUSKey)
Definition: registry.c:3626
LSTATUS WINAPI RegGetValueA(HKEY hKey, LPCSTR pszSubKey, LPCSTR pszValue, DWORD dwFlags, LPDWORD pdwType, PVOID pvData, LPDWORD pcbData)
Definition: registry.c:2038
LONG WINAPI SHRegSetUSValueA(const char *subkey, const char *value, DWORD type, void *data, DWORD data_len, DWORD flags)
Definition: registry.c:3888
LSTATUS WINAPI RegSaveKeyExW(HKEY hkey, LPCWSTR file, SECURITY_ATTRIBUTES *sa, DWORD flags)
Definition: registry.c:2498
static HKEY special_root_keys[ARRAY_SIZE(root_key_names)]
Definition: registry.c:64
LONG WINAPI SHRegEnumUSValueW(HUSKEY hUSKey, DWORD index, WCHAR *value_name, DWORD *value_name_len, DWORD *type, void *data, DWORD *data_len, SHREGENUM_FLAGS flags)
Definition: registry.c:3688
BOOL WINAPI DECLSPEC_HOTPATCH SetComputerNameExW(COMPUTER_NAME_FORMAT type, const WCHAR *name)
Definition: registry.c:3455
static DWORD collect_data(struct perf_provider *provider, const WCHAR *query, void **data, DWORD *size, DWORD *obj_count)
Definition: registry.c:1500
LONG WINAPI SHRegQueryUSValueW(HUSKEY hUSKey, const WCHAR *value, DWORD *type, void *data, DWORD *data_len, BOOL ignore_hkcu, void *default_data, DWORD default_data_len)
Definition: registry.c:4019
static HANDLE open_classes_root(void)
Definition: registry.c:173
LSTATUS WINAPI RegSaveKeyExA(HKEY hkey, LPCSTR file, SECURITY_ATTRIBUTES *sa, DWORD flags)
Definition: registry.c:2531
static LONG load_mui_string(const WCHAR *file_name, UINT res_id, WCHAR *buffer, INT max_chars, INT *req_chars, DWORD flags)
Definition: registry.c:2877
LSTATUS WINAPI RegCopyTreeW(HKEY hsrc, const WCHAR *subkey, HKEY hdst)
Definition: registry.c:3169
static NTSTATUS open_wow6432node_parent(HKEY *retkey, HKEY root, DWORD options, ACCESS_MASK access)
Definition: registry.c:267
static HKEY create_special_root_hkey(HKEY hkey, DWORD access)
Definition: registry.c:471
static DWORD query_perf_help(DWORD *type, void *data, DWORD *ret_size, BOOL unicode)
Definition: registry.c:1376
static BOOL cache_disabled[ARRAY_SIZE(root_key_names)]
Definition: registry.c:65
LONG WINAPI RegSetKeyValueA(HKEY hkey, LPCSTR subkey, LPCSTR name, DWORD type, const void *data, DWORD len)
Definition: registry.c:1334
LSTATUS WINAPI RegDeleteKeyExW(HKEY hkey, LPCWSTR name, REGSAM access, DWORD reserved)
Definition: registry.c:1163
static NTSTATUS create_key(HKEY *retkey, HKEY root, UNICODE_STRING name, ULONG options, ACCESS_MASK access, const UNICODE_STRING *class, PULONG dispos)
Definition: registry.c:412
LSTATUS WINAPI RegLoadKeyA(HKEY hkey, LPCSTR subkey, LPCSTR filename)
Definition: registry.c:2473
LONG WINAPI SHRegDeleteUSValueW(HUSKEY hUSKey, const WCHAR *value, SHREGDEL_FLAGS flags)
Definition: registry.c:3665
LSTATUS WINAPI RegLoadKeyW(HKEY hkey, LPCWSTR subkey, LPCWSTR filename)
Definition: registry.c:2437
LSTATUS WINAPI RegLoadAppKeyA(const char *file, HKEY *result, REGSAM sam, DWORD options, DWORD reserved)
Definition: registry.c:3246
LSTATUS WINAPI RegDeleteKeyExA(HKEY hkey, LPCSTR name, REGSAM access, DWORD reserved)
Definition: registry.c:1186
static CRITICAL_SECTION reg_mui_cs
Definition: registry.c:67
LSTATUS WINAPI RegQueryInfoKeyA(HKEY hkey, LPSTR class, LPDWORD class_len, LPDWORD reserved, LPDWORD subkeys, LPDWORD max_subkey, LPDWORD max_class, LPDWORD values, LPDWORD max_value, LPDWORD max_data, LPDWORD security, FILETIME *modif)
Definition: registry.c:1070
BOOL WINAPI GetComputerNameExA(COMPUTER_NAME_FORMAT type, char *name, DWORD *len)
Definition: registry.c:3308
LONG WINAPI SHRegOpenUSKeyW(const WCHAR *path, REGSAM access_mask, HUSKEY relative_key, HUSKEY *uskey, BOOL ignore_hkcu)
Definition: registry.c:3747
LONG WINAPI SHRegCreateUSKeyW(const WCHAR *path, REGSAM samDesired, HUSKEY relative_key, PHUSKEY new_uskey, DWORD flags)
Definition: registry.c:3582
LONG WINAPI SHRegQueryUSValueA(HUSKEY hUSKey, const char *value, DWORD *type, void *data, DWORD *data_len, BOOL ignore_hkcu, void *default_data, DWORD default_data_len)
Definition: registry.c:3982
LSTATUS WINAPI DECLSPEC_HOTPATCH RegOpenKeyExA(HKEY hkey, LPCSTR name, DWORD options, REGSAM access, PHKEY retkey)
Definition: registry.c:711
LSTATUS WINAPI RegRestoreKeyA(HKEY hkey, LPCSTR lpFile, DWORD dwFlags)
Definition: registry.c:2579
LSTATUS WINAPI DECLSPEC_HOTPATCH RegSetValueExA(HKEY hkey, LPCSTR name, DWORD reserved, DWORD type, const BYTE *data, DWORD count)
Definition: registry.c:1264
LSTATUS WINAPI DECLSPEC_HOTPATCH RegCreateKeyExA(HKEY hkey, LPCSTR name, DWORD reserved, LPSTR class, DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa, PHKEY retkey, LPDWORD dispos)
Definition: registry.c:629
LONG WINAPI SHRegEnumUSKeyW(HUSKEY hUSKey, DWORD index, WCHAR *name, DWORD *name_len, SHREGENUM_FLAGS flags)
Definition: registry.c:3721
LSTATUS WINAPI RegLoadMUIStringA(HKEY hKey, LPCSTR pszValue, LPSTR pszBuffer, DWORD cbBuffer, LPDWORD pcbData, DWORD dwFlags, LPCSTR pszBaseDir)
Definition: registry.c:3072
static void apply_restrictions(DWORD dwFlags, DWORD dwType, DWORD cbData, PLONG ret)
Definition: registry.c:1855
static CRITICAL_SECTION_DEBUG reg_mui_cs_debug
Definition: registry.c:68
LSTATUS WINAPI RegUnLoadKeyA(HKEY hkey, LPCSTR lpSubKey)
Definition: registry.c:2624
static HKEY reg_get_hkey_from_huskey(HUSKEY hUSKey, BOOL is_hkcu)
Definition: registry.c:3559
BOOL WINAPI DECLSPEC_HOTPATCH SetComputerNameA(const char *name)
Definition: registry.c:3414
static NTSTATUS create_subkey(HKEY *subkey, HKEY root, UNICODE_STRING *name, DWORD options, ACCESS_MASK access, const UNICODE_STRING *class, PULONG dispos)
Definition: registry.c:381
static BOOL is_wow6432node(const UNICODE_STRING *name)
Definition: registry.c:101
LSTATUS WINAPI RegFlushKey(HKEY hkey)
Definition: registry.c:2715
LONG WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, const WCHAR *value, DWORD type, void *data, DWORD data_len, DWORD flags)
Definition: registry.c:3814
LSTATUS WINAPI RegLoadAppKeyW(const WCHAR *file, HKEY *result, REGSAM sam, DWORD options, DWORD reserved)
Definition: registry.c:3261
BOOL WINAPI RevertToSelf(void)
Definition: security.c:855
INT WINAPI DECLSPEC_HOTPATCH LoadStringW(HINSTANCE instance, UINT resource_id, LPWSTR buffer, INT buflen)
Definition: string.c:1220
DWORD WINAPI GetVersion(void)
Definition: version.c:1458
#define RRF_NOEXPAND
Definition: driver.c:583
#define RRF_RT_REG_BINARY
Definition: driver.c:577
#define RRF_RT_REG_QWORD
Definition: driver.c:580
#define RRF_RT_REG_DWORD
Definition: driver.c:578
#define RRF_ZEROONFAILURE
Definition: driver.c:584
#define RRF_RT_REG_MULTI_SZ
Definition: driver.c:579
#define RRF_RT_REG_NONE
Definition: driver.c:574
#define RRF_RT_DWORD
Definition: driver.c:581
#define RRF_RT_REG_EXPAND_SZ
Definition: driver.c:576
#define RRF_RT_QWORD
Definition: driver.c:582
#define RRF_RT_REG_SZ
Definition: driver.c:575
static const WCHAR fileW[]
Definition: url.c:111
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
r reserved
Definition: btrfs.c:3006
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ SECURITY_INFORMATION SecurityInformation
Definition: fltkernel.h:1340
std::wstring STRING
Definition: fontsub.cpp:33
#define FILE_OVERWRITE_IF
Definition: from_kernel.h:58
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
FxAutoRegKey hKey
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint GLuint * names
Definition: glext.h:11545
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLuint index
Definition: glext.h:6031
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLboolean GLenum GLenum GLvoid * values
Definition: glext.h:5666
GLbitfield flags
Definition: glext.h:7161
GLuint GLint GLboolean GLint GLenum access
Definition: glext.h:7866
GLuint64EXT * result
Definition: glext.h:11304
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat token
Definition: glfuncs.h:210
static int reg
Definition: i386-dis.c:1290
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define OBJ_OPENLINK
Definition: winternl.h:230
NTSYSAPI NTSTATUS WINAPI NtOpenKeyEx(PHANDLE, ACCESS_MASK, const OBJECT_ATTRIBUTES *, ULONG)
@ KeyNameInformation
Definition: winternl.h:831
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)
NTSYSAPI NTSTATUS WINAPI RtlDosPathNameToNtPathName_U_WithStatus(PCWSTR, PUNICODE_STRING, PWSTR *, CURDIR *)
#define InterlockedCompareExchangePointer
Definition: interlocked.h:144
const char * filename
Definition: ioapi.h:137
#define NtCurrentTeb
uint32_t entry
Definition: isohybrid.c:63
int const JOCTET unsigned int datalen
Definition: jpeglib.h:1031
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_w
Definition: kernel32.h:32
#define wine_dbgstr_w
Definition: kernel32.h:34
BOOL is_wow64
Definition: main.c:38
static const BOOL is_win64
Definition: kernelbase.h:49
#define REG_SZ
Definition: layer.c:22
if(dx< 0)
Definition: linetemp.h:194
@ SecurityIdentification
Definition: lsa.idl:56
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
#define error(str)
Definition: mkdosfs.c:1605
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
static PVOID ptr
Definition: dispmode.c:27
static const WCHAR filenameW[]
Definition: amstream.c:41
static HANDLE hEvent
Definition: comm.c:54
static const struct access_res create[16]
Definition: package.c:7505
static HANDLE PIO_APC_ROUTINE PVOID PIO_STATUS_BLOCK io
Definition: file.c:100
static PIO_STATUS_BLOCK iosb
Definition: file.c:98
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
static ACCESS_MASK const OBJECT_ATTRIBUTES ULONG const UNICODE_STRING ULONG PULONG dispos
Definition: reg.c:132
static CHAR filenameA[MAX_PATH]
Definition: storage32.c:42
static LPCWSTR file_name
Definition: protocol.c:147
#define min(a, b)
Definition: monoChain.cc:55
DWORD SECURITY_INFORMATION
Definition: ms-dtyp.idl:311
unsigned int UINT
Definition: ndis.h:50
NTSYSAPI NTSTATUS NTAPI RtlOpenCurrentUser(_In_ ACCESS_MASK DesiredAccess, _Out_ PHANDLE KeyHandle)
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeStringFromAsciiz(_Out_ PUNICODE_STRING Destination, _In_ PCSZ Source)
NTSYSAPI BOOLEAN NTAPI RtlDosPathNameToNtPathName_U(_In_opt_z_ PCWSTR DosPathName, _Out_ PUNICODE_STRING NtPathName, _Out_opt_ PCWSTR *NtFileNamePart, _Out_opt_ PRTL_RELATIVE_NAME_U DirectoryInfo)
_Use_decl_annotations_ NTSTATUS NTAPI RtlUnicodeToMultiByteN(_Out_ PCHAR MbString, _In_ ULONG MbSize, _Out_opt_ PULONG ResultSize, _In_ PCWCH UnicodeString, _In_ ULONG UnicodeSize)
Definition: nlsboot.c:107
_Use_decl_annotations_ NTSTATUS NTAPI RtlUnicodeToMultiByteSize(_Out_ PULONG MbSize, _In_ PCWCH UnicodeString, _In_ ULONG UnicodeSize)
Definition: nlsboot.c:145
_Use_decl_annotations_ NTSTATUS NTAPI RtlMultiByteToUnicodeN(_Out_ PWCH UnicodeString, _In_ ULONG UnicodeSize, _Out_opt_ PULONG ResultSize, _In_ PCCH MbString, _In_ ULONG MbSize)
Definition: nlsboot.c:62
_Use_decl_annotations_ NTSTATUS NTAPI RtlMultiByteToUnicodeSize(_Out_ PULONG UnicodeSize, _In_ PCCH MbString, _In_ ULONG MbSize)
Definition: nlsboot.c:93
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define SYNCHRONIZE
Definition: nt_native.h:61
NTSYSAPI NTSTATUS NTAPI NtSetValueKey(IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName, IN ULONG TitleIndex OPTIONAL, IN ULONG Type, IN PVOID Data, IN ULONG DataSize)
Definition: ntapi.c:859
@ KeyNodeInformation
Definition: nt_native.h:1132
@ KeyFullInformation
Definition: nt_native.h:1133
#define REG_BINARY
Definition: nt_native.h:1496
#define REG_OPTION_OPEN_LINK
Definition: nt_native.h:1070
@ KeyValuePartialInformation
Definition: nt_native.h:1182
@ KeyValueFullInformation
Definition: nt_native.h:1181
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define KEY_ALL_ACCESS
Definition: nt_native.h:1041
#define KEY_READ
Definition: nt_native.h:1023
NTSYSAPI NTSTATUS NTAPI NtDeleteValueKey(IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName)
Definition: ntapi.c:1014
#define REG_OPTION_CREATE_LINK
Definition: nt_native.h:1063
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI NTSTATUS NTAPI NtQueryValueKey(IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName, IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, IN PVOID KeyValueInformation, IN ULONG Length, IN PULONG ResultLength)
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
#define REG_MULTI_SZ
Definition: nt_native.h:1501
NTSYSAPI NTSTATUS NTAPI NtEnumerateKey(IN HANDLE KeyHandle, IN ULONG Index, IN KEY_INFORMATION_CLASS KeyInformationClass, IN PVOID KeyInformation, IN ULONG Length, IN PULONG ResultLength)
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
#define DELETE
Definition: nt_native.h:57
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define KEY_WRITE
Definition: nt_native.h:1031
#define REG_OPENED_EXISTING_KEY
Definition: nt_native.h:1085
#define REG_NONE
Definition: nt_native.h:1492
NTSTATUS NTAPI NtCreateFile(OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize OPTIONAL, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG CreateDisposition, IN ULONG CreateOptions, IN PVOID EaBuffer OPTIONAL, IN ULONG EaLength)
#define GENERIC_WRITE
Definition: nt_native.h:90
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
NTSYSAPI VOID NTAPI RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString)
#define MAXIMUM_ALLOWED
Definition: nt_native.h:83
#define KEY_SET_VALUE
Definition: nt_native.h:1017
NTSTATUS NTAPI NtUnloadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes)
Definition: ntapi.c:1789
NTSTATUS NTAPI NtDeleteKey(IN HANDLE KeyHandle)
Definition: ntapi.c:408
NTSTATUS NTAPI NtNotifyChangeKey(IN HANDLE KeyHandle, IN HANDLE Event, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG CompletionFilter, IN BOOLEAN WatchTree, OUT PVOID Buffer, IN ULONG Length, IN BOOLEAN Asynchronous)
Definition: ntapi.c:1290
NTSTATUS NTAPI NtCreateKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG TitleIndex, IN PUNICODE_STRING Class OPTIONAL, IN ULONG CreateOptions, OUT PULONG Disposition OPTIONAL)
Definition: ntapi.c:240
NTSTATUS NTAPI NtFlushKey(IN HANDLE KeyHandle)
Definition: ntapi.c:1085
NTSTATUS NTAPI NtSaveKey(IN HANDLE KeyHandle, IN HANDLE FileHandle)
Definition: ntapi.c:1634
NTSTATUS NTAPI NtEnumerateValueKey(IN HANDLE KeyHandle, IN ULONG Index, IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, OUT PVOID KeyValueInformation, IN ULONG Length, OUT PULONG ResultLength)
Definition: ntapi.c:542
NTSTATUS NTAPI NtLoadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes, IN POBJECT_ATTRIBUTES FileObjectAttributes)
Definition: ntapi.c:1129
NTSTATUS NTAPI NtQueryKey(IN HANDLE KeyHandle, IN KEY_INFORMATION_CLASS KeyInformationClass, OUT PVOID KeyInformation, IN ULONG Length, OUT PULONG ResultLength)
Definition: ntapi.c:632
NTSYSAPI NTSTATUS NTAPI RtlConvertSidToUnicodeString(OUT PUNICODE_STRING DestinationString, IN PVOID Sid, IN BOOLEAN AllocateDestinationString)
NTSTATUS NTAPI NtQueryPerformanceCounter(OUT PLARGE_INTEGER PerformanceCounter, OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL)
Definition: profile.c:278
#define STATUS_OBJECT_PATH_INVALID
Definition: ntstatus.h:293
#define STATUS_PREDEFINED_HANDLE
Definition: ntstatus.h:136
NTSTATUS NTAPI NtDuplicateObject(IN HANDLE SourceProcessHandle, IN HANDLE SourceHandle, IN HANDLE TargetProcessHandle OPTIONAL, OUT PHANDLE TargetHandle OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG HandleAttributes, IN ULONG Options)
Definition: obhandle.c:3410
NTSTATUS NTAPI NtQuerySecurityObject(IN HANDLE Handle, IN SECURITY_INFORMATION SecurityInformation, OUT PSECURITY_DESCRIPTOR SecurityDescriptor, IN ULONG Length, OUT PULONG ResultLength)
Definition: obsecure.c:803
long LONG
Definition: pedump.c:60
#define err(...)
#define open_key(r, p, s, k)
Definition: reg_test.h:49
#define test
Definition: rosglue.h:37
#define wine_dbgstr_wn
Definition: testlist.c:2
const WCHAR * str
#define REG_QWORD
Definition: sdbapi.c:597
#define REG_DWORD
Definition: sdbapi.c:596
#define offsetof(TYPE, MEMBER)
_Check_return_ long __cdecl wcstol(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
DWORD LCID
Definition: nls.h:13
#define DECLSPEC_HOTPATCH
Definition: config.h:9
const char int int int static __inline const char * wine_dbgstr_a(const char *s)
Definition: debug.h:187
static void * heap_calloc(SIZE_T count, SIZE_T size)
Definition: heap.h:49
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
__WINE_SERVER_LIST_INLINE struct list * list_prev(const struct list *list, const struct list *elem)
Definition: list.h:123
__WINE_SERVER_LIST_INLINE struct list * list_tail(const struct list *list)
Definition: list.h:137
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR SecurityDescriptor)
#define SHREGSET_HKCU
Definition: shlwapi.h:320
SHREGENUM_FLAGS
Definition: shlwapi.h:313
@ SHREGENUM_HKCU
Definition: shlwapi.h:315
@ SHREGENUM_DEFAULT
Definition: shlwapi.h:314
@ SHREGENUM_HKLM
Definition: shlwapi.h:316
#define SHREGSET_HKLM
Definition: shlwapi.h:322
#define SHREGSET_FORCE_HKLM
Definition: shlwapi.h:323
#define SHREGSET_FORCE_HKCU
Definition: shlwapi.h:321
SHREGDEL_FLAGS
Definition: shlwapi.h:305
#define TRACE(s)
Definition: solgame.cpp:4
DWORD dwOptions
Definition: solitaire.cpp:25
HKEY HKCUstart
Definition: registry.c:3521
HKEY HKLMstart
Definition: registry.c:3523
WCHAR path[MAX_PATH]
Definition: registry.c:3525
HKEY HKLMkey
Definition: registry.c:3524
HKEY HKCUkey
Definition: registry.c:3522
LIST_ENTRY ProcessLocksList
Definition: winbase.h:918
HANDLE RootDirectory
Definition: umtypes.h:184
PVOID SecurityQualityOfService
Definition: umtypes.h:188
PUNICODE_STRING ObjectName
Definition: umtypes.h:185
PVOID SecurityDescriptor
Definition: umtypes.h:187
Definition: cookie.c:202
Definition: cookie.c:42
Definition: fci.c:127
Definition: copy.c:22
WCHAR * path
Definition: copy.c:26
Definition: registry.c:76
struct list entry
Definition: registry.c:77
WCHAR * text
Definition: registry.c:81
LCID locale
Definition: registry.c:80
DWORD index
Definition: registry.c:79
WCHAR * file_name
Definition: registry.c:78
Definition: name.c:39
PM_OPEN_PROC * pOpen
Definition: registry.c:1400
WCHAR linkage[MAX_PATH]
Definition: registry.c:1398
HMODULE perflib
Definition: registry.c:1397
PM_CLOSE_PROC * pClose
Definition: registry.c:1401
PM_COLLECT_PROC * pCollect
Definition: registry.c:1402
WCHAR objects[MAX_PATH]
Definition: registry.c:1399
Definition: ps.c:97
#define max(a, b)
Definition: svc.c:63
#define LIST_INIT(head)
Definition: queue.h:197
#define LIST_ENTRY(type)
Definition: queue.h:175
#define LONG_PTR
Definition: treelist.c:79
#define DWORD_PTR
Definition: treelist.c:76
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char * LPBYTE
Definition: typedefs.h:53
uint32_t * LPDWORD
Definition: typedefs.h:59
int32_t INT
Definition: typedefs.h:58
uint32_t ULONG_PTR
Definition: typedefs.h:65
int32_t * PLONG
Definition: typedefs.h:58
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
Definition: pdh_main.c:96
static const WCHAR classW[]
Definition: lex.c:40
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
#define ZeroMemory
Definition: winbase.h:1753
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
HANDLE WINAPI GetCurrentThread(void)
Definition: proc.c:1148
#define LOAD_LIBRARY_AS_IMAGE_RESOURCE
Definition: winbase.h:380
#define LOAD_LIBRARY_AS_DATAFILE
Definition: winbase.h:375
#define CopyMemory
Definition: winbase.h:1751
#define MAX_COMPUTERNAME_LENGTH
Definition: winbase.h:276
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
_In_ DWORD _Out_writes_bytes_to_opt_ pcbData void _Inout_ DWORD * pcbData
Definition: wincrypt.h:4950
_In_ ULONG _In_opt_ PVOID pvData
Definition: winddi.h:3749
LONG_PTR LRESULT
Definition: windef.h:209
#define WINAPI
Definition: msvc.h:6
#define ERROR_UNSUPPORTED_TYPE
Definition: winerror.h:988
#define ERROR_BADKEY
Definition: winerror.h:589
#define ERROR_DATATYPE_MISMATCH
Definition: winerror.h:987
#define ERROR_NOACCESS
Definition: winerror.h:578
#define ERROR_INVALID_DATA
Definition: winerror.h:116
#define ERROR_NOT_FOUND
Definition: winerror.h:690
#define PERF_DATA_REVISION
Definition: winperf.h:12
#define PERF_DATA_VERSION
Definition: winperf.h:11
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define HKEY_CURRENT_CONFIG
Definition: winreg.h:15
#define HKEY_DYN_DATA
Definition: winreg.h:16
#define HKEY_CURRENT_USER
Definition: winreg.h:11
#define HKEY_PERFORMANCE_TEXT
Definition: winreg.h:17
#define RRF_RT_ANY
Definition: winreg.h:64
ACCESS_MASK REGSAM
Definition: winreg.h:69
#define HKEY_PERFORMANCE_NLSTEXT
Definition: winreg.h:18
#define HKEY_PERFORMANCE_DATA
Definition: winreg.h:14
#define HKEY_CLASSES_ROOT
Definition: winreg.h:10
#define HKEY_USERS
Definition: winreg.h:13
#define KEY_WOW64_32KEY
Definition: cmtypes.h:45
#define KEY_WOW64_64KEY
Definition: cmtypes.h:46
#define DUPLICATE_SAME_ACCESS
#define DACL_SECURITY_INFORMATION
Definition: setypes.h:125
#define TOKEN_QUERY
Definition: setypes.h:940
#define OWNER_SECURITY_INFORMATION
Definition: setypes.h:123
@ TokenUser
Definition: setypes.h:978
#define GROUP_SECURITY_INFORMATION
Definition: setypes.h:124
#define SACL_SECURITY_INFORMATION
Definition: setypes.h:126
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
char CHAR
Definition: xmlstorage.h:175
unsigned char BYTE
Definition: xxhash.c:193