ReactOS 0.4.15-dev-7704-gc07eb9f
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
21LONG
23{
24 UNICODE_STRING InfoName;
25 PKEY_NAME_INFORMATION NameInformation;
26 ULONG InfoLength;
28
29 /* Get info length */
30 InfoLength = 0;
31 Status = NtQueryKey(hKey, KeyNameInformation, NULL, 0, &InfoLength);
33 {
34 ERR("NtQueryKey returned unexpected Status: 0x%08x\n", Status);
36 }
37
38 /* Get it for real */
39 NameInformation = RtlAllocateHeap(RtlGetProcessHeap(), 0, InfoLength);
40 if (NameInformation == NULL)
41 {
42 ERR("Failed to allocate %lu bytes\n", InfoLength);
44 }
45
46 Status = NtQueryKey(hKey, KeyNameInformation, NameInformation, InfoLength, &InfoLength);
47 if (!NT_SUCCESS(Status))
48 {
49 RtlFreeHeap(RtlGetProcessHeap(), 0, NameInformation);
50 ERR("NtQueryKey failed: 0x%08x\n", Status);
52 }
53
54 /* Make it a proper UNICODE_STRING */
55 InfoName.Length = NameInformation->NameLength;
56 InfoName.MaximumLength = NameInformation->NameLength;
57 InfoName.Buffer = NameInformation->Name;
58
60 if (!NT_SUCCESS(Status))
61 {
62 RtlFreeHeap(RtlGetProcessHeap(), 0, NameInformation);
63 ERR("RtlDuplicateUnicodeString failed: 0x%08x\n", Status);
65 }
66
67 RtlFreeHeap(RtlGetProcessHeap(), 0, NameInformation);
68
69 return ERROR_SUCCESS;
70}
71
72static
73LONG
76 _Out_ REGSAM* RegSam)
77{
79 OBJECT_BASIC_INFORMATION ObjectInfo;
80
81 Status = NtQueryObject(hKey, ObjectBasicInformation, &ObjectInfo, sizeof(ObjectInfo), NULL);
82 if (!NT_SUCCESS(Status))
83 {
84 ERR("NtQueryObject failed, Status %x08x\n", Status);
86 }
87
88 *RegSam = ObjectInfo.GrantedAccess;
89 return ERROR_SUCCESS;
90}
91
92/*
93 * Gets a HKLM key from an HKCU key.
94 */
95static
96LONG
99 _Out_ HKEY* MachineKey,
100 _In_ BOOL MustCreate)
101{
105 REGSAM SamDesired;
106
107 /* Get the key name */
110 return ErrorCode;
111
112 /* See if we really need a conversion */
114 {
116 *MachineKey = hKey;
117 return ERROR_SUCCESS;
118 }
119
120 SubKeyName = KeyName.Buffer + 15; /* 15 == wcslen(L"\\Registry\\User\\") */
121 /* Skip the user token */
122 while (*SubKeyName++ != L'\\')
123 {
124 if (!*SubKeyName)
125 {
126 ERR("Key name %S is invalid!\n", KeyName.Buffer);
128 }
129 }
130
131 /* Use the same access mask than the original key */
132 ErrorCode = GetKeySam(hKey, &SamDesired);
134 {
136 return ErrorCode;
137 }
138
139 if (MustCreate)
140 {
144 0,
145 NULL,
146 0,
147 SamDesired,
148 NULL,
149 MachineKey,
150 NULL);
151 }
152 else
153 {
154 /* Open the key. */
158 0,
159 SamDesired,
160 MachineKey);
161 }
162
164
165 return ErrorCode;
166}
167
168/* Get the HKCU key (if it exists) from an HKCR key */
169static
170LONG
172 _In_ HKEY hKey,
173 _Out_ HKEY* PreferredKey)
174{
178 REGSAM SamDesired;
179
180 /* Get the key name */
183 return ErrorCode;
184
185 /* See if we really need a conversion */
187 {
189 *PreferredKey = hKey;
190 return ERROR_SUCCESS;
191 }
192
193 /* 18 == wcslen(L"\\Registry\\Machine\\") */
194 SubKeyName = KeyName.Buffer + 18;
195
196 /* Use the same access mask than the original key */
197 ErrorCode = GetKeySam(hKey, &SamDesired);
199 {
201 return ErrorCode;
202 }
203
204 /* Open the key. */
208 0,
209 SamDesired,
210 PreferredKey);
211
213
214 return ErrorCode;
215}
216
217static
218LONG
220 _In_ HKEY hKey,
221 _Out_opt_ LPDWORD lpSubKeys,
222 _Out_opt_ LPDWORD lpMaxSubKeyLen)
223{
224 LONG err = RegQueryInfoKeyW(hKey, NULL, NULL, NULL, lpSubKeys, lpMaxSubKeyLen,
225 NULL, NULL, NULL, NULL, NULL, NULL);
227 return err;
228
229 /* Windows RegEdit only uses KEY_ENUMERATE_SUB_KEYS when enumerating but
230 * KEY_QUERY_VALUE is required to get the info in EnumHKCRKey.
231 */
233 {
234 err = RegQueryInfoKeyW(hKey, NULL, NULL, NULL, lpSubKeys, lpMaxSubKeyLen,
235 NULL, NULL, NULL, NULL, NULL, NULL);
237 }
238 return err;
239}
240
241/* HKCR version of RegCreateKeyExW. */
242LONG
243WINAPI
245 _In_ HKEY hKey,
246 _In_ LPCWSTR lpSubKey,
248 _In_opt_ LPWSTR lpClass,
250 _In_ REGSAM samDesired,
251 _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
252 _Out_ PHKEY phkResult,
253 _Out_opt_ LPDWORD lpdwDisposition)
254{
256 HKEY QueriedKey, TestKey;
257
259
260 /* Remove the HKCR flag while we're working */
261 hKey = (HKEY)(((ULONG_PTR)hKey) & ~0x2);
262
263 ErrorCode = GetPreferredHKCRKey(hKey, &QueriedKey);
264
266 {
267 /* The current key doesn't exist on HKCU side, so we can only create it in HKLM */
269 hKey,
270 lpSubKey,
271 Reserved,
272 lpClass,
273 dwOptions,
274 samDesired,
275 lpSecurityAttributes,
276 phkResult,
277 lpdwDisposition);
279 MakeHKCRKey(phkResult);
280 return ErrorCode;
281 }
282
284 {
285 /* Somehow we failed for another reason (maybe deleted key or whatever) */
286 return ErrorCode;
287 }
288
289 /* See if the subkey already exists in HKCU. */
290 ErrorCode = RegOpenKeyExW(QueriedKey, lpSubKey, 0, READ_CONTROL, &TestKey);
292 {
294 {
295 /* Great. Close the test one and do the real create operation */
296 RegCloseKey(TestKey);
298 QueriedKey,
299 lpSubKey,
300 Reserved,
301 lpClass,
302 dwOptions,
303 samDesired,
304 lpSecurityAttributes,
305 phkResult,
306 lpdwDisposition);
308 MakeHKCRKey(phkResult);
309 }
310 if (QueriedKey != hKey)
311 RegCloseKey(QueriedKey);
312
313 return ERROR_SUCCESS;
314 }
315
316 if (QueriedKey != hKey)
317 RegCloseKey(QueriedKey);
318
319 /* So we must do the create operation in HKLM, creating the missing parent keys if needed. */
320 ErrorCode = GetFallbackHKCRKey(hKey, &QueriedKey, TRUE);
322 return ErrorCode;
323
324 /* Do the key creation */
326 QueriedKey,
327 lpSubKey,
328 Reserved,
329 lpClass,
330 dwOptions,
331 samDesired,
332 lpSecurityAttributes,
333 phkResult,
334 lpdwDisposition);
335
336 if (QueriedKey != hKey)
337 RegCloseKey(QueriedKey);
338
340 MakeHKCRKey(phkResult);
341
342 return ErrorCode;
343}
344
345/* Same as RegOpenKeyExW, but for HKEY_CLASSES_ROOT subkeys */
346LONG
347WINAPI
349 _In_ HKEY hKey,
350 _In_ LPCWSTR lpSubKey,
351 _In_ DWORD ulOptions,
352 _In_ REGSAM samDesired,
353 _In_ PHKEY phkResult)
354{
355 HKEY QueriedKey;
357
359
360 /* Remove the HKCR flag while we're working */
361 hKey = (HKEY)(((ULONG_PTR)hKey) & ~0x2);
362
363 ErrorCode = GetPreferredHKCRKey(hKey, &QueriedKey);
364
366 {
367 /* The key doesn't exist on HKCU side, no chance for a subkey */
368 ErrorCode = RegOpenKeyExW(hKey, lpSubKey, ulOptions, samDesired, phkResult);
370 MakeHKCRKey(phkResult);
371 return ErrorCode;
372 }
373
375 {
376 /* Somehow we failed for another reason (maybe deleted key or whatever) */
377 return ErrorCode;
378 }
379
380 /* Try on the HKCU side */
381 ErrorCode = RegOpenKeyExW(QueriedKey, lpSubKey, ulOptions, samDesired, phkResult);
383 MakeHKCRKey(phkResult);
384
385 /* Close it if we must */
386 if (QueriedKey != hKey)
387 {
388 RegCloseKey(QueriedKey);
389 }
390
391 /* Anything else than ERROR_FILE_NOT_FOUND means that we found it, even if it is with failures. */
393 return ErrorCode;
394
395 /* If we're here, we must open from HKLM key. */
396 ErrorCode = GetFallbackHKCRKey(hKey, &QueriedKey, FALSE);
398 {
399 /* Maybe the key doesn't exist in the HKLM view */
400 return ErrorCode;
401 }
402
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 return ErrorCode;
414}
415
416/* HKCR version of RegDeleteKeyExW */
417LONG
418WINAPI
420 _In_ HKEY hKey,
421 _In_ LPCWSTR lpSubKey,
422 _In_ REGSAM RegSam,
424{
425 HKEY QueriedKey;
427
429
430 /* Remove the HKCR flag while we're working */
431 hKey = (HKEY)(((ULONG_PTR)hKey) & ~0x2);
432
433 ErrorCode = GetPreferredHKCRKey(hKey, &QueriedKey);
434
436 {
437 /* The key doesn't exist on HKCU side, no chance for a subkey */
438 return RegDeleteKeyExW(hKey, lpSubKey, RegSam, Reserved);
439 }
440
442 {
443 /* Somehow we failed for another reason (maybe deleted key or whatever) */
444 return ErrorCode;
445 }
446
447 ErrorCode = RegDeleteKeyExW(QueriedKey, lpSubKey, RegSam, Reserved);
448
449 /* Close it if we must */
450 if (QueriedKey != hKey)
451 {
452 /* The original key is on the machine view */
453 RegCloseKey(QueriedKey);
454 }
455
456 /* Anything else than ERROR_FILE_NOT_FOUND means that we found it, even if it is with failures. */
458 return ErrorCode;
459
460 /* If we're here, we must open from HKLM key. */
461 ErrorCode = GetFallbackHKCRKey(hKey, &QueriedKey, FALSE);
463 {
464 /* Maybe the key doesn't exist in the HKLM view */
465 return ErrorCode;
466 }
467
468 ErrorCode = RegDeleteKeyExW(QueriedKey, lpSubKey, RegSam, Reserved);
469
470 /* Close it if we must */
471 if (QueriedKey != hKey)
472 {
473 RegCloseKey(QueriedKey);
474 }
475
476 return ErrorCode;
477}
478
479/* HKCR version of RegQueryValueExW */
480LONG
481WINAPI
483 _In_ HKEY hKey,
489{
490 HKEY QueriedKey;
492
494
495 /* Remove the HKCR flag while we're working */
496 hKey = (HKEY)(((ULONG_PTR)hKey) & ~0x2);
497
498 ErrorCode = GetPreferredHKCRKey(hKey, &QueriedKey);
499
501 {
502 /* The key doesn't exist on HKCU side, no chance for a value in it */
504 }
505
507 {
508 /* Somehow we failed for another reason (maybe deleted key or whatever) */
509 return ErrorCode;
510 }
511
513
514 /* Close it if we must */
515 if (QueriedKey != hKey)
516 {
517 /* The original key is on the machine view */
518 RegCloseKey(QueriedKey);
519 }
520
521 /* Anything else than ERROR_FILE_NOT_FOUND means that we found it, even if it is with failures. */
523 return ErrorCode;
524
525 /* If we're here, we must open from HKLM key. */
526 ErrorCode = GetFallbackHKCRKey(hKey, &QueriedKey, FALSE);
528 {
529 /* Maybe the key doesn't exist in the HKLM view */
530 return ErrorCode;
531 }
532
534
535 /* Close it if we must */
536 if (QueriedKey != hKey)
537 {
538 RegCloseKey(QueriedKey);
539 }
540
541 return ErrorCode;
542}
543
544/* HKCR version of RegSetValueExW */
545LONG
546WINAPI
548 _In_ HKEY hKey,
554{
555 HKEY QueriedKey;
557
559
560 /* Remove the HKCR flag while we're working */
561 hKey = (HKEY)(((ULONG_PTR)hKey) & ~0x2);
562
563 ErrorCode = GetPreferredHKCRKey(hKey, &QueriedKey);
564
566 {
567 /* The key doesn't exist on HKCU side, no chance to put a value in it */
569 }
570
572 {
573 /* Somehow we failed for another reason (maybe deleted key or whatever) */
574 return ErrorCode;
575 }
576
577 /* Check if the value already exists in the preferred key */
578 ErrorCode = RegQueryValueExW(QueriedKey, Name, NULL, NULL, NULL, NULL);
580 {
582 {
583 /* Yes, so we have the right to modify it */
585 }
586 if (QueriedKey != hKey)
587 RegCloseKey(QueriedKey);
588 return ErrorCode;
589 }
590 if (QueriedKey != hKey)
591 RegCloseKey(QueriedKey);
592
593 /* So we must set the value in the HKLM version */
594 ErrorCode = GetPreferredHKCRKey(hKey, &QueriedKey);
596 {
597 /* No choice: put this in HKCU */
599 }
600 else if (ErrorCode != ERROR_SUCCESS)
601 {
602 return ErrorCode;
603 }
604
606
607 if (QueriedKey != hKey)
608 RegCloseKey(QueriedKey);
609
610 return ErrorCode;
611}
612
613/* HKCR version of RegEnumKeyExW */
614LONG
615WINAPI
617 _In_ HKEY hKey,
618 _In_ DWORD dwIndex,
620 _Inout_ LPDWORD lpcbName,
621 _Reserved_ LPDWORD lpReserved,
622 _Out_opt_ LPWSTR lpClass,
623 _Inout_opt_ LPDWORD lpcbClass,
624 _Out_opt_ PFILETIME lpftLastWriteTime)
625{
626 HKEY PreferredKey, FallbackKey;
627 DWORD NumPreferredSubKeys;
628 DWORD MaxFallbackSubKeyLen;
629 DWORD FallbackIndex;
630 WCHAR* FallbackSubKeyName = NULL;
632
634
635 /* Remove the HKCR flag while we're working */
636 hKey = (HKEY)(((ULONG_PTR)hKey) & ~0x2);
637
638 /* Get the preferred key */
639 ErrorCode = GetPreferredHKCRKey(hKey, &PreferredKey);
641 {
643 {
644 /* Only the HKLM key exists */
645 return RegEnumKeyExW(
646 hKey,
647 dwIndex,
648 lpName,
649 lpcbName,
650 lpReserved,
651 lpClass,
652 lpcbClass,
653 lpftLastWriteTime);
654 }
655 return ErrorCode;
656 }
657
658 /* Get the fallback key */
659 ErrorCode = GetFallbackHKCRKey(hKey, &FallbackKey, FALSE);
661 {
662 if (PreferredKey != hKey)
663 RegCloseKey(PreferredKey);
665 {
666 /* Only the HKCU key exists */
667 return RegEnumKeyExW(
668 hKey,
669 dwIndex,
670 lpName,
671 lpcbName,
672 lpReserved,
673 lpClass,
674 lpcbClass,
675 lpftLastWriteTime);
676 }
677 return ErrorCode;
678 }
679
680 /* Get some info on the HKCU side */
681 ErrorCode = GetSubkeyInfoHelper(PreferredKey, &NumPreferredSubKeys, NULL);
683 goto Exit;
684
685 if (dwIndex < NumPreferredSubKeys)
686 {
687 /* HKCU side takes precedence */
689 PreferredKey,
690 dwIndex,
691 lpName,
692 lpcbName,
693 lpReserved,
694 lpClass,
695 lpcbClass,
696 lpftLastWriteTime);
697 goto Exit;
698 }
699
700 /* Here it gets tricky. We must enumerate the values from the HKLM side,
701 * without reporting those which are present on the HKCU side */
702
703 /* Squash out the indices from HKCU */
704 dwIndex -= NumPreferredSubKeys;
705
706 /* Get some info */
707 ErrorCode = GetSubkeyInfoHelper(FallbackKey, NULL, &MaxFallbackSubKeyLen);
709 {
710 ERR("Could not query info of key %p (Err: %d)\n", FallbackKey, ErrorCode);
711 goto Exit;
712 }
713
714 MaxFallbackSubKeyLen++;
715 TRACE("Maxfallbacksubkeylen: %d\n", MaxFallbackSubKeyLen);
716
717 /* Allocate our buffer */
718 FallbackSubKeyName = RtlAllocateHeap(
719 RtlGetProcessHeap(), 0, MaxFallbackSubKeyLen * sizeof(WCHAR));
720 if (!FallbackSubKeyName)
721 {
723 goto Exit;
724 }
725
726 /* We must begin at the very first subkey of the fallback key,
727 * and then see if we meet keys that already are in the preferred key.
728 * In that case, we must bump dwIndex, as otherwise we would enumerate a key we already
729 * saw in a previous call.
730 */
731 FallbackIndex = 0;
732 while (TRUE)
733 {
734 HKEY PreferredSubKey;
735 DWORD FallbackSubkeyLen = MaxFallbackSubKeyLen;
736
737 /* Try enumerating */
739 FallbackKey,
740 FallbackIndex,
741 FallbackSubKeyName,
742 &FallbackSubkeyLen,
743 NULL,
744 NULL,
745 NULL,
746 NULL);
748 {
750 ERR("Returning %d.\n", ErrorCode);
751 goto Exit;
752 }
753 FallbackSubKeyName[FallbackSubkeyLen] = L'\0';
754
755 /* See if there is such a value on HKCU side */
757 PreferredKey,
758 FallbackSubKeyName,
759 0,
761 &PreferredSubKey);
762
764 {
765 RegCloseKey(PreferredSubKey);
766 /* So we already enumerated it on HKCU side. */
767 dwIndex++;
768 }
770 {
771 ERR("Got error %d while querying for %s on HKCU side.\n", ErrorCode, FallbackSubKeyName);
772 goto Exit;
773 }
774
775 /* See if we caught up */
776 if (FallbackIndex == dwIndex)
777 break;
778
779 FallbackIndex++;
780 }
781
782 /* We can finally enumerate on the fallback side */
784 FallbackKey,
785 dwIndex,
786 lpName,
787 lpcbName,
788 lpReserved,
789 lpClass,
790 lpcbClass,
791 lpftLastWriteTime);
792
793Exit:
794 if (PreferredKey != hKey)
795 RegCloseKey(PreferredKey);
796 if (FallbackKey != hKey)
797 RegCloseKey(FallbackKey);
798 if (FallbackSubKeyName)
799 RtlFreeHeap(RtlGetProcessHeap(), 0, FallbackSubKeyName);
800
801 return ErrorCode;
802}
803
804/* HKCR version of RegEnumValueW */
805LONG
806WINAPI
808 _In_ HKEY hKey,
809 _In_ DWORD dwIndex,
811 _Inout_ PDWORD lpcbName,
812 _Reserved_ PDWORD lpReserved,
813 _Out_opt_ PDWORD lpdwType,
814 _Out_opt_ LPBYTE lpData,
815 _Inout_opt_ PDWORD lpcbData)
816{
817 HKEY PreferredKey, FallbackKey;
818 DWORD NumPreferredValues;
819 DWORD MaxFallbackValueNameLen;
820 DWORD FallbackIndex;
821 WCHAR* FallbackValueName = NULL;
823
825
826 /* Remove the HKCR flag while we're working */
827 hKey = (HKEY)(((ULONG_PTR)hKey) & ~0x2);
828
829 /* Get the preferred key */
830 ErrorCode = GetPreferredHKCRKey(hKey, &PreferredKey);
832 {
834 {
835 /* Only the HKLM key exists */
836 return RegEnumValueW(
837 hKey,
838 dwIndex,
839 lpName,
840 lpcbName,
841 lpReserved,
842 lpdwType,
843 lpData,
844 lpcbData);
845 }
846 return ErrorCode;
847 }
848
849 /* Get the fallback key */
850 ErrorCode = GetFallbackHKCRKey(hKey, &FallbackKey, FALSE);
852 {
853 if (PreferredKey != hKey)
854 RegCloseKey(PreferredKey);
856 {
857 /* Only the HKCU key exists */
858 return RegEnumValueW(
859 hKey,
860 dwIndex,
861 lpName,
862 lpcbName,
863 lpReserved,
864 lpdwType,
865 lpData,
866 lpcbData);
867 }
868 return ErrorCode;
869 }
870
871 /* Get some info on the HKCU side */
873 PreferredKey,
874 NULL,
875 NULL,
876 NULL,
877 NULL,
878 NULL,
879 NULL,
880 &NumPreferredValues,
881 NULL,
882 NULL,
883 NULL,
884 NULL);
886 goto Exit;
887
888 if (dwIndex < NumPreferredValues)
889 {
890 /* HKCU side takes precedence */
891 return RegEnumValueW(
892 PreferredKey,
893 dwIndex,
894 lpName,
895 lpcbName,
896 lpReserved,
897 lpdwType,
898 lpData,
899 lpcbData);
900 goto Exit;
901 }
902
903 /* Here it gets tricky. We must enumerate the values from the HKLM side,
904 * without reporting those which are present on the HKCU side */
905
906 /* Squash out the indices from HKCU */
907 dwIndex -= NumPreferredValues;
908
909 /* Get some info */
911 FallbackKey,
912 NULL,
913 NULL,
914 NULL,
915 NULL,
916 NULL,
917 NULL,
918 NULL,
919 &MaxFallbackValueNameLen,
920 NULL,
921 NULL,
922 NULL);
924 {
925 ERR("Could not query info of key %p (Err: %d)\n", FallbackKey, ErrorCode);
926 goto Exit;
927 }
928
929 MaxFallbackValueNameLen++;
930 TRACE("Maxfallbacksubkeylen: %d\n", MaxFallbackValueNameLen);
931
932 /* Allocate our buffer */
933 FallbackValueName = RtlAllocateHeap(
934 RtlGetProcessHeap(), 0, MaxFallbackValueNameLen * sizeof(WCHAR));
935 if (!FallbackValueName)
936 {
938 goto Exit;
939 }
940
941 /* We must begin at the very first subkey of the fallback key,
942 * and then see if we meet keys that already are in the preferred key.
943 * In that case, we must bump dwIndex, as otherwise we would enumerate a key we already
944 * saw in a previous call.
945 */
946 FallbackIndex = 0;
947 while (TRUE)
948 {
949 DWORD FallbackValueNameLen = MaxFallbackValueNameLen;
950
951 /* Try enumerating */
953 FallbackKey,
954 FallbackIndex,
955 FallbackValueName,
956 &FallbackValueNameLen,
957 NULL,
958 NULL,
959 NULL,
960 NULL);
962 {
964 ERR("Returning %d.\n", ErrorCode);
965 goto Exit;
966 }
967 FallbackValueName[FallbackValueNameLen] = L'\0';
968
969 /* See if there is such a value on HKCU side */
971 PreferredKey,
972 FallbackValueName,
973 NULL,
974 NULL,
975 NULL,
976 NULL);
977
979 {
980 /* So we already enumerated it on HKCU side. */
981 dwIndex++;
982 }
984 {
985 ERR("Got error %d while querying for %s on HKCU side.\n", ErrorCode, FallbackValueName);
986 goto Exit;
987 }
988
989 /* See if we caught up */
990 if (FallbackIndex == dwIndex)
991 break;
992
993 FallbackIndex++;
994 }
995
996 /* We can finally enumerate on the fallback side */
998 FallbackKey,
999 dwIndex,
1000 lpName,
1001 lpcbName,
1002 lpReserved,
1003 lpdwType,
1004 lpData,
1005 lpcbData);
1006
1007Exit:
1008 if (PreferredKey != hKey)
1009 RegCloseKey(PreferredKey);
1010 if (FallbackKey != hKey)
1011 RegCloseKey(FallbackKey);
1012 if (FallbackValueName)
1013 RtlFreeHeap(RtlGetProcessHeap(), 0, FallbackValueName);
1014
1015 return ErrorCode;
1016}
1017
1018/* HKCR version of RegQueryInfoKeyW */
1019LONG
1020WINAPI
1022 _In_ HKEY hKey,
1023 _Out_writes_to_opt_(*lpcchClass, *lpcchClass + 1) LPWSTR lpClass,
1024 _Inout_opt_ LPDWORD lpcchClass,
1025 _Reserved_ LPDWORD lpReserved,
1026 _Out_opt_ LPDWORD lpcSubKeys,
1027 _Out_opt_ LPDWORD lpcbMaxSubKeyLen,
1028 _Out_opt_ LPDWORD lpcbMaxClassLen,
1029 _Out_opt_ LPDWORD lpcValues,
1030 _Out_opt_ LPDWORD lpcbMaxValueNameLen,
1031 _Out_opt_ LPDWORD lpcbMaxValueLen,
1032 _Out_opt_ LPDWORD lpcbSecurityDescriptor,
1033 _Out_opt_ PFILETIME lpftLastWriteTime)
1034{
1035 HKEY PreferredKey, FallbackKey;
1036 LONG retval, err;
1037 DWORD OtherSubKeys = 0, OtherMaxSub = 0, OtherMaxClass = 0;
1038 DWORD OtherValues = 0, OtherMaxName = 0, OtherMaxVal = 0;
1039
1041
1042 /* Remove the HKCR flag while we're working */
1043 hKey = (HKEY)(((ULONG_PTR)hKey) & ~0x2);
1044
1045 retval = GetFallbackHKCRKey(hKey, &FallbackKey, FALSE);
1046 if (retval == ERROR_SUCCESS)
1047 {
1048 retval = RegQueryInfoKeyW(FallbackKey, lpClass, lpcchClass, lpReserved,
1049 &OtherSubKeys, &OtherMaxSub, &OtherMaxClass,
1050 &OtherValues, &OtherMaxName, &OtherMaxVal,
1051 lpcbSecurityDescriptor, lpftLastWriteTime);
1052 if (FallbackKey != hKey)
1053 RegCloseKey(FallbackKey);
1054 }
1055
1056 err = GetPreferredHKCRKey(hKey, &PreferredKey);
1057 if (err == ERROR_SUCCESS)
1058 {
1059 err = RegQueryInfoKeyW(PreferredKey, lpClass, lpcchClass, lpReserved,
1060 lpcSubKeys, lpcbMaxSubKeyLen, lpcbMaxClassLen,
1061 lpcValues, lpcbMaxValueNameLen, lpcbMaxValueLen,
1062 lpcbSecurityDescriptor, lpftLastWriteTime);
1063 if (PreferredKey != hKey)
1064 RegCloseKey(PreferredKey);
1065 }
1066
1067 if (lpcSubKeys)
1068 *lpcSubKeys = (err ? 0 : *lpcSubKeys) + OtherSubKeys;
1069 if (lpcValues)
1070 *lpcValues = (err ? 0 : *lpcValues) + OtherValues;
1071 if (lpcbMaxSubKeyLen)
1072 *lpcbMaxSubKeyLen = max((err ? 0 : *lpcbMaxSubKeyLen), OtherMaxSub);
1073 if (lpcbMaxClassLen)
1074 *lpcbMaxClassLen = max((err ? 0 : *lpcbMaxClassLen), OtherMaxClass);
1075 if (lpcbMaxValueNameLen)
1076 *lpcbMaxValueNameLen = max((err ? 0 : *lpcbMaxValueNameLen), OtherMaxName);
1077 if (lpcbMaxValueLen)
1078 *lpcbMaxValueLen = max((err ? 0 : *lpcbMaxValueLen), OtherMaxVal);
1079
1080 return (err == ERROR_SUCCESS) ? ERROR_SUCCESS : retval;
1081}
@ 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: debug.h:110
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
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:32
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:3362
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:2533
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:4911
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:2859
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:3691
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4132
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:1021
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:244
static LONG GetFallbackHKCRKey(_In_ HKEY hKey, _Out_ HKEY *MachineKey, _In_ BOOL MustCreate)
Definition: hkcr.c:97
LONG WINAPI QueryHKCRValue(_In_ HKEY hKey, _In_ LPCWSTR Name, _In_ LPDWORD Reserved, _In_ LPDWORD Type, _In_ LPBYTE Data, _In_ LPDWORD Count)
Definition: hkcr.c:482
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:807
static LONG GetKeySam(_In_ HKEY hKey, _Out_ REGSAM *RegSam)
Definition: hkcr.c:74
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:547
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:348
static LONG GetSubkeyInfoHelper(_In_ HKEY hKey, _Out_opt_ LPDWORD lpSubKeys, _Out_opt_ LPDWORD lpMaxSubKeyLen)
Definition: hkcr.c:219
static LONG GetPreferredHKCRKey(_In_ HKEY hKey, _Out_ HKEY *PreferredKey)
Definition: hkcr.c:171
LONG WINAPI DeleteHKCRKey(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ REGSAM RegSam, _In_ DWORD Reserved)
Definition: hkcr.c:419
static LONG GetKeyName(HKEY hKey, PUNICODE_STRING KeyName)
Definition: hkcr.c:22
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:616
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
#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
#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
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2699
_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