ReactOS 0.4.15-dev-7961-gdcf9eb0
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{
1365 HKEY hSubKey = hKey;
1367
1368 if (lpSubKey)
1369 {
1370 ErrorCode = RegOpenKeyExW(hKey, lpSubKey, 0, KEY_SET_VALUE, &hSubKey);
1371 if (ErrorCode)
1372 {
1373 return ErrorCode;
1374 }
1375 }
1376 ErrorCode = RegDeleteValueW(hSubKey, lpValueName);
1377
1378 if (hSubKey != hKey)
1379 {
1380 RegCloseKey(hSubKey);
1381 }
1382 return ErrorCode;
1383}
1384
1385
1386/************************************************************************
1387 * RegDeleteKeyValueA
1388 *
1389 * @implemented
1390 */
1393 IN LPCSTR lpSubKey OPTIONAL,
1394 IN LPCSTR lpValueName OPTIONAL)
1395{
1396 UNICODE_STRING SubKey = { 0, 0, NULL }, ValueName = { 0, 0, NULL };
1397 LONG Ret;
1398
1399 if (lpSubKey != NULL &&
1400 !RtlCreateUnicodeStringFromAsciiz(&SubKey, lpSubKey))
1401 {
1403 }
1404
1405 if (lpValueName != NULL &&
1407 {
1408 RtlFreeUnicodeString(&SubKey);
1410 }
1411
1413 SubKey.Buffer,
1414 ValueName.Buffer);
1415
1416 RtlFreeUnicodeString(&SubKey);
1418
1419 return Ret;
1420}
1421
1422#if 0
1423// Non-recursive RegDeleteTreeW implementation by Thomas, however it needs bugfixing
1424static NTSTATUS
1425RegpDeleteTree(IN HKEY hKey)
1426{
1427 typedef struct
1428 {
1429 LIST_ENTRY ListEntry;
1431 } REGP_DEL_KEYS, *PREG_DEL_KEYS;
1432
1433 LIST_ENTRY delQueueHead;
1434 PREG_DEL_KEYS delKeys, newDelKeys;
1437 PKEY_BASIC_INFORMATION BasicInfo;
1438 PREG_DEL_KEYS KeyDelRoot;
1440 NTSTATUS Status2 = STATUS_SUCCESS;
1441
1442 InitializeListHead(&delQueueHead);
1443
1444 ProcessHeap = RtlGetProcessHeap();
1445
1446 /* NOTE: no need to allocate enough memory for an additional KEY_BASIC_INFORMATION
1447 structure for the root key, we only do that for subkeys as we need to
1448 allocate REGP_DEL_KEYS structures anyway! */
1449 KeyDelRoot = RtlAllocateHeap(ProcessHeap,
1450 0,
1451 sizeof(REGP_DEL_KEYS));
1452 if (KeyDelRoot != NULL)
1453 {
1454 KeyDelRoot->KeyHandle = hKey;
1455 InsertTailList(&delQueueHead,
1456 &KeyDelRoot->ListEntry);
1457
1458 do
1459 {
1460 delKeys = CONTAINING_RECORD(delQueueHead.Flink,
1461 REGP_DEL_KEYS,
1462 ListEntry);
1463
1464 BufferSize = 0;
1465 BasicInfo = NULL;
1466 newDelKeys = NULL;
1467
1468ReadFirstSubKey:
1469 /* check if this key contains subkeys and delete them first by queuing
1470 them at the head of the list */
1471 Status2 = NtEnumerateKey(delKeys->KeyHandle,
1472 0,
1474 BasicInfo,
1475 BufferSize,
1476 &BufferSize);
1477
1478 if (NT_SUCCESS(Status2))
1479 {
1482
1483 ASSERT(newDelKeys != NULL);
1484 ASSERT(BasicInfo != NULL);
1485
1486 /* don't use RtlInitUnicodeString as the string is not NULL-terminated! */
1487 SubKeyName.Length = BasicInfo->NameLength;
1488 SubKeyName.MaximumLength = BasicInfo->NameLength;
1489 SubKeyName.Buffer = BasicInfo->Name;
1490
1492 &SubKeyName,
1494 delKeys->KeyHandle,
1495 NULL);
1496
1497 /* open the subkey */
1498 Status2 = NtOpenKey(&newDelKeys->KeyHandle,
1501 if (!NT_SUCCESS(Status2))
1502 {
1503 goto SubKeyFailure;
1504 }
1505
1506 /* enqueue this key to the head of the deletion queue */
1507 InsertHeadList(&delQueueHead,
1508 &newDelKeys->ListEntry);
1509
1510 /* try again from the head of the list */
1511 continue;
1512 }
1513 else
1514 {
1515 if (Status2 == STATUS_BUFFER_TOO_SMALL)
1516 {
1517 newDelKeys = RtlAllocateHeap(ProcessHeap,
1518 0,
1519 BufferSize + sizeof(REGP_DEL_KEYS));
1520 if (newDelKeys != NULL)
1521 {
1522 BasicInfo = (PKEY_BASIC_INFORMATION)(newDelKeys + 1);
1523
1524 /* try again */
1525 goto ReadFirstSubKey;
1526 }
1527 else
1528 {
1529 /* don't break, let's try to delete as many keys as possible */
1531 goto SubKeyFailureNoFree;
1532 }
1533 }
1534 else if (Status2 == STATUS_BUFFER_OVERFLOW)
1535 {
1536 PREG_DEL_KEYS newDelKeys2;
1537
1538 ASSERT(newDelKeys != NULL);
1539
1540 /* we need more memory to query the key name */
1541 newDelKeys2 = RtlReAllocateHeap(ProcessHeap,
1542 0,
1543 newDelKeys,
1544 BufferSize + sizeof(REGP_DEL_KEYS));
1545 if (newDelKeys2 != NULL)
1546 {
1547 newDelKeys = newDelKeys2;
1548 BasicInfo = (PKEY_BASIC_INFORMATION)(newDelKeys + 1);
1549
1550 /* try again */
1551 goto ReadFirstSubKey;
1552 }
1553 else
1554 {
1555 /* don't break, let's try to delete as many keys as possible */
1557 }
1558 }
1559 else if (Status2 == STATUS_NO_MORE_ENTRIES)
1560 {
1561 /* in some race conditions where another thread would delete
1562 the same tree at the same time, newDelKeys could actually
1563 be != NULL! */
1564 if (newDelKeys != NULL)
1565 {
1567 0,
1568 newDelKeys);
1569 }
1570 break;
1571 }
1572
1573SubKeyFailure:
1574 /* newDelKeys can be NULL here when NtEnumerateKey returned an
1575 error other than STATUS_BUFFER_TOO_SMALL or STATUS_BUFFER_OVERFLOW! */
1576 if (newDelKeys != NULL)
1577 {
1579 0,
1580 newDelKeys);
1581 }
1582
1583SubKeyFailureNoFree:
1584 /* don't break, let's try to delete as many keys as possible */
1585 if (NT_SUCCESS(Status))
1586 {
1587 Status = Status2;
1588 }
1589 }
1590
1591 Status2 = NtDeleteKey(delKeys->KeyHandle);
1592
1593 /* NOTE: do NOT close the handle anymore, it's invalid already! */
1594
1595 if (!NT_SUCCESS(Status2))
1596 {
1597 /* close the key handle so we don't leak handles for keys we were
1598 unable to delete. But only do this for handles not supplied
1599 by the caller! */
1600
1601 if (delKeys->KeyHandle != hKey)
1602 {
1603 NtClose(delKeys->KeyHandle);
1604 }
1605
1606 if (NT_SUCCESS(Status))
1607 {
1608 /* don't break, let's try to delete as many keys as possible */
1609 Status = Status2;
1610 }
1611 }
1612
1613 /* remove the entry from the list */
1614 RemoveEntryList(&delKeys->ListEntry);
1615
1617 0,
1618 delKeys);
1619 } while (!IsListEmpty(&delQueueHead));
1620 }
1621 else
1623
1624 return Status;
1625}
1626
1627
1628/************************************************************************
1629 * RegDeleteTreeW
1630 *
1631 * @implemented
1632 */
1635 IN LPCWSTR lpSubKey OPTIONAL)
1636{
1637 HANDLE KeyHandle, CurKey, SubKeyHandle = NULL;
1639
1641 hKey);
1642 if (!NT_SUCCESS(Status))
1643 {
1645 }
1646
1647 if (lpSubKey != NULL)
1648 {
1651
1652 RtlInitUnicodeString(&SubKeyName, lpSubKey);
1653
1655 &SubKeyName,
1657 KeyHandle,
1658 NULL);
1659
1663 if (!NT_SUCCESS(Status))
1664 {
1665 goto Cleanup;
1666 }
1667
1668 CurKey = SubKeyHandle;
1669 }
1670 else
1671 CurKey = KeyHandle;
1672
1673 Status = RegpDeleteTree(CurKey);
1674
1675 if (NT_SUCCESS(Status))
1676 {
1677 /* make sure we only close hKey (KeyHandle) when the caller specified a
1678 subkey, because the handle would be invalid already! */
1679 if (CurKey != KeyHandle)
1680 {
1682 }
1683
1684 return ERROR_SUCCESS;
1685 }
1686 else
1687 {
1688 /* make sure we close all handles we created! */
1689 if (SubKeyHandle != NULL)
1690 {
1692 }
1693
1694Cleanup:
1696
1698 }
1699}
1700#endif
1701
1702#endif // _ADVAPI32_VISTA_
1703
1704/************************************************************************
1705 * RegDeleteTreeW
1706 *
1707 * @implemented
1708 */
1709LSTATUS
1710WINAPI
1712 LPCWSTR lpszSubKey)
1713{
1714 LONG ret;
1715 DWORD dwMaxSubkeyLen, dwMaxValueLen;
1716 DWORD dwMaxLen, dwSize;
1719 HKEY hSubKey;
1720 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1721
1722 TRACE("(hkey=%p,%p %s)\n", hKey, lpszSubKey, debugstr_w(lpszSubKey));
1723
1725 hKey);
1726 if (!NT_SUCCESS(Status))
1727 {
1729 }
1730
1731 hSubKey = KeyHandle;
1732
1733 if(lpszSubKey)
1734 {
1735 ret = RegOpenKeyExW(KeyHandle, lpszSubKey, 0, KEY_READ, &hSubKey);
1736 if (ret)
1737 {
1739 return ret;
1740 }
1741 }
1742
1743 /* Get highest length for keys, values */
1744 ret = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
1745 &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
1746 if (ret) goto cleanup;
1747
1748 dwMaxSubkeyLen++;
1749 dwMaxValueLen++;
1750 dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
1751 if (dwMaxLen > sizeof(szNameBuf)/sizeof(WCHAR))
1752 {
1753 /* Name too big: alloc a buffer for it */
1754 if (!(lpszName = RtlAllocateHeap( RtlGetProcessHeap(), 0, dwMaxLen*sizeof(WCHAR))))
1755 {
1757 goto cleanup;
1758 }
1759 }
1760
1761
1762 /* Recursively delete all the subkeys */
1763 while (TRUE)
1764 {
1765 dwSize = dwMaxLen;
1766 if (RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL,
1767 NULL, NULL, NULL)) break;
1768
1769 ret = RegDeleteTreeW(hSubKey, lpszName);
1770 if (ret) goto cleanup;
1771 }
1772
1773 if (lpszSubKey)
1774 ret = RegDeleteKeyW(KeyHandle, lpszSubKey);
1775 else
1776 while (TRUE)
1777 {
1778 dwSize = dwMaxLen;
1779 if (RegEnumValueW(KeyHandle, 0, lpszName, &dwSize,
1780 NULL, NULL, NULL, NULL)) break;
1781
1782 ret = RegDeleteValueW(KeyHandle, lpszName);
1783 if (ret) goto cleanup;
1784 }
1785
1786cleanup:
1787 /* Free buffer if allocated */
1788 if (lpszName != szNameBuf)
1789 RtlFreeHeap( RtlGetProcessHeap(), 0, lpszName);
1790 if(lpszSubKey)
1791 RegCloseKey(hSubKey);
1792
1794
1795 return ret;
1796}
1797
1798
1799/************************************************************************
1800 * RegDeleteTreeA
1801 *
1802 * @implemented
1803 */
1806 IN LPCSTR lpSubKey OPTIONAL)
1807{
1808 UNICODE_STRING SubKeyName = { 0, 0, NULL };
1809 LONG Ret;
1810
1811 if (lpSubKey != NULL &&
1813 {
1815 }
1816
1817 Ret = RegDeleteTreeW(hKey,
1818 SubKeyName.Buffer);
1819
1821
1822 return Ret;
1823}
1824
1825#ifndef _ADVAPI32_VISTA_
1826
1827/************************************************************************
1828 * RegDisableReflectionKey
1829 *
1830 * @unimplemented
1831 */
1834{
1835 FIXME("RegDisableReflectionKey(0x%p) UNIMPLEMENTED!\n", hBase);
1837}
1838
1839
1840/************************************************************************
1841 * RegEnableReflectionKey
1842 *
1843 * @unimplemented
1844 */
1847{
1848 FIXME("RegEnableReflectionKey(0x%p) UNIMPLEMENTED!\n", hBase);
1850}
1851
1852
1853/******************************************************************************
1854 * RegpApplyRestrictions [internal]
1855 *
1856 * Helper function for RegGetValueA/W.
1857 */
1858static VOID
1860 DWORD dwType,
1861 DWORD cbData,
1862 PLONG ret)
1863{
1864 /* Check if the type is restricted by the passed flags */
1865 if (*ret == ERROR_SUCCESS || *ret == ERROR_MORE_DATA)
1866 {
1867 DWORD dwMask = 0;
1868
1869 switch (dwType)
1870 {
1871 case REG_NONE: dwMask = RRF_RT_REG_NONE; break;
1872 case REG_SZ: dwMask = RRF_RT_REG_SZ; break;
1873 case REG_EXPAND_SZ: dwMask = RRF_RT_REG_EXPAND_SZ; break;
1874 case REG_MULTI_SZ: dwMask = RRF_RT_REG_MULTI_SZ; break;
1875 case REG_BINARY: dwMask = RRF_RT_REG_BINARY; break;
1876 case REG_DWORD: dwMask = RRF_RT_REG_DWORD; break;
1877 case REG_QWORD: dwMask = RRF_RT_REG_QWORD; break;
1878 }
1879
1880 if (dwFlags & dwMask)
1881 {
1882 /* Type is not restricted, check for size mismatch */
1883 if (dwType == REG_BINARY)
1884 {
1885 DWORD cbExpect = 0;
1886
1887 if ((dwFlags & RRF_RT_ANY) == RRF_RT_DWORD)
1888 cbExpect = 4;
1889 else if ((dwFlags & RRF_RT_ANY) == RRF_RT_QWORD)
1890 cbExpect = 8;
1891
1892 if (cbExpect && cbData != cbExpect)
1894 }
1895 }
1897 }
1898}
1899
1900
1901/******************************************************************************
1902 * RegGetValueW [ADVAPI32.@]
1903 *
1904 * Retrieves the type and data for a value name associated with a key,
1905 * optionally expanding its content and restricting its type.
1906 *
1907 * PARAMS
1908 * hKey [I] Handle to an open key.
1909 * pszSubKey [I] Name of the subkey of hKey.
1910 * pszValue [I] Name of value under hKey/szSubKey to query.
1911 * dwFlags [I] Flags restricting the value type to retrieve.
1912 * pdwType [O] Destination for the values type, may be NULL.
1913 * pvData [O] Destination for the values content, may be NULL.
1914 * pcbData [I/O] Size of pvData, updated with the size in bytes required to
1915 * retrieve the whole content, including the trailing '\0'
1916 * for strings.
1917 *
1918 * RETURNS
1919 * Success: ERROR_SUCCESS
1920 * Failure: nonzero error code from Winerror.h
1921 *
1922 * NOTES
1923 * - Unless RRF_NOEXPAND is specified, REG_EXPAND_SZ values are automatically
1924 * expanded and pdwType is set to REG_SZ instead.
1925 * - Restrictions are applied after expanding, using RRF_RT_REG_EXPAND_SZ
1926 * without RRF_NOEXPAND is thus not allowed.
1927 * An exception is the case where RRF_RT_ANY is specified, because then
1928 * RRF_NOEXPAND is allowed.
1929 */
1932 LPCWSTR pszSubKey,
1933 LPCWSTR pszValue,
1934 DWORD dwFlags,
1935 LPDWORD pdwType,
1936 PVOID pvData,
1938{
1939 DWORD dwType, cbData = pcbData ? *pcbData : 0;
1940 PVOID pvBuf = NULL;
1941 LONG ret;
1942
1943 TRACE("(%p,%s,%s,%ld,%p,%p,%p=%ld)\n",
1944 hKey, debugstr_w(pszSubKey), debugstr_w(pszValue), dwFlags, pdwType,
1945 pvData, pcbData, cbData);
1946
1947 if (pvData && !pcbData)
1950 ((dwFlags & RRF_RT_ANY) != RRF_RT_ANY))
1952
1953 if (pszSubKey && pszSubKey[0])
1954 {
1955 ret = RegOpenKeyExW(hKey, pszSubKey, 0, KEY_QUERY_VALUE, &hKey);
1956 if (ret != ERROR_SUCCESS) return ret;
1957 }
1958
1959 ret = RegQueryValueExW(hKey, pszValue, NULL, &dwType, pvData, &cbData);
1960
1961 /* If we are going to expand we need to read in the whole the value even
1962 * if the passed buffer was too small as the expanded string might be
1963 * smaller than the unexpanded one and could fit into cbData bytes. */
1964 if ((ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) &&
1965 dwType == REG_EXPAND_SZ && !(dwFlags & RRF_NOEXPAND))
1966 {
1967 do
1968 {
1969 HeapFree(GetProcessHeap(), 0, pvBuf);
1970
1971 pvBuf = HeapAlloc(GetProcessHeap(), 0, cbData);
1972 if (!pvBuf)
1973 {
1975 break;
1976 }
1977
1978 if (ret == ERROR_MORE_DATA || !pvData)
1979 ret = RegQueryValueExW(hKey, pszValue, NULL,
1980 &dwType, pvBuf, &cbData);
1981 else
1982 {
1983 /* Even if cbData was large enough we have to copy the
1984 * string since ExpandEnvironmentStrings can't handle
1985 * overlapping buffers. */
1986 CopyMemory(pvBuf, pvData, cbData);
1987 }
1988
1989 /* Both the type or the value itself could have been modified in
1990 * between so we have to keep retrying until the buffer is large
1991 * enough or we no longer have to expand the value. */
1992 }
1993 while (dwType == REG_EXPAND_SZ && ret == ERROR_MORE_DATA);
1994
1995 if (ret == ERROR_SUCCESS)
1996 {
1997 /* Recheck dwType in case it changed since the first call */
1998 if (dwType == REG_EXPAND_SZ)
1999 {
2000 cbData = ExpandEnvironmentStringsW(pvBuf, pvData,
2001 pcbData ? *pcbData : 0) * sizeof(WCHAR);
2002 dwType = REG_SZ;
2003 if (pvData && pcbData && cbData > *pcbData)
2005 }
2006 else if (pvData)
2007 CopyMemory(pvData, pvBuf, *pcbData);
2008 }
2009
2010 HeapFree(GetProcessHeap(), 0, pvBuf);
2011 }
2012
2013 if (pszSubKey && pszSubKey[0])
2015
2016 RegpApplyRestrictions(dwFlags, dwType, cbData, &ret);
2017
2020
2021 if (pdwType)
2022 *pdwType = dwType;
2023
2024 if (pcbData)
2025 *pcbData = cbData;
2026
2027 return ret;
2028}
2029
2030
2031/******************************************************************************
2032 * RegGetValueA [ADVAPI32.@]
2033 *
2034 * See RegGetValueW.
2035 */
2038 LPCSTR pszSubKey,
2039 LPCSTR pszValue,
2040 DWORD dwFlags,
2041 LPDWORD pdwType,
2042 PVOID pvData,
2044{
2045 DWORD dwType, cbData = pcbData ? *pcbData : 0;
2046 PVOID pvBuf = NULL;
2047 LONG ret;
2048
2049 TRACE("(%p,%s,%s,%ld,%p,%p,%p=%ld)\n",
2050 hKey, pszSubKey, pszValue, dwFlags, pdwType, pvData, pcbData,
2051 cbData);
2052
2053 if (pvData && !pcbData)
2056 ((dwFlags & RRF_RT_ANY) != RRF_RT_ANY))
2058
2059 if (pszSubKey && pszSubKey[0])
2060 {
2061 ret = RegOpenKeyExA(hKey, pszSubKey, 0, KEY_QUERY_VALUE, &hKey);
2062 if (ret != ERROR_SUCCESS) return ret;
2063 }
2064
2065 ret = RegQueryValueExA(hKey, pszValue, NULL, &dwType, pvData, &cbData);
2066
2067 /* If we are going to expand we need to read in the whole the value even
2068 * if the passed buffer was too small as the expanded string might be
2069 * smaller than the unexpanded one and could fit into cbData bytes. */
2070 if ((ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) &&
2071 (dwType == REG_EXPAND_SZ && !(dwFlags & RRF_NOEXPAND)))
2072 {
2073 do {
2074 HeapFree(GetProcessHeap(), 0, pvBuf);
2075
2076 pvBuf = HeapAlloc(GetProcessHeap(), 0, cbData);
2077 if (!pvBuf)
2078 {
2080 break;
2081 }
2082
2083 if (ret == ERROR_MORE_DATA || !pvData)
2084 ret = RegQueryValueExA(hKey, pszValue, NULL,
2085 &dwType, pvBuf, &cbData);
2086 else
2087 {
2088 /* Even if cbData was large enough we have to copy the
2089 * string since ExpandEnvironmentStrings can't handle
2090 * overlapping buffers. */
2091 CopyMemory(pvBuf, pvData, cbData);
2092 }
2093
2094 /* Both the type or the value itself could have been modified in
2095 * between so we have to keep retrying until the buffer is large
2096 * enough or we no longer have to expand the value. */
2097 } while (dwType == REG_EXPAND_SZ && ret == ERROR_MORE_DATA);
2098
2099 if (ret == ERROR_SUCCESS)
2100 {
2101 /* Recheck dwType in case it changed since the first call */
2102 if (dwType == REG_EXPAND_SZ)
2103 {
2104 cbData = ExpandEnvironmentStringsA(pvBuf, pvData,
2105 pcbData ? *pcbData : 0);
2106 dwType = REG_SZ;
2107 if(pvData && pcbData && cbData > *pcbData)
2109 }
2110 else if (pvData)
2111 CopyMemory(pvData, pvBuf, *pcbData);
2112 }
2113
2114 HeapFree(GetProcessHeap(), 0, pvBuf);
2115 }
2116
2117 if (pszSubKey && pszSubKey[0])
2119
2120 RegpApplyRestrictions(dwFlags, dwType, cbData, &ret);
2121
2124
2125 if (pdwType) *pdwType = dwType;
2126 if (pcbData) *pcbData = cbData;
2127
2128 return ret;
2129}
2130
2131#endif // _ADVAPI32_VISTA_
2132
2133/************************************************************************
2134 * RegSetKeyValueW
2135 *
2136 * @implemented
2137 */
2140 IN LPCWSTR lpSubKey OPTIONAL,
2141 IN LPCWSTR lpValueName OPTIONAL,
2142 IN DWORD dwType,
2143 IN LPCVOID lpData OPTIONAL,
2144 IN DWORD cbData)
2145{
2146 HANDLE KeyHandle, CurKey, SubKeyHandle = NULL;
2148 LONG Ret;
2149
2151 hKey);
2152 if (!NT_SUCCESS(Status))
2153 {
2155 }
2156
2157 if (lpSubKey != NULL)
2158 {
2161
2162 RtlInitUnicodeString(&SubKeyName, lpSubKey);
2163
2165 &SubKeyName,
2167 KeyHandle,
2168 NULL);
2169
2173 if (!NT_SUCCESS(Status))
2174 {
2176 goto Cleanup;
2177 }
2178
2179 CurKey = SubKeyHandle;
2180 }
2181 else
2182 CurKey = KeyHandle;
2183
2184 Ret = RegSetValueExW(CurKey,
2185 lpValueName,
2186 0,
2187 dwType,
2188 lpData,
2189 cbData);
2190
2191 if (SubKeyHandle != NULL)
2192 {
2194 }
2195
2196Cleanup:
2198
2199 return Ret;
2200}
2201
2202#ifndef _ADVAPI32_VISTA_
2203
2204/************************************************************************
2205 * RegSetKeyValueA
2206 *
2207 * @implemented
2208 */
2211 IN LPCSTR lpSubKey OPTIONAL,
2212 IN LPCSTR lpValueName OPTIONAL,
2213 IN DWORD dwType,
2214 IN LPCVOID lpData OPTIONAL,
2215 IN DWORD cbData)
2216{
2217 HANDLE KeyHandle, CurKey, SubKeyHandle = NULL;
2219 LONG Ret;
2220
2222 hKey);
2223 if (!NT_SUCCESS(Status))
2224 {
2226 }
2227
2228 if (lpSubKey != NULL)
2229 {
2232
2234 {
2236 goto Cleanup;
2237 }
2238
2240 &SubKeyName,
2242 KeyHandle,
2243 NULL);
2244
2248
2250
2251 if (!NT_SUCCESS(Status))
2252 {
2254 goto Cleanup;
2255 }
2256
2257 CurKey = SubKeyHandle;
2258 }
2259 else
2260 CurKey = KeyHandle;
2261
2262 Ret = RegSetValueExA(CurKey,
2263 lpValueName,
2264 0,
2265 dwType,
2266 lpData,
2267 cbData);
2268
2269 if (SubKeyHandle != NULL)
2270 {
2272 }
2273
2274Cleanup:
2276
2277 return Ret;
2278}
2279
2280
2281/************************************************************************
2282 * RegDeleteValueA
2283 *
2284 * @implemented
2285 */
2288 LPCSTR lpValueName)
2289{
2294
2296 hKey);
2297 if (!NT_SUCCESS(Status))
2298 {
2300 }
2301
2302 if (!RtlCreateUnicodeStringFromAsciiz(&ValueName, lpValueName))
2303 {
2306 }
2307
2308 if (IsHKCRKey(KeyHandle))
2309 {
2311 }
2312 else
2313 {
2315 if (!NT_SUCCESS(Status))
2317 }
2320 return ErrorCode;
2321}
2322
2323
2324/************************************************************************
2325 * RegDeleteValueW
2326 *
2327 * @implemented
2328 */
2331 LPCWSTR lpValueName)
2332{
2337
2339 hKey);
2340 if (!NT_SUCCESS(Status))
2341 {
2343 }
2344
2345 RtlInitUnicodeString(&ValueName, lpValueName);
2346
2347 if (IsHKCRKey(KeyHandle))
2348 {
2350 }
2351 else
2352 {
2354 if (!NT_SUCCESS(Status))
2356 }
2358 return ErrorCode;
2359}
2360
2361
2362/************************************************************************
2363 * RegEnumKeyA
2364 *
2365 * @implemented
2366 */
2369 DWORD dwIndex,
2370 LPSTR lpName,
2371 DWORD cbName)
2372{
2374
2375 dwLength = cbName;
2376 return RegEnumKeyExA(hKey,
2377 dwIndex,
2378 lpName,
2379 &dwLength,
2380 NULL,
2381 NULL,
2382 NULL,
2383 NULL);
2384}
2385
2386
2387/************************************************************************
2388 * RegEnumKeyW
2389 *
2390 * @implemented
2391 */
2394 DWORD dwIndex,
2395 LPWSTR lpName,
2396 DWORD cbName)
2397{
2399
2400 dwLength = cbName;
2401 return RegEnumKeyExW(hKey,
2402 dwIndex,
2403 lpName,
2404 &dwLength,
2405 NULL,
2406 NULL,
2407 NULL,
2408 NULL);
2409}
2410
2411
2412/************************************************************************
2413 * RegEnumKeyExA
2414 *
2415 * @implemented
2416 */
2417LONG
2418WINAPI
2420 _In_ HKEY hKey,
2421 _In_ DWORD dwIndex,
2423 _Inout_ LPDWORD lpcbName,
2424 _Reserved_ LPDWORD lpReserved,
2425 _Out_opt_ LPSTR lpClass,
2426 _Inout_opt_ LPDWORD lpcbClass,
2427 _Out_opt_ PFILETIME lpftLastWriteTime)
2428{
2429 WCHAR* NameBuffer = NULL;
2430 WCHAR* ClassBuffer = NULL;
2431 DWORD NameLength, ClassLength;
2433
2434 /* Allocate our buffers */
2435 if (*lpcbName > 0)
2436 {
2437 NameLength = *lpcbName;
2438 NameBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, *lpcbName * sizeof(WCHAR));
2439 if (NameBuffer == NULL)
2440 {
2442 goto Exit;
2443 }
2444 }
2445
2446 if (lpClass)
2447 {
2448 if (*lpcbClass > 0)
2449 {
2450 ClassLength = *lpcbClass;
2451 ClassBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, *lpcbClass * sizeof(WCHAR));
2452 if (ClassBuffer == NULL)
2453 {
2455 goto Exit;
2456 }
2457 }
2458 }
2459
2460 /* Do the actual call */
2462 hKey,
2463 dwIndex,
2464 NameBuffer,
2465 lpcbName,
2466 lpReserved,
2467 ClassBuffer,
2468 lpcbClass,
2469 lpftLastWriteTime);
2470
2471 if (ErrorCode != ERROR_SUCCESS)
2472 goto Exit;
2473
2474 /* Convert the strings */
2475 RtlUnicodeToMultiByteN(lpName, *lpcbName, 0, NameBuffer, *lpcbName * sizeof(WCHAR));
2476 /* NULL terminate if we can */
2477 if (NameLength > *lpcbName)
2478 lpName[*lpcbName] = '\0';
2479
2480 if (lpClass)
2481 {
2482 RtlUnicodeToMultiByteN(lpClass, *lpcbClass, 0, NameBuffer, *lpcbClass * sizeof(WCHAR));
2483 if (ClassLength > *lpcbClass)
2484 lpClass[*lpcbClass] = '\0';
2485 }
2486
2487Exit:
2488 if (NameBuffer)
2489 RtlFreeHeap(RtlGetProcessHeap(), 0, NameBuffer);
2490 if (ClassBuffer)
2491 RtlFreeHeap(RtlGetProcessHeap(), 0, ClassBuffer);
2492
2493 return ErrorCode;
2494}
2495
2496
2497/************************************************************************
2498 * RegEnumKeyExW
2499 *
2500 * @implemented
2501 */
2502LONG
2503WINAPI
2505 _In_ HKEY hKey,
2506 _In_ DWORD dwIndex,
2508 _Inout_ LPDWORD lpcbName,
2509 _Reserved_ LPDWORD lpReserved,
2510 _Out_opt_ LPWSTR lpClass,
2511 _Inout_opt_ LPDWORD lpcbClass,
2512 _Out_opt_ PFILETIME lpftLastWriteTime)
2513{
2514 union
2515 {
2518 } *KeyInfo;
2519
2521 ULONG ResultSize;
2522 ULONG NameLength;
2523 ULONG ClassLength = 0;
2527
2529 hKey);
2530 if (!NT_SUCCESS(Status))
2531 {
2533 }
2534
2535 if (IsHKCRKey(KeyHandle))
2536 {
2538 KeyHandle,
2539 dwIndex,
2540 lpName,
2541 lpcbName,
2542 lpReserved,
2543 lpClass,
2544 lpcbClass,
2545 lpftLastWriteTime);
2547 return ErrorCode;
2548 }
2549
2550 if (*lpcbName > 0)
2551 {
2552 NameLength = min (*lpcbName - 1, REG_MAX_NAME_SIZE) * sizeof (WCHAR);
2553 }
2554 else
2555 {
2556 NameLength = 0;
2557 }
2558
2559 if (lpClass)
2560 {
2561 if (*lpcbClass > 0)
2562 {
2563 ClassLength = min (*lpcbClass - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
2564 }
2565 else
2566 {
2567 ClassLength = 0;
2568 }
2569
2570 BufferSize = ((sizeof(KEY_NODE_INFORMATION) + NameLength + 3) & ~3) + ClassLength;
2571 }
2572 else
2573 {
2574 BufferSize = sizeof(KEY_BASIC_INFORMATION) + NameLength;
2575 }
2576
2577 KeyInfo = RtlAllocateHeap(ProcessHeap,
2578 0,
2579 BufferSize);
2580 if (KeyInfo == NULL)
2581 {
2583 goto Cleanup;
2584 }
2585
2587 (ULONG)dwIndex,
2589 KeyInfo,
2590 BufferSize,
2591 &ResultSize);
2592 TRACE("NtEnumerateKey() returned status 0x%X\n", Status);
2593 if (!NT_SUCCESS(Status))
2594 {
2596 }
2597 else
2598 {
2599 if (lpClass == NULL)
2600 {
2601 if (KeyInfo->Basic.NameLength > NameLength)
2602 {
2604 }
2605 else
2606 {
2608 KeyInfo->Basic.Name,
2609 KeyInfo->Basic.NameLength);
2610 *lpcbName = (DWORD)(KeyInfo->Basic.NameLength / sizeof(WCHAR));
2611 lpName[*lpcbName] = 0;
2612 }
2613 }
2614 else
2615 {
2616 if (KeyInfo->Node.NameLength > NameLength ||
2617 KeyInfo->Node.ClassLength > ClassLength)
2618 {
2620 }
2621 else
2622 {
2624 KeyInfo->Node.Name,
2625 KeyInfo->Node.NameLength);
2626 *lpcbName = KeyInfo->Node.NameLength / sizeof(WCHAR);
2627 lpName[*lpcbName] = 0;
2628 RtlCopyMemory(lpClass,
2629 (PVOID)((ULONG_PTR)KeyInfo->Node.Name + KeyInfo->Node.ClassOffset),
2630 KeyInfo->Node.ClassLength);
2631 *lpcbClass = (DWORD)(KeyInfo->Node.ClassLength / sizeof(WCHAR));
2632 lpClass[*lpcbClass] = 0;
2633 }
2634 }
2635
2636 if (ErrorCode == ERROR_SUCCESS && lpftLastWriteTime != NULL)
2637 {
2638 if (lpClass == NULL)
2639 {
2640 lpftLastWriteTime->dwLowDateTime = KeyInfo->Basic.LastWriteTime.u.LowPart;
2641 lpftLastWriteTime->dwHighDateTime = KeyInfo->Basic.LastWriteTime.u.HighPart;
2642 }
2643 else
2644 {
2645 lpftLastWriteTime->dwLowDateTime = KeyInfo->Node.LastWriteTime.u.LowPart;
2646 lpftLastWriteTime->dwHighDateTime = KeyInfo->Node.LastWriteTime.u.HighPart;
2647 }
2648 }
2649 }
2650
2652 0,
2653 KeyInfo);
2654
2655Cleanup:
2657
2658 return ErrorCode;
2659}
2660
2661
2662/************************************************************************
2663 * RegEnumValueA
2664 *
2665 * @implemented
2666 */
2669 _In_ HKEY hKey,
2670 _In_ DWORD dwIndex,
2672 _Inout_ LPDWORD lpcbName,
2673 _Reserved_ LPDWORD lpdwReserved,
2674 _Out_opt_ LPDWORD lpdwType,
2675 _Out_opt_ LPBYTE lpData,
2676 _Inout_opt_ LPDWORD lpcbData)
2677{
2678 WCHAR* NameBuffer;
2679 DWORD NameBufferSize, NameLength;
2681 DWORD LocalType = REG_NONE;
2682 BOOL NameOverflow = FALSE;
2683
2684 /* Do parameter checks now, once and for all. */
2685 if (!lpName || !lpcbName)
2687
2688 if ((lpData && !lpcbData) || lpdwReserved)
2690
2691 /* Get the size of the buffer we must use for the first call to RegEnumValueW */
2693 hKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &NameBufferSize, NULL, NULL, NULL);
2694 if (ErrorCode != ERROR_SUCCESS)
2695 return ErrorCode;
2696
2697 /* Add space for the null terminator */
2698 NameBufferSize++;
2699
2700 /* Allocate the buffer for the unicode name */
2701 NameBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, NameBufferSize * sizeof(WCHAR));
2702 if (NameBuffer == NULL)
2703 {
2705 }
2706
2707 /*
2708 * This code calls RegEnumValueW twice, because we need to know the type of the enumerated value.
2709 * So for the first call, we check if we overflow on the name, as we have no way of knowing if this
2710 * is an overflow on the data or on the name during the the second call. So the first time, we make the
2711 * call with the supplied value. This is merdique, but this is how it is.
2712 */
2713 NameLength = *lpcbName;
2715 hKey,
2716 dwIndex,
2717 NameBuffer,
2718 &NameLength,
2719 NULL,
2720 &LocalType,
2721 NULL,
2722 NULL);
2723 if (ErrorCode != ERROR_SUCCESS)
2724 {
2726 NameOverflow = TRUE;
2727 else
2728 goto Exit;
2729 }
2730
2731 if (is_string(LocalType) && lpcbData)
2732 {
2733 /* We must allocate a buffer to get the unicode data */
2734 DWORD DataBufferSize = *lpcbData * sizeof(WCHAR);
2735 WCHAR* DataBuffer = NULL;
2736 DWORD DataLength = *lpcbData;
2737 LPSTR DataStr = (LPSTR)lpData;
2738
2739 if (lpData)
2740 DataBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, *lpcbData * sizeof(WCHAR));
2741
2742 /* Do the real call */
2744 hKey,
2745 dwIndex,
2746 NameBuffer,
2747 &NameBufferSize,
2748 lpdwReserved,
2749 lpdwType,
2750 (LPBYTE)DataBuffer,
2751 &DataBufferSize);
2752
2753 *lpcbData = DataBufferSize / sizeof(WCHAR);
2754
2755 if (ErrorCode != ERROR_SUCCESS)
2756 {
2757 RtlFreeHeap(RtlGetProcessHeap(), 0, DataBuffer);
2758 goto Exit;
2759 }
2760
2761 /* Copy the data whatever the error code is */
2762 if (lpData)
2763 {
2764 /* Do the data conversion */
2765 RtlUnicodeToMultiByteN(DataStr, DataLength, 0, DataBuffer, DataBufferSize);
2766 /* NULL-terminate if there is enough room */
2767 if ((DataLength > *lpcbData) && (DataStr[*lpcbData - 1] != '\0'))
2768 DataStr[*lpcbData] = '\0';
2769 }
2770
2771 RtlFreeHeap(RtlGetProcessHeap(), 0, DataBuffer);
2772 }
2773 else
2774 {
2775 /* No data conversion needed. Do the call with provided buffers */
2777 hKey,
2778 dwIndex,
2779 NameBuffer,
2780 &NameBufferSize,
2781 lpdwReserved,
2782 lpdwType,
2783 lpData,
2784 lpcbData);
2785
2786 if (ErrorCode != ERROR_SUCCESS)
2787 {
2788 goto Exit;
2789 }
2790 }
2791
2792 if (NameOverflow)
2793 {
2795 goto Exit;
2796 }
2797
2798 /* Convert the name string */
2799 RtlUnicodeToMultiByteN(lpName, *lpcbName, lpcbName, NameBuffer, NameBufferSize * sizeof(WCHAR));
2800 lpName[*lpcbName] = ANSI_NULL;
2801
2802Exit:
2803 if (NameBuffer)
2804 RtlFreeHeap(RtlGetProcessHeap(), 0, NameBuffer);
2805
2806 return ErrorCode;
2807}
2808
2809
2810/******************************************************************************
2811 * RegEnumValueW [ADVAPI32.@]
2812 * @implemented
2813 *
2814 * PARAMS
2815 * hkey [I] Handle to key to query
2816 * index [I] Index of value to query
2817 * value [O] Value string
2818 * val_count [I/O] Size of value buffer (in wchars)
2819 * reserved [I] Reserved
2820 * type [O] Type code
2821 * data [O] Value data
2822 * count [I/O] Size of data buffer (in bytes)
2823 *
2824 * RETURNS
2825 * Success: ERROR_SUCCESS
2826 * Failure: nonzero error code from Winerror.h
2827 */
2828LONG
2829WINAPI
2831 _In_ HKEY hKey,
2834 _Inout_ PDWORD val_count,
2839{
2842 ULONG total_size;
2843 char buffer[256], *buf_ptr = buffer;
2845 static const int info_size = FIELD_OFFSET( KEY_VALUE_FULL_INFORMATION, Name );
2846
2847 TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
2848 hKey, index, value, val_count, reserved, type, data, count );
2849
2850 if (!value || !val_count)
2852
2853 if ((data && !count) || reserved)
2855
2857 if (!NT_SUCCESS(status))
2858 {
2860 }
2861
2862 if (IsHKCRKey(KeyHandle))
2863 {
2865 KeyHandle,
2866 index,
2867 value,
2868 val_count,
2869 reserved,
2870 type,
2871 data,
2872 count);
2874 return ErrorCode;
2875 }
2876
2877 total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR);
2878 if (data) total_size += *count;
2879 total_size = min( sizeof(buffer), total_size );
2880
2882 buffer, total_size, &total_size );
2883 if (status && (status != STATUS_BUFFER_OVERFLOW) && (status != STATUS_BUFFER_TOO_SMALL)) goto done;
2884
2885 if (value || data)
2886 {
2887 /* retry with a dynamically allocated buffer */
2889 {
2890 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
2891 if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
2892 {
2894 goto done;
2895 }
2896 info = (KEY_VALUE_FULL_INFORMATION *)buf_ptr;
2898 buf_ptr, total_size, &total_size );
2899 }
2900
2901 if (status) goto done;
2902
2903 if (value)
2904 {
2905 if (info->NameLength/sizeof(WCHAR) >= *val_count)
2906 {
2908 goto overflow;
2909 }
2910 memcpy( value, info->Name, info->NameLength );
2911 *val_count = info->NameLength / sizeof(WCHAR);
2912 value[*val_count] = 0;
2913 }
2914
2915 if (data)
2916 {
2917 if (info->DataLength > *count)
2918 {
2920 goto overflow;
2921 }
2922 memcpy( data, buf_ptr + info->DataOffset, info->DataLength );
2923 if (is_string(info->Type) && info->DataLength <= *count - sizeof(WCHAR))
2924 {
2925 /* if the type is REG_SZ and data is not 0-terminated
2926 * and there is enough space in the buffer NT appends a \0 */
2927 WCHAR *ptr = (WCHAR *)(data + info->DataLength);
2928 if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
2929 }
2930 }
2931 }
2932 else status = STATUS_SUCCESS;
2933
2934 overflow:
2935 if (type) *type = info->Type;
2936 if (count) *count = info->DataLength;
2937
2938 done:
2939 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
2942}
2943
2944
2945/************************************************************************
2946 * RegFlushKey
2947 *
2948 * @implemented
2949 */
2952{
2955
2957 {
2958 return ERROR_SUCCESS;
2959 }
2960
2962 hKey);
2963 if (!NT_SUCCESS(Status))
2964 {
2966 }
2967
2969
2971
2972 if (!NT_SUCCESS(Status))
2973 {
2975 }
2976
2977 return ERROR_SUCCESS;
2978}
2979
2980
2981/************************************************************************
2982 * RegGetKeySecurity
2983 *
2984 * @implemented
2985 */
2989 PSECURITY_DESCRIPTOR pSecurityDescriptor,
2990 LPDWORD lpcbSecurityDescriptor)
2991{
2994
2996 {
2997 return ERROR_INVALID_HANDLE;
2998 }
2999
3001 hKey);
3002 if (!NT_SUCCESS(Status))
3003 {
3004 TRACE("MapDefaultKey() failed (Status %lx)\n", Status);
3006 }
3007
3010 pSecurityDescriptor,
3011 *lpcbSecurityDescriptor,
3012 lpcbSecurityDescriptor);
3013
3015
3016 if (!NT_SUCCESS(Status))
3017 {
3018 WARN("NtQuerySecurityObject() failed (Status %lx)\n", Status);
3020 }
3021
3022 return ERROR_SUCCESS;
3023}
3024
3025
3026/************************************************************************
3027 * RegLoadKeyA
3028 *
3029 * @implemented
3030 */
3033 LPCSTR lpSubKey,
3034 LPCSTR lpFile)
3035{
3039
3040 RtlInitEmptyUnicodeString(&KeyName, NULL, 0);
3041 RtlInitEmptyUnicodeString(&FileName, NULL, 0);
3042
3043 if (lpSubKey)
3044 {
3046 {
3048 goto Exit;
3049 }
3050 }
3051
3052 if (lpFile)
3053 {
3055 {
3057 goto Exit;
3058 }
3059 }
3060
3062 KeyName.Buffer,
3063 FileName.Buffer);
3064
3065Exit:
3068
3069 return ErrorCode;
3070}
3071
3072
3073/************************************************************************
3074 * RegLoadKeyW
3075 *
3076 * @implemented
3077 */
3080 LPCWSTR lpSubKey,
3081 LPCWSTR lpFile)
3082{
3084 OBJECT_ATTRIBUTES KeyObjectAttributes;
3090
3092 {
3093 return ERROR_INVALID_HANDLE;
3094 }
3095
3097 hKey);
3098 if (!NT_SUCCESS(Status))
3099 {
3101 }
3102
3103 if (!RtlDosPathNameToNtPathName_U(lpFile,
3104 &FileName,
3105 NULL,
3106 NULL))
3107 {
3109 goto Cleanup;
3110 }
3111
3113 &FileName,
3115 NULL,
3116 NULL);
3117
3118 RtlInitUnicodeString(&KeyName, lpSubKey);
3119
3120 InitializeObjectAttributes(&KeyObjectAttributes,
3121 &KeyName,
3123 KeyHandle,
3124 NULL);
3125
3126 Status = NtLoadKey(&KeyObjectAttributes,
3128
3129 RtlFreeHeap(RtlGetProcessHeap(),
3130 0,
3131 FileName.Buffer);
3132
3133 if (!NT_SUCCESS(Status))
3134 {
3136 goto Cleanup;
3137 }
3138
3139Cleanup:
3141
3142 return ErrorCode;
3143}
3144
3145
3146/************************************************************************
3147 * RegNotifyChangeKeyValue
3148 *
3149 * @unimplemented
3150 */
3153 BOOL bWatchSubtree,
3154 DWORD dwNotifyFilter,
3155 HANDLE hEvent,
3156 BOOL fAsynchronous)
3157{
3162
3164 {
3165 return ERROR_INVALID_HANDLE;
3166 }
3167
3168 if ((fAsynchronous != FALSE) && (hEvent == NULL))
3169 {
3171 }
3172
3174 hKey);
3175 if (!NT_SUCCESS(Status))
3176 {
3178 }
3179
3180 /* FIXME: Remote key handles must fail */
3181
3183 hEvent,
3184 0,
3185 0,
3187 dwNotifyFilter,
3188 bWatchSubtree,
3189 0,
3190 0,
3191 fAsynchronous);
3193 {
3195 }
3196
3198
3199 return ErrorCode;
3200}
3201
3202
3203/************************************************************************
3204 * RegOpenCurrentUser
3205 *
3206 * @implemented
3207 */
3210 OUT PHKEY phkResult)
3211{
3213
3215 (PHANDLE)phkResult);
3216 if (!NT_SUCCESS(Status))
3217 {
3218 /* NOTE - don't set the last error code! just return the error! */
3220 }
3221
3222 return ERROR_SUCCESS;
3223}
3224
3225
3226/************************************************************************
3227 * RegOpenKeyA
3228 *
3229 * 20050503 Fireball - imported from WINE
3230 *
3231 * @implemented
3232 */
3235 LPCSTR lpSubKey,
3236 PHKEY phkResult)
3237{
3238 TRACE("RegOpenKeyA hKey 0x%x lpSubKey %s phkResult %p\n",
3239 hKey, lpSubKey, phkResult);
3240
3241 if (!phkResult)
3243
3244 if (!hKey && !lpSubKey)
3245 {
3246 *phkResult = hKey;
3247 return ERROR_SUCCESS;
3248 }
3249
3250 return RegOpenKeyExA(hKey,
3251 lpSubKey,
3252 0,
3254 phkResult);
3255}
3256
3257
3258/************************************************************************
3259 * RegOpenKeyW
3260 *
3261 * 19981101 Ariadne
3262 * 19990525 EA
3263 * 20050503 Fireball - imported from WINE
3264 *
3265 * @implemented
3266 */
3269 LPCWSTR lpSubKey,
3270 PHKEY phkResult)
3271{
3272 TRACE("RegOpenKeyW hKey 0x%x lpSubKey %S phkResult %p\n",
3273 hKey, lpSubKey, phkResult);
3274
3275 if (!phkResult)
3277
3278 if (!hKey && !lpSubKey)
3279 {
3280 *phkResult = hKey;
3281 return ERROR_SUCCESS;
3282 }
3283
3284 return RegOpenKeyExW(hKey,
3285 lpSubKey,
3286 0,
3288 phkResult);
3289}
3290
3291
3292/************************************************************************
3293 * RegOpenKeyExA
3294 *
3295 * @implemented
3296 */
3299 _In_ HKEY hKey,
3300 _In_ LPCSTR lpSubKey,
3301 _In_ DWORD ulOptions,
3302 _In_ REGSAM samDesired,
3303 _Out_ PHKEY phkResult)
3304{
3305 UNICODE_STRING SubKeyString;
3307
3308 TRACE("RegOpenKeyExA hKey 0x%x lpSubKey %s ulOptions 0x%x samDesired 0x%x phkResult %p\n",
3309 hKey, lpSubKey, ulOptions, samDesired, phkResult);
3310
3311 if (lpSubKey)
3312 {
3313 if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyString, lpSubKey))
3315 }
3316 else
3317 RtlInitEmptyUnicodeString(&SubKeyString, NULL, 0);
3318
3319 ErrorCode = RegOpenKeyExW(hKey, SubKeyString.Buffer, ulOptions, samDesired, phkResult);
3320
3321 RtlFreeUnicodeString(&SubKeyString);
3322
3323 return ErrorCode;
3324}
3325
3326
3327/************************************************************************
3328 * RegOpenKeyExW
3329 *
3330 * @implemented
3331 */
3334 LPCWSTR lpSubKey,
3335 DWORD ulOptions,
3336 REGSAM samDesired,
3337 PHKEY phkResult)
3338{
3340 UNICODE_STRING SubKeyString;
3345 BOOLEAN SubKeyStringAllocated = FALSE;
3346
3347 TRACE("RegOpenKeyExW hKey 0x%x lpSubKey %S ulOptions 0x%x samDesired 0x%x phkResult %p\n",
3348 hKey, lpSubKey, ulOptions, samDesired, phkResult);
3349 if (!phkResult)
3350 {
3352 }
3353
3354 if (!hKey && lpSubKey && phkResult)
3355 {
3356 return ERROR_INVALID_HANDLE;
3357 }
3358
3359 if (IsPredefKey(hKey) && (!lpSubKey || !*lpSubKey))
3360 {
3361 *phkResult = hKey;
3362 return ERROR_SUCCESS;
3363 }
3364
3366 if (!NT_SUCCESS(Status))
3367 {
3369 }
3370
3371 if (IsHKCRKey(KeyHandle))
3372 {
3373 ErrorCode = OpenHKCRKey(KeyHandle, lpSubKey, ulOptions, samDesired, phkResult);
3375 return ErrorCode;
3376 }
3377
3378 if (ulOptions & REG_OPTION_OPEN_LINK)
3380
3381 if (lpSubKey == NULL || wcscmp(lpSubKey, L"\\") == 0)
3382 {
3383 RtlInitUnicodeString(&SubKeyString, L"");
3384 }
3385 else
3386 {
3387 RtlInitUnicodeString(&SubKeyString, lpSubKey);
3388
3389 /* Handle unaligned lpSubKey */
3390 if ((ULONG_PTR)lpSubKey & 1)
3391 {
3392 UNICODE_STRING AlignedString;
3393
3395 &SubKeyString,
3396 &AlignedString);
3397 if (!NT_SUCCESS(Status))
3398 {
3399 goto Exit;
3400 }
3401
3402 SubKeyString = AlignedString;
3403 SubKeyStringAllocated = TRUE;
3404 }
3405 }
3406
3408 &SubKeyString,
3409 Attributes,
3410 KeyHandle,
3411 NULL);
3412
3413 Status = NtOpenKey((PHANDLE)phkResult,
3414 samDesired,
3416
3417Exit:
3418
3419 if (SubKeyStringAllocated)
3420 {
3421 RtlFreeUnicodeString(&SubKeyString);
3422 }
3423
3424 if (!NT_SUCCESS(Status))
3425 {
3427 }
3428
3430
3431 return ErrorCode;
3432}
3433
3434
3435/************************************************************************
3436 * RegOpenUserClassesRoot
3437 *
3438 * @implemented
3439 */
3443 IN REGSAM samDesired,
3444 OUT PHKEY phkResult)
3445{
3446 const WCHAR UserClassesKeyPrefix[] = L"\\Registry\\User\\";
3447 const WCHAR UserClassesKeySuffix[] = L"_Classes";
3448 PTOKEN_USER TokenUserData;
3450 UNICODE_STRING UserSidString, UserClassesKeyRoot;
3453
3454 /* check parameters */
3455 if (hToken == NULL || dwOptions != 0 || phkResult == NULL)
3456 {
3458 }
3459
3460 /*
3461 * Get the user sid from the token
3462 */
3463
3464ReadTokenSid:
3465 /* determine how much memory we need */
3467 TokenUser,
3468 NULL,
3469 0,
3472 {
3473 /* NOTE - as opposed to all other registry functions windows does indeed
3474 change the last error code in case the caller supplied a invalid
3475 handle for example! */
3477 }
3478 RegInitialize(); /* HACK until delay-loading is implemented */
3479 TokenUserData = RtlAllocateHeap(ProcessHeap,
3480 0,
3482 if (TokenUserData == NULL)
3483 {
3485 }
3486
3487 /* attempt to read the information */
3489 TokenUser,
3490 TokenUserData,
3493 if (!NT_SUCCESS(Status))
3494 {
3496 0,
3497 TokenUserData);
3499 {
3500 /* the information appears to have changed?! try again */
3501 goto ReadTokenSid;
3502 }
3503
3504 /* NOTE - as opposed to all other registry functions windows does indeed
3505 change the last error code in case the caller supplied a invalid
3506 handle for example! */
3508 }
3509
3510 /*
3511 * Build the absolute path for the user's registry in the form
3512 * "\Registry\User<SID>_Classes"
3513 */
3514 Status = RtlConvertSidToUnicodeString(&UserSidString,
3515 TokenUserData->User.Sid,
3516 TRUE);
3517
3518 /* we don't need the user data anymore, free it */
3520 0,
3521 TokenUserData);
3522
3523 if (!NT_SUCCESS(Status))
3524 {
3526 }
3527
3528 /* allocate enough memory for the entire key string */
3529 UserClassesKeyRoot.Length = 0;
3530 UserClassesKeyRoot.MaximumLength = UserSidString.Length +
3531 sizeof(UserClassesKeyPrefix) +
3532 sizeof(UserClassesKeySuffix);
3533 UserClassesKeyRoot.Buffer = RtlAllocateHeap(ProcessHeap,
3534 0,
3535 UserClassesKeyRoot.MaximumLength);
3536 if (UserClassesKeyRoot.Buffer == NULL)
3537 {
3538 RtlFreeUnicodeString(&UserSidString);
3540 }
3541
3542 /* build the string */
3543 RtlAppendUnicodeToString(&UserClassesKeyRoot,
3544 UserClassesKeyPrefix);
3545 RtlAppendUnicodeStringToString(&UserClassesKeyRoot,
3546 &UserSidString);
3547 RtlAppendUnicodeToString(&UserClassesKeyRoot,
3548 UserClassesKeySuffix);
3549
3550 TRACE("RegOpenUserClassesRoot: Absolute path: %wZ\n", &UserClassesKeyRoot);
3551
3552 /*
3553 * Open the key
3554 */
3556 &UserClassesKeyRoot,
3558 NULL,
3559 NULL);
3560
3561 Status = NtOpenKey((PHANDLE)phkResult,
3562 samDesired,
3564
3565 RtlFreeUnicodeString(&UserSidString);
3566 RtlFreeUnicodeString(&UserClassesKeyRoot);
3567
3568 if (!NT_SUCCESS(Status))
3569 {
3571 }
3572
3573 return ERROR_SUCCESS;
3574}
3575
3576
3577/************************************************************************
3578 * RegQueryInfoKeyA
3579 *
3580 * @implemented
3581 */
3584 LPSTR lpClass,
3585 LPDWORD lpcClass,
3586 LPDWORD lpReserved,
3587 LPDWORD lpcSubKeys,
3588 LPDWORD lpcMaxSubKeyLen,
3589 LPDWORD lpcMaxClassLen,
3590 LPDWORD lpcValues,
3591 LPDWORD lpcMaxValueNameLen,
3592 LPDWORD lpcMaxValueLen,
3593 LPDWORD lpcbSecurityDescriptor,
3594 PFILETIME lpftLastWriteTime)
3595{
3596 WCHAR ClassName[MAX_PATH];
3601 DWORD cClass = 0;
3602
3603 if ((lpClass) && (!lpcClass))
3604 {
3606 }
3607
3609 NULL);
3610 if (lpClass != NULL)
3611 {
3612 RtlInitEmptyUnicodeString(&UnicodeString,
3613 ClassName,
3614 sizeof(ClassName));
3615 cClass = sizeof(ClassName) / sizeof(WCHAR);
3616 }
3617
3619 UnicodeString.Buffer,
3620 &cClass,
3621 lpReserved,
3622 lpcSubKeys,
3623 lpcMaxSubKeyLen,
3624 lpcMaxClassLen,
3625 lpcValues,
3626 lpcMaxValueNameLen,
3627 lpcMaxValueLen,
3628 lpcbSecurityDescriptor,
3629 lpftLastWriteTime);
3630 if ((ErrorCode == ERROR_SUCCESS) && (lpClass != NULL))
3631 {
3632 if (*lpcClass == 0)
3633 {
3634 return ErrorCode;
3635 }
3636
3637 RtlInitEmptyAnsiString(&AnsiString, lpClass, *lpcClass);
3638 UnicodeString.Length = cClass * sizeof(WCHAR);
3641 FALSE);
3643 cClass = AnsiString.Length;
3644 lpClass[cClass] = ANSI_NULL;
3645 }
3646
3647 if (lpcClass != NULL)
3648 {
3649 *lpcClass = cClass;
3650 }
3651
3652 return ErrorCode;
3653}
3654
3655
3656/************************************************************************
3657 * RegQueryInfoKeyW
3658 *
3659 * @implemented
3660 */
3663 LPWSTR lpClass,
3664 LPDWORD lpcClass,
3665 LPDWORD lpReserved,
3666 LPDWORD lpcSubKeys,
3667 LPDWORD lpcMaxSubKeyLen,
3668 LPDWORD lpcMaxClassLen,
3669 LPDWORD lpcValues,
3670 LPDWORD lpcMaxValueNameLen,
3671 LPDWORD lpcMaxValueLen,
3672 LPDWORD lpcbSecurityDescriptor,
3673 PFILETIME lpftLastWriteTime)
3674{
3675 KEY_FULL_INFORMATION FullInfoBuffer;
3676 PKEY_FULL_INFORMATION FullInfo;
3677 ULONG FullInfoSize;
3678 ULONG ClassLength = 0;
3681 ULONG Length;
3683
3684 if ((lpClass) && (!lpcClass))
3685 {
3687 }
3688
3690 hKey);
3691 if (!NT_SUCCESS(Status))
3692 {
3694 }
3695
3696 if (IsHKCRKey(KeyHandle))
3697 {
3698 ErrorCode = QueryInfoHKCRKey(KeyHandle, lpClass, lpcClass, lpReserved,
3699 lpcSubKeys, lpcMaxSubKeyLen, lpcMaxClassLen,
3700 lpcValues, lpcMaxValueNameLen, lpcMaxValueLen,
3701 lpcbSecurityDescriptor, lpftLastWriteTime);
3703 return ErrorCode;
3704 }
3705
3706 if (lpClass != NULL)
3707 {
3708 if (*lpcClass > 0)
3709 {
3710 ClassLength = min(*lpcClass - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
3711 }
3712 else
3713 {
3714 ClassLength = 0;
3715 }
3716
3717 FullInfoSize = sizeof(KEY_FULL_INFORMATION) + ((ClassLength + 3) & ~3);
3718 FullInfo = RtlAllocateHeap(ProcessHeap,
3719 0,
3720 FullInfoSize);
3721 if (FullInfo == NULL)
3722 {
3724 goto Cleanup;
3725 }
3726 }
3727 else
3728 {
3729 FullInfoSize = sizeof(KEY_FULL_INFORMATION);
3730 FullInfo = &FullInfoBuffer;
3731 }
3732
3733 if (lpcbSecurityDescriptor != NULL)
3734 *lpcbSecurityDescriptor = 0;
3735
3738 FullInfo,
3739 FullInfoSize,
3740 &Length);
3741 TRACE("NtQueryKey() returned status 0x%X\n", Status);
3743 {
3745 goto Cleanup;
3746 }
3747
3748 TRACE("SubKeys %d\n", FullInfo->SubKeys);
3749 if (lpcSubKeys != NULL)
3750 {
3751 *lpcSubKeys = FullInfo->SubKeys;
3752 }
3753
3754 TRACE("MaxNameLen %lu\n", FullInfo->MaxNameLen);
3755 if (lpcMaxSubKeyLen != NULL)
3756 {
3757 *lpcMaxSubKeyLen = FullInfo->MaxNameLen / sizeof(WCHAR);
3758 }
3759
3760 TRACE("MaxClassLen %lu\n", FullInfo->MaxClassLen);
3761 if (lpcMaxClassLen != NULL)
3762 {
3763 *lpcMaxClassLen = FullInfo->MaxClassLen / sizeof(WCHAR);
3764 }
3765
3766 TRACE("Values %lu\n", FullInfo->Values);
3767 if (lpcValues != NULL)
3768 {
3769 *lpcValues = FullInfo->Values;
3770 }
3771
3772 TRACE("MaxValueNameLen %lu\n", FullInfo->MaxValueNameLen);
3773 if (lpcMaxValueNameLen != NULL)
3774 {
3775 *lpcMaxValueNameLen = FullInfo->MaxValueNameLen / sizeof(WCHAR);
3776 }
3777
3778 TRACE("MaxValueDataLen %lu\n", FullInfo->MaxValueDataLen);
3779 if (lpcMaxValueLen != NULL)
3780 {
3781 *lpcMaxValueLen = FullInfo->MaxValueDataLen;
3782 }
3783
3784 if (lpcbSecurityDescriptor != NULL)
3785 {
3790 NULL,
3791 0,
3792 lpcbSecurityDescriptor);
3793 TRACE("NtQuerySecurityObject() returned status 0x%X\n", Status);
3794 }
3795
3796 if (lpftLastWriteTime != NULL)
3797 {
3798 lpftLastWriteTime->dwLowDateTime = FullInfo->LastWriteTime.u.LowPart;
3799 lpftLastWriteTime->dwHighDateTime = FullInfo->LastWriteTime.u.HighPart;
3800 }
3801
3802 if (lpClass != NULL)
3803 {
3804 if (*lpcClass == 0)
3805 {
3806 goto Cleanup;
3807 }
3808
3809 if (FullInfo->ClassLength > ClassLength)
3810 {
3812 }
3813 else
3814 {
3815 RtlCopyMemory(lpClass,
3816 FullInfo->Class,
3817 FullInfo->ClassLength);
3818 lpClass[FullInfo->ClassLength / sizeof(WCHAR)] = UNICODE_NULL;
3819 }
3820 }
3821
3822 if (lpcClass != NULL)
3823 {
3824 *lpcClass = FullInfo->ClassLength / sizeof(WCHAR);
3825 }
3826
3827Cleanup:
3828 if (lpClass != NULL)
3829 {
3831 0,
3832 FullInfo);
3833 }
3834
3836
3837 return ErrorCode;
3838}
3839
3840
3841/************************************************************************
3842 * RegQueryMultipleValuesA
3843 *
3844 * @implemented
3845 */
3848 PVALENTA val_list,
3849 DWORD num_vals,
3850 LPSTR lpValueBuf,
3851 LPDWORD ldwTotsize)
3852{
3853 ULONG i;
3854 DWORD maxBytes = *ldwTotsize;
3855 LPSTR bufptr = lpValueBuf;
3857
3858 if (maxBytes >= (1024*1024))
3859 return ERROR_MORE_DATA;
3860
3861 *ldwTotsize = 0;
3862
3863 TRACE("RegQueryMultipleValuesA(%p,%p,%ld,%p,%p=%ld)\n",
3864 hKey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize);
3865
3866 for (i = 0; i < num_vals; i++)
3867 {
3868 val_list[i].ve_valuelen = 0;
3870 val_list[i].ve_valuename,
3871 NULL,
3872 NULL,
3873 NULL,
3874 &val_list[i].ve_valuelen);
3875 if (ErrorCode != ERROR_SUCCESS)
3876 {
3877 return ErrorCode;
3878 }
3879
3880 if (lpValueBuf != NULL && *ldwTotsize + val_list[i].ve_valuelen <= maxBytes)
3881 {
3883 val_list[i].ve_valuename,
3884 NULL,
3885 &val_list[i].ve_type,
3886 (LPBYTE)bufptr,
3887 &val_list[i].ve_valuelen);
3888 if (ErrorCode != ERROR_SUCCESS)
3889 {
3890 return ErrorCode;
3891 }
3892
3893 val_list[i].ve_valueptr = (DWORD_PTR)bufptr;
3894
3895 bufptr += val_list[i].ve_valuelen;
3896 }
3897
3898 *ldwTotsize += val_list[i].ve_valuelen;
3899 }
3900
3901 return (lpValueBuf != NULL && *ldwTotsize <= maxBytes) ? ERROR_SUCCESS : ERROR_MORE_DATA;
3902}
3903
3904
3905/************************************************************************
3906 * RegQueryMultipleValuesW
3907 *
3908 * @implemented
3909 */
3912 PVALENTW val_list,
3913 DWORD num_vals,
3914 LPWSTR lpValueBuf,
3915 LPDWORD ldwTotsize)
3916{
3917 ULONG i;
3918 DWORD maxBytes = *ldwTotsize;
3919 LPSTR bufptr = (LPSTR)lpValueBuf;
3921
3922 if (maxBytes >= (1024*1024))
3923 return ERROR_MORE_DATA;
3924
3925 *ldwTotsize = 0;
3926
3927 TRACE("RegQueryMultipleValuesW(%p,%p,%ld,%p,%p=%ld)\n",
3928 hKey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize);
3929
3930 for (i = 0; i < num_vals; i++)
3931 {
3932 val_list[i].ve_valuelen = 0;
3934 val_list[i].ve_valuename,
3935 NULL,
3936 NULL,
3937 NULL,
3938 &val_list[i].ve_valuelen);
3939 if (ErrorCode != ERROR_SUCCESS)
3940 {
3941 return ErrorCode;
3942 }
3943
3944 if (lpValueBuf != NULL && *ldwTotsize + val_list[i].ve_valuelen <= maxBytes)
3945 {
3947 val_list[i].ve_valuename,
3948 NULL,
3949 &val_list[i].ve_type,
3950 (LPBYTE)bufptr,
3951 &val_list[i].ve_valuelen);
3952 if (ErrorCode != ERROR_SUCCESS)
3953 {
3954 return ErrorCode;
3955 }
3956
3957 val_list[i].ve_valueptr = (DWORD_PTR)bufptr;
3958
3959 bufptr += val_list[i].ve_valuelen;
3960 }
3961
3962 *ldwTotsize += val_list[i].ve_valuelen;
3963 }
3964
3965 return (lpValueBuf != NULL && *ldwTotsize <= maxBytes) ? ERROR_SUCCESS : ERROR_MORE_DATA;
3966}
3967
3968
3969/************************************************************************
3970 * RegQueryReflectionKey
3971 *
3972 * @unimplemented
3973 */
3976 OUT BOOL* bIsReflectionDisabled)
3977{
3978 FIXME("RegQueryReflectionKey(0x%p, 0x%p) UNIMPLEMENTED!\n",
3979 hBase, bIsReflectionDisabled);
3981}
3982
3983
3984/******************************************************************************
3985 * RegQueryValueExA [ADVAPI32.@]
3986 *
3987 * Get the type and contents of a specified value under with a key.
3988 *
3989 * PARAMS
3990 * hkey [I] Handle of the key to query
3991 * name [I] Name of value under hkey to query
3992 * reserved [I] Reserved - must be NULL
3993 * type [O] Destination for the value type, or NULL if not required
3994 * data [O] Destination for the values contents, or NULL if not required
3995 * count [I/O] Size of data, updated with the number of bytes returned
3996 *
3997 * RETURNS
3998 * Success: ERROR_SUCCESS. *count is updated with the number of bytes copied to data.
3999 * Failure: ERROR_INVALID_HANDLE, if hkey is invalid.
4000 * ERROR_INVALID_PARAMETER, if any other parameter is invalid.
4001 * ERROR_MORE_DATA, if on input *count is too small to hold the contents.
4002 *
4003 * NOTES
4004 * MSDN states that if data is too small it is partially filled. In reality
4005 * it remains untouched.
4006 */
4007LONG
4008WINAPI
4010 _In_ HKEY hkeyorg,
4016{
4020 DWORD BufferSize = 0;
4021 WCHAR* Buffer;
4022 CHAR* DataStr = (CHAR*)data;
4023 DWORD LocalType;
4024
4025 /* Validate those parameters, the rest will be done with the first RegQueryValueExW call */
4026 if ((data && !count) || reserved)
4028
4029 if (name)
4030 {
4033 }
4034 else
4035 RtlInitEmptyUnicodeString(&nameW, NULL, 0);
4036
4037 ErrorCode = RegQueryValueExW(hkeyorg, nameW.Buffer, NULL, &LocalType, NULL, &BufferSize);
4038 if (ErrorCode != ERROR_SUCCESS)
4039 {
4040 if ((!data) && count)
4041 *count = 0;
4043 return ErrorCode;
4044 }
4045
4046 /* See if we can directly handle the call without caring for conversion */
4047 if (!is_string(LocalType) || !count)
4048 {
4049 ErrorCode = RegQueryValueExW(hkeyorg, nameW.Buffer, reserved, type, data, count);
4051 return ErrorCode;
4052 }
4053
4054 /* Allocate a unicode string to get the data */
4055 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
4056 if (!Buffer)
4057 {
4060 }
4061
4063 if (ErrorCode != ERROR_SUCCESS)
4064 {
4065 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
4067 return ErrorCode;
4068 }
4069
4070 /* We don't need this anymore */
4072
4073 /* Get the length for the multi-byte string (without the terminating NULL!) */
4074 DataLength = *count;
4076
4077 if ((!data) || (DataLength < *count))
4078 {
4079 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
4081 }
4082
4083 /* We can finally do the conversion */
4085
4086 /* NULL-terminate if there is enough room */
4087 if (DataLength > *count)
4088 DataStr[*count] = '\0';
4089
4090 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
4091
4092 return ERROR_SUCCESS;
4093}
4094
4095
4096/************************************************************************
4097 * RegQueryValueExW
4098 *
4099 * @implemented
4100 */
4101LONG
4102WINAPI
4104 _In_ HKEY hkeyorg,
4110{
4111 HANDLE hkey;
4113 UNICODE_STRING name_str;
4114 DWORD total_size;
4115 char buffer[256], *buf_ptr = buffer;
4117 static const int info_size = offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data );
4118
4119 TRACE("(%p,%s,%p,%p,%p,%p=%d)\n",
4120 hkeyorg, debugstr_w(name), reserved, type, data, count,
4121 (count && data) ? *count : 0 );
4122
4123 if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
4124
4125 status = MapDefaultKey(&hkey, hkeyorg);
4126 if (!NT_SUCCESS(status))
4127 {
4129 }
4130
4131 if (IsHKCRKey(hkey))
4132 {
4134 ClosePredefKey(hkey);
4135 return ErrorCode;
4136 }
4137
4138 RtlInitUnicodeString( &name_str, name );
4139
4140 if (data)
4141 total_size = min( sizeof(buffer), *count + info_size );
4142 else
4143 total_size = info_size;
4144
4145
4147 buffer, total_size, &total_size );
4148
4150 {
4151 // NT: Valid handles with inexistant/null values or invalid (but not NULL) handles sets type to REG_NONE
4152 // On windows these conditions are likely to be side effects of the implementation...
4153 if (status == STATUS_INVALID_HANDLE && hkey)
4154 {
4155 if (type) *type = REG_NONE;
4156 if (count) *count = 0;
4157 }
4159 {
4160 if (type) *type = REG_NONE;
4161 if (data == NULL && count) *count = 0;
4162 }
4163 goto done;
4164 }
4165
4166 if (data)
4167 {
4168 /* retry with a dynamically allocated buffer */
4169 while (status == STATUS_BUFFER_OVERFLOW && total_size - info_size <= *count)
4170 {
4171 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
4172 if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
4173 {
4174 ClosePredefKey(hkey);
4176 }
4179 buf_ptr, total_size, &total_size );
4180 }
4181
4182 if (NT_SUCCESS(status))
4183 {
4184 memcpy( data, buf_ptr + info_size, total_size - info_size );
4185 /* if the type is REG_SZ and data is not 0-terminated
4186 * and there is enough space in the buffer NT appends a \0 */
4187 if (is_string(info->Type) && total_size - info_size <= *count-sizeof(WCHAR))
4188 {
4189 WCHAR *ptr = (WCHAR *)(data + total_size - info_size);
4190 if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
4191 }
4192 }
4193 else if (status != STATUS_BUFFER_OVERFLOW) goto done;
4194 }
4195 else status = STATUS_SUCCESS;
4196
4197 if (type) *type = info->Type;
4198 if (count) *count = total_size - info_size;
4199
4200 done:
4201 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
4202 ClosePredefKey(hkey);
4204}
4205
4206
4207/************************************************************************
4208 * RegQueryValueA
4209 *
4210 * @implemented
4211 */
4213{
4214 DWORD ret;
4215 HKEY subkey = hkey;
4216
4217 TRACE("(%p,%s,%p,%d)\n", hkey, debugstr_a(name), data, count ? *count : 0 );
4218
4219 if (name && name[0])
4220 {
4221 if ((ret = RegOpenKeyA( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
4222 }
4224 if (subkey != hkey) RegCloseKey( subkey );
4226 {
4227 /* return empty string if default value not found */
4228 if (data) *data = 0;
4229 if (count) *count = 1;
4231 }
4232 return ret;
4233}
4234
4235
4236/************************************************************************
4237 * RegQueryValueW
4238 *
4239 * @implemented
4240 */
4242{
4243 DWORD ret;
4244 HKEY subkey = hkey;
4245
4246 TRACE("(%p,%s,%p,%d)\n", hkey, debugstr_w(name), data, count ? *count : 0 );
4247 if (hkey == NULL)
4248 {
4249 return ERROR_INVALID_HANDLE;
4250 }
4251 if (name && name[0])
4252 {
4253 ret = RegOpenKeyW( hkey, name, &subkey);
4254 if (ret != ERROR_SUCCESS)
4255 {
4256 return ret;
4257 }
4258 }
4259
4261
4262 if (subkey != hkey)
4263 {
4264 RegCloseKey( subkey );
4265 }
4266
4268 {
4269 /* return empty string if default value not found */
4270 if (data)
4271 *data = 0;
4272 if (count)
4273 *count = sizeof(WCHAR);
4275 }
4276 return ret;
4277}
4278
4279
4280/************************************************************************
4281 * RegReplaceKeyA
4282 *
4283 * @implemented
4284 */
4287 LPCSTR lpSubKey,
4288 LPCSTR lpNewFile,
4289 LPCSTR lpOldFile)
4290{
4291 UNICODE_STRING SubKey;
4292 UNICODE_STRING NewFile;
4293 UNICODE_STRING OldFile;
4295
4296 RtlInitEmptyUnicodeString(&SubKey, NULL, 0);
4297 RtlInitEmptyUnicodeString(&OldFile, NULL, 0);
4298 RtlInitEmptyUnicodeString(&NewFile, NULL, 0);
4299
4300 if (lpSubKey)
4301 {
4302 if (!RtlCreateUnicodeStringFromAsciiz(&SubKey, lpSubKey))
4303 {
4305 goto Exit;
4306 }
4307 }
4308
4309 if (lpOldFile)
4310 {
4311 if (!RtlCreateUnicodeStringFromAsciiz(&OldFile, lpOldFile))
4312 {
4314 goto Exit;
4315 }
4316 }
4317
4318 if (lpNewFile)
4319 {
4320 if (!RtlCreateUnicodeStringFromAsciiz(&NewFile, lpNewFile))
4321 {
4323 goto Exit;
4324 }
4325 }
4326
4328 SubKey.Buffer,
4329 NewFile.Buffer,
4330 OldFile.Buffer);
4331
4332Exit:
4333 RtlFreeUnicodeString(&OldFile);
4334 RtlFreeUnicodeString(&NewFile);
4335 RtlFreeUnicodeString(&SubKey);
4336
4337 return ErrorCode;
4338}
4339
4340
4341/************************************************************************
4342 * RegReplaceKeyW
4343 *
4344 * @unimplemented
4345 */
4348 LPCWSTR lpSubKey,
4349 LPCWSTR lpNewFile,
4350 LPCWSTR lpOldFile)
4351{
4352 OBJECT_ATTRIBUTES KeyObjectAttributes;
4353 OBJECT_ATTRIBUTES NewObjectAttributes;
4354 OBJECT_ATTRIBUTES OldObjectAttributes;
4356 UNICODE_STRING NewFileName;
4357 UNICODE_STRING OldFileName;
4358 BOOLEAN CloseRealKey;
4359 HANDLE RealKeyHandle;
4363
4365 {
4366 return ERROR_INVALID_HANDLE;
4367 }
4368
4370 hKey);
4371 if (!NT_SUCCESS(Status))
4372 {
4374 }
4375
4376 /* Open the real key */
4377 if (lpSubKey != NULL && *lpSubKey != (WCHAR)0)
4378 {
4379 RtlInitUnicodeString(&SubKeyName, lpSubKey);
4380 InitializeObjectAttributes(&KeyObjectAttributes,
4381 &SubKeyName,
4383 KeyHandle,
4384 NULL);
4385 Status = NtOpenKey(&RealKeyHandle,
4387 &KeyObjectAttributes);
4388 if (!NT_SUCCESS(Status))
4389 {
4391 goto Cleanup;
4392 }
4393
4394 CloseRealKey = TRUE;
4395 }
4396 else
4397 {
4398 RealKeyHandle = KeyHandle;
4399 CloseRealKey = FALSE;
4400 }
4401
4402 /* Convert new file name */
4403 if (!RtlDosPathNameToNtPathName_U(lpNewFile,
4404 &NewFileName,
4405 NULL,
4406 NULL))
4407 {
4408 if (CloseRealKey)
4409 {
4410 NtClose(RealKeyHandle);
4411 }
4412
4414 goto Cleanup;
4415 }
4416
4417 InitializeObjectAttributes(&NewObjectAttributes,
4418 &NewFileName,
4420 NULL,
4421 NULL);
4422
4423 /* Convert old file name */
4424 if (!RtlDosPathNameToNtPathName_U(lpOldFile,
4425 &OldFileName,
4426 NULL,
4427 NULL))
4428 {
4429 RtlFreeHeap(RtlGetProcessHeap (),
4430 0,
4431 NewFileName.Buffer);
4432 if (CloseRealKey)
4433 {
4434 NtClose(RealKeyHandle);
4435 }
4436
4438 goto Cleanup;
4439 }
4440
4441 InitializeObjectAttributes(&OldObjectAttributes,
4442 &OldFileName,
4444 NULL,
4445 NULL);
4446
4447 Status = NtReplaceKey(&NewObjectAttributes,
4448 RealKeyHandle,
4449 &OldObjectAttributes);
4450
4451 RtlFreeHeap(RtlGetProcessHeap(),
4452 0,
4453 OldFileName.Buffer);
4454 RtlFreeHeap(RtlGetProcessHeap(),
4455 0,
4456 NewFileName.Buffer);
4457
4458 if (CloseRealKey)
4459 {
4460 NtClose(RealKeyHandle);
4461 }
4462
4463 if (!NT_SUCCESS(Status))
4464 {
4466 }
4467
4468Cleanup:
4470
4471 return ErrorCode;
4472}
4473
4474
4475/************************************************************************
4476 * RegRestoreKeyA
4477 *
4478 * @implemented
4479 */
4482 LPCSTR lpFile,
4483 DWORD dwFlags)
4484{
4487
4488 if (lpFile)
4489 {
4492 }
4493 else
4494 RtlInitEmptyUnicodeString(&FileName, NULL, 0);
4495
4497 FileName.Buffer,
4498 dwFlags);
4499
4501
4502 return ErrorCode;
4503}
4504
4505
4506/************************************************************************
4507 * RegRestoreKeyW
4508 *
4509 * @implemented
4510 */
4513 LPCWSTR lpFile,
4514 DWORD dwFlags)
4515{
4522
4524 {
4525 return ERROR_INVALID_HANDLE;
4526 }
4527
4529 hKey);
4530 if (!NT_SUCCESS(Status))
4531 {
4533 }
4534
4535 if (!RtlDosPathNameToNtPathName_U(lpFile,
4536 &FileName,
4537 NULL,
4538 NULL))
4539 {
4541 goto Cleanup;
4542 }
4543
4545 &FileName,
4547 NULL,
4548 NULL);
4549
4556 RtlFreeHeap(RtlGetProcessHeap(),
4557 0,
4558 FileName.Buffer);
4559 if (!NT_SUCCESS(Status))
4560 {
4561 goto Cleanup;
4562 }
4563
4565 FileHandle,
4566 (ULONG)dwFlags);
4568
4569Cleanup:
4571
4572 if (!NT_SUCCESS(Status))
4573 {
4575 }
4576
4577 return ERROR_SUCCESS;
4578}
4579
4580
4581/************************************************************************
4582 * RegSaveKeyA
4583 *
4584 * @implemented
4585 */
4588 LPCSTR lpFile,
4589 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
4590{
4593
4594 if (lpFile)
4595 {
4598 }
4599 else
4600 RtlInitEmptyUnicodeString(&FileName, NULL, 0);
4601
4603 FileName.Buffer,
4604 lpSecurityAttributes);
4606
4607 return ErrorCode;
4608}
4609
4610
4611/************************************************************************
4612 * RegSaveKeyW
4613 *
4614 * @implemented
4615 */
4618 LPCWSTR lpFile,
4619 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
4620{
4628
4630 hKey);
4631 if (!NT_SUCCESS(Status))
4632 {
4634 }
4635
4636 if (!RtlDosPathNameToNtPathName_U(lpFile,
4637 &FileName,
4638 NULL,
4639 NULL))
4640 {
4642 goto Cleanup;
4643 }
4644
4645 if (lpSecurityAttributes != NULL)
4646 {
4647 SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
4648 }
4649
4651 &FileName,
4653 NULL,
4659 NULL,
4664 NULL,
4665 0);
4666 RtlFreeHeap(RtlGetProcessHeap(),
4667 0,
4668 FileName.Buffer);
4669 if (!NT_SUCCESS(Status))
4670 {
4671 goto Cleanup;
4672 }
4673
4675 FileHandle);
4677
4678Cleanup:
4680
4681 if (!NT_SUCCESS(Status))
4682 {
4684 }
4685
4686 return ERROR_SUCCESS;
4687}
4688
4689
4690/************************************************************************
4691 * RegSaveKeyExA
4692 *
4693 * @implemented
4694 */
4695LONG
4696WINAPI
4698 LPCSTR lpFile,
4699 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
4700 DWORD Flags)
4701{
4704
4705 if (lpFile)
4706 {
4709 }
4710 else
4711 RtlInitEmptyUnicodeString(&FileName, NULL, 0);
4712
4714 FileName.Buffer,
4715 lpSecurityAttributes,
4716 Flags);
4718
4719 return ErrorCode;
4720}
4721
4722
4723/************************************************************************
4724 * RegSaveKeyExW
4725 *
4726 * @unimplemented
4727 */
4728LONG
4729WINAPI
4731 LPCWSTR lpFile,
4732 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
4733 DWORD Flags)
4734{
4735 switch (Flags)
4736 {
4738 case REG_LATEST_FORMAT:
4739 case REG_NO_COMPRESSION:
4740 break;
4741 default:
4743 }
4744
4745 FIXME("RegSaveKeyExW(): Flags ignored!\n");
4746
4747 return RegSaveKeyW(hKey,
4748 lpFile,
4749 lpSecurityAttributes);
4750}
4751
4752
4753/************************************************************************
4754 * RegSetKeySecurity
4755 *
4756 * @implemented
4757 */
4761 PSECURITY_DESCRIPTOR pSecurityDescriptor)
4762{
4765
4767 {
4768 return ERROR_INVALID_HANDLE;
4769 }
4770
4772 hKey);
4773 if (!NT_SUCCESS(Status))
4774 {
4776 }
4777
4780 pSecurityDescriptor);
4781
4783
4784 if (!NT_SUCCESS(Status))
4785 {
4787 }
4788
4789 return ERROR_SUCCESS;
4790}
4791
4792
4793/************************************************************************
4794 * RegSetValueExA
4795 *
4796 * @implemented
4797 */
4800 LPCSTR lpValueName,
4802 DWORD dwType,
4803 CONST BYTE* lpData,
4804 DWORD cbData)
4805{
4807 LPWSTR pValueName;
4811 LPBYTE pData;
4814
4815 /* Convert SubKey name to Unicode */
4816 if (lpValueName != NULL && lpValueName[0] != '\0')
4817 {
4818 if (!RtlCreateUnicodeStringFromAsciiz(&ValueName, lpValueName))
4820 }
4821 else
4822 {
4823 ValueName.Buffer = NULL;
4824 }
4825
4826 pValueName = (LPWSTR)ValueName.Buffer;
4827
4828
4829 if (is_string(dwType) && (cbData != 0))
4830 {
4831 /* Convert ANSI string Data to Unicode */
4832 /* If last character NOT zero then increment length */
4833 LONG bNoNulledStr = ((lpData[cbData-1] != '\0') ? 1 : 0);
4834 AnsiString.Buffer = (PSTR)lpData;
4835 AnsiString.Length = cbData + bNoNulledStr;
4836 AnsiString.MaximumLength = cbData + bNoNulledStr;
4838 &AnsiString,
4839 TRUE);
4840
4841 if (!NT_SUCCESS(Status))
4842 {
4843 if (pValueName != NULL)
4845
4847 }
4848 pData = (LPBYTE)Data.Buffer;
4849 DataSize = cbData * sizeof(WCHAR);
4850 }
4851 else
4852 {
4853 Data.Buffer = NULL;
4854 pData = (LPBYTE)lpData;
4855 DataSize = cbData;
4856 }
4857
4859 pValueName,
4860 Reserved,
4861 dwType,
4862 pData,
4863 DataSize);
4864
4865 if (pValueName != NULL)
4867
4868 if (Data.Buffer != NULL)
4870
4871 return ErrorCode;
4872}
4873
4874
4875/************************************************************************
4876 * RegSetValueExW
4877 *
4878 * @implemented
4879 */
4880LONG
4881WINAPI
4883 _In_ HKEY hKey,
4884 _In_ LPCWSTR lpValueName,
4886 _In_ DWORD dwType,
4887 _In_ CONST BYTE* lpData,
4888 _In_ DWORD cbData)
4889{
4893
4895 hKey);
4896 if (!NT_SUCCESS(Status))
4897 {
4899 }
4900
4901 if (IsHKCRKey(KeyHandle))
4902 {
4903 LONG ErrorCode = SetHKCRValue(KeyHandle, lpValueName, Reserved, dwType, lpData, cbData);
4905 return ErrorCode;
4906 }
4907
4908 if (is_string(dwType) && (cbData != 0))
4909 {
4910 PWSTR pwsData = (PWSTR)lpData;
4911
4912 _SEH2_TRY
4913 {
4914 if((pwsData[cbData / sizeof(WCHAR) - 1] != L'\0') &&
4915 (pwsData[cbData / sizeof(WCHAR)] == L'\0'))
4916 {
4917 /* Increment length if last character is not zero and next is zero */
4918 cbData += sizeof(WCHAR);
4919 }
4920 }
4922 {
4923 /* Do not fail if we fault where we were told not to go */
4924 }
4925 _SEH2_END;
4926 }
4927
4928 RtlInitUnicodeString(&ValueName, lpValueName);
4929
4931 &ValueName,
4932 0,
4933 dwType,
4934 (PVOID)lpData,
4935 (ULONG)cbData);
4936
4938
4939 if (!NT_SUCCESS(Status))
4940 {
4942 }
4943
4944 return ERROR_SUCCESS;
4945}
4946
4947
4948/************************************************************************
4949 * RegSetValueA
4950 *
4951 * @implemented
4952 */
4954RegSetValueA(HKEY hKeyOriginal,
4955 LPCSTR lpSubKey,
4956 DWORD dwType,
4957 LPCSTR lpData,
4958 DWORD cbData)
4959{
4960 HKEY subkey;
4961 HANDLE hKey;
4962 DWORD ret;
4964
4965 TRACE("(%p,%s,%d,%s,%d)\n", hKeyOriginal, debugstr_a(lpSubKey), dwType, debugstr_a(lpData), cbData );
4966
4967 if (dwType != REG_SZ || !lpData) return ERROR_INVALID_PARAMETER;
4968
4969 Status = MapDefaultKey(&hKey, hKeyOriginal);
4970 if (!NT_SUCCESS(Status))
4971 {
4973 }
4974 subkey = hKey;
4975
4976 if (lpSubKey && lpSubKey[0]) /* need to create the subkey */
4977 {
4978 ret = RegCreateKeyA(hKey, lpSubKey, &subkey);
4979 if (ret != ERROR_SUCCESS)
4980 goto Cleanup;
4981 }
4982
4983 ret = RegSetValueExA( subkey, NULL, 0, REG_SZ, (const BYTE*)lpData, strlen(lpData)+1 );
4984 if (subkey != hKey)
4985 RegCloseKey(subkey);
4986
4987Cleanup:
4989
4990 return ret;
4991}
4992
4993
4994/************************************************************************
4995 * RegSetValueW
4996 *
4997 * @implemented
4998 */
5000RegSetValueW(HKEY hKeyOriginal,
5001 LPCWSTR lpSubKey,
5002 DWORD dwType,
5003 LPCWSTR lpData,
5004 DWORD cbData)
5005{
5006 HKEY subkey;
5007 HANDLE hKey;
5008 DWORD ret;
5010
5011 TRACE("(%p,%s,%d,%s,%d)\n", hKeyOriginal, debugstr_w(lpSubKey), dwType, debugstr_w(lpData), cbData );
5012
5013 if (dwType != REG_SZ || !lpData)
5015
5017 hKeyOriginal);
5018 if (!NT_SUCCESS(Status))
5019 {
5021 }
5022 subkey = hKey;
5023
5024 if (lpSubKey && lpSubKey[0]) /* need to create the subkey */
5025 {
5026 ret = RegCreateKeyW(hKey, lpSubKey, &subkey);
5027 if (ret != ERROR_SUCCESS)
5028 goto Cleanup;
5029 }
5030
5031 ret = RegSetValueExW( subkey, NULL, 0, REG_SZ, (const BYTE*)lpData,
5032 (wcslen( lpData ) + 1) * sizeof(WCHAR) );
5033 if (subkey != hKey)
5034 RegCloseKey(subkey);
5035
5036Cleanup:
5038
5039 return ret;
5040}
5041
5042
5043/************************************************************************
5044 * RegUnLoadKeyA
5045 *
5046 * @implemented
5047 */
5050 LPCSTR lpSubKey)
5051{
5054
5055 if (lpSubKey)
5056 {
5059 }
5060 else
5061 RtlInitEmptyUnicodeString(&KeyName, NULL, 0);
5062
5064 KeyName.Buffer);
5065
5067
5068 return ErrorCode;
5069}
5070
5071
5072/************************************************************************
5073 * RegUnLoadKeyW
5074 *
5075 * @implemented
5076 */
5079 LPCWSTR lpSubKey)
5080{
5085
5087 {
5088 return ERROR_INVALID_HANDLE;
5089 }
5090
5092 if (!NT_SUCCESS(Status))
5093 {
5095 }
5096
5097 RtlInitUnicodeString(&KeyName, lpSubKey);
5098
5100 &KeyName,
5102 KeyHandle,
5103 NULL);
5104
5106
5108
5109 if (!NT_SUCCESS(Status))
5110 {
5112 }
5113
5114 return ERROR_SUCCESS;
5115}
5116
5117#endif // _ADVAPI32_VISTA_
5118
5119/******************************************************************************
5120 * load_string [Internal]
5121 *
5122 * This is basically a copy of user32/resource.c's LoadStringW. Necessary to
5123 * avoid importing user32, which is higher level than advapi32. Helper for
5124 * RegLoadMUIString.
5125 */
5126static int load_string(HINSTANCE hModule, UINT resId, LPWSTR pwszBuffer, INT cMaxChars)
5127{
5129 HRSRC hResource;
5130 WCHAR* pString;
5131 int idxString;
5132
5133 /* Negative values have to be inverted. */
5134 if (HIWORD(resId) == 0xffff)
5135 resId = (UINT)(-((INT)resId));
5136
5137 /* Load the resource into memory and get a pointer to it. */
5138 hResource = FindResourceW(hModule, MAKEINTRESOURCEW(LOWORD(resId >> 4) + 1), (LPWSTR)RT_STRING);
5139 if (!hResource) return 0;
5140 hMemory = LoadResource(hModule, hResource);
5141 if (!hMemory) return 0;
5143
5144 /* Strings are length-prefixed. Lowest nibble of resId is an index. */
5145 idxString = resId & 0xf;
5146 while (idxString--) pString += *pString + 1;
5147
5148 /* If no buffer is given, return length of the string. */
5149 if (!pwszBuffer) return *pString;
5150
5151 /* Else copy over the string, respecting the buffer size. */
5152 cMaxChars = (*pString < cMaxChars) ? *pString : (cMaxChars - 1);
5153 if (cMaxChars >= 0)
5154 {
5155 memcpy(pwszBuffer, pString + 1, cMaxChars * sizeof(WCHAR));
5156 pwszBuffer[cMaxChars] = L'\0';
5157 }
5158
5159 return cMaxChars;
5160}
5161
5162/************************************************************************
5163 * RegLoadMUIStringW
5164 *
5165 * @implemented
5166 */
5169 IN HKEY hKey,
5170 IN LPCWSTR pszValue OPTIONAL,
5171 OUT LPWSTR pszOutBuf,
5172 IN DWORD cbOutBuf,
5174 IN DWORD Flags,
5175 IN LPCWSTR pszDirectory OPTIONAL)
5176{
5177 DWORD dwValueType, cbData;
5178 LPWSTR pwszTempBuffer = NULL, pwszExpandedBuffer = NULL;
5179 LONG result;
5180
5181 /* Parameter sanity checks. */
5182 if (!hKey || !pszOutBuf)
5184
5185 if (pszDirectory && *pszDirectory)
5186 {
5187 FIXME("BaseDir parameter not yet supported!\n");
5189 }
5190
5191 /* Check for value existence and correctness of it's type, allocate a buffer and load it. */
5192 result = RegQueryValueExW(hKey, pszValue, NULL, &dwValueType, NULL, &cbData);
5193 if (result != ERROR_SUCCESS) goto cleanup;
5194 if (!(dwValueType == REG_SZ || dwValueType == REG_EXPAND_SZ) || !cbData)
5195 {
5197 goto cleanup;
5198 }
5199 pwszTempBuffer = HeapAlloc(GetProcessHeap(), 0, cbData);
5200 if (!pwszTempBuffer)
5201 {
5203 goto cleanup;
5204 }
5205 result = RegQueryValueExW(hKey, pszValue, NULL, &dwValueType, (LPBYTE)pwszTempBuffer, &cbData);
5206 if (result != ERROR_SUCCESS) goto cleanup;
5207
5208 /* Expand environment variables, if appropriate, or copy the original string over. */
5209 if (dwValueType == REG_EXPAND_SZ)
5210 {
5211 cbData = ExpandEnvironmentStringsW(pwszTempBuffer, NULL, 0) * sizeof(WCHAR);
5212 if (!cbData) goto cleanup;
5213 pwszExpandedBuffer = HeapAlloc(GetProcessHeap(), 0, cbData);
5214 if (!pwszExpandedBuffer)
5215 {
5217 goto cleanup;
5218 }
5219 ExpandEnvironmentStringsW(pwszTempBuffer, pwszExpandedBuffer, cbData);
5220 }
5221 else
5222 {
5223 pwszExpandedBuffer = HeapAlloc(GetProcessHeap(), 0, cbData);
5224 memcpy(pwszExpandedBuffer, pwszTempBuffer, cbData);
5225 }
5226
5227 /* If the value references a resource based string, parse the value and load the string.
5228 * Else just copy over the original value. */
5230 if (*pwszExpandedBuffer != L'@') /* '@' is the prefix for resource based string entries. */
5231 {
5232 lstrcpynW(pszOutBuf, pwszExpandedBuffer, cbOutBuf / sizeof(WCHAR));
5233 }
5234 else
5235 {
5236 WCHAR* pComma = wcsrchr(pwszExpandedBuffer, L',');
5237 UINT uiStringId;
5239
5240 /* Format of the expanded value is 'path_to_dll,-resId' */
5241 if (!pComma || pComma[1] != L'-')
5242 {
5244 goto cleanup;
5245 }
5246
5247 uiStringId = _wtoi(pComma + 2);
5248 *pComma = L'\0';
5249
5250 hModule = LoadLibraryExW(pwszExpandedBuffer + 1, NULL, LOAD_LIBRARY_AS_DATAFILE);
5251 if (!hModule || !load_string(hModule, uiStringId, pszOutBuf, cbOutBuf / sizeof(WCHAR)))
5254 }
5255
5256cleanup:
5257 HeapFree(GetProcessHeap(), 0, pwszTempBuffer);
5258 HeapFree(GetProcessHeap(), 0, pwszExpandedBuffer);
5259 return result;
5260}
5261
5262/************************************************************************
5263 * RegLoadMUIStringA
5264 *
5265 * @implemented
5266 */
5269 IN HKEY hKey,
5270 IN LPCSTR pszValue OPTIONAL,
5271 OUT LPSTR pszOutBuf,
5272 IN DWORD cbOutBuf,
5274 IN DWORD Flags,
5275 IN LPCSTR pszDirectory OPTIONAL)
5276{
5277 UNICODE_STRING valueW, baseDirW;
5278 WCHAR* pwszBuffer;
5279 DWORD cbData = cbOutBuf * sizeof(WCHAR);
5280 LONG result;
5281
5282 valueW.Buffer = baseDirW.Buffer = pwszBuffer = NULL;
5283 if (!RtlCreateUnicodeStringFromAsciiz(&valueW, pszValue) ||
5284 !RtlCreateUnicodeStringFromAsciiz(&baseDirW, pszDirectory) ||
5285 !(pwszBuffer = HeapAlloc(GetProcessHeap(), 0, cbData)))
5286 {
5288 goto cleanup;
5289 }
5290
5291 result = RegLoadMUIStringW(hKey, valueW.Buffer, pwszBuffer, cbData, NULL, Flags,
5292 baseDirW.Buffer);
5293
5294 if (result == ERROR_SUCCESS)
5295 {
5296 cbData = WideCharToMultiByte(CP_ACP, 0, pwszBuffer, -1, pszOutBuf, cbOutBuf, NULL, NULL);
5297 if (pcbData)
5298 *pcbData = cbData;
5299 }
5300
5301cleanup:
5302 HeapFree(GetProcessHeap(), 0, pwszBuffer);
5303 RtlFreeUnicodeString(&baseDirW);
5305
5306 return result;
5307}
5308
5309/* 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:4799
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
LONG WINAPI RegUnLoadKeyW(HKEY hKey, LPCWSTR lpSubKey)
Definition: reg.c:5078
LONG WINAPI RegLoadKeyA(HKEY hKey, LPCSTR lpSubKey, LPCSTR lpFile)
Definition: reg.c:3032
#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:1931
LONG WINAPI RegOpenKeyExA(_In_ HKEY hKey, _In_ LPCSTR lpSubKey, _In_ DWORD ulOptions, _In_ REGSAM samDesired, _Out_ PHKEY phkResult)
Definition: reg.c:3298
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:2504
static NTSTATUS OpenLocalMachineKey(PHANDLE KeyHandle)
Definition: reg.c:264
LONG WINAPI RegFlushKey(HKEY hKey)
Definition: reg.c:2951
static NTSTATUS OpenClassesRootKey(PHANDLE KeyHandle)
LONG WINAPI RegDeleteTreeA(IN HKEY hKey, IN LPCSTR lpSubKey OPTIONAL)
Definition: reg.c:1805
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:3583
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:3234
LONG WINAPI RegQueryReflectionKey(IN HKEY hBase, OUT BOOL *bIsReflectionDisabled)
Definition: reg.c:3975
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:2668
LONG WINAPI RegOpenCurrentUser(IN REGSAM samDesired, OUT PHKEY phkResult)
Definition: reg.c:3209
static int load_string(HINSTANCE hModule, UINT resId, LPWSTR pwszBuffer, INT cMaxChars)
Definition: reg.c:5126
LONG WINAPI RegGetKeySecurity(HKEY hKey, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, LPDWORD lpcbSecurityDescriptor)
Definition: reg.c:2987
LONG WINAPI RegDeleteValueA(HKEY hKey, LPCSTR lpValueName)
Definition: reg.c:2287
LONG WINAPI RegSetValueA(HKEY hKeyOriginal, LPCSTR lpSubKey, DWORD dwType, LPCSTR lpData, DWORD cbData)
Definition: reg.c:4954
LONG WINAPI RegReplaceKeyW(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpNewFile, LPCWSTR lpOldFile)
Definition: reg.c:4347
static HANDLE DefaultHandleTable[MAX_DEFAULT_HANDLES]
Definition: reg.c:34
LONG WINAPI RegLoadKeyW(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpFile)
Definition: reg.c:3079
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:3268
LONG WINAPI RegEnumKeyA(HKEY hKey, DWORD dwIndex, LPSTR lpName, DWORD cbName)
Definition: reg.c:2368
static BOOLEAN DefaultHandlesDisabled
Definition: reg.c:36
LSTATUS WINAPI RegDeleteTreeW(HKEY hKey, LPCWSTR lpszSubKey)
Definition: reg.c:1711
LONG WINAPI RegSetKeySecurity(HKEY hKey, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor)
Definition: reg.c:4759
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:4882
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:5168
LONG WINAPI RegQueryMultipleValuesW(HKEY hKey, PVALENTW val_list, DWORD num_vals, LPWSTR lpValueBuf, LPDWORD ldwTotsize)
Definition: reg.c:3911
LSTATUS WINAPI RegQueryValueA(HKEY hkey, LPCSTR name, LPSTR data, LPLONG count)
Definition: reg.c:4212
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:2037
LONG WINAPI RegDeleteKeyW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey)
Definition: reg.c:1239
LONG WINAPI RegDeleteValueW(HKEY hKey, LPCWSTR lpValueName)
Definition: reg.c:2330
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:2830
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:4512
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:4697
#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:3847
LONG WINAPI RegEnableReflectionKey(IN HKEY hBase)
Definition: reg.c:1846
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:3441
#define IsPredefKey(HKey)
Definition: reg.c:48
static VOID RegpApplyRestrictions(DWORD dwFlags, DWORD dwType, DWORD cbData, PLONG ret)
Definition: reg.c:1859
LONG WINAPI RegRestoreKeyA(HKEY hKey, LPCSTR lpFile, DWORD dwFlags)
Definition: reg.c:4481
LONG WINAPI RegReplaceKeyA(HKEY hKey, LPCSTR lpSubKey, LPCSTR lpNewFile, LPCSTR lpOldFile)
Definition: reg.c:4286
LONG WINAPI RegQueryInfoKeyW(HKEY hKey, LPWSTR lpClass, LPDWORD lpcClass, LPDWORD lpReserved, LPDWORD lpcSubKeys, LPDWORD lpcMaxSubKeyLen, LPDWORD lpcMaxClassLen, LPDWORD lpcValues, LPDWORD lpcMaxValueNameLen, LPDWORD lpcMaxValueLen, LPDWORD lpcbSecurityDescriptor, PFILETIME lpftLastWriteTime)
Definition: reg.c:3662
LONG WINAPI 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:2210
LSTATUS WINAPI RegQueryValueW(HKEY hkey, LPCWSTR name, LPWSTR data, LPLONG count)
Definition: reg.c:4241
#define GetPredefKeyIndex(HKey)
Definition: reg.c:50
LONG WINAPI RegSaveKeyW(HKEY hKey, LPCWSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: reg.c:4617
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:4009
LONG WINAPI RegSaveKeyA(HKEY hKey, LPCSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: reg.c:4587
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:5268
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:4730
LONG WINAPI RegDisableReflectionKey(IN HKEY hBase)
Definition: reg.c:1833
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:2419
BOOL RegCleanup(VOID)
Definition: reg.c:93
LONG WINAPI RegNotifyChangeKeyValue(HKEY hKey, BOOL bWatchSubtree, DWORD dwNotifyFilter, HANDLE hEvent, BOOL fAsynchronous)
Definition: reg.c:3152
LONG WINAPI RegSetValueW(HKEY hKeyOriginal, LPCWSTR lpSubKey, DWORD dwType, LPCWSTR lpData, DWORD cbData)
Definition: reg.c:5000
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
LONG WINAPI RegDeleteKeyValueA(IN HKEY hKey, IN LPCSTR lpSubKey OPTIONAL, IN LPCSTR lpValueName OPTIONAL)
Definition: reg.c:1392
LONG WINAPI RegEnumKeyW(HKEY hKey, DWORD dwIndex, LPWSTR lpName, DWORD cbName)
Definition: reg.c:2393
LONG WINAPI RegUnLoadKeyA(HKEY hKey, LPCSTR lpSubKey)
Definition: reg.c:5049
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:2139
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:1087
LONG WINAPI CreateHKCRKey(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ DWORD Reserved, _In_opt_ LPWSTR lpClass, _In_ DWORD dwOptions, _In_ REGSAM samDesired, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _Out_ PHKEY phkResult, _Out_opt_ LPDWORD lpdwDisposition)
Definition: hkcr.c:266
LONG WINAPI QueryHKCRValue(_In_ HKEY hKey, _In_ LPCWSTR Name, _In_ LPDWORD Reserved, _In_ LPDWORD Type, _In_ LPBYTE Data, _In_ LPDWORD Count)
Definition: hkcr.c:548
LONG WINAPI EnumHKCRValue(_In_ HKEY hKey, _In_ DWORD dwIndex, _Out_ LPWSTR lpName, _Inout_ PDWORD lpcbName, _Reserved_ PDWORD lpReserved, _Out_opt_ PDWORD lpdwType, _Out_opt_ LPBYTE lpData, _Inout_opt_ PDWORD lpcbData)
Definition: hkcr.c:873
LONG WINAPI DeleteHKCRValue(_In_ HKEY hKey, _In_ PUNICODE_STRING ValueName)
Definition: hkcr.c:504
LONG WINAPI SetHKCRValue(_In_ HKEY hKey, _In_ LPCWSTR Name, _In_ DWORD Reserved, _In_ DWORD Type, _In_ CONST BYTE *Data, _In_ DWORD DataSize)
Definition: hkcr.c:613
LONG WINAPI OpenHKCRKey(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ DWORD ulOptions, _In_ REGSAM samDesired, _In_ PHKEY phkResult)
Definition: hkcr.c:370
LONG WINAPI DeleteHKCRKey(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ REGSAM RegSam, _In_ DWORD Reserved)
Definition: hkcr.c:441
LONG WINAPI EnumHKCRKey(_In_ HKEY hKey, _In_ DWORD dwIndex, _Out_ LPWSTR lpName, _Inout_ LPDWORD lpcbName, _Reserved_ LPDWORD lpReserved, _Out_opt_ LPWSTR lpClass, _Inout_opt_ LPDWORD lpcbClass, _Out_opt_ PFILETIME lpftLastWriteTime)
Definition: hkcr.c:682
static int reg
Definition: i386-dis.c:1290
#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::@2295 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