ReactOS 0.4.16-dev-122-g325d74c
hkcr.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/advapi32/reg/hkcr.c
5 * PURPOSE: Registry functions - HKEY_CLASSES_ROOT abstraction
6 * PROGRAMMER: Jerôme Gardou (jerome.gardou@reactos.org)
7 */
8
9#include <advapi32.h>
10
11#include <ndk/cmfuncs.h>
12#include <pseh/pseh2.h>
13
14#include "reg.h"
15
17
18static const UNICODE_STRING HKLM_ClassesPath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Software\\Classes");
19
20static
21BOOL
23{
25 ULONG total_size = sizeof(kvi);
27
28 ASSERT(!IsHKCRKey(hNormalKey));
30 &kvi, total_size, &total_size);
32}
33
34static
35LONG
37{
38 UNICODE_STRING InfoName;
39 PKEY_NAME_INFORMATION NameInformation;
40 ULONG InfoLength;
42
43 /* Get info length */
44 InfoLength = 0;
45 Status = NtQueryKey(hKey, KeyNameInformation, NULL, 0, &InfoLength);
47 {
48 ERR("NtQueryKey returned unexpected Status: 0x%08x\n", Status);
50 }
51
52 /* Get it for real */
53 NameInformation = RtlAllocateHeap(RtlGetProcessHeap(), 0, InfoLength);
54 if (NameInformation == NULL)
55 {
56 ERR("Failed to allocate %lu bytes\n", InfoLength);
58 }
59
60 Status = NtQueryKey(hKey, KeyNameInformation, NameInformation, InfoLength, &InfoLength);
61 if (!NT_SUCCESS(Status))
62 {
63 RtlFreeHeap(RtlGetProcessHeap(), 0, NameInformation);
64 ERR("NtQueryKey failed: 0x%08x\n", Status);
66 }
67
68 /* Make it a proper UNICODE_STRING */
69 InfoName.Length = NameInformation->NameLength;
70 InfoName.MaximumLength = NameInformation->NameLength;
71 InfoName.Buffer = NameInformation->Name;
72
74 if (!NT_SUCCESS(Status))
75 {
76 RtlFreeHeap(RtlGetProcessHeap(), 0, NameInformation);
77 ERR("RtlDuplicateUnicodeString failed: 0x%08x\n", Status);
79 }
80
81 RtlFreeHeap(RtlGetProcessHeap(), 0, NameInformation);
82
83 return ERROR_SUCCESS;
84}
85
86static
87LONG
90 _Out_ REGSAM* RegSam)
91{
93 OBJECT_BASIC_INFORMATION ObjectInfo;
94
95 Status = NtQueryObject(hKey, ObjectBasicInformation, &ObjectInfo, sizeof(ObjectInfo), NULL);
96 if (!NT_SUCCESS(Status))
97 {
98 ERR("NtQueryObject failed, Status %x08x\n", Status);
100 }
101
102 *RegSam = ObjectInfo.GrantedAccess;
103 return ERROR_SUCCESS;
104}
105
106/*
107 * Gets a HKLM key from an HKCU key.
108 */
109static
110LONG
112 _In_ HKEY hKey,
113 _Out_ HKEY* MachineKey,
114 _In_ BOOL MustCreate)
115{
119 REGSAM SamDesired;
120
121 /* Get the key name */
124 {
125 *MachineKey = hKey;
126 return ErrorCode;
127 }
128
129 /* See if we really need a conversion */
131 {
133 *MachineKey = hKey;
134 return ERROR_SUCCESS;
135 }
136
137 SubKeyName = KeyName.Buffer + 15; /* 15 == wcslen(L"\\Registry\\User\\") */
138 /* Skip the user token */
139 while (*SubKeyName++ != L'\\')
140 {
141 if (!*SubKeyName)
142 {
143 ERR("Key name %S is invalid!\n", KeyName.Buffer);
145 }
146 }
147
148 /* Use the same access mask than the original key */
149 ErrorCode = GetKeySam(hKey, &SamDesired);
151 {
153 *MachineKey = hKey;
154 return ErrorCode;
155 }
156
157 if (MustCreate)
158 {
162 0,
163 NULL,
164 0,
165 SamDesired,
166 NULL,
167 MachineKey,
168 NULL);
169 }
170 else
171 {
172 /* Open the key. */
176 0,
177 SamDesired,
178 MachineKey);
179 }
180
182
183 return ErrorCode;
184}
185
186/* Get the HKCU key (if it exists) from an HKCR key */
187static
188LONG
190 _In_ HKEY hKey,
191 _Out_ HKEY* PreferredKey)
192{
196 REGSAM SamDesired;
197
198 /* Get the key name */
201 {
202 *PreferredKey = hKey;
203 return ErrorCode;
204 }
205
206 /* See if we really need a conversion */
208 {
210 *PreferredKey = hKey;
211 return ERROR_SUCCESS;
212 }
213
214 /* 18 == wcslen(L"\\Registry\\Machine\\") */
215 SubKeyName = KeyName.Buffer + 18;
216
217 /* Use the same access mask than the original key */
218 ErrorCode = GetKeySam(hKey, &SamDesired);
220 {
222 *PreferredKey = hKey;
223 return ErrorCode;
224 }
225
226 /* Open the key. */
230 0,
231 SamDesired,
232 PreferredKey);
233
235
236 return ErrorCode;
237}
238
239static
240LONG
242 _In_ HKEY hKey,
243 _Out_opt_ LPDWORD lpSubKeys,
244 _Out_opt_ LPDWORD lpMaxSubKeyLen)
245{
246 LONG err = RegQueryInfoKeyW(hKey, NULL, NULL, NULL, lpSubKeys, lpMaxSubKeyLen,
247 NULL, NULL, NULL, NULL, NULL, NULL);
249 return err;
250
251 /* Windows RegEdit only uses KEY_ENUMERATE_SUB_KEYS when enumerating but
252 * KEY_QUERY_VALUE is required to get the info in EnumHKCRKey.
253 */
255 {
256 err = RegQueryInfoKeyW(hKey, NULL, NULL, NULL, lpSubKeys, lpMaxSubKeyLen,
257 NULL, NULL, NULL, NULL, NULL, NULL);
259 }
260 return err;
261}
262
263/* HKCR version of RegCreateKeyExW. */
264LONG
265WINAPI
267 _In_ HKEY hKey,
268 _In_ LPCWSTR lpSubKey,
270 _In_opt_ LPWSTR lpClass,
272 _In_ REGSAM samDesired,
273 _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
274 _Out_ PHKEY phkResult,
275 _Out_opt_ LPDWORD lpdwDisposition)
276{
278 HKEY QueriedKey, TestKey;
279
281
282 /* Remove the HKCR flag while we're working */
283 hKey = (HKEY)(((ULONG_PTR)hKey) & ~0x2);
284
285 ErrorCode = GetPreferredHKCRKey(hKey, &QueriedKey);
286
288 {
289 /* The current key doesn't exist on HKCU side, so we can only create it in HKLM */
291 hKey,
292 lpSubKey,
293 Reserved,
294 lpClass,
295 dwOptions,
296 samDesired,
297 lpSecurityAttributes,
298 phkResult,
299 lpdwDisposition);
301 MakeHKCRKey(phkResult);
302 return ErrorCode;
303 }
304
306 {
307 /* Somehow we failed for another reason (maybe deleted key or whatever) */
308 return ErrorCode;
309 }
310
311 /* See if the subkey already exists in HKCU. */
312 ErrorCode = RegOpenKeyExW(QueriedKey, lpSubKey, 0, READ_CONTROL, &TestKey);
314 {
316 {
317 /* Great. Close the test one and do the real create operation */
318 RegCloseKey(TestKey);
320 QueriedKey,
321 lpSubKey,
322 Reserved,
323 lpClass,
324 dwOptions,
325 samDesired,
326 lpSecurityAttributes,
327 phkResult,
328 lpdwDisposition);
330 MakeHKCRKey(phkResult);
331 }
332 if (QueriedKey != hKey)
333 RegCloseKey(QueriedKey);
334
335 return ERROR_SUCCESS;
336 }
337
338 if (QueriedKey != hKey)
339 RegCloseKey(QueriedKey);
340
341 /* So we must do the create operation in HKLM, creating the missing parent keys if needed. */
342 ErrorCode = GetFallbackHKCRKey(hKey, &QueriedKey, TRUE);
344 return ErrorCode;
345
346 /* Do the key creation */
348 QueriedKey,
349 lpSubKey,
350 Reserved,
351 lpClass,
352 dwOptions,
353 samDesired,
354 lpSecurityAttributes,
355 phkResult,
356 lpdwDisposition);
357
358 if (QueriedKey != hKey)
359 RegCloseKey(QueriedKey);
360
362 MakeHKCRKey(phkResult);
363
364 return ErrorCode;
365}
366
367/* Same as RegOpenKeyExW, but for HKEY_CLASSES_ROOT subkeys */
368LONG
369WINAPI
371 _In_ HKEY hKey,
372 _In_ LPCWSTR lpSubKey,
373 _In_ DWORD ulOptions,
374 _In_ REGSAM samDesired,
375 _In_ PHKEY phkResult)
376{
377 HKEY QueriedKey;
379
381
382 /* Remove the HKCR flag while we're working */
383 hKey = (HKEY)(((ULONG_PTR)hKey) & ~0x2);
384
385 ErrorCode = GetPreferredHKCRKey(hKey, &QueriedKey);
386
388 {
389 /* The key doesn't exist on HKCU side, no chance for a subkey */
390 ErrorCode = RegOpenKeyExW(hKey, lpSubKey, ulOptions, samDesired, phkResult);
392 MakeHKCRKey(phkResult);
393 return ErrorCode;
394 }
395
397 {
398 /* Somehow we failed for another reason (maybe deleted key or whatever) */
399 return ErrorCode;
400 }
401
402 /* Try on the HKCU side */
403 ErrorCode = RegOpenKeyExW(QueriedKey, lpSubKey, ulOptions, samDesired, phkResult);
405 MakeHKCRKey(phkResult);
406
407 /* Close it if we must */
408 if (QueriedKey != hKey)
409 {
410 RegCloseKey(QueriedKey);
411 }
412
413 /* Anything else than ERROR_FILE_NOT_FOUND means that we found it, even if it is with failures. */
415 return ErrorCode;
416
417 /* If we're here, we must open from HKLM key. */
418 ErrorCode = GetFallbackHKCRKey(hKey, &QueriedKey, FALSE);
420 {
421 /* Maybe the key doesn't exist in the HKLM view */
422 return ErrorCode;
423 }
424
425 ErrorCode = RegOpenKeyExW(QueriedKey, lpSubKey, ulOptions, samDesired, phkResult);
427 MakeHKCRKey(phkResult);
428
429 /* Close it if we must */
430 if (QueriedKey != hKey)
431 {
432 RegCloseKey(QueriedKey);
433 }
434
435 return ErrorCode;
436}
437
438/* HKCR version of RegDeleteKeyExW */
439LONG
440WINAPI
442 _In_ HKEY hKey,
443 _In_ LPCWSTR lpSubKey,
444 _In_ REGSAM RegSam,
446{
447 HKEY QueriedKey;
449
451
452 /* Remove the HKCR flag while we're working */
453 hKey = (HKEY)(((ULONG_PTR)hKey) & ~0x2);
454
455 ErrorCode = GetPreferredHKCRKey(hKey, &QueriedKey);
456
458 {
459 /* The key doesn't exist on HKCU side, no chance for a subkey */
460 return RegDeleteKeyExW(hKey, lpSubKey, RegSam, Reserved);
461 }
462
464 {
465 /* Somehow we failed for another reason (maybe deleted key or whatever) */
466 return ErrorCode;
467 }
468
469 ErrorCode = RegDeleteKeyExW(QueriedKey, lpSubKey, RegSam, Reserved);
470
471 /* Close it if we must */
472 if (QueriedKey != hKey)
473 {
474 /* The original key is on the machine view */
475 RegCloseKey(QueriedKey);
476 }
477
478 /* Anything else than ERROR_FILE_NOT_FOUND means that we found it, even if it is with failures. */
480 return ErrorCode;
481
482 /* If we're here, we must open from HKLM key. */
483 ErrorCode = GetFallbackHKCRKey(hKey, &QueriedKey, FALSE);
485 {
486 /* Maybe the key doesn't exist in the HKLM view */
487 return ErrorCode;
488 }
489
490 ErrorCode = RegDeleteKeyExW(QueriedKey, lpSubKey, RegSam, Reserved);
491
492 /* Close it if we must */
493 if (QueriedKey != hKey)
494 {
495 RegCloseKey(QueriedKey);
496 }
497
498 return ErrorCode;
499}
500
501/* HKCR version of RegDeleteValueA+W */
502LONG
503WINAPI
505 _In_ HKEY hKey,
507{
508 HKEY hActualKey;
510
512 /* Remove the HKCR flag while we're working */
513 hKey = (HKEY)(((ULONG_PTR)hKey) & ~0x2);
514
515 /* Does the HKCU key and value exist? */
516 ErrorCode = GetPreferredHKCRKey(hKey, &hActualKey);
518 {
519 if (!ValueExists(hActualKey, ValueName))
520 {
521 if (hActualKey != hKey)
522 {
523 RegCloseKey(hActualKey);
524 }
526 }
527 }
529 {
530 ErrorCode = GetFallbackHKCRKey(hKey, &hActualKey, FALSE);
531 }
532
534 {
537 }
538 if (hActualKey != hKey)
539 {
540 RegCloseKey(hActualKey);
541 }
542 return ErrorCode;
543}
544
545/* HKCR version of RegQueryValueExW */
546LONG
547WINAPI
549 _In_ HKEY hKey,
555{
556 HKEY QueriedKey;
558
560
561 /* Remove the HKCR flag while we're working */
562 hKey = (HKEY)(((ULONG_PTR)hKey) & ~0x2);
563
564 ErrorCode = GetPreferredHKCRKey(hKey, &QueriedKey);
565
567 {
568 /* The key doesn't exist on HKCU side, no chance for a value in it */
570 }
571
573 {
574 /* Somehow we failed for another reason (maybe deleted key or whatever) */
575 return ErrorCode;
576 }
577
579
580 /* Close it if we must */
581 if (QueriedKey != hKey)
582 {
583 /* The original key is on the machine view */
584 RegCloseKey(QueriedKey);
585 }
586
587 /* Anything else than ERROR_FILE_NOT_FOUND means that we found it, even if it is with failures. */
589 return ErrorCode;
590
591 /* If we're here, we must open from HKLM key. */
592 ErrorCode = GetFallbackHKCRKey(hKey, &QueriedKey, FALSE);
594 {
595 /* Maybe the key doesn't exist in the HKLM view */
596 return ErrorCode;
597 }
598
600
601 /* Close it if we must */
602 if (QueriedKey != hKey)
603 {
604 RegCloseKey(QueriedKey);
605 }
606
607 return ErrorCode;
608}
609
610/* HKCR version of RegSetValueExW */
611LONG
612WINAPI
614 _In_ HKEY hKey,
620{
621 HKEY QueriedKey;
623
625
626 /* Remove the HKCR flag while we're working */
627 hKey = (HKEY)(((ULONG_PTR)hKey) & ~0x2);
628
629 ErrorCode = GetPreferredHKCRKey(hKey, &QueriedKey);
630
632 {
633 /* The key doesn't exist on HKCU side, no chance to put a value in it */
635 }
636
638 {
639 /* Somehow we failed for another reason (maybe deleted key or whatever) */
640 return ErrorCode;
641 }
642
643 /* Check if the value already exists in the preferred key */
644 ErrorCode = RegQueryValueExW(QueriedKey, Name, NULL, NULL, NULL, NULL);
646 {
648 {
649 /* Yes, so we have the right to modify it */
651 }
652 if (QueriedKey != hKey)
653 RegCloseKey(QueriedKey);
654 return ErrorCode;
655 }
656 if (QueriedKey != hKey)
657 RegCloseKey(QueriedKey);
658
659 /* So we must set the value in the HKLM version */
660 ErrorCode = GetPreferredHKCRKey(hKey, &QueriedKey);
662 {
663 /* No choice: put this in HKCU */
665 }
666 else if (ErrorCode != ERROR_SUCCESS)
667 {
668 return ErrorCode;
669 }
670
672
673 if (QueriedKey != hKey)
674 RegCloseKey(QueriedKey);
675
676 return ErrorCode;
677}
678
679/* HKCR version of RegEnumKeyExW */
680LONG
681WINAPI
683 _In_ HKEY hKey,
684 _In_ DWORD dwIndex,
686 _Inout_ LPDWORD lpcbName,
687 _Reserved_ LPDWORD lpReserved,
688 _Out_opt_ LPWSTR lpClass,
689 _Inout_opt_ LPDWORD lpcbClass,
690 _Out_opt_ PFILETIME lpftLastWriteTime)
691{
692 HKEY PreferredKey, FallbackKey;
693 DWORD NumPreferredSubKeys;
694 DWORD MaxFallbackSubKeyLen;
695 DWORD FallbackIndex;
696 WCHAR* FallbackSubKeyName = NULL;
698
700
701 /* Remove the HKCR flag while we're working */
702 hKey = (HKEY)(((ULONG_PTR)hKey) & ~0x2);
703
704 /* Get the preferred key */
705 ErrorCode = GetPreferredHKCRKey(hKey, &PreferredKey);
707 {
709 {
710 /* Only the HKLM key exists */
711 return RegEnumKeyExW(
712 hKey,
713 dwIndex,
714 lpName,
715 lpcbName,
716 lpReserved,
717 lpClass,
718 lpcbClass,
719 lpftLastWriteTime);
720 }
721 return ErrorCode;
722 }
723
724 /* Get the fallback key */
725 ErrorCode = GetFallbackHKCRKey(hKey, &FallbackKey, FALSE);
727 {
728 if (PreferredKey != hKey)
729 RegCloseKey(PreferredKey);
731 {
732 /* Only the HKCU key exists */
733 return RegEnumKeyExW(
734 hKey,
735 dwIndex,
736 lpName,
737 lpcbName,
738 lpReserved,
739 lpClass,
740 lpcbClass,
741 lpftLastWriteTime);
742 }
743 return ErrorCode;
744 }
745
746 /* Get some info on the HKCU side */
747 ErrorCode = GetSubkeyInfoHelper(PreferredKey, &NumPreferredSubKeys, NULL);
749 goto Exit;
750
751 if (dwIndex < NumPreferredSubKeys)
752 {
753 /* HKCU side takes precedence */
755 PreferredKey,
756 dwIndex,
757 lpName,
758 lpcbName,
759 lpReserved,
760 lpClass,
761 lpcbClass,
762 lpftLastWriteTime);
763 goto Exit;
764 }
765
766 /* Here it gets tricky. We must enumerate the values from the HKLM side,
767 * without reporting those which are present on the HKCU side */
768
769 /* Squash out the indices from HKCU */
770 dwIndex -= NumPreferredSubKeys;
771
772 /* Get some info */
773 ErrorCode = GetSubkeyInfoHelper(FallbackKey, NULL, &MaxFallbackSubKeyLen);
775 {
776 ERR("Could not query info of key %p (Err: %d)\n", FallbackKey, ErrorCode);
777 goto Exit;
778 }
779
780 MaxFallbackSubKeyLen++;
781 TRACE("Maxfallbacksubkeylen: %d\n", MaxFallbackSubKeyLen);
782
783 /* Allocate our buffer */
784 FallbackSubKeyName = RtlAllocateHeap(
785 RtlGetProcessHeap(), 0, MaxFallbackSubKeyLen * sizeof(WCHAR));
786 if (!FallbackSubKeyName)
787 {
789 goto Exit;
790 }
791
792 /* We must begin at the very first subkey of the fallback key,
793 * and then see if we meet keys that already are in the preferred key.
794 * In that case, we must bump dwIndex, as otherwise we would enumerate a key we already
795 * saw in a previous call.
796 */
797 FallbackIndex = 0;
798 while (TRUE)
799 {
800 HKEY PreferredSubKey;
801 DWORD FallbackSubkeyLen = MaxFallbackSubKeyLen;
802
803 /* Try enumerating */
805 FallbackKey,
806 FallbackIndex,
807 FallbackSubKeyName,
808 &FallbackSubkeyLen,
809 NULL,
810 NULL,
811 NULL,
812 NULL);
814 {
816 ERR("Returning %d.\n", ErrorCode);
817 goto Exit;
818 }
819 FallbackSubKeyName[FallbackSubkeyLen] = L'\0';
820
821 /* See if there is such a value on HKCU side */
823 PreferredKey,
824 FallbackSubKeyName,
825 0,
827 &PreferredSubKey);
828
830 {
831 RegCloseKey(PreferredSubKey);
832 /* So we already enumerated it on HKCU side. */
833 dwIndex++;
834 }
836 {
837 ERR("Got error %d while querying for %s on HKCU side.\n", ErrorCode, FallbackSubKeyName);
838 goto Exit;
839 }
840
841 /* See if we caught up */
842 if (FallbackIndex == dwIndex)
843 break;
844
845 FallbackIndex++;
846 }
847
848 /* We can finally enumerate on the fallback side */
850 FallbackKey,
851 dwIndex,
852 lpName,
853 lpcbName,
854 lpReserved,
855 lpClass,
856 lpcbClass,
857 lpftLastWriteTime);
858
859Exit:
860 if (PreferredKey != hKey)
861 RegCloseKey(PreferredKey);
862 if (FallbackKey != hKey)
863 RegCloseKey(FallbackKey);
864 if (FallbackSubKeyName)
865 RtlFreeHeap(RtlGetProcessHeap(), 0, FallbackSubKeyName);
866
867 return ErrorCode;
868}
869
870/* HKCR version of RegEnumValueW */
871LONG
872WINAPI
874 _In_ HKEY hKey,
875 _In_ DWORD dwIndex,
877 _Inout_ PDWORD lpcbName,
878 _Reserved_ PDWORD lpReserved,
879 _Out_opt_ PDWORD lpdwType,
880 _Out_opt_ LPBYTE lpData,
881 _Inout_opt_ PDWORD lpcbData)
882{
883 HKEY PreferredKey, FallbackKey;
884 DWORD NumPreferredValues;
885 DWORD MaxFallbackValueNameLen;
886 DWORD FallbackIndex;
887 WCHAR* FallbackValueName = NULL;
889
891
892 /* Remove the HKCR flag while we're working */
893 hKey = (HKEY)(((ULONG_PTR)hKey) & ~0x2);
894
895 /* Get the preferred key */
896 ErrorCode = GetPreferredHKCRKey(hKey, &PreferredKey);
898 {
900 {
901 /* Only the HKLM key exists */
902 return RegEnumValueW(
903 hKey,
904 dwIndex,
905 lpName,
906 lpcbName,
907 lpReserved,
908 lpdwType,
909 lpData,
910 lpcbData);
911 }
912 return ErrorCode;
913 }
914
915 /* Get the fallback key */
916 ErrorCode = GetFallbackHKCRKey(hKey, &FallbackKey, FALSE);
918 {
919 if (PreferredKey != hKey)
920 RegCloseKey(PreferredKey);
922 {
923 /* Only the HKCU key exists */
924 return RegEnumValueW(
925 hKey,
926 dwIndex,
927 lpName,
928 lpcbName,
929 lpReserved,
930 lpdwType,
931 lpData,
932 lpcbData);
933 }
934 return ErrorCode;
935 }
936
937 /* Get some info on the HKCU side */
939 PreferredKey,
940 NULL,
941 NULL,
942 NULL,
943 NULL,
944 NULL,
945 NULL,
946 &NumPreferredValues,
947 NULL,
948 NULL,
949 NULL,
950 NULL);
952 goto Exit;
953
954 if (dwIndex < NumPreferredValues)
955 {
956 /* HKCU side takes precedence */
957 return RegEnumValueW(
958 PreferredKey,
959 dwIndex,
960 lpName,
961 lpcbName,
962 lpReserved,
963 lpdwType,
964 lpData,
965 lpcbData);
966 goto Exit;
967 }
968
969 /* Here it gets tricky. We must enumerate the values from the HKLM side,
970 * without reporting those which are present on the HKCU side */
971
972 /* Squash out the indices from HKCU */
973 dwIndex -= NumPreferredValues;
974
975 /* Get some info */
977 FallbackKey,
978 NULL,
979 NULL,
980 NULL,
981 NULL,
982 NULL,
983 NULL,
984 NULL,
985 &MaxFallbackValueNameLen,
986 NULL,
987 NULL,
988 NULL);
990 {
991 ERR("Could not query info of key %p (Err: %d)\n", FallbackKey, ErrorCode);
992 goto Exit;
993 }
994
995 MaxFallbackValueNameLen++;
996 TRACE("Maxfallbacksubkeylen: %d\n", MaxFallbackValueNameLen);
997
998 /* Allocate our buffer */
999 FallbackValueName = RtlAllocateHeap(
1000 RtlGetProcessHeap(), 0, MaxFallbackValueNameLen * sizeof(WCHAR));
1001 if (!FallbackValueName)
1002 {
1004 goto Exit;
1005 }
1006
1007 /* We must begin at the very first subkey of the fallback key,
1008 * and then see if we meet keys that already are in the preferred key.
1009 * In that case, we must bump dwIndex, as otherwise we would enumerate a key we already
1010 * saw in a previous call.
1011 */
1012 FallbackIndex = 0;
1013 while (TRUE)
1014 {
1015 DWORD FallbackValueNameLen = MaxFallbackValueNameLen;
1016
1017 /* Try enumerating */
1019 FallbackKey,
1020 FallbackIndex,
1021 FallbackValueName,
1022 &FallbackValueNameLen,
1023 NULL,
1024 NULL,
1025 NULL,
1026 NULL);
1027 if (ErrorCode != ERROR_SUCCESS)
1028 {
1030 ERR("Returning %d.\n", ErrorCode);
1031 goto Exit;
1032 }
1033 FallbackValueName[FallbackValueNameLen] = L'\0';
1034
1035 /* See if there is such a value on HKCU side */
1037 PreferredKey,
1038 FallbackValueName,
1039 NULL,
1040 NULL,
1041 NULL,
1042 NULL);
1043
1044 if (ErrorCode == ERROR_SUCCESS)
1045 {
1046 /* So we already enumerated it on HKCU side. */
1047 dwIndex++;
1048 }
1049 else if (ErrorCode != ERROR_FILE_NOT_FOUND)
1050 {
1051 ERR("Got error %d while querying for %s on HKCU side.\n", ErrorCode, FallbackValueName);
1052 goto Exit;
1053 }
1054
1055 /* See if we caught up */
1056 if (FallbackIndex == dwIndex)
1057 break;
1058
1059 FallbackIndex++;
1060 }
1061
1062 /* We can finally enumerate on the fallback side */
1064 FallbackKey,
1065 dwIndex,
1066 lpName,
1067 lpcbName,
1068 lpReserved,
1069 lpdwType,
1070 lpData,
1071 lpcbData);
1072
1073Exit:
1074 if (PreferredKey != hKey)
1075 RegCloseKey(PreferredKey);
1076 if (FallbackKey != hKey)
1077 RegCloseKey(FallbackKey);
1078 if (FallbackValueName)
1079 RtlFreeHeap(RtlGetProcessHeap(), 0, FallbackValueName);
1080
1081 return ErrorCode;
1082}
1083
1084/* HKCR version of RegQueryInfoKeyW */
1085LONG
1086WINAPI
1088 _In_ HKEY hKey,
1089 _Out_writes_to_opt_(*lpcchClass, *lpcchClass + 1) LPWSTR lpClass,
1090 _Inout_opt_ LPDWORD lpcchClass,
1091 _Reserved_ LPDWORD lpReserved,
1092 _Out_opt_ LPDWORD lpcSubKeys,
1093 _Out_opt_ LPDWORD lpcbMaxSubKeyLen,
1094 _Out_opt_ LPDWORD lpcbMaxClassLen,
1095 _Out_opt_ LPDWORD lpcValues,
1096 _Out_opt_ LPDWORD lpcbMaxValueNameLen,
1097 _Out_opt_ LPDWORD lpcbMaxValueLen,
1098 _Out_opt_ LPDWORD lpcbSecurityDescriptor,
1099 _Out_opt_ PFILETIME lpftLastWriteTime)
1100{
1101 HKEY PreferredKey, FallbackKey;
1102 LONG retval, err;
1103 DWORD OtherSubKeys = 0, OtherMaxSub = 0, OtherMaxClass = 0;
1104 DWORD OtherValues = 0, OtherMaxName = 0, OtherMaxVal = 0;
1105
1107
1108 /* Remove the HKCR flag while we're working */
1109 hKey = (HKEY)(((ULONG_PTR)hKey) & ~0x2);
1110
1111 retval = GetFallbackHKCRKey(hKey, &FallbackKey, FALSE);
1112 if (retval == ERROR_SUCCESS)
1113 {
1114 retval = RegQueryInfoKeyW(FallbackKey, lpClass, lpcchClass, lpReserved,
1115 &OtherSubKeys, &OtherMaxSub, &OtherMaxClass,
1116 &OtherValues, &OtherMaxName, &OtherMaxVal,
1117 lpcbSecurityDescriptor, lpftLastWriteTime);
1118 if (FallbackKey != hKey)
1119 RegCloseKey(FallbackKey);
1120 }
1121
1122 err = GetPreferredHKCRKey(hKey, &PreferredKey);
1123 if (err == ERROR_SUCCESS)
1124 {
1125 err = RegQueryInfoKeyW(PreferredKey, lpClass, lpcchClass, lpReserved,
1126 lpcSubKeys, lpcbMaxSubKeyLen, lpcbMaxClassLen,
1127 lpcValues, lpcbMaxValueNameLen, lpcbMaxValueLen,
1128 lpcbSecurityDescriptor, lpftLastWriteTime);
1129 if (PreferredKey != hKey)
1130 RegCloseKey(PreferredKey);
1131 }
1132
1133 if (lpcSubKeys)
1134 *lpcSubKeys = (err ? 0 : *lpcSubKeys) + OtherSubKeys;
1135 if (lpcValues)
1136 *lpcValues = (err ? 0 : *lpcValues) + OtherValues;
1137 if (lpcbMaxSubKeyLen)
1138 *lpcbMaxSubKeyLen = max((err ? 0 : *lpcbMaxSubKeyLen), OtherMaxSub);
1139 if (lpcbMaxClassLen)
1140 *lpcbMaxClassLen = max((err ? 0 : *lpcbMaxClassLen), OtherMaxClass);
1141 if (lpcbMaxValueNameLen)
1142 *lpcbMaxValueNameLen = max((err ? 0 : *lpcbMaxValueNameLen), OtherMaxName);
1143 if (lpcbMaxValueLen)
1144 *lpcbMaxValueLen = max((err ? 0 : *lpcbMaxValueLen), OtherMaxVal);
1145
1146 return (err == ERROR_SUCCESS) ? ERROR_SUCCESS : retval;
1147}
@ ObjectBasicInformation
Definition: DriverTester.h:54
NTSTATUS NtQueryObject(IN HANDLE Handle, IN OBJECT_INFO_CLASS ObjectInformationClass, OUT PVOID ObjectInformation, IN ULONG ObjectInformationLength, OUT PULONG ReturnLength)
Type
Definition: Type.h:7
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
LONG NTSTATUS
Definition: precomp.h:26
#define ERR(fmt,...)
Definition: precomp.h:57
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:590
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:608
HANDLE HKEY
Definition: registry.h:26
#define RegCloseKey(hKey)
Definition: registry.h:49
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
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 RegDeleteKeyExW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ REGSAM samDesired, _In_ DWORD Reserved)
Definition: reg.c:1286
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 RegEnumValueW(_In_ HKEY hKey, _In_ DWORD index, _Out_ LPWSTR value, _Inout_ PDWORD val_count, _Reserved_ PDWORD reserved, _Out_opt_ PDWORD type, _Out_opt_ LPBYTE data, _Inout_opt_ PDWORD count)
Definition: reg.c:2830
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
FORCEINLINE BOOL IsHKCRKey(_In_ HKEY hKey)
Definition: reg.h:13
FORCEINLINE void MakeHKCRKey(_Inout_ HKEY *hKey)
Definition: reg.h:20
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
FxAutoRegKey hKey
Status
Definition: gdiplustypes.h:25
#define RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
Definition: green.h:15
LONG WINAPI QueryInfoHKCRKey(_In_ HKEY hKey, _Out_writes_to_opt_(*lpcchClass, *lpcchClass+1) LPWSTR lpClass, _Inout_opt_ LPDWORD lpcchClass, _Reserved_ LPDWORD lpReserved, _Out_opt_ LPDWORD lpcSubKeys, _Out_opt_ LPDWORD lpcbMaxSubKeyLen, _Out_opt_ LPDWORD lpcbMaxClassLen, _Out_opt_ LPDWORD lpcValues, _Out_opt_ LPDWORD lpcbMaxValueNameLen, _Out_opt_ LPDWORD lpcbMaxValueLen, _Out_opt_ LPDWORD lpcbSecurityDescriptor, _Out_opt_ PFILETIME lpftLastWriteTime)
Definition: hkcr.c:1087
LONG WINAPI CreateHKCRKey(_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: hkcr.c:266
static BOOL ValueExists(_In_ HKEY hNormalKey, _In_ PUNICODE_STRING Name)
Definition: hkcr.c:22
static LONG GetFallbackHKCRKey(_In_ HKEY hKey, _Out_ HKEY *MachineKey, _In_ BOOL MustCreate)
Definition: hkcr.c:111
LONG WINAPI QueryHKCRValue(_In_ HKEY hKey, _In_ LPCWSTR Name, _In_ LPDWORD Reserved, _In_ LPDWORD Type, _In_ LPBYTE Data, _In_ LPDWORD Count)
Definition: hkcr.c:548
LONG WINAPI EnumHKCRValue(_In_ HKEY hKey, _In_ DWORD dwIndex, _Out_ LPWSTR lpName, _Inout_ PDWORD lpcbName, _Reserved_ PDWORD lpReserved, _Out_opt_ PDWORD lpdwType, _Out_opt_ LPBYTE lpData, _Inout_opt_ PDWORD lpcbData)
Definition: hkcr.c:873
LONG WINAPI DeleteHKCRValue(_In_ HKEY hKey, _In_ PUNICODE_STRING ValueName)
Definition: hkcr.c:504
static LONG GetKeySam(_In_ HKEY hKey, _Out_ REGSAM *RegSam)
Definition: hkcr.c:88
LONG WINAPI SetHKCRValue(_In_ HKEY hKey, _In_ LPCWSTR Name, _In_ DWORD Reserved, _In_ DWORD Type, _In_ CONST BYTE *Data, _In_ DWORD DataSize)
Definition: hkcr.c:613
static const UNICODE_STRING HKLM_ClassesPath
Definition: hkcr.c:18
LONG WINAPI OpenHKCRKey(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ DWORD ulOptions, _In_ REGSAM samDesired, _In_ PHKEY phkResult)
Definition: hkcr.c:370
static LONG GetSubkeyInfoHelper(_In_ HKEY hKey, _Out_opt_ LPDWORD lpSubKeys, _Out_opt_ LPDWORD lpMaxSubKeyLen)
Definition: hkcr.c:241
static LONG GetPreferredHKCRKey(_In_ HKEY hKey, _Out_ HKEY *PreferredKey)
Definition: hkcr.c:189
LONG WINAPI DeleteHKCRKey(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ REGSAM RegSam, _In_ DWORD Reserved)
Definition: hkcr.c:441
static LONG GetKeyName(HKEY hKey, PUNICODE_STRING KeyName)
Definition: hkcr.c:36
LONG WINAPI EnumHKCRKey(_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: hkcr.c:682
static int reg
Definition: i386-dis.c:1290
@ KeyNameInformation
Definition: winternl.h:831
NTSYSAPI NTSTATUS WINAPI RtlDuplicateUnicodeString(int, const UNICODE_STRING *, UNICODE_STRING *)
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)
#define ASSERT(a)
Definition: mode.c:44
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
#define _Out_opt_
Definition: ms_sal.h:346
#define _Inout_
Definition: ms_sal.h:378
#define _Inout_opt_
Definition: ms_sal.h:379
#define _Out_
Definition: ms_sal.h:345
#define _Out_writes_to_opt_(size, count)
Definition: ms_sal.h:356
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
#define _Reserved_
Definition: ms_sal.h:295
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4755
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ PNDIS_STRING SubKeyName
Definition: ndis.h:4725
_In_ NDIS_ERROR_CODE ErrorCode
Definition: ndis.h:4436
int Count
Definition: noreturn.cpp:7
@ KeyValuePartialInformation
Definition: nt_native.h:1182
NTSYSAPI NTSTATUS NTAPI NtDeleteValueKey(IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName)
Definition: ntapi.c:1014
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 KEY_QUERY_VALUE
Definition: nt_native.h:1016
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)
#define READ_CONTROL
Definition: nt_native.h:58
NTSTATUS NTAPI NtQueryKey(IN HANDLE KeyHandle, IN KEY_INFORMATION_CLASS KeyInformationClass, OUT PVOID KeyInformation, IN ULONG Length, OUT PULONG ResultLength)
Definition: ntapi.c:632
#define L(x)
Definition: ntvdm.h:50
#define CONST
Definition: pedump.c:81
DWORD * PDWORD
Definition: pedump.c:68
long LONG
Definition: pedump.c:60
#define err(...)
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
static void Exit(void)
Definition: sock.c:1330
#define TRACE(s)
Definition: solgame.cpp:4
DWORD dwOptions
Definition: solitaire.cpp:25
ACCESS_MASK GrantedAccess
Definition: winternl.h:1251
USHORT MaximumLength
Definition: env_spec_w32.h:370
Definition: ps.c:97
#define max(a, b)
Definition: svc.c:63
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
unsigned char * LPBYTE
Definition: typedefs.h:53
uint32_t * LPDWORD
Definition: typedefs.h:59
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2699
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:243
_In_ LPCSTR lpName
Definition: winbase.h:2789
_Reserved_ PVOID Reserved
Definition: winddi.h:3974
#define WINAPI
Definition: msvc.h:6
#define ERROR_INTERNAL_ERROR
Definition: winerror.h:840
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define HKEY_CURRENT_USER
Definition: winreg.h:11
#define RegCreateKeyEx
Definition: winreg.h:501
ACCESS_MASK REGSAM
Definition: winreg.h:69
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
unsigned char BYTE
Definition: xxhash.c:193