ReactOS 0.4.15-dev-7788-g1ad9096
reg.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/reg.c
5 * PURPOSE: Registry functions
6 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
7 * Thomas Weidenmueller <w3seek@reactos.com>
8 * UPDATE HISTORY:
9 * Created 01/11/98
10 * 19990309 EA Stubs
11 * 20050502 Fireball imported some stuff from WINE
12 */
13
14/* INCLUDES *****************************************************************/
15
16#include <advapi32.h>
17
18#include <ndk/cmfuncs.h>
19#include <pseh/pseh2.h>
20
21#include "reg.h"
22
24
25/* DEFINES ******************************************************************/
26
27#define MAX_DEFAULT_HANDLES 6
28#define REG_MAX_NAME_SIZE 256
29#define REG_MAX_DATA_SIZE 2048
30
31/* GLOBALS ******************************************************************/
32
38static BOOLEAN DllInitialized = FALSE; /* HACK */
39
40/* PROTOTYPES ***************************************************************/
41
44#define ClosePredefKey(Handle) \
45 if ((ULONG_PTR)Handle & 0x1) { \
46 NtClose(Handle); \
47 }
48#define IsPredefKey(HKey) \
49 (((ULONG_PTR)(HKey) & 0xF0000000) == 0x80000000)
50#define GetPredefKeyIndex(HKey) \
51 ((ULONG_PTR)(HKey) & 0x0FFFFFFF)
52
57
58
59/* FUNCTIONS ****************************************************************/
60/* check if value type needs string conversion (Ansi<->Unicode) */
61__inline static int is_string( DWORD type )
62{
63 return (type == REG_SZ) || (type == REG_EXPAND_SZ) || (type == REG_MULTI_SZ);
64}
65
66/************************************************************************
67 * RegInitDefaultHandles
68 */
69BOOL
71{
72 TRACE("RegInitialize()\n");
73
74 /* Lazy init hack */
75 if (!DllInitialized)
76 {
77 ProcessHeap = RtlGetProcessHeap();
79 MAX_DEFAULT_HANDLES * sizeof(HANDLE));
81
83 }
84
85 return TRUE;
86}
87
88
89/************************************************************************
90 * RegInit
91 */
92BOOL
94{
95 TRACE("RegCleanup()\n");
96
99
100 return TRUE;
101}
102
103
104static NTSTATUS
107{
109
110 switch (Index)
111 {
112 case 0: /* HKEY_CLASSES_ROOT */
114 break;
115
116 case 1: /* HKEY_CURRENT_USER */
118 Handle);
119 break;
120
121 case 2: /* HKEY_LOCAL_MACHINE */
123 break;
124
125 case 3: /* HKEY_USERS */
127 break;
128#if 0
129 case 4: /* HKEY_PERFORMANCE_DATA */
130 Status = OpenPerformanceDataKey (Handle);
131 break;
132#endif
133
134 case 5: /* HKEY_CURRENT_CONFIG */
136 break;
137
138 case 6: /* HKEY_DYN_DATA */
140 break;
141
142 default:
143 WARN("MapDefaultHandle() no handle creator\n");
145 break;
146 }
147
148 return Status;
149}
150
151
152static NTSTATUS
154 IN HKEY Key)
155{
157 ULONG Index;
158 BOOLEAN DoOpen, DefDisabled;
160
161 TRACE("MapDefaultKey (Key %x)\n", Key);
162
163 if (!IsPredefKey(Key))
164 {
165 *RealKey = (HANDLE)((ULONG_PTR)Key & ~0x1);
166 return STATUS_SUCCESS;
167 }
168
169 /* Handle special cases here */
172 {
174 }
175 RegInitialize(); /* HACK until delay-loading is implemented */
177
178 if (Key == HKEY_CURRENT_USER)
179 DefDisabled = DefaultHandleHKUDisabled;
180 else
181 DefDisabled = DefaultHandlesDisabled;
182
183 if (!DefDisabled)
184 {
186 DoOpen = (*Handle == NULL);
187 }
188 else
189 {
190 Handle = RealKey;
191 DoOpen = TRUE;
192 }
193
194 if (DoOpen)
195 {
196 /* create/open the default handle */
198 Handle);
199 }
200
201 if (NT_SUCCESS(Status))
202 {
203 if (!DefDisabled)
204 *RealKey = *Handle;
205 else
206 *(PULONG_PTR)Handle |= 0x1;
207 }
208
210
211 return Status;
212}
213
214
215static VOID
217{
218 ULONG i;
219 RegInitialize(); /* HACK until delay-loading is implemented */
221
222 for (i = 0; i < MAX_DEFAULT_HANDLES; i++)
223 {
224 if (DefaultHandleTable[i] != NULL)
225 {
228 }
229 }
230
232}
233
234
235static NTSTATUS
237{
239 UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Software\\CLASSES");
241
242 TRACE("OpenClassesRootKey()\n");
243
245 &KeyName,
247 NULL,
248 NULL);
251 &Attributes);
252
253 if (!NT_SUCCESS(Status))
254 return Status;
255
256 /* Mark it as HKCR */
258
259 return Status;
260}
261
262
263static NTSTATUS
265{
267 UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine");
269
270 TRACE("OpenLocalMachineKey()\n");
271
273 &KeyName,
275 NULL,
276 NULL);
279 &Attributes);
280
281 TRACE("NtOpenKey(%wZ) => %08x\n", &KeyName, Status);
282
283 return Status;
284}
285
286
287static NTSTATUS
289{
291 UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\User");
292
293 TRACE("OpenUsersKey()\n");
294
296 &KeyName,
298 NULL,
299 NULL);
300 return NtOpenKey(KeyHandle,
302 &Attributes);
303}
304
305
306static NTSTATUS
308{
311 RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current");
312
313 TRACE("OpenCurrentConfigKey()\n");
314
316 &KeyName,
318 NULL,
319 NULL);
320 return NtOpenKey(KeyHandle,
322 &Attributes);
323}
324
325#ifndef _ADVAPI32_VISTA_
326
327/************************************************************************
328 * RegDisablePredefinedCache
329 *
330 * @implemented
331 */
334{
335 RegInitialize(); /* HACK until delay-loading is implemented */
339 return ERROR_SUCCESS;
340}
341
342
343/************************************************************************
344 * RegDisablePredefinedCacheEx
345 *
346 * @implemented
347 */
350{
351 RegInitialize(); /* HACK until delay-loading is implemented */
356 return ERROR_SUCCESS;
357}
358
359
360/************************************************************************
361 * RegOverridePredefKey
362 *
363 * @implemented
364 */
367 IN HKEY hNewHKey OPTIONAL)
368{
370
371 if ((hKey == HKEY_CLASSES_ROOT ||
376 hKey == HKEY_USERS) &&
377 !IsPredefKey(hNewHKey))
378 {
380 ULONG Index;
381
384
385 if (hNewHKey == NULL)
386 {
387 /* restore the default mapping */
389 &hNewHKey);
390 if (!NT_SUCCESS(Status))
391 {
393 }
394
395 ASSERT(hNewHKey != NULL);
396 }
397 RegInitialize(); /* HACK until delay-loading is implemented */
399
400 /* close the currently mapped handle if existing */
401 if (*Handle != NULL)
402 {
403 NtClose(*Handle);
404 }
405
406 /* update the mapping */
407 *Handle = hNewHKey;
408
410 }
411 else
413
414 return ErrorCode;
415}
416
417
418/************************************************************************
419 * RegCloseKey
420 *
421 * @implemented
422 */
425{
427
428 /* don't close null handle or a pseudo handle */
429 if (!hKey)
430 {
432 }
433
434 if (((ULONG_PTR)hKey & 0xF0000000) == 0x80000000)
435 {
436 return ERROR_SUCCESS;
437 }
438
440 if (!NT_SUCCESS(Status))
441 {
443 }
444
445 return ERROR_SUCCESS;
446}
447
448#endif // _ADVAPI32_VISTA_
449
450static NTSTATUS
452 IN HKEY hKeyDest)
453{
454 typedef struct
455 {
456 LIST_ENTRY ListEntry;
457 HANDLE hKeySrc;
458 HANDLE hKeyDest;
459 } REGP_COPY_KEYS, *PREGP_COPY_KEYS;
460
461 LIST_ENTRY copyQueueHead;
462 PREGP_COPY_KEYS copyKeys, newCopyKeys;
463 union
464 {
466 KEY_NODE_INFORMATION *KeyNode;
468 } Info;
469 ULONG Index, BufferSizeRequired, BufferSize = 0x200;
471 NTSTATUS Status2 = STATUS_SUCCESS;
472
473 InitializeListHead(&copyQueueHead);
474
476 0,
477 BufferSize);
478 if (Info.Buffer == NULL)
479 {
481 }
482
483 copyKeys = RtlAllocateHeap(ProcessHeap,
484 0,
485 sizeof(REGP_COPY_KEYS));
486 if (copyKeys != NULL)
487 {
488 copyKeys->hKeySrc = hKeySrc;
489 copyKeys->hKeyDest = hKeyDest;
490 InsertHeadList(&copyQueueHead,
491 &copyKeys->ListEntry);
492
493 /* FIXME - copy security from hKeySrc to hKeyDest or just for the subkeys? */
494
495 do
496 {
497 copyKeys = CONTAINING_RECORD(copyQueueHead.Flink,
498 REGP_COPY_KEYS,
499 ListEntry);
500
501 /* enumerate all values and copy them */
502 Index = 0;
503 for (;;)
504 {
505 Status2 = NtEnumerateValueKey(copyKeys->hKeySrc,
506 Index,
508 Info.KeyValue,
510 &BufferSizeRequired);
511 if (NT_SUCCESS(Status2))
512 {
514 PVOID Data;
515
516 /* don't use RtlInitUnicodeString as the string is not NULL-terminated! */
517 ValueName.Length = Info.KeyValue->NameLength;
518 ValueName.MaximumLength = ValueName.Length;
519 ValueName.Buffer = Info.KeyValue->Name;
520
521 Data = (PVOID)((ULONG_PTR)Info.KeyValue + Info.KeyValue->DataOffset);
522
523 Status2 = NtSetValueKey(copyKeys->hKeyDest,
524 &ValueName,
525 Info.KeyValue->TitleIndex,
526 Info.KeyValue->Type,
527 Data,
528 Info.KeyValue->DataLength);
529
530 /* don't break, let's try to copy as many values as possible */
531 if (!NT_SUCCESS(Status2) && NT_SUCCESS(Status))
532 {
533 Status = Status2;
534 }
535
536 Index++;
537 }
538 else if (Status2 == STATUS_BUFFER_OVERFLOW)
539 {
541
542 ASSERT(BufferSize < BufferSizeRequired);
543
545 0,
546 Info.Buffer,
547 BufferSizeRequired);
548 if (Buffer != NULL)
549 {
550 Info.Buffer = Buffer;
551 BufferSize = BufferSizeRequired;
552 /* try again */
553 }
554 else
555 {
556 /* don't break, let's try to copy as many values as possible */
558 Index++;
559
560 if (NT_SUCCESS(Status))
561 {
562 Status = Status2;
563 }
564 }
565 }
566 else
567 {
568 /* break to avoid an infinite loop in case of denied access or
569 other errors! */
570 if (Status2 != STATUS_NO_MORE_ENTRIES && NT_SUCCESS(Status))
571 {
572 Status = Status2;
573 }
574
575 break;
576 }
577 }
578
579 /* enumerate all subkeys and open and enqueue them */
580 Index = 0;
581 for (;;)
582 {
583 Status2 = NtEnumerateKey(copyKeys->hKeySrc,
584 Index,
586 Info.KeyNode,
588 &BufferSizeRequired);
589 if (NT_SUCCESS(Status2))
590 {
591 HANDLE KeyHandle, NewKeyHandle;
593 UNICODE_STRING SubKeyName, ClassName;
594
595 /* don't use RtlInitUnicodeString as the string is not NULL-terminated! */
596 SubKeyName.Length = Info.KeyNode->NameLength;
597 SubKeyName.MaximumLength = SubKeyName.Length;
598 SubKeyName.Buffer = Info.KeyNode->Name;
599 ClassName.Length = Info.KeyNode->ClassLength;
600 ClassName.MaximumLength = ClassName.Length;
601 ClassName.Buffer = (PWSTR)((ULONG_PTR)Info.KeyNode + Info.KeyNode->ClassOffset);
602
603 /* open the subkey with sufficient rights */
604
606 &SubKeyName,
608 copyKeys->hKeySrc,
609 NULL);
610
611 Status2 = NtOpenKey(&KeyHandle,
614 if (NT_SUCCESS(Status2))
615 {
616 /* FIXME - attempt to query the security information */
617
619 &SubKeyName,
621 copyKeys->hKeyDest,
622 NULL);
623
624 Status2 = NtCreateKey(&NewKeyHandle,
627 Info.KeyNode->TitleIndex,
628 &ClassName,
629 0,
630 NULL);
631 if (NT_SUCCESS(Status2))
632 {
633 newCopyKeys = RtlAllocateHeap(ProcessHeap,
634 0,
635 sizeof(REGP_COPY_KEYS));
636 if (newCopyKeys != NULL)
637 {
638 /* save the handles and enqueue the subkey */
639 newCopyKeys->hKeySrc = KeyHandle;
640 newCopyKeys->hKeyDest = NewKeyHandle;
641 InsertTailList(&copyQueueHead,
642 &newCopyKeys->ListEntry);
643 }
644 else
645 {
647 NtClose(NewKeyHandle);
648
650 }
651 }
652 else
653 {
655 }
656 }
657
658 if (!NT_SUCCESS(Status2) && NT_SUCCESS(Status))
659 {
660 Status = Status2;
661 }
662
663 Index++;
664 }
665 else if (Status2 == STATUS_BUFFER_OVERFLOW)
666 {
668
669 ASSERT(BufferSize < BufferSizeRequired);
670
672 0,
673 Info.Buffer,
674 BufferSizeRequired);
675 if (Buffer != NULL)
676 {
677 Info.Buffer = Buffer;
678 BufferSize = BufferSizeRequired;
679 /* try again */
680 }
681 else
682 {
683 /* don't break, let's try to copy as many keys as possible */
685 Index++;
686
687 if (NT_SUCCESS(Status))
688 {
689 Status = Status2;
690 }
691 }
692 }
693 else
694 {
695 /* break to avoid an infinite loop in case of denied access or
696 other errors! */
697 if (Status2 != STATUS_NO_MORE_ENTRIES && NT_SUCCESS(Status))
698 {
699 Status = Status2;
700 }
701
702 break;
703 }
704 }
705
706 /* close the handles and remove the entry from the list */
707 if (copyKeys->hKeySrc != hKeySrc)
708 {
709 NtClose(copyKeys->hKeySrc);
710 }
711 if (copyKeys->hKeyDest != hKeyDest)
712 {
713 NtClose(copyKeys->hKeyDest);
714 }
715
716 RemoveEntryList(&copyKeys->ListEntry);
717
719 0,
720 copyKeys);
721 } while (!IsListEmpty(&copyQueueHead));
722 }
723 else
725
727 0,
728 Info.Buffer);
729
730 return Status;
731}
732
733
734/************************************************************************
735 * RegCopyTreeW
736 *
737 * @implemented
738 */
741 IN LPCWSTR lpSubKey OPTIONAL,
742 IN HKEY hKeyDest)
743{
744 HANDLE DestKeyHandle, KeyHandle, CurKey, SubKeyHandle = NULL;
746
748 hKeySrc);
749 if (!NT_SUCCESS(Status))
750 {
752 }
753
754 Status = MapDefaultKey(&DestKeyHandle,
755 hKeyDest);
756 if (!NT_SUCCESS(Status))
757 {
758 goto Cleanup2;
759 }
760
761 if (lpSubKey != NULL)
762 {
765
767
769 &SubKeyName,
771 KeyHandle,
772 NULL);
773
777 if (!NT_SUCCESS(Status))
778 {
779 goto Cleanup;
780 }
781
782 CurKey = SubKeyHandle;
783 }
784 else
785 CurKey = KeyHandle;
786
787 Status = RegpCopyTree(CurKey,
788 hKeyDest);
789
790 if (SubKeyHandle != NULL)
791 {
793 }
794
795Cleanup:
796 ClosePredefKey(DestKeyHandle);
797Cleanup2:
799
800 if (!NT_SUCCESS(Status))
801 {
803 }
804
805 return ERROR_SUCCESS;
806}
807
808#ifndef _ADVAPI32_VISTA_
809
810/************************************************************************
811 * RegCopyTreeA
812 *
813 * @implemented
814 */
817 IN LPCSTR lpSubKey OPTIONAL,
818 IN HKEY hKeyDest)
819{
820 UNICODE_STRING SubKeyName = { 0, 0, NULL };
821 LONG Ret;
822
823 if (lpSubKey != NULL &&
825 {
827 }
828
829 Ret = RegCopyTreeW(hKeySrc,
830 SubKeyName.Buffer,
831 hKeyDest);
832
834
835 return Ret;
836}
837
838
839/************************************************************************
840 * RegConnectRegistryA
841 *
842 * @implemented
843 */
846 IN HKEY hKey,
847 OUT PHKEY phkResult)
848{
849 UNICODE_STRING MachineName = { 0, 0, NULL };
850 LONG Ret;
851
852 if (lpMachineName != NULL &&
854 {
856 }
857
858 Ret = RegConnectRegistryW(MachineName.Buffer,
859 hKey,
860 phkResult);
861
863
864 return Ret;
865}
866
867
868/************************************************************************
869 * RegConnectRegistryW
870 *
871 * @unimplemented
872 */
875 HKEY hKey,
876 PHKEY phkResult)
877{
878 LONG ret;
879
880 TRACE("(%s,%p,%p): stub\n",debugstr_w(lpMachineName),hKey,phkResult);
881
882 if (!lpMachineName || !*lpMachineName)
883 {
884 /* Use the local machine name */
885 ret = RegOpenKeyW( hKey, NULL, phkResult );
886 }
887 else
888 {
889 WCHAR compName[MAX_COMPUTERNAME_LENGTH + 1];
890 DWORD len = sizeof(compName) / sizeof(WCHAR);
891
892 /* MSDN says lpMachineName must start with \\ : not so */
893 if( lpMachineName[0] == '\\' && lpMachineName[1] == '\\')
894 lpMachineName += 2;
895
896 if (GetComputerNameW(compName, &len))
897 {
898 if (!_wcsicmp(lpMachineName, compName))
899 ret = RegOpenKeyW(hKey, NULL, phkResult);
900 else
901 {
902 FIXME("Connect to %s is not supported.\n",debugstr_w(lpMachineName));
904 }
905 }
906 else
907 ret = GetLastError();
908 }
909
910 return ret;
911}
912
913
914/************************************************************************
915 * CreateNestedKey
916 *
917 * Create key and all necessary intermediate keys
918 */
919static NTSTATUS
922 PUNICODE_STRING ClassString,
924 REGSAM samDesired,
925 DWORD *lpdwDisposition)
926{
927 OBJECT_ATTRIBUTES LocalObjectAttributes;
928 UNICODE_STRING LocalKeyName;
931 ULONG FullNameLength;
933 PWCHAR Ptr;
934 HANDLE LocalKeyHandle;
935
937 samDesired,
939 0,
940 ClassString,
941 dwOptions,
942 (PULONG)lpdwDisposition);
943 TRACE("NtCreateKey(%wZ) called (Status %lx)\n", ObjectAttributes->ObjectName, Status);
945 return Status;
946
947 /* Copy object attributes */
948 RtlCopyMemory(&LocalObjectAttributes,
950 sizeof(OBJECT_ATTRIBUTES));
951 RtlCreateUnicodeString(&LocalKeyName,
952 ObjectAttributes->ObjectName->Buffer);
953 LocalObjectAttributes.ObjectName = &LocalKeyName;
954 FullNameLength = LocalKeyName.Length / sizeof(WCHAR);
955
956 LocalKeyHandle = NULL;
957
958 /* Remove the last part of the key name and try to create the key again. */
960 {
961 Ptr = wcsrchr(LocalKeyName.Buffer, '\\');
962 if (Ptr == NULL || Ptr == LocalKeyName.Buffer)
963 {
965 break;
966 }
967
968 *Ptr = (WCHAR)0;
969 LocalKeyName.Length = (USHORT)wcslen(LocalKeyName.Buffer) * sizeof(WCHAR);
970
971 Status = NtCreateKey(&LocalKeyHandle,
973 &LocalObjectAttributes,
974 0,
975 NULL,
976 0,
977 &Disposition);
978 TRACE("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName, Status);
979 }
980
981 if (!NT_SUCCESS(Status))
982 {
983 RtlFreeUnicodeString(&LocalKeyName);
984 return Status;
985 }
986
987 /* Add removed parts of the key name and create them too. */
988 Length = wcslen(LocalKeyName.Buffer);
989 while (TRUE)
990 {
991 if (LocalKeyHandle)
992 NtClose (LocalKeyHandle);
993
994 LocalKeyName.Buffer[Length] = L'\\';
995 Length = wcslen (LocalKeyName.Buffer);
996 LocalKeyName.Length = Length * sizeof(WCHAR);
997
998 if (Length == FullNameLength)
999 {
1001 samDesired,
1003 0,
1004 ClassString,
1005 dwOptions,
1006 (PULONG)lpdwDisposition);
1007 break;
1008 }
1009
1010 Status = NtCreateKey(&LocalKeyHandle,
1012 &LocalObjectAttributes,
1013 0,
1014 NULL,
1015 0,
1016 &Disposition);
1017 TRACE("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName, Status);
1018 if (!NT_SUCCESS(Status))
1019 break;
1020 }
1021
1022 RtlFreeUnicodeString(&LocalKeyName);
1023
1024 return Status;
1025}
1026
1027
1028/************************************************************************
1029 * RegCreateKeyExA
1030 *
1031 * @implemented
1032 */
1035 _In_ HKEY hKey,
1036 _In_ LPCSTR lpSubKey,
1038 _In_ LPSTR lpClass,
1040 _In_ REGSAM samDesired,
1041 _In_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
1042 _Out_ PHKEY phkResult,
1043 _Out_ LPDWORD lpdwDisposition)
1044{
1045 UNICODE_STRING SubKeyString;
1046 UNICODE_STRING ClassString;
1048
1049 RtlInitEmptyUnicodeString(&ClassString, NULL, 0);
1050 RtlInitEmptyUnicodeString(&SubKeyString, NULL, 0);
1051
1052 if (lpClass)
1053 {
1054 if (!RtlCreateUnicodeStringFromAsciiz(&ClassString, lpClass))
1055 {
1057 goto Exit;
1058 }
1059 }
1060
1061 if (lpSubKey)
1062 {
1063 if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyString, lpSubKey))
1064 {
1066 goto Exit;
1067 }
1068 }
1069
1071 hKey,
1072 SubKeyString.Buffer,
1073 Reserved,
1074 ClassString.Buffer,
1075 dwOptions,
1076 samDesired,
1077 lpSecurityAttributes,
1078 phkResult,
1079 lpdwDisposition);
1080
1081Exit:
1082 RtlFreeUnicodeString(&SubKeyString);
1083 RtlFreeUnicodeString(&ClassString);
1084
1085 return ErrorCode;
1086}
1087
1088
1089/************************************************************************
1090 * RegCreateKeyExW
1091 *
1092 * @implemented
1093 */
1094LONG
1095WINAPI
1097 _In_ HKEY hKey,
1098 _In_ LPCWSTR lpSubKey,
1100 _In_opt_ LPWSTR lpClass,
1102 _In_ REGSAM samDesired,
1103 _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
1104 _Out_ PHKEY phkResult,
1105 _Out_opt_ LPDWORD lpdwDisposition)
1106{
1107 UNICODE_STRING SubKeyString;
1108 UNICODE_STRING ClassString;
1113
1114 TRACE("RegCreateKeyExW() called\n");
1115
1116 /* get the real parent key */
1118 hKey);
1119 if (!NT_SUCCESS(Status))
1120 {
1122 }
1123
1124 TRACE("ParentKey %p\n", ParentKey);
1125
1126 if (IsHKCRKey(ParentKey))
1127 {
1129 ParentKey,
1130 lpSubKey,
1131 Reserved,
1132 lpClass,
1133 dwOptions,
1134 samDesired,
1135 lpSecurityAttributes,
1136 phkResult,
1137 lpdwDisposition);
1139 return ErrorCode;
1140 }
1141
1144
1145 RtlInitUnicodeString(&ClassString,
1146 lpClass);
1147 RtlInitUnicodeString(&SubKeyString,
1148 lpSubKey);
1150 &SubKeyString,
1151 Attributes,
1153 lpSecurityAttributes ? (PSECURITY_DESCRIPTOR)lpSecurityAttributes->lpSecurityDescriptor : NULL);
1154 Status = CreateNestedKey(phkResult,
1156 (lpClass == NULL)? NULL : &ClassString,
1157 dwOptions,
1158 samDesired,
1159 lpdwDisposition);
1160
1162
1163 TRACE("Status %x\n", Status);
1164 if (!NT_SUCCESS(Status))
1165 {
1167 }
1168
1169 return ERROR_SUCCESS;
1170}
1171
1172
1173/************************************************************************
1174 * RegCreateKeyA
1175 *
1176 * @implemented
1177 */
1180 LPCSTR lpSubKey,
1181 PHKEY phkResult)
1182{
1183 return RegCreateKeyExA(hKey,
1184 lpSubKey,
1185 0,
1186 NULL,
1187 0,
1189 NULL,
1190 phkResult,
1191 NULL);
1192}
1193
1194
1195/************************************************************************
1196 * RegCreateKeyW
1197 *
1198 * @implemented
1199 */
1202 LPCWSTR lpSubKey,
1203 PHKEY phkResult)
1204{
1205 return RegCreateKeyExW(hKey,
1206 lpSubKey,
1207 0,
1208 NULL,
1209 0,
1211 NULL,
1212 phkResult,
1213 NULL);
1214}
1215
1216
1217/************************************************************************
1218 * RegDeleteKeyA
1219 *
1220 * @implemented
1221 */
1222LONG
1223WINAPI
1225 _In_ HKEY hKey,
1226 _In_ LPCSTR lpSubKey)
1227{
1228 return RegDeleteKeyExA(hKey, lpSubKey, 0, 0);
1229}
1230
1231
1232/************************************************************************
1233 * RegDeleteKeyW
1234 *
1235 * @implemented
1236 */
1237LONG
1238WINAPI
1240 _In_ HKEY hKey,
1241 _In_ LPCWSTR lpSubKey)
1242{
1243 return RegDeleteKeyExW(hKey, lpSubKey, 0, 0);
1244}
1245
1246
1247/************************************************************************
1248 * RegDeleteKeyExA
1249 *
1250 * @implemented
1251 */
1252LONG
1253WINAPI
1255 _In_ HKEY hKey,
1256 _In_ LPCSTR lpSubKey,
1257 _In_ REGSAM samDesired,
1259{
1262
1263 if (lpSubKey)
1264 {
1267 }
1268 else
1269 RtlInitEmptyUnicodeString(&SubKeyName, NULL, 0);
1270
1271 ErrorCode = RegDeleteKeyExW(hKey, SubKeyName.Buffer, samDesired, Reserved);
1272
1274
1275 return ErrorCode;
1276}
1277
1278
1279/************************************************************************
1280 * RegDeleteKeyExW
1281 *
1282 * @implemented
1283 */
1284LONG
1285WINAPI
1287 _In_ HKEY hKey,
1288 _In_ LPCWSTR lpSubKey,
1289 _In_ REGSAM samDesired,
1291{
1295 HANDLE TargetKey;
1297
1298 /* Make sure we got a subkey */
1299 if (!lpSubKey)
1300 {
1301 /* Fail */
1303 }
1304
1306 hKey);
1307 if (!NT_SUCCESS(Status))
1308 {
1310 }
1311
1312 if (IsHKCRKey(ParentKey))
1313 {
1314 LONG ErrorCode = DeleteHKCRKey(ParentKey, lpSubKey, samDesired, Reserved);
1316 return ErrorCode;
1317 }
1318
1319 if (samDesired & KEY_WOW64_32KEY)
1320 ERR("Wow64 not yet supported!\n");
1321
1322 if (samDesired & KEY_WOW64_64KEY)
1323 ERR("Wow64 not yet supported!\n");
1324
1325
1326 RtlInitUnicodeString(&SubKeyName, lpSubKey);
1328 &SubKeyName,
1330 ParentKey,
1331 NULL);
1332 Status = NtOpenKey(&TargetKey,
1333 DELETE,
1335 if (!NT_SUCCESS(Status))
1336 {
1337 goto Cleanup;
1338 }
1339
1340 Status = NtDeleteKey(TargetKey);
1341 NtClose(TargetKey);
1342
1343Cleanup:
1345
1346 if (!NT_SUCCESS(Status))
1347 {
1349 }
1350
1351 return ERROR_SUCCESS;
1352}
1353
1354
1355/************************************************************************
1356 * RegDeleteKeyValueW
1357 *
1358 * @implemented
1359 */
1362 IN LPCWSTR lpSubKey OPTIONAL,
1363 IN LPCWSTR lpValueName OPTIONAL)
1364{
1366 HANDLE KeyHandle, CurKey, SubKeyHandle = NULL;
1368
1370 hKey);
1371 if (!NT_SUCCESS(Status))
1372 {
1374 }
1375
1376 if (lpSubKey != NULL)
1377 {
1380
1381 RtlInitUnicodeString(&SubKeyName, lpSubKey);
1382
1384 &SubKeyName,
1386 KeyHandle,
1387 NULL);
1388
1392 if (!NT_SUCCESS(Status))
1393 {
1394 goto Cleanup;
1395 }
1396
1397 CurKey = SubKeyHandle;
1398 }
1399 else
1400 CurKey = KeyHandle;
1401
1402 RtlInitUnicodeString(&ValueName, lpValueName);
1403
1404 Status = NtDeleteValueKey(CurKey,
1405 &ValueName);
1406
1407 if (SubKeyHandle != NULL)
1408 {
1410 }
1411
1412Cleanup:
1414
1415 if (!NT_SUCCESS(Status))
1416 {
1418 }
1419
1420 return ERROR_SUCCESS;
1421}
1422
1423
1424/************************************************************************
1425 * RegDeleteKeyValueA
1426 *
1427 * @implemented
1428 */
1431 IN LPCSTR lpSubKey OPTIONAL,
1432 IN LPCSTR lpValueName OPTIONAL)
1433{
1434 UNICODE_STRING SubKey = { 0, 0, NULL }, ValueName = { 0, 0, NULL };
1435 LONG Ret;
1436
1437 if (lpSubKey != NULL &&
1438 !RtlCreateUnicodeStringFromAsciiz(&SubKey, lpSubKey))
1439 {
1441 }
1442
1443 if (lpValueName != NULL &&
1445 {
1446 RtlFreeUnicodeString(&SubKey);
1448 }
1449
1451 SubKey.Buffer,
1452 SubKey.Buffer);
1453
1454 RtlFreeUnicodeString(&SubKey);
1456
1457 return Ret;
1458}
1459
1460#if 0
1461// Non-recursive RegDeleteTreeW implementation by Thomas, however it needs bugfixing
1462static NTSTATUS
1463RegpDeleteTree(IN HKEY hKey)
1464{
1465 typedef struct
1466 {
1467 LIST_ENTRY ListEntry;
1469 } REGP_DEL_KEYS, *PREG_DEL_KEYS;
1470
1471 LIST_ENTRY delQueueHead;
1472 PREG_DEL_KEYS delKeys, newDelKeys;
1475 PKEY_BASIC_INFORMATION BasicInfo;
1476 PREG_DEL_KEYS KeyDelRoot;
1478 NTSTATUS Status2 = STATUS_SUCCESS;
1479
1480 InitializeListHead(&delQueueHead);
1481
1482 ProcessHeap = RtlGetProcessHeap();
1483
1484 /* NOTE: no need to allocate enough memory for an additional KEY_BASIC_INFORMATION
1485 structure for the root key, we only do that for subkeys as we need to
1486 allocate REGP_DEL_KEYS structures anyway! */
1487 KeyDelRoot = RtlAllocateHeap(ProcessHeap,
1488 0,
1489 sizeof(REGP_DEL_KEYS));
1490 if (KeyDelRoot != NULL)
1491 {
1492 KeyDelRoot->KeyHandle = hKey;
1493 InsertTailList(&delQueueHead,
1494 &KeyDelRoot->ListEntry);
1495
1496 do
1497 {
1498 delKeys = CONTAINING_RECORD(delQueueHead.Flink,
1499 REGP_DEL_KEYS,
1500 ListEntry);
1501
1502 BufferSize = 0;
1503 BasicInfo = NULL;
1504 newDelKeys = NULL;
1505
1506ReadFirstSubKey:
1507 /* check if this key contains subkeys and delete them first by queuing
1508 them at the head of the list */
1509 Status2 = NtEnumerateKey(delKeys->KeyHandle,
1510 0,
1512 BasicInfo,
1513 BufferSize,
1514 &BufferSize);
1515
1516 if (NT_SUCCESS(Status2))
1517 {
1520
1521 ASSERT(newDelKeys != NULL);
1522 ASSERT(BasicInfo != NULL);
1523
1524 /* don't use RtlInitUnicodeString as the string is not NULL-terminated! */
1525 SubKeyName.Length = BasicInfo->NameLength;
1526 SubKeyName.MaximumLength = BasicInfo->NameLength;
1527 SubKeyName.Buffer = BasicInfo->Name;
1528
1530 &SubKeyName,
1532 delKeys->KeyHandle,
1533 NULL);
1534
1535 /* open the subkey */
1536 Status2 = NtOpenKey(&newDelKeys->KeyHandle,
1539 if (!NT_SUCCESS(Status2))
1540 {
1541 goto SubKeyFailure;
1542 }
1543
1544 /* enqueue this key to the head of the deletion queue */
1545 InsertHeadList(&delQueueHead,
1546 &newDelKeys->ListEntry);
1547
1548 /* try again from the head of the list */
1549 continue;
1550 }
1551 else
1552 {
1553 if (Status2 == STATUS_BUFFER_TOO_SMALL)
1554 {
1555 newDelKeys = RtlAllocateHeap(ProcessHeap,
1556 0,
1557 BufferSize + sizeof(REGP_DEL_KEYS));
1558 if (newDelKeys != NULL)
1559 {
1560 BasicInfo = (PKEY_BASIC_INFORMATION)(newDelKeys + 1);
1561
1562 /* try again */
1563 goto ReadFirstSubKey;
1564 }
1565 else
1566 {
1567 /* don't break, let's try to delete as many keys as possible */
1569 goto SubKeyFailureNoFree;
1570 }
1571 }
1572 else if (Status2 == STATUS_BUFFER_OVERFLOW)
1573 {
1574 PREG_DEL_KEYS newDelKeys2;
1575
1576 ASSERT(newDelKeys != NULL);
1577
1578 /* we need more memory to query the key name */
1579 newDelKeys2 = RtlReAllocateHeap(ProcessHeap,
1580 0,
1581 newDelKeys,
1582 BufferSize + sizeof(REGP_DEL_KEYS));
1583 if (newDelKeys2 != NULL)
1584 {
1585 newDelKeys = newDelKeys2;
1586 BasicInfo = (PKEY_BASIC_INFORMATION)(newDelKeys + 1);
1587
1588 /* try again */
1589 goto ReadFirstSubKey;
1590 }
1591 else
1592 {
1593 /* don't break, let's try to delete as many keys as possible */
1595 }
1596 }
1597 else if (Status2 == STATUS_NO_MORE_ENTRIES)
1598 {
1599 /* in some race conditions where another thread would delete
1600 the same tree at the same time, newDelKeys could actually
1601 be != NULL! */
1602 if (newDelKeys != NULL)
1603 {
1605 0,
1606 newDelKeys);
1607 }
1608 break;
1609 }
1610
1611SubKeyFailure:
1612 /* newDelKeys can be NULL here when NtEnumerateKey returned an
1613 error other than STATUS_BUFFER_TOO_SMALL or STATUS_BUFFER_OVERFLOW! */
1614 if (newDelKeys != NULL)
1615 {
1617 0,
1618 newDelKeys);
1619 }
1620
1621SubKeyFailureNoFree:
1622 /* don't break, let's try to delete as many keys as possible */
1623 if (NT_SUCCESS(Status))
1624 {
1625 Status = Status2;
1626 }
1627 }
1628
1629 Status2 = NtDeleteKey(delKeys->KeyHandle);
1630
1631 /* NOTE: do NOT close the handle anymore, it's invalid already! */
1632
1633 if (!NT_SUCCESS(Status2))
1634 {
1635 /* close the key handle so we don't leak handles for keys we were
1636 unable to delete. But only do this for handles not supplied
1637 by the caller! */
1638
1639 if (delKeys->KeyHandle != hKey)
1640 {
1641 NtClose(delKeys->KeyHandle);
1642 }
1643
1644 if (NT_SUCCESS(Status))
1645 {
1646 /* don't break, let's try to delete as many keys as possible */
1647 Status = Status2;
1648 }
1649 }
1650
1651 /* remove the entry from the list */
1652 RemoveEntryList(&delKeys->ListEntry);
1653
1655 0,
1656 delKeys);
1657 } while (!IsListEmpty(&delQueueHead));
1658 }
1659 else
1661
1662 return Status;
1663}
1664
1665
1666/************************************************************************
1667 * RegDeleteTreeW
1668 *
1669 * @implemented
1670 */
1673 IN LPCWSTR lpSubKey OPTIONAL)
1674{
1675 HANDLE KeyHandle, CurKey, SubKeyHandle = NULL;
1677
1679 hKey);
1680 if (!NT_SUCCESS(Status))
1681 {
1683 }
1684
1685 if (lpSubKey != NULL)
1686 {
1689
1690 RtlInitUnicodeString(&SubKeyName, lpSubKey);
1691
1693 &SubKeyName,
1695 KeyHandle,
1696 NULL);
1697
1701 if (!NT_SUCCESS(Status))
1702 {
1703 goto Cleanup;
1704 }
1705
1706 CurKey = SubKeyHandle;
1707 }
1708 else
1709 CurKey = KeyHandle;
1710
1711 Status = RegpDeleteTree(CurKey);
1712
1713 if (NT_SUCCESS(Status))
1714 {
1715 /* make sure we only close hKey (KeyHandle) when the caller specified a
1716 subkey, because the handle would be invalid already! */
1717 if (CurKey != KeyHandle)
1718 {
1720 }
1721
1722 return ERROR_SUCCESS;
1723 }
1724 else
1725 {
1726 /* make sure we close all handles we created! */
1727 if (SubKeyHandle != NULL)
1728 {
1730 }
1731
1732Cleanup:
1734
1736 }
1737}
1738#endif
1739
1740#endif // _ADVAPI32_VISTA_
1741
1742/************************************************************************
1743 * RegDeleteTreeW
1744 *
1745 * @implemented
1746 */
1747LSTATUS
1748WINAPI
1750 LPCWSTR lpszSubKey)
1751{
1752 LONG ret;
1753 DWORD dwMaxSubkeyLen, dwMaxValueLen;
1754 DWORD dwMaxLen, dwSize;
1757 HKEY hSubKey;
1758 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1759
1760 TRACE("(hkey=%p,%p %s)\n", hKey, lpszSubKey, debugstr_w(lpszSubKey));
1761
1763 hKey);
1764 if (!NT_SUCCESS(Status))
1765 {
1767 }
1768
1769 hSubKey = KeyHandle;
1770
1771 if(lpszSubKey)
1772 {
1773 ret = RegOpenKeyExW(KeyHandle, lpszSubKey, 0, KEY_READ, &hSubKey);
1774 if (ret)
1775 {
1777 return ret;
1778 }
1779 }
1780
1781 /* Get highest length for keys, values */
1782 ret = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
1783 &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
1784 if (ret) goto cleanup;
1785
1786 dwMaxSubkeyLen++;
1787 dwMaxValueLen++;
1788 dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
1789 if (dwMaxLen > sizeof(szNameBuf)/sizeof(WCHAR))
1790 {
1791 /* Name too big: alloc a buffer for it */
1792 if (!(lpszName = RtlAllocateHeap( RtlGetProcessHeap(), 0, dwMaxLen*sizeof(WCHAR))))
1793 {
1795 goto cleanup;
1796 }
1797 }
1798
1799
1800 /* Recursively delete all the subkeys */
1801 while (TRUE)
1802 {
1803 dwSize = dwMaxLen;
1804 if (RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL,
1805 NULL, NULL, NULL)) break;
1806
1807 ret = RegDeleteTreeW(hSubKey, lpszName);
1808 if (ret) goto cleanup;
1809 }
1810
1811 if (lpszSubKey)
1812 ret = RegDeleteKeyW(KeyHandle, lpszSubKey);
1813 else
1814 while (TRUE)
1815 {
1816 dwSize = dwMaxLen;
1817 if (RegEnumValueW(KeyHandle, 0, lpszName, &dwSize,
1818 NULL, NULL, NULL, NULL)) break;
1819
1820 ret = RegDeleteValueW(KeyHandle, lpszName);
1821 if (ret) goto cleanup;
1822 }
1823
1824cleanup:
1825 /* Free buffer if allocated */
1826 if (lpszName != szNameBuf)
1827 RtlFreeHeap( RtlGetProcessHeap(), 0, lpszName);
1828 if(lpszSubKey)
1829 RegCloseKey(hSubKey);
1830
1832
1833 return ret;
1834}
1835
1836
1837/************************************************************************
1838 * RegDeleteTreeA
1839 *
1840 * @implemented
1841 */
1844 IN LPCSTR lpSubKey OPTIONAL)
1845{
1846 UNICODE_STRING SubKeyName = { 0, 0, NULL };
1847 LONG Ret;
1848
1849 if (lpSubKey != NULL &&
1851 {
1853 }
1854
1855 Ret = RegDeleteTreeW(hKey,
1856 SubKeyName.Buffer);
1857
1859
1860 return Ret;
1861}
1862
1863#ifndef _ADVAPI32_VISTA_
1864
1865/************************************************************************
1866 * RegDisableReflectionKey
1867 *
1868 * @unimplemented
1869 */
1872{
1873 FIXME("RegDisableReflectionKey(0x%p) UNIMPLEMENTED!\n", hBase);
1875}
1876
1877
1878/************************************************************************
1879 * RegEnableReflectionKey
1880 *
1881 * @unimplemented
1882 */
1885{
1886 FIXME("RegEnableReflectionKey(0x%p) UNIMPLEMENTED!\n", hBase);
1888}
1889
1890
1891/******************************************************************************
1892 * RegpApplyRestrictions [internal]
1893 *
1894 * Helper function for RegGetValueA/W.
1895 */
1896static VOID
1898 DWORD dwType,
1899 DWORD cbData,
1900 PLONG ret)
1901{
1902 /* Check if the type is restricted by the passed flags */
1903 if (*ret == ERROR_SUCCESS || *ret == ERROR_MORE_DATA)
1904 {
1905 DWORD dwMask = 0;
1906
1907 switch (dwType)
1908 {
1909 case REG_NONE: dwMask = RRF_RT_REG_NONE; break;
1910 case REG_SZ: dwMask = RRF_RT_REG_SZ; break;
1911 case REG_EXPAND_SZ: dwMask = RRF_RT_REG_EXPAND_SZ; break;
1912 case REG_MULTI_SZ: dwMask = RRF_RT_REG_MULTI_SZ; break;
1913 case REG_BINARY: dwMask = RRF_RT_REG_BINARY; break;
1914 case REG_DWORD: dwMask = RRF_RT_REG_DWORD; break;
1915 case REG_QWORD: dwMask = RRF_RT_REG_QWORD; break;
1916 }
1917
1918 if (dwFlags & dwMask)
1919 {
1920 /* Type is not restricted, check for size mismatch */
1921 if (dwType == REG_BINARY)
1922 {
1923 DWORD cbExpect = 0;
1924
1925 if ((dwFlags & RRF_RT_ANY) == RRF_RT_DWORD)
1926 cbExpect = 4;
1927 else if ((dwFlags & RRF_RT_ANY) == RRF_RT_QWORD)
1928 cbExpect = 8;
1929
1930 if (cbExpect && cbData != cbExpect)
1932 }
1933 }
1935 }
1936}
1937
1938
1939/******************************************************************************
1940 * RegGetValueW [ADVAPI32.@]
1941 *
1942 * Retrieves the type and data for a value name associated with a key,
1943 * optionally expanding its content and restricting its type.
1944 *
1945 * PARAMS
1946 * hKey [I] Handle to an open key.
1947 * pszSubKey [I] Name of the subkey of hKey.
1948 * pszValue [I] Name of value under hKey/szSubKey to query.
1949 * dwFlags [I] Flags restricting the value type to retrieve.
1950 * pdwType [O] Destination for the values type, may be NULL.
1951 * pvData [O] Destination for the values content, may be NULL.
1952 * pcbData [I/O] Size of pvData, updated with the size in bytes required to
1953 * retrieve the whole content, including the trailing '\0'
1954 * for strings.
1955 *
1956 * RETURNS
1957 * Success: ERROR_SUCCESS
1958 * Failure: nonzero error code from Winerror.h
1959 *
1960 * NOTES
1961 * - Unless RRF_NOEXPAND is specified, REG_EXPAND_SZ values are automatically
1962 * expanded and pdwType is set to REG_SZ instead.
1963 * - Restrictions are applied after expanding, using RRF_RT_REG_EXPAND_SZ
1964 * without RRF_NOEXPAND is thus not allowed.
1965 * An exception is the case where RRF_RT_ANY is specified, because then
1966 * RRF_NOEXPAND is allowed.
1967 */
1970 LPCWSTR pszSubKey,
1971 LPCWSTR pszValue,
1972 DWORD dwFlags,
1973 LPDWORD pdwType,
1974 PVOID pvData,
1976{
1977 DWORD dwType, cbData = pcbData ? *pcbData : 0;
1978 PVOID pvBuf = NULL;
1979 LONG ret;
1980
1981 TRACE("(%p,%s,%s,%ld,%p,%p,%p=%ld)\n",
1982 hKey, debugstr_w(pszSubKey), debugstr_w(pszValue), dwFlags, pdwType,
1983 pvData, pcbData, cbData);
1984
1985 if (pvData && !pcbData)
1988 ((dwFlags & RRF_RT_ANY) != RRF_RT_ANY))
1990
1991 if (pszSubKey && pszSubKey[0])
1992 {
1993 ret = RegOpenKeyExW(hKey, pszSubKey, 0, KEY_QUERY_VALUE, &hKey);
1994 if (ret != ERROR_SUCCESS) return ret;
1995 }
1996
1997 ret = RegQueryValueExW(hKey, pszValue, NULL, &dwType, pvData, &cbData);
1998
1999 /* If we are going to expand we need to read in the whole the value even
2000 * if the passed buffer was too small as the expanded string might be
2001 * smaller than the unexpanded one and could fit into cbData bytes. */
2002 if ((ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) &&
2003 dwType == REG_EXPAND_SZ && !(dwFlags & RRF_NOEXPAND))
2004 {
2005 do
2006 {
2007 HeapFree(GetProcessHeap(), 0, pvBuf);
2008
2009 pvBuf = HeapAlloc(GetProcessHeap(), 0, cbData);
2010 if (!pvBuf)
2011 {
2013 break;
2014 }
2015
2016 if (ret == ERROR_MORE_DATA || !pvData)
2017 ret = RegQueryValueExW(hKey, pszValue, NULL,
2018 &dwType, pvBuf, &cbData);
2019 else
2020 {
2021 /* Even if cbData was large enough we have to copy the
2022 * string since ExpandEnvironmentStrings can't handle
2023 * overlapping buffers. */
2024 CopyMemory(pvBuf, pvData, cbData);
2025 }
2026
2027 /* Both the type or the value itself could have been modified in
2028 * between so we have to keep retrying until the buffer is large
2029 * enough or we no longer have to expand the value. */
2030 }
2031 while (dwType == REG_EXPAND_SZ && ret == ERROR_MORE_DATA);
2032
2033 if (ret == ERROR_SUCCESS)
2034 {
2035 /* Recheck dwType in case it changed since the first call */
2036 if (dwType == REG_EXPAND_SZ)
2037 {
2038 cbData = ExpandEnvironmentStringsW(pvBuf, pvData,
2039 pcbData ? *pcbData : 0) * sizeof(WCHAR);
2040 dwType = REG_SZ;
2041 if (pvData && pcbData && cbData > *pcbData)
2043 }
2044 else if (pvData)
2045 CopyMemory(pvData, pvBuf, *pcbData);
2046 }
2047
2048 HeapFree(GetProcessHeap(), 0, pvBuf);
2049 }
2050
2051 if (pszSubKey && pszSubKey[0])
2053
2054 RegpApplyRestrictions(dwFlags, dwType, cbData, &ret);
2055
2058
2059 if (pdwType)
2060 *pdwType = dwType;
2061
2062 if (pcbData)
2063 *pcbData = cbData;
2064
2065 return ret;
2066}
2067
2068
2069/******************************************************************************
2070 * RegGetValueA [ADVAPI32.@]
2071 *
2072 * See RegGetValueW.
2073 */
2076 LPCSTR pszSubKey,
2077 LPCSTR pszValue,
2078 DWORD dwFlags,
2079 LPDWORD pdwType,
2080 PVOID pvData,
2082{
2083 DWORD dwType, cbData = pcbData ? *pcbData : 0;
2084 PVOID pvBuf = NULL;
2085 LONG ret;
2086
2087 TRACE("(%p,%s,%s,%ld,%p,%p,%p=%ld)\n",
2088 hKey, pszSubKey, pszValue, dwFlags, pdwType, pvData, pcbData,
2089 cbData);
2090
2091 if (pvData && !pcbData)
2094 ((dwFlags & RRF_RT_ANY) != RRF_RT_ANY))
2096
2097 if (pszSubKey && pszSubKey[0])
2098 {
2099 ret = RegOpenKeyExA(hKey, pszSubKey, 0, KEY_QUERY_VALUE, &hKey);
2100 if (ret != ERROR_SUCCESS) return ret;
2101 }
2102
2103 ret = RegQueryValueExA(hKey, pszValue, NULL, &dwType, pvData, &cbData);
2104
2105 /* If we are going to expand we need to read in the whole the value even
2106 * if the passed buffer was too small as the expanded string might be
2107 * smaller than the unexpanded one and could fit into cbData bytes. */
2108 if ((ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) &&
2109 (dwType == REG_EXPAND_SZ && !(dwFlags & RRF_NOEXPAND)))
2110 {
2111 do {
2112 HeapFree(GetProcessHeap(), 0, pvBuf);
2113
2114 pvBuf = HeapAlloc(GetProcessHeap(), 0, cbData);
2115 if (!pvBuf)
2116 {
2118 break;
2119 }
2120
2121 if (ret == ERROR_MORE_DATA || !pvData)
2122 ret = RegQueryValueExA(hKey, pszValue, NULL,
2123 &dwType, pvBuf, &cbData);
2124 else
2125 {
2126 /* Even if cbData was large enough we have to copy the
2127 * string since ExpandEnvironmentStrings can't handle
2128 * overlapping buffers. */
2129 CopyMemory(pvBuf, pvData, cbData);
2130 }
2131
2132 /* Both the type or the value itself could have been modified in
2133 * between so we have to keep retrying until the buffer is large
2134 * enough or we no longer have to expand the value. */
2135 } while (dwType == REG_EXPAND_SZ && ret == ERROR_MORE_DATA);
2136
2137 if (ret == ERROR_SUCCESS)
2138 {
2139 /* Recheck dwType in case it changed since the first call */
2140 if (dwType == REG_EXPAND_SZ)
2141 {
2142 cbData = ExpandEnvironmentStringsA(pvBuf, pvData,
2143 pcbData ? *pcbData : 0);
2144 dwType = REG_SZ;
2145 if(pvData && pcbData && cbData > *pcbData)
2147 }
2148 else if (pvData)
2149 CopyMemory(pvData, pvBuf, *pcbData);
2150 }
2151
2152 HeapFree(GetProcessHeap(), 0, pvBuf);
2153 }
2154
2155 if (pszSubKey && pszSubKey[0])
2157
2158 RegpApplyRestrictions(dwFlags, dwType, cbData, &ret);
2159
2162
2163 if (pdwType) *pdwType = dwType;
2164 if (pcbData) *pcbData = cbData;
2165
2166 return ret;
2167}
2168
2169#endif // _ADVAPI32_VISTA_
2170
2171/************************************************************************
2172 * RegSetKeyValueW
2173 *
2174 * @implemented
2175 */
2178 IN LPCWSTR lpSubKey OPTIONAL,
2179 IN LPCWSTR lpValueName OPTIONAL,
2180 IN DWORD dwType,
2181 IN LPCVOID lpData OPTIONAL,
2182 IN DWORD cbData)
2183{
2184 HANDLE KeyHandle, CurKey, SubKeyHandle = NULL;
2186 LONG Ret;
2187
2189 hKey);
2190 if (!NT_SUCCESS(Status))
2191 {
2193 }
2194
2195 if (lpSubKey != NULL)
2196 {
2199
2200 RtlInitUnicodeString(&SubKeyName, lpSubKey);
2201
2203 &SubKeyName,
2205 KeyHandle,
2206 NULL);
2207
2211 if (!NT_SUCCESS(Status))
2212 {
2214 goto Cleanup;
2215 }
2216
2217 CurKey = SubKeyHandle;
2218 }
2219 else
2220 CurKey = KeyHandle;
2221
2222 Ret = RegSetValueExW(CurKey,
2223 lpValueName,
2224 0,
2225 dwType,
2226 lpData,
2227 cbData);
2228
2229 if (SubKeyHandle != NULL)
2230 {
2232 }
2233
2234Cleanup:
2236
2237 return Ret;
2238}
2239
2240#ifndef _ADVAPI32_VISTA_
2241
2242/************************************************************************
2243 * RegSetKeyValueA
2244 *
2245 * @implemented
2246 */
2249 IN LPCSTR lpSubKey OPTIONAL,
2250 IN LPCSTR lpValueName OPTIONAL,
2251 IN DWORD dwType,
2252 IN LPCVOID lpData OPTIONAL,
2253 IN DWORD cbData)
2254{
2255 HANDLE KeyHandle, CurKey, SubKeyHandle = NULL;
2257 LONG Ret;
2258
2260 hKey);
2261 if (!NT_SUCCESS(Status))
2262 {
2264 }
2265
2266 if (lpSubKey != NULL)
2267 {
2270
2272 {
2274 goto Cleanup;
2275 }
2276
2278 &SubKeyName,
2280 KeyHandle,
2281 NULL);
2282
2286
2288
2289 if (!NT_SUCCESS(Status))
2290 {
2292 goto Cleanup;
2293 }
2294
2295 CurKey = SubKeyHandle;
2296 }
2297 else
2298 CurKey = KeyHandle;
2299
2300 Ret = RegSetValueExA(CurKey,
2301 lpValueName,
2302 0,
2303 dwType,
2304 lpData,
2305 cbData);
2306
2307 if (SubKeyHandle != NULL)
2308 {
2310 }
2311
2312Cleanup:
2314
2315 return Ret;
2316}
2317
2318
2319/************************************************************************
2320 * RegDeleteValueA
2321 *
2322 * @implemented
2323 */
2326 LPCSTR lpValueName)
2327{
2331
2333 hKey);
2334 if (!NT_SUCCESS(Status))
2335 {
2337 }
2338
2341 &ValueName);
2343
2345
2346 if (!NT_SUCCESS(Status))
2347 {
2349 }
2350
2351 return ERROR_SUCCESS;
2352}
2353
2354
2355/************************************************************************
2356 * RegDeleteValueW
2357 *
2358 * @implemented
2359 */
2362 LPCWSTR lpValueName)
2363{
2367
2369 hKey);
2370 if (!NT_SUCCESS(Status))
2371 {
2373 }
2374
2375 RtlInitUnicodeString(&ValueName, lpValueName);
2376
2378 &ValueName);
2379
2381
2382 if (!NT_SUCCESS(Status))
2383 {
2385 }
2386
2387 return ERROR_SUCCESS;
2388}
2389
2390
2391/************************************************************************
2392 * RegEnumKeyA
2393 *
2394 * @implemented
2395 */
2398 DWORD dwIndex,
2399 LPSTR lpName,
2400 DWORD cbName)
2401{
2403
2404 dwLength = cbName;
2405 return RegEnumKeyExA(hKey,
2406 dwIndex,
2407 lpName,
2408 &dwLength,
2409 NULL,
2410 NULL,
2411 NULL,
2412 NULL);
2413}
2414
2415
2416/************************************************************************
2417 * RegEnumKeyW
2418 *
2419 * @implemented
2420 */
2423 DWORD dwIndex,
2424 LPWSTR lpName,
2425 DWORD cbName)
2426{
2428
2429 dwLength = cbName;
2430 return RegEnumKeyExW(hKey,
2431 dwIndex,
2432 lpName,
2433 &dwLength,
2434 NULL,
2435 NULL,
2436 NULL,
2437 NULL);
2438}
2439
2440
2441/************************************************************************
2442 * RegEnumKeyExA
2443 *
2444 * @implemented
2445 */
2446LONG
2447WINAPI
2449 _In_ HKEY hKey,
2450 _In_ DWORD dwIndex,
2452 _Inout_ LPDWORD lpcbName,
2453 _Reserved_ LPDWORD lpReserved,
2454 _Out_opt_ LPSTR lpClass,
2455 _Inout_opt_ LPDWORD lpcbClass,
2456 _Out_opt_ PFILETIME lpftLastWriteTime)
2457{
2458 WCHAR* NameBuffer = NULL;
2459 WCHAR* ClassBuffer = NULL;
2460 DWORD NameLength, ClassLength;
2462
2463 /* Allocate our buffers */
2464 if (*lpcbName > 0)
2465 {
2466 NameLength = *lpcbName;
2467 NameBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, *lpcbName * sizeof(WCHAR));
2468 if (NameBuffer == NULL)
2469 {
2471 goto Exit;
2472 }
2473 }
2474
2475 if (lpClass)
2476 {
2477 if (*lpcbClass > 0)
2478 {
2479 ClassLength = *lpcbClass;
2480 ClassBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, *lpcbClass * sizeof(WCHAR));
2481 if (ClassBuffer == NULL)
2482 {
2484 goto Exit;
2485 }
2486 }
2487 }
2488
2489 /* Do the actual call */
2491 hKey,
2492 dwIndex,
2493 NameBuffer,
2494 lpcbName,
2495 lpReserved,
2496 ClassBuffer,
2497 lpcbClass,
2498 lpftLastWriteTime);
2499
2500 if (ErrorCode != ERROR_SUCCESS)
2501 goto Exit;
2502
2503 /* Convert the strings */
2504 RtlUnicodeToMultiByteN(lpName, *lpcbName, 0, NameBuffer, *lpcbName * sizeof(WCHAR));
2505 /* NULL terminate if we can */
2506 if (NameLength > *lpcbName)
2507 lpName[*lpcbName] = '\0';
2508
2509 if (lpClass)
2510 {
2511 RtlUnicodeToMultiByteN(lpClass, *lpcbClass, 0, NameBuffer, *lpcbClass * sizeof(WCHAR));
2512 if (ClassLength > *lpcbClass)
2513 lpClass[*lpcbClass] = '\0';
2514 }
2515
2516Exit:
2517 if (NameBuffer)
2518 RtlFreeHeap(RtlGetProcessHeap(), 0, NameBuffer);
2519 if (ClassBuffer)
2520 RtlFreeHeap(RtlGetProcessHeap(), 0, ClassBuffer);
2521
2522 return ErrorCode;
2523}
2524
2525
2526/************************************************************************
2527 * RegEnumKeyExW
2528 *
2529 * @implemented
2530 */
2531LONG
2532WINAPI
2534 _In_ HKEY hKey,
2535 _In_ DWORD dwIndex,
2537 _Inout_ LPDWORD lpcbName,
2538 _Reserved_ LPDWORD lpReserved,
2539 _Out_opt_ LPWSTR lpClass,
2540 _Inout_opt_ LPDWORD lpcbClass,
2541 _Out_opt_ PFILETIME lpftLastWriteTime)
2542{
2543 union
2544 {
2547 } *KeyInfo;
2548
2550 ULONG ResultSize;
2551 ULONG NameLength;
2552 ULONG ClassLength = 0;
2556
2558 hKey);
2559 if (!NT_SUCCESS(Status))
2560 {
2562 }
2563
2564 if (IsHKCRKey(KeyHandle))
2565 {
2567 KeyHandle,
2568 dwIndex,
2569 lpName,
2570 lpcbName,
2571 lpReserved,
2572 lpClass,
2573 lpcbClass,
2574 lpftLastWriteTime);
2576 return ErrorCode;
2577 }
2578
2579 if (*lpcbName > 0)
2580 {
2581 NameLength = min (*lpcbName - 1, REG_MAX_NAME_SIZE) * sizeof (WCHAR);
2582 }
2583 else
2584 {
2585 NameLength = 0;
2586 }
2587
2588 if (lpClass)
2589 {
2590 if (*lpcbClass > 0)
2591 {
2592 ClassLength = min (*lpcbClass - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
2593 }
2594 else
2595 {
2596 ClassLength = 0;
2597 }
2598
2599 BufferSize = ((sizeof(KEY_NODE_INFORMATION) + NameLength + 3) & ~3) + ClassLength;
2600 }
2601 else
2602 {
2603 BufferSize = sizeof(KEY_BASIC_INFORMATION) + NameLength;
2604 }
2605
2606 KeyInfo = RtlAllocateHeap(ProcessHeap,
2607 0,
2608 BufferSize);
2609 if (KeyInfo == NULL)
2610 {
2612 goto Cleanup;
2613 }
2614
2616 (ULONG)dwIndex,
2618 KeyInfo,
2619 BufferSize,
2620 &ResultSize);
2621 TRACE("NtEnumerateKey() returned status 0x%X\n", Status);
2622 if (!NT_SUCCESS(Status))
2623 {
2625 }
2626 else
2627 {
2628 if (lpClass == NULL)
2629 {
2630 if (KeyInfo->Basic.NameLength > NameLength)
2631 {
2633 }
2634 else
2635 {
2637 KeyInfo->Basic.Name,
2638 KeyInfo->Basic.NameLength);
2639 *lpcbName = (DWORD)(KeyInfo->Basic.NameLength / sizeof(WCHAR));
2640 lpName[*lpcbName] = 0;
2641 }
2642 }
2643 else
2644 {
2645 if (KeyInfo->Node.NameLength > NameLength ||
2646 KeyInfo->Node.ClassLength > ClassLength)
2647 {
2649 }
2650 else
2651 {
2653 KeyInfo->Node.Name,
2654 KeyInfo->Node.NameLength);
2655 *lpcbName = KeyInfo->Node.NameLength / sizeof(WCHAR);
2656 lpName[*lpcbName] = 0;
2657 RtlCopyMemory(lpClass,
2658 (PVOID)((ULONG_PTR)KeyInfo->Node.Name + KeyInfo->Node.ClassOffset),
2659 KeyInfo->Node.ClassLength);
2660 *lpcbClass = (DWORD)(KeyInfo->Node.ClassLength / sizeof(WCHAR));
2661 lpClass[*lpcbClass] = 0;
2662 }
2663 }
2664
2665 if (ErrorCode == ERROR_SUCCESS && lpftLastWriteTime != NULL)
2666 {
2667 if (lpClass == NULL)
2668 {
2669 lpftLastWriteTime->dwLowDateTime = KeyInfo->Basic.LastWriteTime.u.LowPart;
2670 lpftLastWriteTime->dwHighDateTime = KeyInfo->Basic.LastWriteTime.u.HighPart;
2671 }
2672 else
2673 {
2674 lpftLastWriteTime->dwLowDateTime = KeyInfo->Node.LastWriteTime.u.LowPart;
2675 lpftLastWriteTime->dwHighDateTime = KeyInfo->Node.LastWriteTime.u.HighPart;
2676 }
2677 }
2678 }
2679
2681 0,
2682 KeyInfo);
2683
2684Cleanup:
2686
2687 return ErrorCode;
2688}
2689
2690
2691/************************************************************************
2692 * RegEnumValueA
2693 *
2694 * @implemented
2695 */
2698 _In_ HKEY hKey,
2699 _In_ DWORD dwIndex,
2701 _Inout_ LPDWORD lpcbName,
2702 _Reserved_ LPDWORD lpdwReserved,
2703 _Out_opt_ LPDWORD lpdwType,
2704 _Out_opt_ LPBYTE lpData,
2705 _Inout_opt_ LPDWORD lpcbData)
2706{
2707 WCHAR* NameBuffer;
2708 DWORD NameBufferSize, NameLength;
2710 DWORD LocalType = REG_NONE;
2711 BOOL NameOverflow = FALSE;
2712
2713 /* Do parameter checks now, once and for all. */
2714 if (!lpName || !lpcbName)
2716
2717 if ((lpData && !lpcbData) || lpdwReserved)
2719
2720 /* Get the size of the buffer we must use for the first call to RegEnumValueW */
2722 hKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &NameBufferSize, NULL, NULL, NULL);
2723 if (ErrorCode != ERROR_SUCCESS)
2724 return ErrorCode;
2725
2726 /* Add space for the null terminator */
2727 NameBufferSize++;
2728
2729 /* Allocate the buffer for the unicode name */
2730 NameBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, NameBufferSize * sizeof(WCHAR));
2731 if (NameBuffer == NULL)
2732 {
2734 }
2735
2736 /*
2737 * This code calls RegEnumValueW twice, because we need to know the type of the enumerated value.
2738 * So for the first call, we check if we overflow on the name, as we have no way of knowing if this
2739 * is an overflow on the data or on the name during the the second call. So the first time, we make the
2740 * call with the supplied value. This is merdique, but this is how it is.
2741 */
2742 NameLength = *lpcbName;
2744 hKey,
2745 dwIndex,
2746 NameBuffer,
2747 &NameLength,
2748 NULL,
2749 &LocalType,
2750 NULL,
2751 NULL);
2752 if (ErrorCode != ERROR_SUCCESS)
2753 {
2755 NameOverflow = TRUE;
2756 else
2757 goto Exit;
2758 }
2759
2760 if (is_string(LocalType) && lpcbData)
2761 {
2762 /* We must allocate a buffer to get the unicode data */
2763 DWORD DataBufferSize = *lpcbData * sizeof(WCHAR);
2764 WCHAR* DataBuffer = NULL;
2765 DWORD DataLength = *lpcbData;
2766 LPSTR DataStr = (LPSTR)lpData;
2767
2768 if (lpData)
2769 DataBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, *lpcbData * sizeof(WCHAR));
2770
2771 /* Do the real call */
2773 hKey,
2774 dwIndex,
2775 NameBuffer,
2776 &NameBufferSize,
2777 lpdwReserved,
2778 lpdwType,
2779 (LPBYTE)DataBuffer,
2780 &DataBufferSize);
2781
2782 *lpcbData = DataBufferSize / sizeof(WCHAR);
2783
2784 if (ErrorCode != ERROR_SUCCESS)
2785 {
2786 RtlFreeHeap(RtlGetProcessHeap(), 0, DataBuffer);
2787 goto Exit;
2788 }
2789
2790 /* Copy the data whatever the error code is */
2791 if (lpData)
2792 {
2793 /* Do the data conversion */
2794 RtlUnicodeToMultiByteN(DataStr, DataLength, 0, DataBuffer, DataBufferSize);
2795 /* NULL-terminate if there is enough room */
2796 if ((DataLength > *lpcbData) && (DataStr[*lpcbData - 1] != '\0'))
2797 DataStr[*lpcbData] = '\0';
2798 }
2799
2800 RtlFreeHeap(RtlGetProcessHeap(), 0, DataBuffer);
2801 }
2802 else
2803 {
2804 /* No data conversion needed. Do the call with provided buffers */
2806 hKey,
2807 dwIndex,
2808 NameBuffer,
2809 &NameBufferSize,
2810 lpdwReserved,
2811 lpdwType,
2812 lpData,
2813 lpcbData);
2814
2815 if (ErrorCode != ERROR_SUCCESS)
2816 {
2817 goto Exit;
2818 }
2819 }
2820
2821 if (NameOverflow)
2822 {
2824 goto Exit;
2825 }
2826
2827 /* Convert the name string */
2828 RtlUnicodeToMultiByteN(lpName, *lpcbName, lpcbName, NameBuffer, NameBufferSize * sizeof(WCHAR));
2829 lpName[*lpcbName] = ANSI_NULL;
2830
2831Exit:
2832 if (NameBuffer)
2833 RtlFreeHeap(RtlGetProcessHeap(), 0, NameBuffer);
2834
2835 return ErrorCode;
2836}
2837
2838
2839/******************************************************************************
2840 * RegEnumValueW [ADVAPI32.@]
2841 * @implemented
2842 *
2843 * PARAMS
2844 * hkey [I] Handle to key to query
2845 * index [I] Index of value to query
2846 * value [O] Value string
2847 * val_count [I/O] Size of value buffer (in wchars)
2848 * reserved [I] Reserved
2849 * type [O] Type code
2850 * data [O] Value data
2851 * count [I/O] Size of data buffer (in bytes)
2852 *
2853 * RETURNS
2854 * Success: ERROR_SUCCESS
2855 * Failure: nonzero error code from Winerror.h
2856 */
2857LONG
2858WINAPI
2860 _In_ HKEY hKey,
2863 _Inout_ PDWORD val_count,
2868{
2871 ULONG total_size;
2872 char buffer[256], *buf_ptr = buffer;
2874 static const int info_size = FIELD_OFFSET( KEY_VALUE_FULL_INFORMATION, Name );
2875
2876 TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
2877 hKey, index, value, val_count, reserved, type, data, count );
2878
2879 if (!value || !val_count)
2881
2882 if ((data && !count) || reserved)
2884
2886 if (!NT_SUCCESS(status))
2887 {
2889 }
2890
2891 if (IsHKCRKey(KeyHandle))
2892 {
2894 KeyHandle,
2895 index,
2896 value,
2897 val_count,
2898 reserved,
2899 type,
2900 data,
2901 count);
2903 return ErrorCode;
2904 }
2905
2906 total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR);
2907 if (data) total_size += *count;
2908 total_size = min( sizeof(buffer), total_size );
2909
2911 buffer, total_size, &total_size );
2912 if (status && (status != STATUS_BUFFER_OVERFLOW) && (status != STATUS_BUFFER_TOO_SMALL)) goto done;
2913
2914 if (value || data)
2915 {
2916 /* retry with a dynamically allocated buffer */
2918 {
2919 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
2920 if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
2921 {
2923 goto done;
2924 }
2925 info = (KEY_VALUE_FULL_INFORMATION *)buf_ptr;
2927 buf_ptr, total_size, &total_size );
2928 }
2929
2930 if (status) goto done;
2931
2932 if (value)
2933 {
2934 if (info->NameLength/sizeof(WCHAR) >= *val_count)
2935 {
2937 goto overflow;
2938 }
2939 memcpy( value, info->Name, info->NameLength );
2940 *val_count = info->NameLength / sizeof(WCHAR);
2941 value[*val_count] = 0;
2942 }
2943
2944 if (data)
2945 {
2946 if (info->DataLength > *count)
2947 {
2949 goto overflow;
2950 }
2951 memcpy( data, buf_ptr + info->DataOffset, info->DataLength );
2952 if (is_string(info->Type) && info->DataLength <= *count - sizeof(WCHAR))
2953 {
2954 /* if the type is REG_SZ and data is not 0-terminated
2955 * and there is enough space in the buffer NT appends a \0 */
2956 WCHAR *ptr = (WCHAR *)(data + info->DataLength);
2957 if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
2958 }
2959 }
2960 }
2961 else status = STATUS_SUCCESS;
2962
2963 overflow:
2964 if (type) *type = info->Type;
2965 if (count) *count = info->DataLength;
2966
2967 done:
2968 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
2971}
2972
2973
2974/************************************************************************
2975 * RegFlushKey
2976 *
2977 * @implemented
2978 */
2981{
2984
2986 {
2987 return ERROR_SUCCESS;
2988 }
2989
2991 hKey);
2992 if (!NT_SUCCESS(Status))
2993 {
2995 }
2996
2998
3000
3001 if (!NT_SUCCESS(Status))
3002 {
3004 }
3005
3006 return ERROR_SUCCESS;
3007}
3008
3009
3010/************************************************************************
3011 * RegGetKeySecurity
3012 *
3013 * @implemented
3014 */
3018 PSECURITY_DESCRIPTOR pSecurityDescriptor,
3019 LPDWORD lpcbSecurityDescriptor)
3020{
3023
3025 {
3026 return ERROR_INVALID_HANDLE;
3027 }
3028
3030 hKey);
3031 if (!NT_SUCCESS(Status))
3032 {
3033 TRACE("MapDefaultKey() failed (Status %lx)\n", Status);
3035 }
3036
3039 pSecurityDescriptor,
3040 *lpcbSecurityDescriptor,
3041 lpcbSecurityDescriptor);
3042
3044
3045 if (!NT_SUCCESS(Status))
3046 {
3047 WARN("NtQuerySecurityObject() failed (Status %lx)\n", Status);
3049 }
3050
3051 return ERROR_SUCCESS;
3052}
3053
3054
3055/************************************************************************
3056 * RegLoadKeyA
3057 *
3058 * @implemented
3059 */
3062 LPCSTR lpSubKey,
3063 LPCSTR lpFile)
3064{
3068
3069 RtlInitEmptyUnicodeString(&KeyName, NULL, 0);
3070 RtlInitEmptyUnicodeString(&FileName, NULL, 0);
3071
3072 if (lpSubKey)
3073 {
3075 {
3077 goto Exit;
3078 }
3079 }
3080
3081 if (lpFile)
3082 {
3084 {
3086 goto Exit;
3087 }
3088 }
3089
3091 KeyName.Buffer,
3092 FileName.Buffer);
3093
3094Exit:
3097
3098 return ErrorCode;
3099}
3100
3101
3102/************************************************************************
3103 * RegLoadKeyW
3104 *
3105 * @implemented
3106 */
3109 LPCWSTR lpSubKey,
3110 LPCWSTR lpFile)
3111{
3113 OBJECT_ATTRIBUTES KeyObjectAttributes;
3119
3121 {
3122 return ERROR_INVALID_HANDLE;
3123 }
3124
3126 hKey);
3127 if (!NT_SUCCESS(Status))
3128 {
3130 }
3131
3132 if (!RtlDosPathNameToNtPathName_U(lpFile,
3133 &FileName,
3134 NULL,
3135 NULL))
3136 {
3138 goto Cleanup;
3139 }
3140
3142 &FileName,
3144 NULL,
3145 NULL);
3146
3147 RtlInitUnicodeString(&KeyName, lpSubKey);
3148
3149 InitializeObjectAttributes(&KeyObjectAttributes,
3150 &KeyName,
3152 KeyHandle,
3153 NULL);
3154
3155 Status = NtLoadKey(&KeyObjectAttributes,
3157
3158 RtlFreeHeap(RtlGetProcessHeap(),
3159 0,
3160 FileName.Buffer);
3161
3162 if (!NT_SUCCESS(Status))
3163 {
3165 goto Cleanup;
3166 }
3167
3168Cleanup:
3170
3171 return ErrorCode;
3172}
3173
3174
3175/************************************************************************
3176 * RegNotifyChangeKeyValue
3177 *
3178 * @unimplemented
3179 */
3182 BOOL bWatchSubtree,
3183 DWORD dwNotifyFilter,
3184 HANDLE hEvent,
3185 BOOL fAsynchronous)
3186{
3191
3193 {
3194 return ERROR_INVALID_HANDLE;
3195 }
3196
3197 if ((fAsynchronous != FALSE) && (hEvent == NULL))
3198 {
3200 }
3201
3203 hKey);
3204 if (!NT_SUCCESS(Status))
3205 {
3207 }
3208
3209 /* FIXME: Remote key handles must fail */
3210
3212 hEvent,
3213 0,
3214 0,
3216 dwNotifyFilter,
3217 bWatchSubtree,
3218 0,
3219 0,
3220 fAsynchronous);
3222 {
3224 }
3225
3227
3228 return ErrorCode;
3229}
3230
3231
3232/************************************************************************
3233 * RegOpenCurrentUser
3234 *
3235 * @implemented
3236 */
3239 OUT PHKEY phkResult)
3240{
3242
3244 (PHANDLE)phkResult);
3245 if (!NT_SUCCESS(Status))
3246 {
3247 /* NOTE - don't set the last error code! just return the error! */
3249 }
3250
3251 return ERROR_SUCCESS;
3252}
3253
3254
3255/************************************************************************
3256 * RegOpenKeyA
3257 *
3258 * 20050503 Fireball - imported from WINE
3259 *
3260 * @implemented
3261 */
3264 LPCSTR lpSubKey,
3265 PHKEY phkResult)
3266{
3267 TRACE("RegOpenKeyA hKey 0x%x lpSubKey %s phkResult %p\n",
3268 hKey, lpSubKey, phkResult);
3269
3270 if (!phkResult)
3272
3273 if (!hKey && !lpSubKey)
3274 {
3275 *phkResult = hKey;
3276 return ERROR_SUCCESS;
3277 }
3278
3279 return RegOpenKeyExA(hKey,
3280 lpSubKey,
3281 0,
3283 phkResult);
3284}
3285
3286
3287/************************************************************************
3288 * RegOpenKeyW
3289 *
3290 * 19981101 Ariadne
3291 * 19990525 EA
3292 * 20050503 Fireball - imported from WINE
3293 *
3294 * @implemented
3295 */
3298 LPCWSTR lpSubKey,
3299 PHKEY phkResult)
3300{
3301 TRACE("RegOpenKeyW hKey 0x%x lpSubKey %S phkResult %p\n",
3302 hKey, lpSubKey, phkResult);
3303
3304 if (!phkResult)
3306
3307 if (!hKey && !lpSubKey)
3308 {
3309 *phkResult = hKey;
3310 return ERROR_SUCCESS;
3311 }
3312
3313 return RegOpenKeyExW(hKey,
3314 lpSubKey,
3315 0,
3317 phkResult);
3318}
3319
3320
3321/************************************************************************
3322 * RegOpenKeyExA
3323 *
3324 * @implemented
3325 */
3328 _In_ HKEY hKey,
3329 _In_ LPCSTR lpSubKey,
3330 _In_ DWORD ulOptions,
3331 _In_ REGSAM samDesired,
3332 _Out_ PHKEY phkResult)
3333{
3334 UNICODE_STRING SubKeyString;
3336
3337 TRACE("RegOpenKeyExA hKey 0x%x lpSubKey %s ulOptions 0x%x samDesired 0x%x phkResult %p\n",
3338 hKey, lpSubKey, ulOptions, samDesired, phkResult);
3339
3340 if (lpSubKey)
3341 {
3342 if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyString, lpSubKey))
3344 }
3345 else
3346 RtlInitEmptyUnicodeString(&SubKeyString, NULL, 0);
3347
3348 ErrorCode = RegOpenKeyExW(hKey, SubKeyString.Buffer, ulOptions, samDesired, phkResult);
3349
3350 RtlFreeUnicodeString(&SubKeyString);
3351
3352 return ErrorCode;
3353}
3354
3355
3356/************************************************************************
3357 * RegOpenKeyExW
3358 *
3359 * @implemented
3360 */
3363 LPCWSTR lpSubKey,
3364 DWORD ulOptions,
3365 REGSAM samDesired,
3366 PHKEY phkResult)
3367{
3369 UNICODE_STRING SubKeyString;
3374 BOOLEAN SubKeyStringAllocated = FALSE;
3375
3376 TRACE("RegOpenKeyExW hKey 0x%x lpSubKey %S ulOptions 0x%x samDesired 0x%x phkResult %p\n",
3377 hKey, lpSubKey, ulOptions, samDesired, phkResult);
3378 if (!phkResult)
3379 {
3381 }
3382
3383 if (!hKey && lpSubKey && phkResult)
3384 {
3385 return ERROR_INVALID_HANDLE;
3386 }
3387
3388 if (IsPredefKey(hKey) && (!lpSubKey || !*lpSubKey))
3389 {
3390 *phkResult = hKey;
3391 return ERROR_SUCCESS;
3392 }
3393
3395 if (!NT_SUCCESS(Status))
3396 {
3398 }
3399
3400 if (IsHKCRKey(KeyHandle))
3401 {
3402 ErrorCode = OpenHKCRKey(KeyHandle, lpSubKey, ulOptions, samDesired, phkResult);
3404 return ErrorCode;
3405 }
3406
3407 if (ulOptions & REG_OPTION_OPEN_LINK)
3409
3410 if (lpSubKey == NULL || wcscmp(lpSubKey, L"\\") == 0)
3411 {
3412 RtlInitUnicodeString(&SubKeyString, L"");
3413 }
3414 else
3415 {
3416 RtlInitUnicodeString(&SubKeyString, lpSubKey);
3417
3418 /* Handle unaligned lpSubKey */
3419 if ((ULONG_PTR)lpSubKey & 1)
3420 {
3421 UNICODE_STRING AlignedString;
3422
3424 &SubKeyString,
3425 &AlignedString);
3426 if (!NT_SUCCESS(Status))
3427 {
3428 goto Exit;
3429 }
3430
3431 SubKeyString = AlignedString;
3432 SubKeyStringAllocated = TRUE;
3433 }
3434 }
3435
3437 &SubKeyString,
3438 Attributes,
3439 KeyHandle,
3440 NULL);
3441
3442 Status = NtOpenKey((PHANDLE)phkResult,
3443 samDesired,
3445
3446Exit:
3447
3448 if (SubKeyStringAllocated)
3449 {
3450 RtlFreeUnicodeString(&SubKeyString);
3451 }
3452
3453 if (!NT_SUCCESS(Status))
3454 {
3456 }
3457
3459
3460 return ErrorCode;
3461}
3462
3463
3464/************************************************************************
3465 * RegOpenUserClassesRoot
3466 *
3467 * @implemented
3468 */
3472 IN REGSAM samDesired,
3473 OUT PHKEY phkResult)
3474{
3475 const WCHAR UserClassesKeyPrefix[] = L"\\Registry\\User\\";
3476 const WCHAR UserClassesKeySuffix[] = L"_Classes";
3477 PTOKEN_USER TokenUserData;
3479 UNICODE_STRING UserSidString, UserClassesKeyRoot;
3482
3483 /* check parameters */
3484 if (hToken == NULL || dwOptions != 0 || phkResult == NULL)
3485 {
3487 }
3488
3489 /*
3490 * Get the user sid from the token
3491 */
3492
3493ReadTokenSid:
3494 /* determine how much memory we need */
3496 TokenUser,
3497 NULL,
3498 0,
3501 {
3502 /* NOTE - as opposed to all other registry functions windows does indeed
3503 change the last error code in case the caller supplied a invalid
3504 handle for example! */
3506 }
3507 RegInitialize(); /* HACK until delay-loading is implemented */
3508 TokenUserData = RtlAllocateHeap(ProcessHeap,
3509 0,
3511 if (TokenUserData == NULL)
3512 {
3514 }
3515
3516 /* attempt to read the information */
3518 TokenUser,
3519 TokenUserData,
3522 if (!NT_SUCCESS(Status))
3523 {
3525 0,
3526 TokenUserData);
3528 {
3529 /* the information appears to have changed?! try again */
3530 goto ReadTokenSid;
3531 }
3532
3533 /* NOTE - as opposed to all other registry functions windows does indeed
3534 change the last error code in case the caller supplied a invalid
3535 handle for example! */
3537 }
3538
3539 /*
3540 * Build the absolute path for the user's registry in the form
3541 * "\Registry\User<SID>_Classes"
3542 */
3543 Status = RtlConvertSidToUnicodeString(&UserSidString,
3544 TokenUserData->User.Sid,
3545 TRUE);
3546
3547 /* we don't need the user data anymore, free it */
3549 0,
3550 TokenUserData);
3551
3552 if (!NT_SUCCESS(Status))
3553 {
3555 }
3556
3557 /* allocate enough memory for the entire key string */
3558 UserClassesKeyRoot.Length = 0;
3559 UserClassesKeyRoot.MaximumLength = UserSidString.Length +
3560 sizeof(UserClassesKeyPrefix) +
3561 sizeof(UserClassesKeySuffix);
3562 UserClassesKeyRoot.Buffer = RtlAllocateHeap(ProcessHeap,
3563 0,
3564 UserClassesKeyRoot.MaximumLength);
3565 if (UserClassesKeyRoot.Buffer == NULL)
3566 {
3567 RtlFreeUnicodeString(&UserSidString);
3569 }
3570
3571 /* build the string */
3572 RtlAppendUnicodeToString(&UserClassesKeyRoot,
3573 UserClassesKeyPrefix);
3574 RtlAppendUnicodeStringToString(&UserClassesKeyRoot,
3575 &UserSidString);
3576 RtlAppendUnicodeToString(&UserClassesKeyRoot,
3577 UserClassesKeySuffix);
3578
3579 TRACE("RegOpenUserClassesRoot: Absolute path: %wZ\n", &UserClassesKeyRoot);
3580
3581 /*
3582 * Open the key
3583 */
3585 &UserClassesKeyRoot,
3587 NULL,
3588 NULL);
3589
3590 Status = NtOpenKey((PHANDLE)phkResult,
3591 samDesired,
3593
3594 RtlFreeUnicodeString(&UserSidString);
3595 RtlFreeUnicodeString(&UserClassesKeyRoot);
3596
3597 if (!NT_SUCCESS(Status))
3598 {
3600 }
3601
3602 return ERROR_SUCCESS;
3603}
3604
3605
3606/************************************************************************
3607 * RegQueryInfoKeyA
3608 *
3609 * @implemented
3610 */
3613 LPSTR lpClass,
3614 LPDWORD lpcClass,
3615 LPDWORD lpReserved,
3616 LPDWORD lpcSubKeys,
3617 LPDWORD lpcMaxSubKeyLen,
3618 LPDWORD lpcMaxClassLen,
3619 LPDWORD lpcValues,
3620 LPDWORD lpcMaxValueNameLen,
3621 LPDWORD lpcMaxValueLen,
3622 LPDWORD lpcbSecurityDescriptor,
3623 PFILETIME lpftLastWriteTime)
3624{
3625 WCHAR ClassName[MAX_PATH];
3630 DWORD cClass = 0;
3631
3632 if ((lpClass) && (!lpcClass))
3633 {
3635 }
3636
3638 NULL);
3639 if (lpClass != NULL)
3640 {
3641 RtlInitEmptyUnicodeString(&UnicodeString,
3642 ClassName,
3643 sizeof(ClassName));
3644 cClass = sizeof(ClassName) / sizeof(WCHAR);
3645 }
3646
3648 UnicodeString.Buffer,
3649 &cClass,
3650 lpReserved,
3651 lpcSubKeys,
3652 lpcMaxSubKeyLen,
3653 lpcMaxClassLen,
3654 lpcValues,
3655 lpcMaxValueNameLen,
3656 lpcMaxValueLen,
3657 lpcbSecurityDescriptor,
3658 lpftLastWriteTime);
3659 if ((ErrorCode == ERROR_SUCCESS) && (lpClass != NULL))
3660 {
3661 if (*lpcClass == 0)
3662 {
3663 return ErrorCode;
3664 }
3665
3666 RtlInitEmptyAnsiString(&AnsiString, lpClass, *lpcClass);
3667 UnicodeString.Length = cClass * sizeof(WCHAR);
3670 FALSE);
3672 cClass = AnsiString.Length;
3673 lpClass[cClass] = ANSI_NULL;
3674 }
3675
3676 if (lpcClass != NULL)
3677 {
3678 *lpcClass = cClass;
3679 }
3680
3681 return ErrorCode;
3682}
3683
3684
3685/************************************************************************
3686 * RegQueryInfoKeyW
3687 *
3688 * @implemented
3689 */
3692 LPWSTR lpClass,
3693 LPDWORD lpcClass,
3694 LPDWORD lpReserved,
3695 LPDWORD lpcSubKeys,
3696 LPDWORD lpcMaxSubKeyLen,
3697 LPDWORD lpcMaxClassLen,
3698 LPDWORD lpcValues,
3699 LPDWORD lpcMaxValueNameLen,
3700 LPDWORD lpcMaxValueLen,
3701 LPDWORD lpcbSecurityDescriptor,
3702 PFILETIME lpftLastWriteTime)
3703{
3704 KEY_FULL_INFORMATION FullInfoBuffer;
3705 PKEY_FULL_INFORMATION FullInfo;
3706 ULONG FullInfoSize;
3707 ULONG ClassLength = 0;
3710 ULONG Length;
3712
3713 if ((lpClass) && (!lpcClass))
3714 {
3716 }
3717
3719 hKey);
3720 if (!NT_SUCCESS(Status))
3721 {
3723 }
3724
3725 if (IsHKCRKey(KeyHandle))
3726 {
3727 ErrorCode = QueryInfoHKCRKey(KeyHandle, lpClass, lpcClass, lpReserved,
3728 lpcSubKeys, lpcMaxSubKeyLen, lpcMaxClassLen,
3729 lpcValues, lpcMaxValueNameLen, lpcMaxValueLen,
3730 lpcbSecurityDescriptor, lpftLastWriteTime);
3732 return ErrorCode;
3733 }
3734
3735 if (lpClass != NULL)
3736 {
3737 if (*lpcClass > 0)
3738 {
3739 ClassLength = min(*lpcClass - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
3740 }
3741 else
3742 {
3743 ClassLength = 0;
3744 }
3745
3746 FullInfoSize = sizeof(KEY_FULL_INFORMATION) + ((ClassLength + 3) & ~3);
3747 FullInfo = RtlAllocateHeap(ProcessHeap,
3748 0,
3749 FullInfoSize);
3750 if (FullInfo == NULL)
3751 {
3753 goto Cleanup;
3754 }
3755 }
3756 else
3757 {
3758 FullInfoSize = sizeof(KEY_FULL_INFORMATION);
3759 FullInfo = &FullInfoBuffer;
3760 }
3761
3762 if (lpcbSecurityDescriptor != NULL)
3763 *lpcbSecurityDescriptor = 0;
3764
3767 FullInfo,
3768 FullInfoSize,
3769 &Length);
3770 TRACE("NtQueryKey() returned status 0x%X\n", Status);
3772 {
3774 goto Cleanup;
3775 }
3776
3777 TRACE("SubKeys %d\n", FullInfo->SubKeys);
3778 if (lpcSubKeys != NULL)
3779 {
3780 *lpcSubKeys = FullInfo->SubKeys;
3781 }
3782
3783 TRACE("MaxNameLen %lu\n", FullInfo->MaxNameLen);
3784 if (lpcMaxSubKeyLen != NULL)
3785 {
3786 *lpcMaxSubKeyLen = FullInfo->MaxNameLen / sizeof(WCHAR);
3787 }
3788
3789 TRACE("MaxClassLen %lu\n", FullInfo->MaxClassLen);
3790 if (lpcMaxClassLen != NULL)
3791 {
3792 *lpcMaxClassLen = FullInfo->MaxClassLen / sizeof(WCHAR);
3793 }
3794
3795 TRACE("Values %lu\n", FullInfo->Values);
3796 if (lpcValues != NULL)
3797 {
3798 *lpcValues = FullInfo->Values;
3799 }
3800
3801 TRACE("MaxValueNameLen %lu\n", FullInfo->MaxValueNameLen);
3802 if (lpcMaxValueNameLen != NULL)
3803 {
3804 *lpcMaxValueNameLen = FullInfo->MaxValueNameLen / sizeof(WCHAR);
3805 }
3806
3807 TRACE("MaxValueDataLen %lu\n", FullInfo->MaxValueDataLen);
3808 if (lpcMaxValueLen != NULL)
3809 {
3810 *lpcMaxValueLen = FullInfo->MaxValueDataLen;
3811 }
3812
3813 if (lpcbSecurityDescriptor != NULL)
3814 {
3819 NULL,
3820 0,
3821 lpcbSecurityDescriptor);
3822 TRACE("NtQuerySecurityObject() returned status 0x%X\n", Status);
3823 }
3824
3825 if (lpftLastWriteTime != NULL)
3826 {
3827 lpftLastWriteTime->dwLowDateTime = FullInfo->LastWriteTime.u.LowPart;
3828 lpftLastWriteTime->dwHighDateTime = FullInfo->LastWriteTime.u.HighPart;
3829 }
3830
3831 if (lpClass != NULL)
3832 {
3833 if (*lpcClass == 0)
3834 {
3835 goto Cleanup;
3836 }
3837
3838 if (FullInfo->ClassLength > ClassLength)
3839 {
3841 }
3842 else
3843 {
3844 RtlCopyMemory(lpClass,
3845 FullInfo->Class,
3846 FullInfo->ClassLength);
3847 lpClass[FullInfo->ClassLength / sizeof(WCHAR)] = UNICODE_NULL;
3848 }
3849 }
3850
3851 if (lpcClass != NULL)
3852 {
3853 *lpcClass = FullInfo->ClassLength / sizeof(WCHAR);
3854 }
3855
3856Cleanup:
3857 if (lpClass != NULL)
3858 {
3860 0,
3861 FullInfo);
3862 }
3863
3865
3866 return ErrorCode;
3867}
3868
3869
3870/************************************************************************
3871 * RegQueryMultipleValuesA
3872 *
3873 * @implemented
3874 */
3877 PVALENTA val_list,
3878 DWORD num_vals,
3879 LPSTR lpValueBuf,
3880 LPDWORD ldwTotsize)
3881{
3882 ULONG i;
3883 DWORD maxBytes = *ldwTotsize;
3884 LPSTR bufptr = lpValueBuf;
3886
3887 if (maxBytes >= (1024*1024))
3888 return ERROR_MORE_DATA;
3889
3890 *ldwTotsize = 0;
3891
3892 TRACE("RegQueryMultipleValuesA(%p,%p,%ld,%p,%p=%ld)\n",
3893 hKey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize);
3894
3895 for (i = 0; i < num_vals; i++)
3896 {
3897 val_list[i].ve_valuelen = 0;
3899 val_list[i].ve_valuename,
3900 NULL,
3901 NULL,
3902 NULL,
3903 &val_list[i].ve_valuelen);
3904 if (ErrorCode != ERROR_SUCCESS)
3905 {
3906 return ErrorCode;
3907 }
3908
3909 if (lpValueBuf != NULL && *ldwTotsize + val_list[i].ve_valuelen <= maxBytes)
3910 {
3912 val_list[i].ve_valuename,
3913 NULL,
3914 &val_list[i].ve_type,
3915 (LPBYTE)bufptr,
3916 &val_list[i].ve_valuelen);
3917 if (ErrorCode != ERROR_SUCCESS)
3918 {
3919 return ErrorCode;
3920 }
3921
3922 val_list[i].ve_valueptr = (DWORD_PTR)bufptr;
3923
3924 bufptr += val_list[i].ve_valuelen;
3925 }
3926
3927 *ldwTotsize += val_list[i].ve_valuelen;
3928 }
3929
3930 return (lpValueBuf != NULL && *ldwTotsize <= maxBytes) ? ERROR_SUCCESS : ERROR_MORE_DATA;
3931}
3932
3933
3934/************************************************************************
3935 * RegQueryMultipleValuesW
3936 *
3937 * @implemented
3938 */
3941 PVALENTW val_list,
3942 DWORD num_vals,
3943 LPWSTR lpValueBuf,
3944 LPDWORD ldwTotsize)
3945{
3946 ULONG i;
3947 DWORD maxBytes = *ldwTotsize;
3948 LPSTR bufptr = (LPSTR)lpValueBuf;
3950
3951 if (maxBytes >= (1024*1024))
3952 return ERROR_MORE_DATA;
3953
3954 *ldwTotsize = 0;
3955
3956 TRACE("RegQueryMultipleValuesW(%p,%p,%ld,%p,%p=%ld)\n",
3957 hKey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize);
3958
3959 for (i = 0; i < num_vals; i++)
3960 {
3961 val_list[i].ve_valuelen = 0;
3963 val_list[i].ve_valuename,
3964 NULL,
3965 NULL,
3966 NULL,
3967 &val_list[i].ve_valuelen);
3968 if (ErrorCode != ERROR_SUCCESS)
3969 {
3970 return ErrorCode;
3971 }
3972
3973 if (lpValueBuf != NULL && *ldwTotsize + val_list[i].ve_valuelen <= maxBytes)
3974 {
3976 val_list[i].ve_valuename,
3977 NULL,
3978 &val_list[i].ve_type,
3979 (LPBYTE)bufptr,
3980 &val_list[i].ve_valuelen);
3981 if (ErrorCode != ERROR_SUCCESS)
3982 {
3983 return ErrorCode;
3984 }
3985
3986 val_list[i].ve_valueptr = (DWORD_PTR)bufptr;
3987
3988 bufptr += val_list[i].ve_valuelen;
3989 }
3990
3991 *ldwTotsize += val_list[i].ve_valuelen;
3992 }
3993
3994 return (lpValueBuf != NULL && *ldwTotsize <= maxBytes) ? ERROR_SUCCESS : ERROR_MORE_DATA;
3995}
3996
3997
3998/************************************************************************
3999 * RegQueryReflectionKey
4000 *
4001 * @unimplemented
4002 */
4005 OUT BOOL* bIsReflectionDisabled)
4006{
4007 FIXME("RegQueryReflectionKey(0x%p, 0x%p) UNIMPLEMENTED!\n",
4008 hBase, bIsReflectionDisabled);
4010}
4011
4012
4013/******************************************************************************
4014 * RegQueryValueExA [ADVAPI32.@]
4015 *
4016 * Get the type and contents of a specified value under with a key.
4017 *
4018 * PARAMS
4019 * hkey [I] Handle of the key to query
4020 * name [I] Name of value under hkey to query
4021 * reserved [I] Reserved - must be NULL
4022 * type [O] Destination for the value type, or NULL if not required
4023 * data [O] Destination for the values contents, or NULL if not required
4024 * count [I/O] Size of data, updated with the number of bytes returned
4025 *
4026 * RETURNS
4027 * Success: ERROR_SUCCESS. *count is updated with the number of bytes copied to data.
4028 * Failure: ERROR_INVALID_HANDLE, if hkey is invalid.
4029 * ERROR_INVALID_PARAMETER, if any other parameter is invalid.
4030 * ERROR_MORE_DATA, if on input *count is too small to hold the contents.
4031 *
4032 * NOTES
4033 * MSDN states that if data is too small it is partially filled. In reality
4034 * it remains untouched.
4035 */
4036LONG
4037WINAPI
4039 _In_ HKEY hkeyorg,
4045{
4049 DWORD BufferSize = 0;
4050 WCHAR* Buffer;
4051 CHAR* DataStr = (CHAR*)data;
4052 DWORD LocalType;
4053
4054 /* Validate those parameters, the rest will be done with the first RegQueryValueExW call */
4055 if ((data && !count) || reserved)
4057
4058 if (name)
4059 {
4062 }
4063 else
4064 RtlInitEmptyUnicodeString(&nameW, NULL, 0);
4065
4066 ErrorCode = RegQueryValueExW(hkeyorg, nameW.Buffer, NULL, &LocalType, NULL, &BufferSize);
4067 if (ErrorCode != ERROR_SUCCESS)
4068 {
4069 if ((!data) && count)
4070 *count = 0;
4072 return ErrorCode;
4073 }
4074
4075 /* See if we can directly handle the call without caring for conversion */
4076 if (!is_string(LocalType) || !count)
4077 {
4078 ErrorCode = RegQueryValueExW(hkeyorg, nameW.Buffer, reserved, type, data, count);
4080 return ErrorCode;
4081 }
4082
4083 /* Allocate a unicode string to get the data */
4084 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
4085 if (!Buffer)
4086 {
4089 }
4090
4092 if (ErrorCode != ERROR_SUCCESS)
4093 {
4094 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
4096 return ErrorCode;
4097 }
4098
4099 /* We don't need this anymore */
4101
4102 /* Get the length for the multi-byte string (without the terminating NULL!) */
4103 DataLength = *count;
4105
4106 if ((!data) || (DataLength < *count))
4107 {
4108 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
4110 }
4111
4112 /* We can finally do the conversion */
4114
4115 /* NULL-terminate if there is enough room */
4116 if (DataLength > *count)
4117 DataStr[*count] = '\0';
4118
4119 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
4120
4121 return ERROR_SUCCESS;
4122}
4123
4124
4125/************************************************************************
4126 * RegQueryValueExW
4127 *
4128 * @implemented
4129 */
4130LONG
4131WINAPI
4133 _In_ HKEY hkeyorg,
4139{
4140 HANDLE hkey;
4142 UNICODE_STRING name_str;
4143 DWORD total_size;
4144 char buffer[256], *buf_ptr = buffer;
4146 static const int info_size = offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data );
4147
4148 TRACE("(%p,%s,%p,%p,%p,%p=%d)\n",
4149 hkeyorg, debugstr_w(name), reserved, type, data, count,
4150 (count && data) ? *count : 0 );
4151
4152 if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
4153
4154 status = MapDefaultKey(&hkey, hkeyorg);
4155 if (!NT_SUCCESS(status))
4156 {
4158 }
4159
4160 if (IsHKCRKey(hkey))
4161 {
4163 ClosePredefKey(hkey);
4164 return ErrorCode;
4165 }
4166
4167 RtlInitUnicodeString( &name_str, name );
4168
4169 if (data)
4170 total_size = min( sizeof(buffer), *count + info_size );
4171 else
4172 total_size = info_size;
4173
4174
4176 buffer, total_size, &total_size );
4177
4179 {
4180 // NT: Valid handles with inexistant/null values or invalid (but not NULL) handles sets type to REG_NONE
4181 // On windows these conditions are likely to be side effects of the implementation...
4182 if (status == STATUS_INVALID_HANDLE && hkey)
4183 {
4184 if (type) *type = REG_NONE;
4185 if (count) *count = 0;
4186 }
4188 {
4189 if (type) *type = REG_NONE;
4190 if (data == NULL && count) *count = 0;
4191 }
4192 goto done;
4193 }
4194
4195 if (data)
4196 {
4197 /* retry with a dynamically allocated buffer */
4198 while (status == STATUS_BUFFER_OVERFLOW && total_size - info_size <= *count)
4199 {
4200 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
4201 if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
4202 {
4203 ClosePredefKey(hkey);
4205 }
4208 buf_ptr, total_size, &total_size );
4209 }
4210
4211 if (NT_SUCCESS(status))
4212 {
4213 memcpy( data, buf_ptr + info_size, total_size - info_size );
4214 /* if the type is REG_SZ and data is not 0-terminated
4215 * and there is enough space in the buffer NT appends a \0 */
4216 if (is_string(info->Type) && total_size - info_size <= *count-sizeof(WCHAR))
4217 {
4218 WCHAR *ptr = (WCHAR *)(data + total_size - info_size);
4219 if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
4220 }
4221 }
4222 else if (status != STATUS_BUFFER_OVERFLOW) goto done;
4223 }
4224 else status = STATUS_SUCCESS;
4225
4226 if (type) *type = info->Type;
4227 if (count) *count = total_size - info_size;
4228
4229 done:
4230 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
4231 ClosePredefKey(hkey);
4233}
4234
4235
4236/************************************************************************
4237 * RegQueryValueA
4238 *
4239 * @implemented
4240 */
4242{
4243 DWORD ret;
4244 HKEY subkey = hkey;
4245
4246 TRACE("(%p,%s,%p,%d)\n", hkey, debugstr_a(name), data, count ? *count : 0 );
4247
4248 if (name && name[0])
4249 {
4250 if ((ret = RegOpenKeyA( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
4251 }
4253 if (subkey != hkey) RegCloseKey( subkey );
4255 {
4256 /* return empty string if default value not found */
4257 if (data) *data = 0;
4258 if (count) *count = 1;
4260 }
4261 return ret;
4262}
4263
4264
4265/************************************************************************
4266 * RegQueryValueW
4267 *
4268 * @implemented
4269 */
4271{
4272 DWORD ret;
4273 HKEY subkey = hkey;
4274
4275 TRACE("(%p,%s,%p,%d)\n", hkey, debugstr_w(name), data, count ? *count : 0 );
4276 if (hkey == NULL)
4277 {
4278 return ERROR_INVALID_HANDLE;
4279 }
4280 if (name && name[0])
4281 {
4282 ret = RegOpenKeyW( hkey, name, &subkey);
4283 if (ret != ERROR_SUCCESS)
4284 {
4285 return ret;
4286 }
4287 }
4288
4290
4291 if (subkey != hkey)
4292 {
4293 RegCloseKey( subkey );
4294 }
4295
4297 {
4298 /* return empty string if default value not found */
4299 if (data)
4300 *data = 0;
4301 if (count)
4302 *count = sizeof(WCHAR);
4304 }
4305 return ret;
4306}
4307
4308
4309/************************************************************************
4310 * RegReplaceKeyA
4311 *
4312 * @implemented
4313 */
4316 LPCSTR lpSubKey,
4317 LPCSTR lpNewFile,
4318 LPCSTR lpOldFile)
4319{
4320 UNICODE_STRING SubKey;
4321 UNICODE_STRING NewFile;
4322 UNICODE_STRING OldFile;
4324
4325 RtlInitEmptyUnicodeString(&SubKey, NULL, 0);
4326 RtlInitEmptyUnicodeString(&OldFile, NULL, 0);
4327 RtlInitEmptyUnicodeString(&NewFile, NULL, 0);
4328
4329 if (lpSubKey)
4330 {
4331 if (!RtlCreateUnicodeStringFromAsciiz(&SubKey, lpSubKey))
4332 {
4334 goto Exit;
4335 }
4336 }
4337
4338 if (lpOldFile)
4339 {
4340 if (!RtlCreateUnicodeStringFromAsciiz(&OldFile, lpOldFile))
4341 {
4343 goto Exit;
4344 }
4345 }
4346
4347 if (lpNewFile)
4348 {
4349 if (!RtlCreateUnicodeStringFromAsciiz(&NewFile, lpNewFile))
4350 {
4352 goto Exit;
4353 }
4354 }
4355
4357 SubKey.Buffer,
4358 NewFile.Buffer,
4359 OldFile.Buffer);
4360
4361Exit:
4362 RtlFreeUnicodeString(&OldFile);
4363 RtlFreeUnicodeString(&NewFile);
4364 RtlFreeUnicodeString(&SubKey);
4365
4366 return ErrorCode;
4367}
4368
4369
4370/************************************************************************
4371 * RegReplaceKeyW
4372 *
4373 * @unimplemented
4374 */
4377 LPCWSTR lpSubKey,
4378 LPCWSTR lpNewFile,
4379 LPCWSTR lpOldFile)
4380{
4381 OBJECT_ATTRIBUTES KeyObjectAttributes;
4382 OBJECT_ATTRIBUTES NewObjectAttributes;
4383 OBJECT_ATTRIBUTES OldObjectAttributes;
4385 UNICODE_STRING NewFileName;
4386 UNICODE_STRING OldFileName;
4387 BOOLEAN CloseRealKey;
4388 HANDLE RealKeyHandle;
4392
4394 {
4395 return ERROR_INVALID_HANDLE;
4396 }
4397
4399 hKey);
4400 if (!NT_SUCCESS(Status))
4401 {
4403 }
4404
4405 /* Open the real key */
4406 if (lpSubKey != NULL && *lpSubKey != (WCHAR)0)
4407 {
4408 RtlInitUnicodeString(&SubKeyName, lpSubKey);
4409 InitializeObjectAttributes(&KeyObjectAttributes,
4410 &SubKeyName,
4412 KeyHandle,
4413 NULL);
4414 Status = NtOpenKey(&RealKeyHandle,
4416 &KeyObjectAttributes);
4417 if (!NT_SUCCESS(Status))
4418 {
4420 goto Cleanup;
4421 }
4422
4423 CloseRealKey = TRUE;
4424 }
4425 else
4426 {
4427 RealKeyHandle = KeyHandle;
4428 CloseRealKey = FALSE;
4429 }
4430
4431 /* Convert new file name */
4432 if (!RtlDosPathNameToNtPathName_U(lpNewFile,
4433 &NewFileName,
4434 NULL,
4435 NULL))
4436 {
4437 if (CloseRealKey)
4438 {
4439 NtClose(RealKeyHandle);
4440 }
4441
4443 goto Cleanup;
4444 }
4445
4446 InitializeObjectAttributes(&NewObjectAttributes,
4447 &NewFileName,
4449 NULL,
4450 NULL);
4451
4452 /* Convert old file name */
4453 if (!RtlDosPathNameToNtPathName_U(lpOldFile,
4454 &OldFileName,
4455 NULL,
4456 NULL))
4457 {
4458 RtlFreeHeap(RtlGetProcessHeap (),
4459 0,
4460 NewFileName.Buffer);
4461 if (CloseRealKey)
4462 {
4463 NtClose(RealKeyHandle);
4464 }
4465
4467 goto Cleanup;
4468 }
4469
4470 InitializeObjectAttributes(&OldObjectAttributes,
4471 &OldFileName,
4473 NULL,
4474 NULL);
4475
4476 Status = NtReplaceKey(&NewObjectAttributes,
4477 RealKeyHandle,
4478 &OldObjectAttributes);
4479
4480 RtlFreeHeap(RtlGetProcessHeap(),
4481 0,
4482 OldFileName.Buffer);
4483 RtlFreeHeap(RtlGetProcessHeap(),
4484 0,
4485 NewFileName.Buffer);
4486
4487 if (CloseRealKey)
4488 {
4489 NtClose(RealKeyHandle);
4490 }
4491
4492 if (!NT_SUCCESS(Status))
4493 {
4495 }
4496
4497Cleanup:
4499
4500 return ErrorCode;
4501}
4502
4503
4504/************************************************************************
4505 * RegRestoreKeyA
4506 *
4507 * @implemented
4508 */
4511 LPCSTR lpFile,
4512 DWORD dwFlags)
4513{
4516
4517 if (lpFile)
4518 {
4521 }
4522 else
4523 RtlInitEmptyUnicodeString(&FileName, NULL, 0);
4524
4526 FileName.Buffer,
4527 dwFlags);
4528
4530
4531 return ErrorCode;
4532}
4533
4534
4535/************************************************************************
4536 * RegRestoreKeyW
4537 *
4538 * @implemented
4539 */
4542 LPCWSTR lpFile,
4543 DWORD dwFlags)
4544{
4551
4553 {
4554 return ERROR_INVALID_HANDLE;
4555 }
4556
4558 hKey);
4559 if (!NT_SUCCESS(Status))
4560 {
4562 }
4563
4564 if (!RtlDosPathNameToNtPathName_U(lpFile,
4565 &FileName,
4566 NULL,
4567 NULL))
4568 {
4570 goto Cleanup;
4571 }
4572
4574 &FileName,
4576 NULL,
4577 NULL);
4578
4585 RtlFreeHeap(RtlGetProcessHeap(),
4586 0,
4587 FileName.Buffer);
4588 if (!NT_SUCCESS(Status))
4589 {
4590 goto Cleanup;
4591 }
4592
4594 FileHandle,
4595 (ULONG)dwFlags);
4597
4598Cleanup:
4600
4601 if (!NT_SUCCESS(Status))
4602 {
4604 }
4605
4606 return ERROR_SUCCESS;
4607}
4608
4609
4610/************************************************************************
4611 * RegSaveKeyA
4612 *
4613 * @implemented
4614 */
4617 LPCSTR lpFile,
4618 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
4619{
4622
4623 if (lpFile)
4624 {
4627 }
4628 else
4629 RtlInitEmptyUnicodeString(&FileName, NULL, 0);
4630
4632 FileName.Buffer,
4633 lpSecurityAttributes);
4635
4636 return ErrorCode;
4637}
4638
4639
4640/************************************************************************
4641 * RegSaveKeyW
4642 *
4643 * @implemented
4644 */
4647 LPCWSTR lpFile,
4648 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
4649{
4657
4659 hKey);
4660 if (!NT_SUCCESS(Status))
4661 {
4663 }
4664
4665 if (!RtlDosPathNameToNtPathName_U(lpFile,
4666 &FileName,
4667 NULL,
4668 NULL))
4669 {
4671 goto Cleanup;
4672 }
4673
4674 if (lpSecurityAttributes != NULL)
4675 {
4676 SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
4677 }
4678
4680 &FileName,
4682 NULL,
4688 NULL,
4693 NULL,
4694 0);
4695 RtlFreeHeap(RtlGetProcessHeap(),
4696 0,
4697 FileName.Buffer);
4698 if (!NT_SUCCESS(Status))
4699 {
4700 goto Cleanup;
4701 }
4702
4704 FileHandle);
4706
4707Cleanup:
4709
4710 if (!NT_SUCCESS(Status))
4711 {
4713 }
4714
4715 return ERROR_SUCCESS;
4716}
4717
4718
4719/************************************************************************
4720 * RegSaveKeyExA
4721 *
4722 * @implemented
4723 */
4724LONG
4725WINAPI
4727 LPCSTR lpFile,
4728 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
4729 DWORD Flags)
4730{
4733
4734 if (lpFile)
4735 {
4738 }
4739 else
4740 RtlInitEmptyUnicodeString(&FileName, NULL, 0);
4741
4743 FileName.Buffer,
4744 lpSecurityAttributes,
4745 Flags);
4747
4748 return ErrorCode;
4749}
4750
4751
4752/************************************************************************
4753 * RegSaveKeyExW
4754 *
4755 * @unimplemented
4756 */
4757LONG
4758WINAPI
4760 LPCWSTR lpFile,
4761 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
4762 DWORD Flags)
4763{
4764 switch (Flags)
4765 {
4767 case REG_LATEST_FORMAT:
4768 case REG_NO_COMPRESSION:
4769 break;
4770 default:
4772 }
4773
4774 FIXME("RegSaveKeyExW(): Flags ignored!\n");
4775
4776 return RegSaveKeyW(hKey,
4777 lpFile,
4778 lpSecurityAttributes);
4779}
4780
4781
4782/************************************************************************
4783 * RegSetKeySecurity
4784 *
4785 * @implemented
4786 */
4790 PSECURITY_DESCRIPTOR pSecurityDescriptor)
4791{
4794
4796 {
4797 return ERROR_INVALID_HANDLE;
4798 }
4799
4801 hKey);
4802 if (!NT_SUCCESS(Status))
4803 {
4805 }
4806
4809 pSecurityDescriptor);
4810
4812
4813 if (!NT_SUCCESS(Status))
4814 {
4816 }
4817
4818 return ERROR_SUCCESS;
4819}
4820
4821
4822/************************************************************************
4823 * RegSetValueExA
4824 *
4825 * @implemented
4826 */
4829 LPCSTR lpValueName,
4831 DWORD dwType,
4832 CONST BYTE* lpData,
4833 DWORD cbData)
4834{
4836 LPWSTR pValueName;
4840 LPBYTE pData;
4843
4844 /* Convert SubKey name to Unicode */
4845 if (lpValueName != NULL && lpValueName[0] != '\0')
4846 {
4847 if (!RtlCreateUnicodeStringFromAsciiz(&ValueName, lpValueName))
4849 }
4850 else
4851 {
4852 ValueName.Buffer = NULL;
4853 }
4854
4855 pValueName = (LPWSTR)ValueName.Buffer;
4856
4857
4858 if (is_string(dwType) && (cbData != 0))
4859 {
4860 /* Convert ANSI string Data to Unicode */
4861 /* If last character NOT zero then increment length */
4862 LONG bNoNulledStr = ((lpData[cbData-1] != '\0') ? 1 : 0);
4863 AnsiString.Buffer = (PSTR)lpData;
4864 AnsiString.Length = cbData + bNoNulledStr;
4865 AnsiString.MaximumLength = cbData + bNoNulledStr;
4867 &AnsiString,
4868 TRUE);
4869
4870 if (!NT_SUCCESS(Status))
4871 {
4872 if (pValueName != NULL)
4874
4876 }
4877 pData = (LPBYTE)Data.Buffer;
4878 DataSize = cbData * sizeof(WCHAR);
4879 }
4880 else
4881 {
4882 Data.Buffer = NULL;
4883 pData = (LPBYTE)lpData;
4884 DataSize = cbData;
4885 }
4886
4888 pValueName,
4889 Reserved,
4890 dwType,
4891 pData,
4892 DataSize);
4893
4894 if (pValueName != NULL)
4896
4897 if (Data.Buffer != NULL)
4899
4900 return ErrorCode;
4901}
4902
4903
4904/************************************************************************
4905 * RegSetValueExW
4906 *
4907 * @implemented
4908 */
4909LONG
4910WINAPI
4912 _In_ HKEY hKey,
4913 _In_ LPCWSTR lpValueName,
4915 _In_ DWORD dwType,
4916 _In_ CONST BYTE* lpData,
4917 _In_ DWORD cbData)
4918{
4922
4924 hKey);
4925 if (!NT_SUCCESS(Status))
4926 {
4928 }
4929
4930 if (IsHKCRKey(KeyHandle))
4931 {
4932 LONG ErrorCode = SetHKCRValue(KeyHandle, lpValueName, Reserved, dwType, lpData, cbData);
4934 return ErrorCode;
4935 }
4936
4937 if (is_string(dwType) && (cbData != 0))
4938 {
4939 PWSTR pwsData = (PWSTR)lpData;
4940
4941 _SEH2_TRY
4942 {
4943 if((pwsData[cbData / sizeof(WCHAR) - 1] != L'\0') &&
4944 (pwsData[cbData / sizeof(WCHAR)] == L'\0'))
4945 {
4946 /* Increment length if last character is not zero and next is zero */
4947 cbData += sizeof(WCHAR);
4948 }
4949 }
4951 {
4952 /* Do not fail if we fault where we were told not to go */
4953 }
4954 _SEH2_END;
4955 }
4956
4957 RtlInitUnicodeString(&ValueName, lpValueName);
4958
4960 &ValueName,
4961 0,
4962 dwType,
4963 (PVOID)lpData,
4964 (ULONG)cbData);
4965
4967
4968 if (!NT_SUCCESS(Status))
4969 {
4971 }
4972
4973 return ERROR_SUCCESS;
4974}
4975
4976
4977/************************************************************************
4978 * RegSetValueA
4979 *
4980 * @implemented
4981 */
4983RegSetValueA(HKEY hKeyOriginal,
4984 LPCSTR lpSubKey,
4985 DWORD dwType,
4986 LPCSTR lpData,
4987 DWORD cbData)
4988{
4989 HKEY subkey;
4990 HANDLE hKey;
4991 DWORD ret;
4993
4994 TRACE("(%p,%s,%d,%s,%d)\n", hKeyOriginal, debugstr_a(lpSubKey), dwType, debugstr_a(lpData), cbData );
4995
4996 if (dwType != REG_SZ || !lpData) return ERROR_INVALID_PARAMETER;
4997
4998 Status = MapDefaultKey(&hKey, hKeyOriginal);
4999 if (!NT_SUCCESS(Status))
5000 {
5002 }
5003 subkey = hKey;
5004
5005 if (lpSubKey && lpSubKey[0]) /* need to create the subkey */
5006 {
5007 ret = RegCreateKeyA(hKey, lpSubKey, &subkey);
5008 if (ret != ERROR_SUCCESS)
5009 goto Cleanup;
5010 }
5011
5012 ret = RegSetValueExA( subkey, NULL, 0, REG_SZ, (const BYTE*)lpData, strlen(lpData)+1 );
5013 if (subkey != hKey)
5014 RegCloseKey(subkey);
5015
5016Cleanup:
5018
5019 return ret;
5020}
5021
5022
5023/************************************************************************
5024 * RegSetValueW
5025 *
5026 * @implemented
5027 */
5029RegSetValueW(HKEY hKeyOriginal,
5030 LPCWSTR lpSubKey,
5031 DWORD dwType,
5032 LPCWSTR lpData,
5033 DWORD cbData)
5034{
5035 HKEY subkey;
5036 HANDLE hKey;
5037 DWORD ret;
5039
5040 TRACE("(%p,%s,%d,%s,%d)\n", hKeyOriginal, debugstr_w(lpSubKey), dwType, debugstr_w(lpData), cbData );
5041
5042 if (dwType != REG_SZ || !lpData)
5044
5046 hKeyOriginal);
5047 if (!NT_SUCCESS(Status))
5048 {
5050 }
5051 subkey = hKey;
5052
5053 if (lpSubKey && lpSubKey[0]) /* need to create the subkey */
5054 {
5055 ret = RegCreateKeyW(hKey, lpSubKey, &subkey);
5056 if (ret != ERROR_SUCCESS)
5057 goto Cleanup;
5058 }
5059
5060 ret = RegSetValueExW( subkey, NULL, 0, REG_SZ, (const BYTE*)lpData,
5061 (wcslen( lpData ) + 1) * sizeof(WCHAR) );
5062 if (subkey != hKey)
5063 RegCloseKey(subkey);
5064
5065Cleanup:
5067
5068 return ret;
5069}
5070
5071
5072/************************************************************************
5073 * RegUnLoadKeyA
5074 *
5075 * @implemented
5076 */
5079 LPCSTR lpSubKey)
5080{
5083
5084 if (lpSubKey)
5085 {
5088 }
5089 else
5090 RtlInitEmptyUnicodeString(&KeyName, NULL, 0);
5091
5093 KeyName.Buffer);
5094
5096
5097 return ErrorCode;
5098}
5099
5100
5101/************************************************************************
5102 * RegUnLoadKeyW
5103 *
5104 * @implemented
5105 */
5108 LPCWSTR lpSubKey)
5109{
5114
5116 {
5117 return ERROR_INVALID_HANDLE;
5118 }
5119
5121 if (!NT_SUCCESS(Status))
5122 {
5124 }
5125
5126 RtlInitUnicodeString(&KeyName, lpSubKey);
5127
5129 &KeyName,
5131 KeyHandle,
5132 NULL);
5133
5135
5137
5138 if (!NT_SUCCESS(Status))
5139 {
5141 }
5142
5143 return ERROR_SUCCESS;
5144}
5145
5146#endif // _ADVAPI32_VISTA_
5147
5148/******************************************************************************
5149 * load_string [Internal]
5150 *
5151 * This is basically a copy of user32/resource.c's LoadStringW. Necessary to
5152 * avoid importing user32, which is higher level than advapi32. Helper for
5153 * RegLoadMUIString.
5154 */
5155static int load_string(HINSTANCE hModule, UINT resId, LPWSTR pwszBuffer, INT cMaxChars)
5156{
5158 HRSRC hResource;
5159 WCHAR* pString;
5160 int idxString;
5161
5162 /* Negative values have to be inverted. */
5163 if (HIWORD(resId) == 0xffff)
5164 resId = (UINT)(-((INT)resId));
5165
5166 /* Load the resource into memory and get a pointer to it. */
5167 hResource = FindResourceW(hModule, MAKEINTRESOURCEW(LOWORD(resId >> 4) + 1), (LPWSTR)RT_STRING);
5168 if (!hResource) return 0;
5169 hMemory = LoadResource(hModule, hResource);
5170 if (!hMemory) return 0;
5172
5173 /* Strings are length-prefixed. Lowest nibble of resId is an index. */
5174 idxString = resId & 0xf;
5175 while (idxString--) pString += *pString + 1;
5176
5177 /* If no buffer is given, return length of the string. */
5178 if (!pwszBuffer) return *pString;
5179
5180 /* Else copy over the string, respecting the buffer size. */
5181 cMaxChars = (*pString < cMaxChars) ? *pString : (cMaxChars - 1);
5182 if (cMaxChars >= 0)
5183 {
5184 memcpy(pwszBuffer, pString + 1, cMaxChars * sizeof(WCHAR));
5185 pwszBuffer[cMaxChars] = L'\0';
5186 }
5187
5188 return cMaxChars;
5189}
5190
5191/************************************************************************
5192 * RegLoadMUIStringW
5193 *
5194 * @implemented
5195 */
5198 IN HKEY hKey,
5199 IN LPCWSTR pszValue OPTIONAL,
5200 OUT LPWSTR pszOutBuf,
5201 IN DWORD cbOutBuf,
5203 IN DWORD Flags,
5204 IN LPCWSTR pszDirectory OPTIONAL)
5205{
5206 DWORD dwValueType, cbData;
5207 LPWSTR pwszTempBuffer = NULL, pwszExpandedBuffer = NULL;
5208 LONG result;
5209
5210 /* Parameter sanity checks. */
5211 if (!hKey || !pszOutBuf)
5213
5214 if (pszDirectory && *pszDirectory)
5215 {
5216 FIXME("BaseDir parameter not yet supported!\n");
5218 }
5219
5220 /* Check for value existence and correctness of it's type, allocate a buffer and load it. */
5221 result = RegQueryValueExW(hKey, pszValue, NULL, &dwValueType, NULL, &cbData);
5222 if (result != ERROR_SUCCESS) goto cleanup;
5223 if (!(dwValueType == REG_SZ || dwValueType == REG_EXPAND_SZ) || !cbData)
5224 {
5226 goto cleanup;
5227 }
5228 pwszTempBuffer = HeapAlloc(GetProcessHeap(), 0, cbData);
5229 if (!pwszTempBuffer)
5230 {
5232 goto cleanup;
5233 }
5234 result = RegQueryValueExW(hKey, pszValue, NULL, &dwValueType, (LPBYTE)pwszTempBuffer, &cbData);
5235 if (result != ERROR_SUCCESS) goto cleanup;
5236
5237 /* Expand environment variables, if appropriate, or copy the original string over. */
5238 if (dwValueType == REG_EXPAND_SZ)
5239 {
5240 cbData = ExpandEnvironmentStringsW(pwszTempBuffer, NULL, 0) * sizeof(WCHAR);
5241 if (!cbData) goto cleanup;
5242 pwszExpandedBuffer = HeapAlloc(GetProcessHeap(), 0, cbData);
5243 if (!pwszExpandedBuffer)
5244 {
5246 goto cleanup;
5247 }
5248 ExpandEnvironmentStringsW(pwszTempBuffer, pwszExpandedBuffer, cbData);
5249 }
5250 else
5251 {
5252 pwszExpandedBuffer = HeapAlloc(GetProcessHeap(), 0, cbData);
5253 memcpy(pwszExpandedBuffer, pwszTempBuffer, cbData);
5254 }
5255
5256 /* If the value references a resource based string, parse the value and load the string.
5257 * Else just copy over the original value. */
5259 if (*pwszExpandedBuffer != L'@') /* '@' is the prefix for resource based string entries. */
5260 {
5261 lstrcpynW(pszOutBuf, pwszExpandedBuffer, cbOutBuf / sizeof(WCHAR));
5262 }
5263 else
5264 {
5265 WCHAR* pComma = wcsrchr(pwszExpandedBuffer, L',');
5266 UINT uiStringId;
5268
5269 /* Format of the expanded value is 'path_to_dll,-resId' */
5270 if (!pComma || pComma[1] != L'-')
5271 {
5273 goto cleanup;
5274 }
5275
5276 uiStringId = _wtoi(pComma + 2);
5277 *pComma = L'\0';
5278
5279 hModule = LoadLibraryExW(pwszExpandedBuffer + 1, NULL, LOAD_LIBRARY_AS_DATAFILE);
5280 if (!hModule || !load_string(hModule, uiStringId, pszOutBuf, cbOutBuf / sizeof(WCHAR)))
5283 }
5284
5285cleanup:
5286 HeapFree(GetProcessHeap(), 0, pwszTempBuffer);
5287 HeapFree(GetProcessHeap(), 0, pwszExpandedBuffer);
5288 return result;
5289}
5290
5291/************************************************************************
5292 * RegLoadMUIStringA
5293 *
5294 * @implemented
5295 */
5298 IN HKEY hKey,
5299 IN LPCSTR pszValue OPTIONAL,
5300 OUT LPSTR pszOutBuf,
5301 IN DWORD cbOutBuf,
5303 IN DWORD Flags,
5304 IN LPCSTR pszDirectory OPTIONAL)
5305{
5306 UNICODE_STRING valueW, baseDirW;
5307 WCHAR* pwszBuffer;
5308 DWORD cbData = cbOutBuf * sizeof(WCHAR);
5309 LONG result;
5310
5311 valueW.Buffer = baseDirW.Buffer = pwszBuffer = NULL;
5312 if (!RtlCreateUnicodeStringFromAsciiz(&valueW, pszValue) ||
5313 !RtlCreateUnicodeStringFromAsciiz(&baseDirW, pszDirectory) ||
5314 !(pwszBuffer = HeapAlloc(GetProcessHeap(), 0, cbData)))
5315 {
5317 goto cleanup;
5318 }
5319
5320 result = RegLoadMUIStringW(hKey, valueW.Buffer, pwszBuffer, cbData, NULL, Flags,
5321 baseDirW.Buffer);
5322
5323 if (result == ERROR_SUCCESS)
5324 {
5325 cbData = WideCharToMultiByte(CP_ACP, 0, pwszBuffer, -1, pszOutBuf, cbOutBuf, NULL, NULL);
5326 if (pcbData)
5327 *pcbData = cbData;
5328 }
5329
5330cleanup:
5331 HeapFree(GetProcessHeap(), 0, pwszBuffer);
5332 RtlFreeUnicodeString(&baseDirW);
5334
5335 return result;
5336}
5337
5338/* EOF */
unsigned char BOOLEAN
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
LONG NTSTATUS
Definition: precomp.h:26
static const WCHAR nameW[]
Definition: main.c:46
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
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
#define RegCloseKey(hKey)
Definition: registry.h:49
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1444
Definition: bufpool.h:45
BOOL WINAPI GetComputerNameW(LPWSTR lpBuffer, LPDWORD lpnSize)
Definition: compname.c:446
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define ERROR_MORE_DATA
Definition: dderror.h:13
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define BufferSize
Definition: mmc.h:75
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
#define ERROR_SUCCESS
Definition: deptool.c:10
static LSTATUS(WINAPI *pRegDeleteTreeW)(HKEY
#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
union node Node
Definition: types.h:1255
LONG WINAPI RegCreateKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:1179
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 RegOverridePredefKey(IN HKEY hKey, IN HKEY hNewHKey OPTIONAL)
Definition: reg.c:366
LONG WINAPI RegSetValueExA(HKEY hKey, LPCSTR lpValueName, DWORD Reserved, DWORD dwType, CONST BYTE *lpData, DWORD cbData)
Definition: reg.c:4828
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3362
LONG WINAPI RegUnLoadKeyW(HKEY hKey, LPCWSTR lpSubKey)
Definition: reg.c:5107
LONG WINAPI RegLoadKeyA(HKEY hKey, LPCSTR lpSubKey, LPCSTR lpFile)
Definition: reg.c:3061
#define ClosePredefKey(Handle)
Definition: reg.c:44
LSTATUS WINAPI RegGetValueW(HKEY hKey, LPCWSTR pszSubKey, LPCWSTR pszValue, DWORD dwFlags, LPDWORD pdwType, PVOID pvData, LPDWORD pcbData)
Definition: reg.c:1969
LONG WINAPI RegOpenKeyExA(_In_ HKEY hKey, _In_ LPCSTR lpSubKey, _In_ DWORD ulOptions, _In_ REGSAM samDesired, _Out_ PHKEY phkResult)
Definition: reg.c:3327
LONG WINAPI RegDeleteKeyExA(_In_ HKEY hKey, _In_ LPCSTR lpSubKey, _In_ REGSAM samDesired, _In_ DWORD Reserved)
Definition: reg.c:1254
static VOID CloseDefaultKeys(VOID)
Definition: reg.c:216
LONG WINAPI RegCopyTreeW(IN HKEY hKeySrc, IN LPCWSTR lpSubKey OPTIONAL, IN HKEY hKeyDest)
Definition: reg.c:740
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
static NTSTATUS OpenLocalMachineKey(PHANDLE KeyHandle)
Definition: reg.c:264
LONG WINAPI RegFlushKey(HKEY hKey)
Definition: reg.c:2980
static NTSTATUS OpenClassesRootKey(PHANDLE KeyHandle)
LONG WINAPI RegDeleteTreeA(IN HKEY hKey, IN LPCSTR lpSubKey OPTIONAL)
Definition: reg.c:1843
LONG WINAPI RegQueryInfoKeyA(HKEY hKey, LPSTR lpClass, LPDWORD lpcClass, LPDWORD lpReserved, LPDWORD lpcSubKeys, LPDWORD lpcMaxSubKeyLen, LPDWORD lpcMaxClassLen, LPDWORD lpcValues, LPDWORD lpcMaxValueNameLen, LPDWORD lpcMaxValueLen, LPDWORD lpcbSecurityDescriptor, PFILETIME lpftLastWriteTime)
Definition: reg.c:3612
LONG WINAPI RegDisablePredefinedCacheEx(VOID)
Definition: reg.c:349
static HANDLE ProcessHeap
Definition: reg.c:35
#define REG_MAX_NAME_SIZE
Definition: reg.c:28
LONG WINAPI RegOpenKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3263
LONG WINAPI RegQueryReflectionKey(IN HKEY hBase, OUT BOOL *bIsReflectionDisabled)
Definition: reg.c:4004
LONG WINAPI RegEnumValueA(_In_ HKEY hKey, _In_ DWORD dwIndex, _Out_ LPSTR lpName, _Inout_ LPDWORD lpcbName, _Reserved_ LPDWORD lpdwReserved, _Out_opt_ LPDWORD lpdwType, _Out_opt_ LPBYTE lpData, _Inout_opt_ LPDWORD lpcbData)
Definition: reg.c:2697
LONG WINAPI RegOpenCurrentUser(IN REGSAM samDesired, OUT PHKEY phkResult)
Definition: reg.c:3238
static int load_string(HINSTANCE hModule, UINT resId, LPWSTR pwszBuffer, INT cMaxChars)
Definition: reg.c:5155
LONG WINAPI RegGetKeySecurity(HKEY hKey, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, LPDWORD lpcbSecurityDescriptor)
Definition: reg.c:3016
LONG WINAPI RegDeleteValueA(HKEY hKey, LPCSTR lpValueName)
Definition: reg.c:2325
LONG WINAPI RegSetValueA(HKEY hKeyOriginal, LPCSTR lpSubKey, DWORD dwType, LPCSTR lpData, DWORD cbData)
Definition: reg.c:4983
LONG WINAPI RegReplaceKeyW(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpNewFile, LPCWSTR lpOldFile)
Definition: reg.c:4376
static HANDLE DefaultHandleTable[MAX_DEFAULT_HANDLES]
Definition: reg.c:34
LONG WINAPI RegLoadKeyW(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpFile)
Definition: reg.c:3108
LONG WINAPI RegDeleteKeyExW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ REGSAM samDesired, _In_ DWORD Reserved)
Definition: reg.c:1286
LONG WINAPI RegOpenKeyW(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3297
LONG WINAPI RegEnumKeyA(HKEY hKey, DWORD dwIndex, LPSTR lpName, DWORD cbName)
Definition: reg.c:2397
static BOOLEAN DefaultHandlesDisabled
Definition: reg.c:36
LSTATUS WINAPI RegDeleteTreeW(HKEY hKey, LPCWSTR lpszSubKey)
Definition: reg.c:1749
LONG WINAPI RegSetKeySecurity(HKEY hKey, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor)
Definition: reg.c:4788
static NTSTATUS CreateNestedKey(PHKEY KeyHandle, POBJECT_ATTRIBUTES ObjectAttributes, PUNICODE_STRING ClassString, DWORD dwOptions, REGSAM samDesired, DWORD *lpdwDisposition)
Definition: reg.c:920
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
static __inline int is_string(DWORD type)
Definition: reg.c:61
LONG WINAPI RegLoadMUIStringW(IN HKEY hKey, IN LPCWSTR pszValue OPTIONAL, OUT LPWSTR pszOutBuf, IN DWORD cbOutBuf, OUT LPDWORD pcbData OPTIONAL, IN DWORD Flags, IN LPCWSTR pszDirectory OPTIONAL)
Definition: reg.c:5197
LONG WINAPI RegQueryMultipleValuesW(HKEY hKey, PVALENTW val_list, DWORD num_vals, LPWSTR lpValueBuf, LPDWORD ldwTotsize)
Definition: reg.c:3940
LSTATUS WINAPI RegQueryValueA(HKEY hkey, LPCSTR name, LPSTR data, LPLONG count)
Definition: reg.c:4241
static BOOLEAN DefaultHandleHKUDisabled
Definition: reg.c:37
BOOL RegInitialize(VOID)
Definition: reg.c:70
static NTSTATUS OpenCurrentConfigKey(PHANDLE KeyHandle)
Definition: reg.c:307
static NTSTATUS OpenUsersKey(PHANDLE KeyHandle)
Definition: reg.c:288
static NTSTATUS MapDefaultKey(PHANDLE ParentKey, HKEY Key)
LSTATUS WINAPI RegGetValueA(HKEY hKey, LPCSTR pszSubKey, LPCSTR pszValue, DWORD dwFlags, LPDWORD pdwType, PVOID pvData, LPDWORD pcbData)
Definition: reg.c:2075
LONG WINAPI RegDeleteKeyW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey)
Definition: reg.c:1239
LONG WINAPI RegDeleteValueW(HKEY hKey, LPCWSTR lpValueName)
Definition: reg.c:2361
static NTSTATUS RegpCopyTree(IN HKEY hKeySrc, IN HKEY hKeyDest)
Definition: reg.c:451
LONG WINAPI RegDisablePredefinedCache(VOID)
Definition: reg.c:333
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
static NTSTATUS OpenPredefinedKey(IN ULONG Index, OUT HANDLE Handle)
Definition: reg.c:105
LONG WINAPI RegRestoreKeyW(HKEY hKey, LPCWSTR lpFile, DWORD dwFlags)
Definition: reg.c:4541
LONG WINAPI RegConnectRegistryW(LPCWSTR lpMachineName, HKEY hKey, PHKEY phkResult)
Definition: reg.c:874
LONG WINAPI RegSaveKeyExA(HKEY hKey, LPCSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD Flags)
Definition: reg.c:4726
#define MAX_DEFAULT_HANDLES
Definition: reg.c:27
LONG WINAPI RegQueryMultipleValuesA(HKEY hKey, PVALENTA val_list, DWORD num_vals, LPSTR lpValueBuf, LPDWORD ldwTotsize)
Definition: reg.c:3876
LONG WINAPI RegEnableReflectionKey(IN HKEY hBase)
Definition: reg.c:1884
static RTL_CRITICAL_SECTION HandleTableCS
Definition: reg.c:33
LONG WINAPI RegOpenUserClassesRoot(IN HANDLE hToken, IN DWORD dwOptions, IN REGSAM samDesired, OUT PHKEY phkResult)
Definition: reg.c:3470
#define IsPredefKey(HKey)
Definition: reg.c:48
static VOID RegpApplyRestrictions(DWORD dwFlags, DWORD dwType, DWORD cbData, PLONG ret)
Definition: reg.c:1897
LONG WINAPI RegRestoreKeyA(HKEY hKey, LPCSTR lpFile, DWORD dwFlags)
Definition: reg.c:4510
LONG WINAPI RegReplaceKeyA(HKEY hKey, LPCSTR lpSubKey, LPCSTR lpNewFile, LPCSTR lpOldFile)
Definition: reg.c:4315
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 RegSetKeyValueA(IN HKEY hKey, IN LPCSTR lpSubKey OPTIONAL, IN LPCSTR lpValueName OPTIONAL, IN DWORD dwType, IN LPCVOID lpData OPTIONAL, IN DWORD cbData)
Definition: reg.c:2248
LSTATUS WINAPI RegQueryValueW(HKEY hkey, LPCWSTR name, LPWSTR data, LPLONG count)
Definition: reg.c:4270
#define GetPredefKeyIndex(HKey)
Definition: reg.c:50
LONG WINAPI RegSaveKeyW(HKEY hKey, LPCWSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: reg.c:4646
LONG WINAPI RegCopyTreeA(IN HKEY hKeySrc, IN LPCSTR lpSubKey OPTIONAL, IN HKEY hKeyDest)
Definition: reg.c:816
LONG WINAPI RegQueryValueExA(_In_ HKEY hkeyorg, _In_ LPCSTR name, _In_ LPDWORD reserved, _Out_opt_ LPDWORD type, _Out_opt_ LPBYTE data, _Inout_opt_ LPDWORD count)
Definition: reg.c:4038
LONG WINAPI RegSaveKeyA(HKEY hKey, LPCSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: reg.c:4616
LONG WINAPI RegLoadMUIStringA(IN HKEY hKey, IN LPCSTR pszValue OPTIONAL, OUT LPSTR pszOutBuf, IN DWORD cbOutBuf, OUT LPDWORD pcbData OPTIONAL, IN DWORD Flags, IN LPCSTR pszDirectory OPTIONAL)
Definition: reg.c:5297
static BOOLEAN DllInitialized
Definition: reg.c:38
LONG WINAPI RegConnectRegistryA(IN LPCSTR lpMachineName, IN HKEY hKey, OUT PHKEY phkResult)
Definition: reg.c:845
LONG WINAPI RegSaveKeyExW(HKEY hKey, LPCWSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD Flags)
Definition: reg.c:4759
LONG WINAPI RegDisableReflectionKey(IN HKEY hBase)
Definition: reg.c:1871
LONG WINAPI RegDeleteKeyValueW(IN HKEY hKey, IN LPCWSTR lpSubKey OPTIONAL, IN LPCWSTR lpValueName OPTIONAL)
Definition: reg.c:1361
LONG WINAPI RegCreateKeyExA(_In_ HKEY hKey, _In_ LPCSTR lpSubKey, _In_ DWORD Reserved, _In_ LPSTR lpClass, _In_ DWORD dwOptions, _In_ REGSAM samDesired, _In_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _Out_ PHKEY phkResult, _Out_ LPDWORD lpdwDisposition)
Definition: reg.c:1034
LONG WINAPI RegEnumKeyExA(_In_ HKEY hKey, _In_ DWORD dwIndex, _Out_ LPSTR lpName, _Inout_ LPDWORD lpcbName, _Reserved_ LPDWORD lpReserved, _Out_opt_ LPSTR lpClass, _Inout_opt_ LPDWORD lpcbClass, _Out_opt_ PFILETIME lpftLastWriteTime)
Definition: reg.c:2448
BOOL RegCleanup(VOID)
Definition: reg.c:93
LONG WINAPI RegNotifyChangeKeyValue(HKEY hKey, BOOL bWatchSubtree, DWORD dwNotifyFilter, HANDLE hEvent, BOOL fAsynchronous)
Definition: reg.c:3181
LONG WINAPI RegSetValueW(HKEY hKeyOriginal, LPCWSTR lpSubKey, DWORD dwType, LPCWSTR lpData, DWORD cbData)
Definition: reg.c:5029
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
LONG WINAPI RegDeleteKeyValueA(IN HKEY hKey, IN LPCSTR lpSubKey OPTIONAL, IN LPCSTR lpValueName OPTIONAL)
Definition: reg.c:1430
LONG WINAPI RegEnumKeyW(HKEY hKey, DWORD dwIndex, LPWSTR lpName, DWORD cbName)
Definition: reg.c:2422
LONG WINAPI RegUnLoadKeyA(HKEY hKey, LPCSTR lpSubKey)
Definition: reg.c:5078
LONG WINAPI RegCreateKeyW(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:1201
LONG WINAPI RegDeleteKeyA(_In_ HKEY hKey, _In_ LPCSTR lpSubKey)
Definition: reg.c:1224
LONG WINAPI RegSetKeyValueW(IN HKEY hKey, IN LPCWSTR lpSubKey OPTIONAL, IN LPCWSTR lpValueName OPTIONAL, IN DWORD dwType, IN LPCVOID lpData OPTIONAL, IN DWORD cbData)
Definition: reg.c:2177
FORCEINLINE BOOL IsHKCRKey(_In_ HKEY hKey)
Definition: reg.h:13
FORCEINLINE void MakeHKCRKey(_Inout_ HKEY *hKey)
Definition: reg.h:20
HMODULE hModule
Definition: animate.c:44
#define GetProcessHeap()
Definition: compat.h:736
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define wcsrchr
Definition: compat.h:16
#define CP_ACP
Definition: compat.h:109
#define HeapAlloc
Definition: compat.h:733
#define FreeLibrary(x)
Definition: compat.h:748
#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 FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define WideCharToMultiByte
Definition: compat.h:111
#define FILE_SHARE_READ
Definition: compat.h:136
#define lstrcpynW
Definition: compat.h:738
static DWORD DWORD * dwLength
Definition: fusion.c:86
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
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
Definition: loader.c:288
HRSRC WINAPI FindResourceW(HINSTANCE hModule, LPCWSTR name, LPCWSTR type)
Definition: res.c:176
LPVOID WINAPI LockResource(HGLOBAL handle)
Definition: res.c:550
HGLOBAL WINAPI LoadResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:532
#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 Cleanup[]
Definition: register.c:80
@ AnsiString
Definition: dnslib.h:19
r reserved
Definition: btrfs.c:3006
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
NTSTATUS RtlAppendUnicodeToString(IN PUNICODE_STRING Str1, IN PWSTR Str2)
Definition: string_lib.cpp:62
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
struct _FileName FileName
Definition: fatprocs.h:896
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ SECURITY_INFORMATION SecurityInformation
Definition: fltkernel.h:1340
#define FILE_CREATE
Definition: from_kernel.h:55
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
#define FILE_OPEN_FOR_BACKUP_INTENT
Definition: from_kernel.h:42
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
FxString * pString
FxAutoRegKey hKey
WDFMEMORY hMemory
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:25
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint buffer
Definition: glext.h:5915
GLuint index
Definition: glext.h:6031
GLenum GLsizei len
Definition: glext.h:6722
GLuint64EXT * result
Definition: glext.h:11304
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
#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
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
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
LONG WINAPI OpenHKCRKey(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ DWORD ulOptions, _In_ REGSAM samDesired, _In_ PHKEY phkResult)
Definition: hkcr.c:348
LONG WINAPI DeleteHKCRKey(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ REGSAM RegSam, _In_ DWORD Reserved)
Definition: hkcr.c:419
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
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
_Check_return_ _CRTIMP int __cdecl _wtoi(_In_z_ const wchar_t *_Str)
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define OBJ_OPENLINK
Definition: winternl.h:230
NTSYSAPI PVOID WINAPI RtlReAllocateHeap(HANDLE, ULONG, PVOID, SIZE_T)
Definition: heap.c:2667
NTSYSAPI NTSTATUS WINAPI RtlDuplicateUnicodeString(int, const UNICODE_STRING *, UNICODE_STRING *)
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_w
Definition: kernel32.h:32
#define REG_SZ
Definition: layer.c:22
if(dx< 0)
Definition: linetemp.h:194
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define ASSERT(a)
Definition: mode.c:44
int DoOpen(void)
Definition: cmds.c:2168
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
static PVOID ptr
Definition: dispmode.c:27
static HANDLE hEvent
Definition: comm.c:54
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define min(a, b)
Definition: monoChain.cc:55
DWORD SECURITY_INFORMATION
Definition: ms-dtyp.idl:311
#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 _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
unsigned int UINT
Definition: ndis.h:50
_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
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ PNDIS_STRING _Out_ PNDIS_HANDLE SubKeyHandle
Definition: ndis.h:4726
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4715
_In_ ACCESS_MASK _In_ POBJECT_ATTRIBUTES _Reserved_ ULONG _In_opt_ PUNICODE_STRING _In_ ULONG _Out_opt_ PULONG Disposition
Definition: cmfuncs.h:56
NTSYSAPI NTSTATUS NTAPI RtlOpenCurrentUser(_In_ ACCESS_MASK DesiredAccess, _Out_ PHANDLE KeyHandle)
NTSYSAPI NTSTATUS NTAPI RtlDeleteCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlInitializeCriticalSection(_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
NTSYSAPI NTSTATUS NTAPI NtOpenFile(OUT PHANDLE phFile, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG ShareMode, IN ULONG OpenMode)
Definition: file.c:3952
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToAnsiString(PANSI_STRING DestinationString, PUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
NTSYSAPI NTSTATUS NTAPI NtOpenKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: ntapi.c:336
#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
@ KeyBasicInformation
Definition: nt_native.h:1131
@ 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
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
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
struct _KEY_BASIC_INFORMATION KEY_BASIC_INFORMATION
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define KEY_CREATE_SUB_KEY
Definition: nt_native.h:1018
struct _KEY_NODE_INFORMATION KEY_NODE_INFORMATION
struct _KEY_BASIC_INFORMATION * PKEY_BASIC_INFORMATION
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)
struct _KEY_FULL_INFORMATION KEY_FULL_INFORMATION
#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)
#define KEY_ENUMERATE_SUB_KEYS
Definition: nt_native.h:1019
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 DWORD
Definition: nt_native.h:44
#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
#define FILE_GENERIC_READ
Definition: nt_native.h:653
#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
NTSTATUS NTAPI NtRestoreKey(IN HANDLE KeyHandle, IN HANDLE FileHandle, IN ULONG RestoreFlags)
Definition: ntapi.c:1624
NTSTATUS NTAPI NtReplaceKey(IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE Key, IN POBJECT_ATTRIBUTES ReplacedObjectAttributes)
Definition: ntapi.c:1614
#define UNICODE_NULL
#define ANSI_NULL
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
NTSYSAPI NTSTATUS NTAPI RtlConvertSidToUnicodeString(OUT PUNICODE_STRING DestinationString, IN PVOID Sid, IN BOOLEAN AllocateDestinationString)
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
#define STATUS_INVALID_HANDLE
Definition: ntstatus.h:245
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:205
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define L(x)
Definition: ntvdm.h:50
NTSTATUS NTAPI NtQuerySecurityObject(IN HANDLE Handle, IN SECURITY_INFORMATION SecurityInformation, OUT PSECURITY_DESCRIPTOR SecurityDescriptor, IN ULONG Length, OUT PULONG ResultLength)
Definition: obsecure.c:803
#define LOWORD(l)
Definition: pedump.c:82
#define RT_STRING
Definition: pedump.c:368
#define CONST
Definition: pedump.c:81
DWORD * PDWORD
Definition: pedump.c:68
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define REG_QWORD
Definition: sdbapi.c:597
#define REG_DWORD
Definition: sdbapi.c:596
#define offsetof(TYPE, MEMBER)
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
_In_ DWORD _Out_ PDWORD _In_opt_ PCSTR MachineName
Definition: setupapi.h:1293
#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)
static void Exit(void)
Definition: sock.c:1330
#define TRACE(s)
Definition: solgame.cpp:4
DWORD dwOptions
Definition: solitaire.cpp:25
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
std::string Name
Definition: xml2sdb.h:101
DWORD dwHighDateTime
Definition: mapidefs.h:66
DWORD dwLowDateTime
Definition: mapidefs.h:65
LARGE_INTEGER LastWriteTime
Definition: nt_native.h:1117
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
PUNICODE_STRING ObjectName
Definition: umtypes.h:185
LPVOID lpSecurityDescriptor
Definition: compat.h:193
SID_AND_ATTRIBUTES User
Definition: setypes.h:1010
USHORT MaximumLength
Definition: env_spec_w32.h:370
Definition: name.c:39
Definition: ps.c:97
DWORD ve_valuelen
Definition: winreg.h:73
DWORD ve_valueptr
Definition: winreg.h:74
DWORD ve_valuelen
Definition: winreg.h:79
DWORD ve_valueptr
Definition: winreg.h:80
#define max(a, b)
Definition: svc.c:63
static unsigned int bufptr
Definition: tncon.cpp:77
_Must_inspect_result_ __kernel_entry NTSTATUS NTAPI NtQueryInformationToken(_In_ HANDLE TokenHandle, _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, _Out_writes_bytes_to_opt_(TokenInformationLength, *ReturnLength) PVOID TokenInformation, _In_ ULONG TokenInformationLength, _Out_ PULONG ReturnLength)
Queries a specific type of information in regard of an access token based upon the information class....
Definition: tokencls.c:473
#define DWORD_PTR
Definition: treelist.c:76
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
TW_UINT32 TW_UINT16 TW_UINT16 TW_MEMREF pData
Definition: twain.h:1830
uint16_t * PWSTR
Definition: typedefs.h:56
uint32_t * PULONG_PTR
Definition: typedefs.h:65
uint32_t * PULONG
Definition: typedefs.h:59
char * PSTR
Definition: typedefs.h:51
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned char * LPBYTE
Definition: typedefs.h:53
int32_t * LPLONG
Definition: typedefs.h:58
void * PVOID
Definition: typedefs.h:50
PVOID HANDLE
Definition: typedefs.h:73
uint32_t * LPDWORD
Definition: typedefs.h:59
int32_t INT
Definition: typedefs.h:58
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
int32_t * PLONG
Definition: typedefs.h:58
uint16_t * PWCHAR
Definition: typedefs.h:56
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define HIWORD(l)
Definition: typedefs.h:247
#define OUT
Definition: typedefs.h:40
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
struct _LARGE_INTEGER::@2290 u
Definition: pdh_main.c:94
int ret
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:690
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDMAENABLER _In_ _In_opt_ PWDF_OBJECT_ATTRIBUTES Attributes
_In_ PWDFDEVICE_INIT _In_ PWDF_FILEOBJECT_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES FileObjectAttributes
Definition: wdfdevice.h:3400
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2699
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
_Must_inspect_result_ _In_opt_ WDFKEY ParentKey
Definition: wdfregistry.h:69
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:243
#define ZeroMemory
Definition: winbase.h:1712
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define LOAD_LIBRARY_AS_DATAFILE
Definition: winbase.h:342
_In_ LPCSTR lpName
Definition: winbase.h:2789
#define CopyMemory
Definition: winbase.h:1710
#define MAX_COMPUTERNAME_LENGTH
Definition: winbase.h:243
_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
_Reserved_ PVOID Reserved
Definition: winddi.h:3974
CONST void * LPCVOID
Definition: windef.h:191
#define WINAPI
Definition: msvc.h:6
#define ERROR_BAD_NETPATH
Definition: winerror.h:145
#define ERROR_UNSUPPORTED_TYPE
Definition: winerror.h:988
#define ERROR_BADKEY
Definition: winerror.h:589
#define ERROR_BAD_PATHNAME
Definition: winerror.h:233
#define ERROR_DATATYPE_MISMATCH
Definition: winerror.h:987
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define HKEY_CURRENT_CONFIG
Definition: winreg.h:15
#define HKEY_CURRENT_USER
Definition: winreg.h:11
#define RRF_RT_ANY
Definition: winreg.h:64
ACCESS_MASK REGSAM
Definition: winreg.h:69
#define HKEY_PERFORMANCE_DATA
Definition: winreg.h:14
#define HKEY_CLASSES_ROOT
Definition: winreg.h:10
#define HKEY_USERS
Definition: winreg.h:13
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
_In_ ULONG _Out_opt_ PULONG RequiredLength
Definition: wmifuncs.h:30
_In_ USHORT _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR _Reserved_ ULONG _In_opt_ PVOID _In_opt_ const WSK_CLIENT_CONNECTION_DISPATCH _In_opt_ PEPROCESS _In_opt_ PETHREAD _In_opt_ PSECURITY_DESCRIPTOR SecurityDescriptor
Definition: wsk.h:191
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define REG_LATEST_FORMAT
Definition: cmtypes.h:98
#define KEY_WOW64_32KEY
Definition: cmtypes.h:45
#define REG_NO_COMPRESSION
Definition: cmtypes.h:99
#define REG_STANDARD_FORMAT
Definition: cmtypes.h:97
#define KEY_WOW64_64KEY
Definition: cmtypes.h:46
#define DACL_SECURITY_INFORMATION
Definition: setypes.h:125
#define OWNER_SECURITY_INFORMATION
Definition: setypes.h:123
@ TokenUser
Definition: setypes.h:966
#define GROUP_SECURITY_INFORMATION
Definition: setypes.h:124
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