ReactOS  0.4.11-dev-791-gf6f1255
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 
38 static BOOLEAN DllInitialized = FALSE; /* HACK */
39 
40 /* PROTOTYPES ***************************************************************/
41 
42 static NTSTATUS MapDefaultKey (PHANDLE ParentKey, HKEY Key);
43 static VOID CloseDefaultKeys(VOID);
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  */
69 BOOL
71 {
72  TRACE("RegInitialize()\n");
73 
74  /* Lazy init hack */
75  if (!DllInitialized)
76  {
77  ProcessHeap = RtlGetProcessHeap();
79  MAX_DEFAULT_HANDLES * sizeof(HANDLE));
80  RtlInitializeCriticalSection(&HandleTableCS);
81 
83  }
84 
85  return TRUE;
86 }
87 
88 
89 /************************************************************************
90  * RegInit
91  */
92 BOOL
94 {
95  TRACE("RegCleanup()\n");
96 
98  RtlDeleteCriticalSection(&HandleTableCS);
99 
100  return TRUE;
101 }
102 
103 
104 static NTSTATUS
106  OUT HANDLE Handle)
107 {
109 
110  switch (Index)
111  {
112  case 0: /* HKEY_CLASSES_ROOT */
113  Status = OpenClassesRootKey (Handle);
114  break;
115 
116  case 1: /* HKEY_CURRENT_USER */
118  Handle);
119  break;
120 
121  case 2: /* HKEY_LOCAL_MACHINE */
122  Status = OpenLocalMachineKey (Handle);
123  break;
124 
125  case 3: /* HKEY_USERS */
126  Status = OpenUsersKey (Handle);
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 */
135  Status = OpenCurrentConfigKey (Handle);
136  break;
137 
138  case 6: /* HKEY_DYN_DATA */
139  Status = STATUS_NOT_IMPLEMENTED;
140  break;
141 
142  default:
143  WARN("MapDefaultHandle() no handle creator\n");
144  Status = STATUS_INVALID_PARAMETER;
145  break;
146  }
147 
148  return Status;
149 }
150 
151 
152 static NTSTATUS
154  IN HKEY Key)
155 {
156  PHANDLE Handle;
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 */
170  Index = GetPredefKeyIndex(Key);
171  if (Index >= MAX_DEFAULT_HANDLES)
172  {
174  }
175  RegInitialize(); /* HACK until delay-loading is implemented */
176  RtlEnterCriticalSection (&HandleTableCS);
177 
178  if (Key == HKEY_CURRENT_USER)
179  DefDisabled = DefaultHandleHKUDisabled;
180  else
181  DefDisabled = DefaultHandlesDisabled;
182 
183  if (!DefDisabled)
184  {
185  Handle = &DefaultHandleTable[Index];
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 */
197  Status = OpenPredefinedKey(Index,
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 
209  RtlLeaveCriticalSection (&HandleTableCS);
210 
211  return Status;
212 }
213 
214 
215 static VOID
217 {
218  ULONG i;
219  RegInitialize(); /* HACK until delay-loading is implemented */
220  RtlEnterCriticalSection(&HandleTableCS);
221 
222  for (i = 0; i < MAX_DEFAULT_HANDLES; i++)
223  {
224  if (DefaultHandleTable[i] != NULL)
225  {
228  }
229  }
230 
231  RtlLeaveCriticalSection(&HandleTableCS);
232 }
233 
234 
235 static NTSTATUS
237 {
239  UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Software\\CLASSES");
241 
242  TRACE("OpenClassesRootKey()\n");
243 
244  InitializeObjectAttributes(&Attributes,
245  &KeyName,
247  NULL,
248  NULL);
249  Status = NtOpenKey(KeyHandle,
251  &Attributes);
252 
253  if (!NT_SUCCESS(Status))
254  return Status;
255 
256  /* Mark it as HKCR */
257  MakeHKCRKey((HKEY*)KeyHandle);
258 
259  return Status;
260 }
261 
262 
263 static NTSTATUS
265 {
267  UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine");
269 
270  TRACE("OpenLocalMachineKey()\n");
271 
272  InitializeObjectAttributes(&Attributes,
273  &KeyName,
275  NULL,
276  NULL);
277  Status = NtOpenKey(KeyHandle,
279  &Attributes);
280 
281  TRACE("NtOpenKey(%wZ) => %08x\n", &KeyName, Status);
282 
283  return Status;
284 }
285 
286 
287 static NTSTATUS
289 {
291  UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\User");
292 
293  TRACE("OpenUsersKey()\n");
294 
295  InitializeObjectAttributes(&Attributes,
296  &KeyName,
298  NULL,
299  NULL);
300  return NtOpenKey(KeyHandle,
302  &Attributes);
303 }
304 
305 
306 static NTSTATUS
308 {
311  RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current");
312 
313  TRACE("OpenCurrentConfigKey()\n");
314 
315  InitializeObjectAttributes(&Attributes,
316  &KeyName,
318  NULL,
319  NULL);
320  return NtOpenKey(KeyHandle,
322  &Attributes);
323 }
324 
325 
326 /************************************************************************
327  * RegDisablePredefinedCache
328  *
329  * @implemented
330  */
331 LONG WINAPI
333 {
334  RegInitialize(); /* HACK until delay-loading is implemented */
335  RtlEnterCriticalSection(&HandleTableCS);
337  RtlLeaveCriticalSection(&HandleTableCS);
338  return ERROR_SUCCESS;
339 }
340 
341 
342 /************************************************************************
343  * RegDisablePredefinedCacheEx
344  *
345  * @implemented
346  */
347 LONG WINAPI
349 {
350  RegInitialize(); /* HACK until delay-loading is implemented */
351  RtlEnterCriticalSection(&HandleTableCS);
354  RtlLeaveCriticalSection(&HandleTableCS);
355  return ERROR_SUCCESS;
356 }
357 
358 
359 /************************************************************************
360  * RegOverridePredefKey
361  *
362  * @implemented
363  */
364 LONG WINAPI
366  IN HKEY hNewHKey OPTIONAL)
367 {
369 
370  if ((hKey == HKEY_CLASSES_ROOT ||
371  hKey == HKEY_CURRENT_CONFIG ||
372  hKey == HKEY_CURRENT_USER ||
373  hKey == HKEY_LOCAL_MACHINE ||
374  hKey == HKEY_PERFORMANCE_DATA ||
375  hKey == HKEY_USERS) &&
376  !IsPredefKey(hNewHKey))
377  {
378  PHANDLE Handle;
379  ULONG Index;
380 
381  Index = GetPredefKeyIndex(hKey);
382  Handle = &DefaultHandleTable[Index];
383 
384  if (hNewHKey == NULL)
385  {
386  /* restore the default mapping */
388  &hNewHKey);
389  if (!NT_SUCCESS(Status))
390  {
391  return RtlNtStatusToDosError(Status);
392  }
393 
394  ASSERT(hNewHKey != NULL);
395  }
396  RegInitialize(); /* HACK until delay-loading is implemented */
397  RtlEnterCriticalSection(&HandleTableCS);
398 
399  /* close the currently mapped handle if existing */
400  if (*Handle != NULL)
401  {
402  NtClose(*Handle);
403  }
404 
405  /* update the mapping */
406  *Handle = hNewHKey;
407 
408  RtlLeaveCriticalSection(&HandleTableCS);
409  }
410  else
411  ErrorCode = ERROR_INVALID_HANDLE;
412 
413  return ErrorCode;
414 }
415 
416 
417 /************************************************************************
418  * RegCloseKey
419  *
420  * @implemented
421  */
422 LONG WINAPI
424 {
426 
427  /* don't close null handle or a pseudo handle */
428  if (!hKey)
429  {
430  return ERROR_INVALID_HANDLE;
431  }
432 
433  if (((ULONG_PTR)hKey & 0xF0000000) == 0x80000000)
434  {
435  return ERROR_SUCCESS;
436  }
437 
438  Status = NtClose(hKey);
439  if (!NT_SUCCESS(Status))
440  {
441  return RtlNtStatusToDosError(Status);
442  }
443 
444  return ERROR_SUCCESS;
445 }
446 
447 
448 static NTSTATUS
450  IN HKEY hKeyDest)
451 {
452  typedef struct
453  {
454  LIST_ENTRY ListEntry;
455  HANDLE hKeySrc;
456  HANDLE hKeyDest;
457  } REGP_COPY_KEYS, *PREGP_COPY_KEYS;
458 
459  LIST_ENTRY copyQueueHead;
460  PREGP_COPY_KEYS copyKeys, newCopyKeys;
461  union
462  {
463  KEY_VALUE_FULL_INFORMATION *KeyValue;
464  KEY_NODE_INFORMATION *KeyNode;
465  PVOID Buffer;
466  } Info;
467  ULONG Index, BufferSizeRequired, BufferSize = 0x200;
469  NTSTATUS Status2 = STATUS_SUCCESS;
470 
471  InitializeListHead(&copyQueueHead);
472 
474  0,
475  BufferSize);
476  if (Info.Buffer == NULL)
477  {
479  }
480 
481  copyKeys = RtlAllocateHeap(ProcessHeap,
482  0,
483  sizeof(REGP_COPY_KEYS));
484  if (copyKeys != NULL)
485  {
486  copyKeys->hKeySrc = hKeySrc;
487  copyKeys->hKeyDest = hKeyDest;
488  InsertHeadList(&copyQueueHead,
489  &copyKeys->ListEntry);
490 
491  /* FIXME - copy security from hKeySrc to hKeyDest or just for the subkeys? */
492 
493  do
494  {
495  copyKeys = CONTAINING_RECORD(copyQueueHead.Flink,
496  REGP_COPY_KEYS,
497  ListEntry);
498 
499  /* enumerate all values and copy them */
500  Index = 0;
501  for (;;)
502  {
503  Status2 = NtEnumerateValueKey(copyKeys->hKeySrc,
504  Index,
506  Info.KeyValue,
507  BufferSize,
508  &BufferSizeRequired);
509  if (NT_SUCCESS(Status2))
510  {
512  PVOID Data;
513 
514  /* don't use RtlInitUnicodeString as the string is not NULL-terminated! */
515  ValueName.Length = Info.KeyValue->NameLength;
516  ValueName.MaximumLength = ValueName.Length;
517  ValueName.Buffer = Info.KeyValue->Name;
518 
519  Data = (PVOID)((ULONG_PTR)Info.KeyValue + Info.KeyValue->DataOffset);
520 
521  Status2 = NtSetValueKey(copyKeys->hKeyDest,
522  &ValueName,
523  Info.KeyValue->TitleIndex,
524  Info.KeyValue->Type,
525  Data,
526  Info.KeyValue->DataLength);
527 
528  /* don't break, let's try to copy as many values as possible */
529  if (!NT_SUCCESS(Status2) && NT_SUCCESS(Status))
530  {
531  Status = Status2;
532  }
533 
534  Index++;
535  }
536  else if (Status2 == STATUS_BUFFER_OVERFLOW)
537  {
538  PVOID Buffer;
539 
540  ASSERT(BufferSize < BufferSizeRequired);
541 
543  0,
544  Info.Buffer,
545  BufferSizeRequired);
546  if (Buffer != NULL)
547  {
548  Info.Buffer = Buffer;
549  /* try again */
550  }
551  else
552  {
553  /* don't break, let's try to copy as many values as possible */
555  Index++;
556 
557  if (NT_SUCCESS(Status))
558  {
559  Status = Status2;
560  }
561  }
562  }
563  else
564  {
565  /* break to avoid an infinite loop in case of denied access or
566  other errors! */
567  if (Status2 != STATUS_NO_MORE_ENTRIES && NT_SUCCESS(Status))
568  {
569  Status = Status2;
570  }
571 
572  break;
573  }
574  }
575 
576  /* enumerate all subkeys and open and enqueue them */
577  Index = 0;
578  for (;;)
579  {
580  Status2 = NtEnumerateKey(copyKeys->hKeySrc,
581  Index,
583  Info.KeyNode,
584  BufferSize,
585  &BufferSizeRequired);
586  if (NT_SUCCESS(Status2))
587  {
588  HANDLE KeyHandle, NewKeyHandle;
590  UNICODE_STRING SubKeyName, ClassName;
591 
592  /* don't use RtlInitUnicodeString as the string is not NULL-terminated! */
593  SubKeyName.Length = Info.KeyNode->NameLength;
594  SubKeyName.MaximumLength = SubKeyName.Length;
595  SubKeyName.Buffer = Info.KeyNode->Name;
596  ClassName.Length = Info.KeyNode->ClassLength;
597  ClassName.MaximumLength = ClassName.Length;
598  ClassName.Buffer = (PWSTR)((ULONG_PTR)Info.KeyNode + Info.KeyNode->ClassOffset);
599 
600  /* open the subkey with sufficient rights */
601 
602  InitializeObjectAttributes(&ObjectAttributes,
603  &SubKeyName,
605  copyKeys->hKeySrc,
606  NULL);
607 
608  Status2 = NtOpenKey(&KeyHandle,
610  &ObjectAttributes);
611  if (NT_SUCCESS(Status2))
612  {
613  /* FIXME - attempt to query the security information */
614 
615  InitializeObjectAttributes(&ObjectAttributes,
616  &SubKeyName,
618  copyKeys->hKeyDest,
619  NULL);
620 
621  Status2 = NtCreateKey(&NewKeyHandle,
623  &ObjectAttributes,
624  Info.KeyNode->TitleIndex,
625  &ClassName,
626  0,
627  NULL);
628  if (NT_SUCCESS(Status2))
629  {
630  newCopyKeys = RtlAllocateHeap(ProcessHeap,
631  0,
632  sizeof(REGP_COPY_KEYS));
633  if (newCopyKeys != NULL)
634  {
635  /* save the handles and enqueue the subkey */
636  newCopyKeys->hKeySrc = KeyHandle;
637  newCopyKeys->hKeyDest = NewKeyHandle;
638  InsertTailList(&copyQueueHead,
639  &newCopyKeys->ListEntry);
640  }
641  else
642  {
643  NtClose(KeyHandle);
644  NtClose(NewKeyHandle);
645 
647  }
648  }
649  else
650  {
651  NtClose(KeyHandle);
652  }
653  }
654 
655  if (!NT_SUCCESS(Status2) && NT_SUCCESS(Status))
656  {
657  Status = Status2;
658  }
659 
660  Index++;
661  }
662  else if (Status2 == STATUS_BUFFER_OVERFLOW)
663  {
664  PVOID Buffer;
665 
666  ASSERT(BufferSize < BufferSizeRequired);
667 
669  0,
670  Info.Buffer,
671  BufferSizeRequired);
672  if (Buffer != NULL)
673  {
674  Info.Buffer = Buffer;
675  /* try again */
676  }
677  else
678  {
679  /* don't break, let's try to copy as many keys as possible */
681  Index++;
682 
683  if (NT_SUCCESS(Status))
684  {
685  Status = Status2;
686  }
687  }
688  }
689  else
690  {
691  /* break to avoid an infinite loop in case of denied access or
692  other errors! */
693  if (Status2 != STATUS_NO_MORE_ENTRIES && NT_SUCCESS(Status))
694  {
695  Status = Status2;
696  }
697 
698  break;
699  }
700  }
701 
702  /* close the handles and remove the entry from the list */
703  if (copyKeys->hKeySrc != hKeySrc)
704  {
705  NtClose(copyKeys->hKeySrc);
706  }
707  if (copyKeys->hKeyDest != hKeyDest)
708  {
709  NtClose(copyKeys->hKeyDest);
710  }
711 
712  RemoveEntryList(&copyKeys->ListEntry);
713 
715  0,
716  copyKeys);
717  } while (!IsListEmpty(&copyQueueHead));
718  }
719  else
721 
723  0,
724  Info.Buffer);
725 
726  return Status;
727 }
728 
729 
730 /************************************************************************
731  * RegCopyTreeW
732  *
733  * @implemented
734  */
735 LONG WINAPI
737  IN LPCWSTR lpSubKey OPTIONAL,
738  IN HKEY hKeyDest)
739 {
740  HANDLE DestKeyHandle, KeyHandle, CurKey, SubKeyHandle = NULL;
742 
743  Status = MapDefaultKey(&KeyHandle,
744  hKeySrc);
745  if (!NT_SUCCESS(Status))
746  {
747  return RtlNtStatusToDosError(Status);
748  }
749 
750  Status = MapDefaultKey(&DestKeyHandle,
751  hKeyDest);
752  if (!NT_SUCCESS(Status))
753  {
754  goto Cleanup2;
755  }
756 
757  if (lpSubKey != NULL)
758  {
761 
762  RtlInitUnicodeString(&SubKeyName,
763  (LPWSTR)lpSubKey);
764 
765  InitializeObjectAttributes(&ObjectAttributes,
766  &SubKeyName,
768  KeyHandle,
769  NULL);
770 
771  Status = NtOpenKey(&SubKeyHandle,
773  &ObjectAttributes);
774  if (!NT_SUCCESS(Status))
775  {
776  goto Cleanup;
777  }
778 
779  CurKey = SubKeyHandle;
780  }
781  else
782  CurKey = KeyHandle;
783 
784  Status = RegpCopyTree(CurKey,
785  hKeyDest);
786 
787  if (SubKeyHandle != NULL)
788  {
789  NtClose(SubKeyHandle);
790  }
791 
792 Cleanup:
793  ClosePredefKey(DestKeyHandle);
794 Cleanup2:
795  ClosePredefKey(KeyHandle);
796 
797  if (!NT_SUCCESS(Status))
798  {
799  return RtlNtStatusToDosError(Status);
800  }
801 
802  return ERROR_SUCCESS;
803 }
804 
805 
806 /************************************************************************
807  * RegCopyTreeA
808  *
809  * @implemented
810  */
811 LONG WINAPI
813  IN LPCSTR lpSubKey OPTIONAL,
814  IN HKEY hKeyDest)
815 {
816  UNICODE_STRING SubKeyName = { 0, 0, NULL };
817  LONG Ret;
818 
819  if (lpSubKey != NULL &&
821  (LPSTR)lpSubKey))
822  {
824  }
825 
826  Ret = RegCopyTreeW(hKeySrc,
827  SubKeyName.Buffer,
828  hKeyDest);
829 
830  RtlFreeUnicodeString(&SubKeyName);
831 
832  return Ret;
833 }
834 
835 
836 /************************************************************************
837  * RegConnectRegistryA
838  *
839  * @implemented
840  */
841 LONG WINAPI
843  IN HKEY hKey,
844  OUT PHKEY phkResult)
845 {
846  UNICODE_STRING MachineName = { 0, 0, NULL };
847  LONG Ret;
848 
849  if (lpMachineName != NULL &&
850  !RtlCreateUnicodeStringFromAsciiz(&MachineName,
851  (LPSTR)lpMachineName))
852  {
854  }
855 
856  Ret = RegConnectRegistryW(MachineName.Buffer,
857  hKey,
858  phkResult);
859 
860  RtlFreeUnicodeString(&MachineName);
861 
862  return Ret;
863 }
864 
865 
866 /************************************************************************
867  * RegConnectRegistryW
868  *
869  * @unimplemented
870  */
871 LONG WINAPI
873  HKEY hKey,
874  PHKEY phkResult)
875 {
876  LONG ret;
877 
878  TRACE("(%s,%p,%p): stub\n",debugstr_w(lpMachineName),hKey,phkResult);
879 
880  if (!lpMachineName || !*lpMachineName)
881  {
882  /* Use the local machine name */
883  ret = RegOpenKeyW( hKey, NULL, phkResult );
884  }
885  else
886  {
887  WCHAR compName[MAX_COMPUTERNAME_LENGTH + 1];
888  DWORD len = sizeof(compName) / sizeof(WCHAR);
889 
890  /* MSDN says lpMachineName must start with \\ : not so */
891  if( lpMachineName[0] == '\\' && lpMachineName[1] == '\\')
892  lpMachineName += 2;
893 
894  if (GetComputerNameW(compName, &len))
895  {
896  if (!_wcsicmp(lpMachineName, compName))
897  ret = RegOpenKeyW(hKey, NULL, phkResult);
898  else
899  {
900  FIXME("Connect to %s is not supported.\n",debugstr_w(lpMachineName));
901  ret = ERROR_BAD_NETPATH;
902  }
903  }
904  else
905  ret = GetLastError();
906  }
907 
908  return ret;
909 }
910 
911 
912 /************************************************************************
913  * CreateNestedKey
914  *
915  * Create key and all necessary intermediate keys
916  */
917 static NTSTATUS
920  PUNICODE_STRING ClassString,
922  REGSAM samDesired,
923  DWORD *lpdwDisposition)
924 {
925  OBJECT_ATTRIBUTES LocalObjectAttributes;
926  UNICODE_STRING LocalKeyName;
929  ULONG FullNameLength;
930  ULONG Length;
931  PWCHAR Ptr;
932  HANDLE LocalKeyHandle;
933 
934  Status = NtCreateKey((PHANDLE) KeyHandle,
935  samDesired,
936  ObjectAttributes,
937  0,
938  ClassString,
939  dwOptions,
940  (PULONG)lpdwDisposition);
941  TRACE("NtCreateKey(%wZ) called (Status %lx)\n", ObjectAttributes->ObjectName, Status);
942  if (Status != STATUS_OBJECT_NAME_NOT_FOUND)
943  return Status;
944 
945  /* Copy object attributes */
946  RtlCopyMemory(&LocalObjectAttributes,
947  ObjectAttributes,
948  sizeof(OBJECT_ATTRIBUTES));
949  RtlCreateUnicodeString(&LocalKeyName,
950  ObjectAttributes->ObjectName->Buffer);
951  LocalObjectAttributes.ObjectName = &LocalKeyName;
952  FullNameLength = LocalKeyName.Length / sizeof(WCHAR);
953 
954  LocalKeyHandle = NULL;
955 
956  /* Remove the last part of the key name and try to create the key again. */
957  while (Status == STATUS_OBJECT_NAME_NOT_FOUND)
958  {
959  Ptr = wcsrchr(LocalKeyName.Buffer, '\\');
960  if (Ptr == NULL || Ptr == LocalKeyName.Buffer)
961  {
962  Status = STATUS_UNSUCCESSFUL;
963  break;
964  }
965 
966  *Ptr = (WCHAR)0;
967  LocalKeyName.Length = wcslen(LocalKeyName.Buffer) * sizeof(WCHAR);
968 
969  Status = NtCreateKey(&LocalKeyHandle,
971  &LocalObjectAttributes,
972  0,
973  NULL,
974  0,
975  &Disposition);
976  TRACE("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName, Status);
977  }
978 
979  if (!NT_SUCCESS(Status))
980  {
981  RtlFreeUnicodeString(&LocalKeyName);
982  return Status;
983  }
984 
985  /* Add removed parts of the key name and create them too. */
986  Length = wcslen(LocalKeyName.Buffer);
987  while (TRUE)
988  {
989  if (LocalKeyHandle)
990  NtClose (LocalKeyHandle);
991 
992  LocalKeyName.Buffer[Length] = L'\\';
993  Length = wcslen (LocalKeyName.Buffer);
994  LocalKeyName.Length = Length * sizeof(WCHAR);
995 
996  if (Length == FullNameLength)
997  {
998  Status = NtCreateKey((PHANDLE) KeyHandle,
999  samDesired,
1000  ObjectAttributes,
1001  0,
1002  ClassString,
1003  dwOptions,
1004  (PULONG)lpdwDisposition);
1005  break;
1006  }
1007 
1008  Status = NtCreateKey(&LocalKeyHandle,
1010  &LocalObjectAttributes,
1011  0,
1012  NULL,
1013  0,
1014  &Disposition);
1015  TRACE("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName, Status);
1016  if (!NT_SUCCESS(Status))
1017  break;
1018  }
1019 
1020  RtlFreeUnicodeString(&LocalKeyName);
1021 
1022  return Status;
1023 }
1024 
1025 
1026 /************************************************************************
1027  * RegCreateKeyExA
1028  *
1029  * @implemented
1030  */
1031 LONG WINAPI
1033  _In_ HKEY hKey,
1034  _In_ LPCSTR lpSubKey,
1036  _In_ LPSTR lpClass,
1038  _In_ REGSAM samDesired,
1039  _In_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
1040  _Out_ PHKEY phkResult,
1041  _Out_ LPDWORD lpdwDisposition)
1042 {
1043  UNICODE_STRING SubKeyString;
1044  UNICODE_STRING ClassString;
1045  DWORD ErrorCode;
1046 
1047  RtlInitEmptyUnicodeString(&ClassString, NULL, 0);
1048  RtlInitEmptyUnicodeString(&SubKeyString, NULL, 0);
1049 
1050  if (lpClass)
1051  {
1052  if (!RtlCreateUnicodeStringFromAsciiz(&ClassString, lpClass))
1053  {
1054  ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1055  goto Exit;
1056  }
1057  }
1058 
1059  if (lpSubKey)
1060  {
1061  if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyString, lpSubKey))
1062  {
1063  ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1064  goto Exit;
1065  }
1066  }
1067 
1068  ErrorCode = RegCreateKeyExW(
1069  hKey,
1070  SubKeyString.Buffer,
1071  Reserved,
1072  ClassString.Buffer,
1073  dwOptions,
1074  samDesired,
1075  lpSecurityAttributes,
1076  phkResult,
1077  lpdwDisposition);
1078 
1079 Exit:
1080  RtlFreeUnicodeString(&SubKeyString);
1081  RtlFreeUnicodeString(&ClassString);
1082 
1083  return ErrorCode;
1084 }
1085 
1086 
1087 /************************************************************************
1088  * RegCreateKeyExW
1089  *
1090  * @implemented
1091  */
1092 LONG
1093 WINAPI
1095  _In_ HKEY hKey,
1096  _In_ LPCWSTR lpSubKey,
1098  _In_opt_ LPWSTR lpClass,
1100  _In_ REGSAM samDesired,
1101  _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
1102  _Out_ PHKEY phkResult,
1103  _Out_opt_ LPDWORD lpdwDisposition)
1104 {
1105  UNICODE_STRING SubKeyString;
1106  UNICODE_STRING ClassString;
1108  HANDLE ParentKey;
1110  NTSTATUS Status;
1111 
1112  TRACE("RegCreateKeyExW() called\n");
1113 
1114  if (lpSecurityAttributes && lpSecurityAttributes->nLength != sizeof(SECURITY_ATTRIBUTES))
1116 
1117  /* get the real parent key */
1118  Status = MapDefaultKey(&ParentKey,
1119  hKey);
1120  if (!NT_SUCCESS(Status))
1121  {
1122  return RtlNtStatusToDosError(Status);
1123  }
1124 
1125  TRACE("ParentKey %p\n", ParentKey);
1126 
1127  if (IsHKCRKey(ParentKey))
1128  {
1130  ParentKey,
1131  lpSubKey,
1132  Reserved,
1133  lpClass,
1134  dwOptions,
1135  samDesired,
1136  lpSecurityAttributes,
1137  phkResult,
1138  lpdwDisposition);
1139  ClosePredefKey(ParentKey);
1140  return ErrorCode;
1141  }
1142 
1143  if (dwOptions & REG_OPTION_OPEN_LINK)
1144  Attributes |= OBJ_OPENLINK;
1145 
1146  RtlInitUnicodeString(&ClassString,
1147  lpClass);
1148  RtlInitUnicodeString(&SubKeyString,
1149  lpSubKey);
1150  InitializeObjectAttributes(&ObjectAttributes,
1151  &SubKeyString,
1152  Attributes,
1153  (HANDLE)ParentKey,
1154  lpSecurityAttributes ? (PSECURITY_DESCRIPTOR)lpSecurityAttributes->lpSecurityDescriptor : NULL);
1155  Status = CreateNestedKey(phkResult,
1156  &ObjectAttributes,
1157  (lpClass == NULL)? NULL : &ClassString,
1158  dwOptions,
1159  samDesired,
1160  lpdwDisposition);
1161 
1162  ClosePredefKey(ParentKey);
1163 
1164  TRACE("Status %x\n", Status);
1165  if (!NT_SUCCESS(Status))
1166  {
1167  return RtlNtStatusToDosError(Status);
1168  }
1169 
1170  return ERROR_SUCCESS;
1171 }
1172 
1173 
1174 /************************************************************************
1175  * RegCreateKeyA
1176  *
1177  * @implemented
1178  */
1179 LONG WINAPI
1181  LPCSTR lpSubKey,
1182  PHKEY phkResult)
1183 {
1184  return RegCreateKeyExA(hKey,
1185  lpSubKey,
1186  0,
1187  NULL,
1188  0,
1190  NULL,
1191  phkResult,
1192  NULL);
1193 }
1194 
1195 
1196 /************************************************************************
1197  * RegCreateKeyW
1198  *
1199  * @implemented
1200  */
1201 LONG WINAPI
1203  LPCWSTR lpSubKey,
1204  PHKEY phkResult)
1205 {
1206  return RegCreateKeyExW(hKey,
1207  lpSubKey,
1208  0,
1209  NULL,
1210  0,
1212  NULL,
1213  phkResult,
1214  NULL);
1215 }
1216 
1217 
1218 /************************************************************************
1219  * RegDeleteKeyA
1220  *
1221  * @implemented
1222  */
1223 LONG
1224 WINAPI
1226  _In_ HKEY hKey,
1227  _In_ LPCSTR lpSubKey)
1228 {
1229  return RegDeleteKeyExA(hKey, lpSubKey, 0, 0);
1230 }
1231 
1232 
1233 /************************************************************************
1234  * RegDeleteKeyW
1235  *
1236  * @implemented
1237  */
1238 LONG
1239 WINAPI
1241  _In_ HKEY hKey,
1242  _In_ LPCWSTR lpSubKey)
1243 {
1244  return RegDeleteKeyExW(hKey, lpSubKey, 0, 0);
1245 }
1246 
1247 
1248 /************************************************************************
1249  * RegDeleteKeyExA
1250  *
1251  * @implemented
1252  */
1253 LONG
1254 WINAPI
1256  _In_ HKEY hKey,
1257  _In_ LPCSTR lpSubKey,
1258  _In_ REGSAM samDesired,
1260 {
1261  LONG ErrorCode;
1263 
1264  if (lpSubKey)
1265  {
1266  if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyName, lpSubKey))
1267  return ERROR_NOT_ENOUGH_MEMORY;
1268  }
1269  else
1270  RtlInitEmptyUnicodeString(&SubKeyName, NULL, 0);
1271 
1272  ErrorCode = RegDeleteKeyExW(hKey, SubKeyName.Buffer, samDesired, Reserved);
1273 
1274  RtlFreeUnicodeString(&SubKeyName);
1275 
1276  return ErrorCode;
1277 }
1278 
1279 
1280 /************************************************************************
1281  * RegDeleteKeyExW
1282  *
1283  * @implemented
1284  */
1285 LONG
1286 WINAPI
1288  _In_ HKEY hKey,
1289  _In_ LPCWSTR lpSubKey,
1290  _In_ REGSAM samDesired,
1292 {
1295  HANDLE ParentKey;
1296  HANDLE TargetKey;
1297  NTSTATUS Status;
1298 
1299  /* Make sure we got a subkey */
1300  if (!lpSubKey)
1301  {
1302  /* Fail */
1303  return ERROR_INVALID_PARAMETER;
1304  }
1305 
1306  Status = MapDefaultKey(&ParentKey,
1307  hKey);
1308  if (!NT_SUCCESS(Status))
1309  {
1310  return RtlNtStatusToDosError(Status);
1311  }
1312 
1313  if (IsHKCRKey(ParentKey))
1314  {
1315  LONG ErrorCode = DeleteHKCRKey(ParentKey, lpSubKey, samDesired, Reserved);
1316  ClosePredefKey(ParentKey);
1317  return ErrorCode;
1318  }
1319 
1320  if (samDesired & KEY_WOW64_32KEY)
1321  ERR("Wow64 not yet supported!\n");
1322 
1323  if (samDesired & KEY_WOW64_64KEY)
1324  ERR("Wow64 not yet supported!\n");
1325 
1326 
1327  RtlInitUnicodeString(&SubKeyName,
1328  (LPWSTR)lpSubKey);
1329  InitializeObjectAttributes(&ObjectAttributes,
1330  &SubKeyName,
1332  ParentKey,
1333  NULL);
1334  Status = NtOpenKey(&TargetKey,
1335  DELETE,
1336  &ObjectAttributes);
1337  if (!NT_SUCCESS(Status))
1338  {
1339  goto Cleanup;
1340  }
1341 
1342  Status = NtDeleteKey(TargetKey);
1343  NtClose(TargetKey);
1344 
1345 Cleanup:
1346  ClosePredefKey(ParentKey);
1347 
1348  if (!NT_SUCCESS(Status))
1349  {
1350  return RtlNtStatusToDosError(Status);
1351  }
1352 
1353  return ERROR_SUCCESS;
1354 }
1355 
1356 
1357 /************************************************************************
1358  * RegDeleteKeyValueW
1359  *
1360  * @implemented
1361  */
1362 LONG WINAPI
1364  IN LPCWSTR lpSubKey OPTIONAL,
1365  IN LPCWSTR lpValueName OPTIONAL)
1366 {
1368  HANDLE KeyHandle, CurKey, SubKeyHandle = NULL;
1369  NTSTATUS Status;
1370 
1371  Status = MapDefaultKey(&KeyHandle,
1372  hKey);
1373  if (!NT_SUCCESS(Status))
1374  {
1375  return RtlNtStatusToDosError(Status);
1376  }
1377 
1378  if (lpSubKey != NULL)
1379  {
1382 
1383  RtlInitUnicodeString(&SubKeyName,
1384  (LPWSTR)lpSubKey);
1385 
1386  InitializeObjectAttributes(&ObjectAttributes,
1387  &SubKeyName,
1389  KeyHandle,
1390  NULL);
1391 
1392  Status = NtOpenKey(&SubKeyHandle,
1393  KEY_SET_VALUE,
1394  &ObjectAttributes);
1395  if (!NT_SUCCESS(Status))
1396  {
1397  goto Cleanup;
1398  }
1399 
1400  CurKey = SubKeyHandle;
1401  }
1402  else
1403  CurKey = KeyHandle;
1404 
1405  RtlInitUnicodeString(&ValueName,
1406  (LPWSTR)lpValueName);
1407 
1408  Status = NtDeleteValueKey(CurKey,
1409  &ValueName);
1410 
1411  if (SubKeyHandle != NULL)
1412  {
1413  NtClose(SubKeyHandle);
1414  }
1415 
1416 Cleanup:
1417  ClosePredefKey(KeyHandle);
1418 
1419  if (!NT_SUCCESS(Status))
1420  {
1421  return RtlNtStatusToDosError(Status);
1422  }
1423 
1424  return ERROR_SUCCESS;
1425 }
1426 
1427 
1428 /************************************************************************
1429  * RegDeleteKeyValueA
1430  *
1431  * @implemented
1432  */
1433 LONG WINAPI
1435  IN LPCSTR lpSubKey OPTIONAL,
1436  IN LPCSTR lpValueName OPTIONAL)
1437 {
1438  UNICODE_STRING SubKey = { 0, 0, NULL }, ValueName = { 0, 0, NULL };
1439  LONG Ret;
1440 
1441  if (lpSubKey != NULL &&
1443  (LPSTR)lpSubKey))
1444  {
1445  return ERROR_NOT_ENOUGH_MEMORY;
1446  }
1447 
1448  if (lpValueName != NULL &&
1450  (LPSTR)lpValueName))
1451  {
1452  RtlFreeUnicodeString(&SubKey);
1453  return ERROR_NOT_ENOUGH_MEMORY;
1454  }
1455 
1456  Ret = RegDeleteKeyValueW(hKey,
1457  SubKey.Buffer,
1458  SubKey.Buffer);
1459 
1460  RtlFreeUnicodeString(&SubKey);
1462 
1463  return Ret;
1464 }
1465 
1466 #if 0
1467 // Non-recursive RegDeleteTreeW implementation by Thomas, however it needs bugfixing
1468 static NTSTATUS
1469 RegpDeleteTree(IN HKEY hKey)
1470 {
1471  typedef struct
1472  {
1473  LIST_ENTRY ListEntry;
1474  HANDLE KeyHandle;
1475  } REGP_DEL_KEYS, *PREG_DEL_KEYS;
1476 
1477  LIST_ENTRY delQueueHead;
1478  PREG_DEL_KEYS delKeys, newDelKeys;
1480  ULONG BufferSize;
1481  PKEY_BASIC_INFORMATION BasicInfo;
1482  PREG_DEL_KEYS KeyDelRoot;
1484  NTSTATUS Status2 = STATUS_SUCCESS;
1485 
1486  InitializeListHead(&delQueueHead);
1487 
1488  ProcessHeap = RtlGetProcessHeap();
1489 
1490  /* NOTE: no need to allocate enough memory for an additional KEY_BASIC_INFORMATION
1491  structure for the root key, we only do that for subkeys as we need to
1492  allocate REGP_DEL_KEYS structures anyway! */
1493  KeyDelRoot = RtlAllocateHeap(ProcessHeap,
1494  0,
1495  sizeof(REGP_DEL_KEYS));
1496  if (KeyDelRoot != NULL)
1497  {
1498  KeyDelRoot->KeyHandle = hKey;
1499  InsertTailList(&delQueueHead,
1500  &KeyDelRoot->ListEntry);
1501 
1502  do
1503  {
1504  delKeys = CONTAINING_RECORD(delQueueHead.Flink,
1505  REGP_DEL_KEYS,
1506  ListEntry);
1507 
1508  BufferSize = 0;
1509  BasicInfo = NULL;
1510  newDelKeys = NULL;
1511 
1512 ReadFirstSubKey:
1513  /* check if this key contains subkeys and delete them first by queuing
1514  them at the head of the list */
1515  Status2 = NtEnumerateKey(delKeys->KeyHandle,
1516  0,
1518  BasicInfo,
1519  BufferSize,
1520  &BufferSize);
1521 
1522  if (NT_SUCCESS(Status2))
1523  {
1526 
1527  ASSERT(newDelKeys != NULL);
1528  ASSERT(BasicInfo != NULL);
1529 
1530  /* don't use RtlInitUnicodeString as the string is not NULL-terminated! */
1531  SubKeyName.Length = BasicInfo->NameLength;
1532  SubKeyName.MaximumLength = BasicInfo->NameLength;
1533  SubKeyName.Buffer = BasicInfo->Name;
1534 
1535  InitializeObjectAttributes(&ObjectAttributes,
1536  &SubKeyName,
1538  delKeys->KeyHandle,
1539  NULL);
1540 
1541  /* open the subkey */
1542  Status2 = NtOpenKey(&newDelKeys->KeyHandle,
1544  &ObjectAttributes);
1545  if (!NT_SUCCESS(Status2))
1546  {
1547  goto SubKeyFailure;
1548  }
1549 
1550  /* enqueue this key to the head of the deletion queue */
1551  InsertHeadList(&delQueueHead,
1552  &newDelKeys->ListEntry);
1553 
1554  /* try again from the head of the list */
1555  continue;
1556  }
1557  else
1558  {
1559  if (Status2 == STATUS_BUFFER_TOO_SMALL)
1560  {
1561  newDelKeys = RtlAllocateHeap(ProcessHeap,
1562  0,
1563  BufferSize + sizeof(REGP_DEL_KEYS));
1564  if (newDelKeys != NULL)
1565  {
1566  BasicInfo = (PKEY_BASIC_INFORMATION)(newDelKeys + 1);
1567 
1568  /* try again */
1569  goto ReadFirstSubKey;
1570  }
1571  else
1572  {
1573  /* don't break, let's try to delete as many keys as possible */
1575  goto SubKeyFailureNoFree;
1576  }
1577  }
1578  else if (Status2 == STATUS_BUFFER_OVERFLOW)
1579  {
1580  PREG_DEL_KEYS newDelKeys2;
1581 
1582  ASSERT(newDelKeys != NULL);
1583 
1584  /* we need more memory to query the key name */
1585  newDelKeys2 = RtlReAllocateHeap(ProcessHeap,
1586  0,
1587  newDelKeys,
1588  BufferSize + sizeof(REGP_DEL_KEYS));
1589  if (newDelKeys2 != NULL)
1590  {
1591  newDelKeys = newDelKeys2;
1592  BasicInfo = (PKEY_BASIC_INFORMATION)(newDelKeys + 1);
1593 
1594  /* try again */
1595  goto ReadFirstSubKey;
1596  }
1597  else
1598  {
1599  /* don't break, let's try to delete as many keys as possible */
1601  }
1602  }
1603  else if (Status2 == STATUS_NO_MORE_ENTRIES)
1604  {
1605  /* in some race conditions where another thread would delete
1606  the same tree at the same time, newDelKeys could actually
1607  be != NULL! */
1608  if (newDelKeys != NULL)
1609  {
1610  RtlFreeHeap(ProcessHeap,
1611  0,
1612  newDelKeys);
1613  }
1614  break;
1615  }
1616 
1617 SubKeyFailure:
1618  /* newDelKeys can be NULL here when NtEnumerateKey returned an
1619  error other than STATUS_BUFFER_TOO_SMALL or STATUS_BUFFER_OVERFLOW! */
1620  if (newDelKeys != NULL)
1621  {
1622  RtlFreeHeap(ProcessHeap,
1623  0,
1624  newDelKeys);
1625  }
1626 
1627 SubKeyFailureNoFree:
1628  /* don't break, let's try to delete as many keys as possible */
1629  if (NT_SUCCESS(Status))
1630  {
1631  Status = Status2;
1632  }
1633  }
1634 
1635  Status2 = NtDeleteKey(delKeys->KeyHandle);
1636 
1637  /* NOTE: do NOT close the handle anymore, it's invalid already! */
1638 
1639  if (!NT_SUCCESS(Status2))
1640  {
1641  /* close the key handle so we don't leak handles for keys we were
1642  unable to delete. But only do this for handles not supplied
1643  by the caller! */
1644 
1645  if (delKeys->KeyHandle != hKey)
1646  {
1647  NtClose(delKeys->KeyHandle);
1648  }
1649 
1650  if (NT_SUCCESS(Status))
1651  {
1652  /* don't break, let's try to delete as many keys as possible */
1653  Status = Status2;
1654  }
1655  }
1656 
1657  /* remove the entry from the list */
1658  RemoveEntryList(&delKeys->ListEntry);
1659 
1660  RtlFreeHeap(ProcessHeap,
1661  0,
1662  delKeys);
1663  } while (!IsListEmpty(&delQueueHead));
1664  }
1665  else
1667 
1668  return Status;
1669 }
1670 
1671 
1672 /************************************************************************
1673  * RegDeleteTreeW
1674  *
1675  * @implemented
1676  */
1677 LONG WINAPI
1678 RegDeleteTreeW(IN HKEY hKey,
1679  IN LPCWSTR lpSubKey OPTIONAL)
1680 {
1681  HANDLE KeyHandle, CurKey, SubKeyHandle = NULL;
1682  NTSTATUS Status;
1683 
1684  Status = MapDefaultKey(&KeyHandle,
1685  hKey);
1686  if (!NT_SUCCESS(Status))
1687  {
1688  return RtlNtStatusToDosError(Status);
1689  }
1690 
1691  if (lpSubKey != NULL)
1692  {
1695 
1696  RtlInitUnicodeString(&SubKeyName,
1697  (LPWSTR)lpSubKey);
1698 
1699  InitializeObjectAttributes(&ObjectAttributes,
1700  &SubKeyName,
1702  KeyHandle,
1703  NULL);
1704 
1705  Status = NtOpenKey(&SubKeyHandle,
1707  &ObjectAttributes);
1708  if (!NT_SUCCESS(Status))
1709  {
1710  goto Cleanup;
1711  }
1712 
1713  CurKey = SubKeyHandle;
1714  }
1715  else
1716  CurKey = KeyHandle;
1717 
1718  Status = RegpDeleteTree(CurKey);
1719 
1720  if (NT_SUCCESS(Status))
1721  {
1722  /* make sure we only close hKey (KeyHandle) when the caller specified a
1723  subkey, because the handle would be invalid already! */
1724  if (CurKey != KeyHandle)
1725  {
1726  ClosePredefKey(KeyHandle);
1727  }
1728 
1729  return ERROR_SUCCESS;
1730  }
1731  else
1732  {
1733  /* make sure we close all handles we created! */
1734  if (SubKeyHandle != NULL)
1735  {
1736  NtClose(SubKeyHandle);
1737  }
1738 
1739 Cleanup:
1740  ClosePredefKey(KeyHandle);
1741 
1742  return RtlNtStatusToDosError(Status);
1743  }
1744 }
1745 #endif
1746 
1747 
1748 /************************************************************************
1749  * RegDeleteTreeW
1750  *
1751  * @implemented
1752  */
1753 LSTATUS
1754 WINAPI
1756  LPCWSTR lpszSubKey)
1757 {
1758  LONG ret;
1759  DWORD dwMaxSubkeyLen, dwMaxValueLen;
1760  DWORD dwMaxLen, dwSize;
1761  NTSTATUS Status;
1762  HANDLE KeyHandle;
1763  HKEY hSubKey;
1764  WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1765 
1766  TRACE("(hkey=%p,%p %s)\n", hKey, lpszSubKey, debugstr_w(lpszSubKey));
1767 
1768  Status = MapDefaultKey(&KeyHandle,
1769  hKey);
1770  if (!NT_SUCCESS(Status))
1771  {
1772  return RtlNtStatusToDosError(Status);
1773  }
1774 
1775  hSubKey = KeyHandle;
1776 
1777  if(lpszSubKey)
1778  {
1779  ret = RegOpenKeyExW(KeyHandle, lpszSubKey, 0, KEY_READ, &hSubKey);
1780  if (ret)
1781  {
1782  ClosePredefKey(KeyHandle);
1783  return ret;
1784  }
1785  }
1786 
1787  /* Get highest length for keys, values */
1788  ret = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
1789  &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
1790  if (ret) goto cleanup;
1791 
1792  dwMaxSubkeyLen++;
1793  dwMaxValueLen++;
1794  dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
1795  if (dwMaxLen > sizeof(szNameBuf)/sizeof(WCHAR))
1796  {
1797  /* Name too big: alloc a buffer for it */
1798  if (!(lpszName = RtlAllocateHeap( RtlGetProcessHeap(), 0, dwMaxLen*sizeof(WCHAR))))
1799  {
1801  goto cleanup;
1802  }
1803  }
1804 
1805 
1806  /* Recursively delete all the subkeys */
1807  while (TRUE)
1808  {
1809  dwSize = dwMaxLen;
1810  if (RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL,
1811  NULL, NULL, NULL)) break;
1812 
1813  ret = RegDeleteTreeW(hSubKey, lpszName);
1814  if (ret) goto cleanup;
1815  }
1816 
1817  if (lpszSubKey)
1818  ret = RegDeleteKeyW(KeyHandle, lpszSubKey);
1819  else
1820  while (TRUE)
1821  {
1822  dwSize = dwMaxLen;
1823  if (RegEnumValueW(KeyHandle, 0, lpszName, &dwSize,
1824  NULL, NULL, NULL, NULL)) break;
1825 
1826  ret = RegDeleteValueW(KeyHandle, lpszName);
1827  if (ret) goto cleanup;
1828  }
1829 
1830 cleanup:
1831  /* Free buffer if allocated */
1832  if (lpszName != szNameBuf)
1833  RtlFreeHeap( RtlGetProcessHeap(), 0, lpszName);
1834  if(lpszSubKey)
1835  RegCloseKey(hSubKey);
1836 
1837  ClosePredefKey(KeyHandle);
1838 
1839  return ret;
1840 }
1841 
1842 
1843 /************************************************************************
1844  * RegDeleteTreeA
1845  *
1846  * @implemented
1847  */
1848 LONG WINAPI
1850  IN LPCSTR lpSubKey OPTIONAL)
1851 {
1852  UNICODE_STRING SubKeyName = { 0, 0, NULL };
1853  LONG Ret;
1854 
1855  if (lpSubKey != NULL &&
1856  !RtlCreateUnicodeStringFromAsciiz(&SubKeyName,
1857  (LPSTR)lpSubKey))
1858  {
1859  return ERROR_NOT_ENOUGH_MEMORY;
1860  }
1861 
1862  Ret = RegDeleteTreeW(hKey,
1863  SubKeyName.Buffer);
1864 
1865  RtlFreeUnicodeString(&SubKeyName);
1866 
1867  return Ret;
1868 }
1869 
1870 
1871 /************************************************************************
1872  * RegDisableReflectionKey
1873  *
1874  * @unimplemented
1875  */
1876 LONG WINAPI
1878 {
1879  FIXME("RegDisableReflectionKey(0x%p) UNIMPLEMENTED!\n", hBase);
1881 }
1882 
1883 
1884 /************************************************************************
1885  * RegEnableReflectionKey
1886  *
1887  * @unimplemented
1888  */
1889 LONG WINAPI
1891 {
1892  FIXME("RegEnableReflectionKey(0x%p) UNIMPLEMENTED!\n", hBase);
1894 }
1895 
1896 
1897 /******************************************************************************
1898  * RegpApplyRestrictions [internal]
1899  *
1900  * Helper function for RegGetValueA/W.
1901  */
1902 static VOID
1904  DWORD dwType,
1905  DWORD cbData,
1906  PLONG ret)
1907 {
1908  /* Check if the type is restricted by the passed flags */
1909  if (*ret == ERROR_SUCCESS || *ret == ERROR_MORE_DATA)
1910  {
1911  DWORD dwMask = 0;
1912 
1913  switch (dwType)
1914  {
1915  case REG_NONE: dwMask = RRF_RT_REG_NONE; break;
1916  case REG_SZ: dwMask = RRF_RT_REG_SZ; break;
1917  case REG_EXPAND_SZ: dwMask = RRF_RT_REG_EXPAND_SZ; break;
1918  case REG_MULTI_SZ: dwMask = RRF_RT_REG_MULTI_SZ; break;
1919  case REG_BINARY: dwMask = RRF_RT_REG_BINARY; break;
1920  case REG_DWORD: dwMask = RRF_RT_REG_DWORD; break;
1921  case REG_QWORD: dwMask = RRF_RT_REG_QWORD; break;
1922  }
1923 
1924  if (dwFlags & dwMask)
1925  {
1926  /* Type is not restricted, check for size mismatch */
1927  if (dwType == REG_BINARY)
1928  {
1929  DWORD cbExpect = 0;
1930 
1931  if ((dwFlags & RRF_RT_ANY) == RRF_RT_DWORD)
1932  cbExpect = 4;
1933  else if ((dwFlags & RRF_RT_ANY) == RRF_RT_QWORD)
1934  cbExpect = 8;
1935 
1936  if (cbExpect && cbData != cbExpect)
1937  *ret = ERROR_DATATYPE_MISMATCH;
1938  }
1939  }
1940  else *ret = ERROR_UNSUPPORTED_TYPE;
1941  }
1942 }
1943 
1944 
1945 /******************************************************************************
1946  * RegGetValueW [ADVAPI32.@]
1947  *
1948  * Retrieves the type and data for a value name associated with a key,
1949  * optionally expanding its content and restricting its type.
1950  *
1951  * PARAMS
1952  * hKey [I] Handle to an open key.
1953  * pszSubKey [I] Name of the subkey of hKey.
1954  * pszValue [I] Name of value under hKey/szSubKey to query.
1955  * dwFlags [I] Flags restricting the value type to retrieve.
1956  * pdwType [O] Destination for the values type, may be NULL.
1957  * pvData [O] Destination for the values content, may be NULL.
1958  * pcbData [I/O] Size of pvData, updated with the size in bytes required to
1959  * retrieve the whole content, including the trailing '\0'
1960  * for strings.
1961  *
1962  * RETURNS
1963  * Success: ERROR_SUCCESS
1964  * Failure: nonzero error code from Winerror.h
1965  *
1966  * NOTES
1967  * - Unless RRF_NOEXPAND is specified, REG_EXPAND_SZ values are automatically
1968  * expanded and pdwType is set to REG_SZ instead.
1969  * - Restrictions are applied after expanding, using RRF_RT_REG_EXPAND_SZ
1970  * without RRF_NOEXPAND is thus not allowed.
1971  * An exception is the case where RRF_RT_ANY is specified, because then
1972  * RRF_NOEXPAND is allowed.
1973  */
1976  LPCWSTR pszSubKey,
1977  LPCWSTR pszValue,
1978  DWORD dwFlags,
1979  LPDWORD pdwType,
1980  PVOID pvData,
1981  LPDWORD pcbData)
1982 {
1983  DWORD dwType, cbData = pcbData ? *pcbData : 0;
1984  PVOID pvBuf = NULL;
1985  LONG ret;
1986 
1987  TRACE("(%p,%s,%s,%ld,%p,%p,%p=%ld)\n",
1988  hKey, debugstr_w(pszSubKey), debugstr_w(pszValue), dwFlags, pdwType,
1989  pvData, pcbData, cbData);
1990 
1991  if (pvData && !pcbData)
1992  return ERROR_INVALID_PARAMETER;
1993  if ((dwFlags & RRF_RT_REG_EXPAND_SZ) && !(dwFlags & RRF_NOEXPAND) &&
1994  ((dwFlags & RRF_RT_ANY) != RRF_RT_ANY))
1995  return ERROR_INVALID_PARAMETER;
1996 
1997  if (pszSubKey && pszSubKey[0])
1998  {
1999  ret = RegOpenKeyExW(hKey, pszSubKey, 0, KEY_QUERY_VALUE, &hKey);
2000  if (ret != ERROR_SUCCESS) return ret;
2001  }
2002 
2003  ret = RegQueryValueExW(hKey, pszValue, NULL, &dwType, pvData, &cbData);
2004 
2005  /* If we are going to expand we need to read in the whole the value even
2006  * if the passed buffer was too small as the expanded string might be
2007  * smaller than the unexpanded one and could fit into cbData bytes. */
2008  if ((ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) &&
2009  dwType == REG_EXPAND_SZ && !(dwFlags & RRF_NOEXPAND))
2010  {
2011  do
2012  {
2013  HeapFree(GetProcessHeap(), 0, pvBuf);
2014 
2015  pvBuf = HeapAlloc(GetProcessHeap(), 0, cbData);
2016  if (!pvBuf)
2017  {
2019  break;
2020  }
2021 
2022  if (ret == ERROR_MORE_DATA || !pvData)
2023  ret = RegQueryValueExW(hKey, pszValue, NULL,
2024  &dwType, pvBuf, &cbData);
2025  else
2026  {
2027  /* Even if cbData was large enough we have to copy the
2028  * string since ExpandEnvironmentStrings can't handle
2029  * overlapping buffers. */
2030  CopyMemory(pvBuf, pvData, cbData);
2031  }
2032 
2033  /* Both the type or the value itself could have been modified in
2034  * between so we have to keep retrying until the buffer is large
2035  * enough or we no longer have to expand the value. */
2036  }
2037  while (dwType == REG_EXPAND_SZ && ret == ERROR_MORE_DATA);
2038 
2039  if (ret == ERROR_SUCCESS)
2040  {
2041  /* Recheck dwType in case it changed since the first call */
2042  if (dwType == REG_EXPAND_SZ)
2043  {
2044  cbData = ExpandEnvironmentStringsW(pvBuf, pvData,
2045  pcbData ? *pcbData : 0) * sizeof(WCHAR);
2046  dwType = REG_SZ;
2047  if (pvData && pcbData && cbData > *pcbData)
2048  ret = ERROR_MORE_DATA;
2049  }
2050  else if (pvData)
2051  CopyMemory(pvData, pvBuf, *pcbData);
2052  }
2053 
2054  HeapFree(GetProcessHeap(), 0, pvBuf);
2055  }
2056 
2057  if (pszSubKey && pszSubKey[0])
2058  RegCloseKey(hKey);
2059 
2060  RegpApplyRestrictions(dwFlags, dwType, cbData, &ret);
2061 
2062  if (pvData && ret != ERROR_SUCCESS && (dwFlags & RRF_ZEROONFAILURE))
2063  ZeroMemory(pvData, *pcbData);
2064 
2065  if (pdwType)
2066  *pdwType = dwType;
2067 
2068  if (pcbData)
2069  *pcbData = cbData;
2070 
2071  return ret;
2072 }
2073 
2074 
2075 /******************************************************************************
2076  * RegGetValueA [ADVAPI32.@]
2077  *
2078  * See RegGetValueW.
2079  */
2082  LPCSTR pszSubKey,
2083  LPCSTR pszValue,
2084  DWORD dwFlags,
2085  LPDWORD pdwType,
2086  PVOID pvData,
2087  LPDWORD pcbData)
2088 {
2089  DWORD dwType, cbData = pcbData ? *pcbData : 0;
2090  PVOID pvBuf = NULL;
2091  LONG ret;
2092 
2093  TRACE("(%p,%s,%s,%ld,%p,%p,%p=%ld)\n",
2094  hKey, pszSubKey, pszValue, dwFlags, pdwType, pvData, pcbData,
2095  cbData);
2096 
2097  if (pvData && !pcbData)
2098  return ERROR_INVALID_PARAMETER;
2099  if ((dwFlags & RRF_RT_REG_EXPAND_SZ) && !(dwFlags & RRF_NOEXPAND) &&
2100  ((dwFlags & RRF_RT_ANY) != RRF_RT_ANY))
2101  return ERROR_INVALID_PARAMETER;
2102 
2103  if (pszSubKey && pszSubKey[0])
2104  {
2105  ret = RegOpenKeyExA(hKey, pszSubKey, 0, KEY_QUERY_VALUE, &hKey);
2106  if (ret != ERROR_SUCCESS) return ret;
2107  }
2108 
2109  ret = RegQueryValueExA(hKey, pszValue, NULL, &dwType, pvData, &cbData);
2110 
2111  /* If we are going to expand we need to read in the whole the value even
2112  * if the passed buffer was too small as the expanded string might be
2113  * smaller than the unexpanded one and could fit into cbData bytes. */
2114  if ((ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) &&
2115  (dwType == REG_EXPAND_SZ && !(dwFlags & RRF_NOEXPAND)))
2116  {
2117  do {
2118  HeapFree(GetProcessHeap(), 0, pvBuf);
2119 
2120  pvBuf = HeapAlloc(GetProcessHeap(), 0, cbData);
2121  if (!pvBuf)
2122  {
2124  break;
2125  }
2126 
2127  if (ret == ERROR_MORE_DATA || !pvData)
2128  ret = RegQueryValueExA(hKey, pszValue, NULL,
2129  &dwType, pvBuf, &cbData);
2130  else
2131  {
2132  /* Even if cbData was large enough we have to copy the
2133  * string since ExpandEnvironmentStrings can't handle
2134  * overlapping buffers. */
2135  CopyMemory(pvBuf, pvData, cbData);
2136  }
2137 
2138  /* Both the type or the value itself could have been modified in
2139  * between so we have to keep retrying until the buffer is large
2140  * enough or we no longer have to expand the value. */
2141  } while (dwType == REG_EXPAND_SZ && ret == ERROR_MORE_DATA);
2142 
2143  if (ret == ERROR_SUCCESS)
2144  {
2145  /* Recheck dwType in case it changed since the first call */
2146  if (dwType == REG_EXPAND_SZ)
2147  {
2148  cbData = ExpandEnvironmentStringsA(pvBuf, pvData,
2149  pcbData ? *pcbData : 0);
2150  dwType = REG_SZ;
2151  if(pvData && pcbData && cbData > *pcbData)
2152  ret = ERROR_MORE_DATA;
2153  }
2154  else if (pvData)
2155  CopyMemory(pvData, pvBuf, *pcbData);
2156  }
2157 
2158  HeapFree(GetProcessHeap(), 0, pvBuf);
2159  }
2160 
2161  if (pszSubKey && pszSubKey[0])
2162  RegCloseKey(hKey);
2163 
2164  RegpApplyRestrictions(dwFlags, dwType, cbData, &ret);
2165 
2166  if (pvData && ret != ERROR_SUCCESS && (dwFlags & RRF_ZEROONFAILURE))
2167  ZeroMemory(pvData, *pcbData);
2168 
2169  if (pdwType) *pdwType = dwType;
2170  if (pcbData) *pcbData = cbData;
2171 
2172  return ret;
2173 }
2174 
2175 
2176 /************************************************************************
2177  * RegSetKeyValueW
2178  *
2179  * @implemented
2180  */
2181 LONG WINAPI
2183  IN LPCWSTR lpSubKey OPTIONAL,
2184  IN LPCWSTR lpValueName OPTIONAL,
2185  IN DWORD dwType,
2186  IN LPCVOID lpData OPTIONAL,
2187  IN DWORD cbData)
2188 {
2189  HANDLE KeyHandle, CurKey, SubKeyHandle = NULL;
2190  NTSTATUS Status;
2191  LONG Ret;
2192 
2193  Status = MapDefaultKey(&KeyHandle,
2194  hKey);
2195  if (!NT_SUCCESS(Status))
2196  {
2197  return RtlNtStatusToDosError(Status);
2198  }
2199 
2200  if (lpSubKey != NULL)
2201  {
2204 
2205  RtlInitUnicodeString(&SubKeyName,
2206  (LPWSTR)lpSubKey);
2207 
2208  InitializeObjectAttributes(&ObjectAttributes,
2209  &SubKeyName,
2211  KeyHandle,
2212  NULL);
2213 
2214  Status = NtOpenKey(&SubKeyHandle,
2215  KEY_SET_VALUE,
2216  &ObjectAttributes);
2217  if (!NT_SUCCESS(Status))
2218  {
2219  Ret = RtlNtStatusToDosError(Status);
2220  goto Cleanup;
2221  }
2222 
2223  CurKey = SubKeyHandle;
2224  }
2225  else
2226  CurKey = KeyHandle;
2227 
2228  Ret = RegSetValueExW(CurKey,
2229  lpValueName,
2230  0,
2231  dwType,
2232  lpData,
2233  cbData);
2234 
2235  if (SubKeyHandle != NULL)
2236  {
2237  NtClose(SubKeyHandle);
2238  }
2239 
2240 Cleanup:
2241  ClosePredefKey(KeyHandle);
2242 
2243  return Ret;
2244 }
2245 
2246 
2247 /************************************************************************
2248  * RegSetKeyValueA
2249  *
2250  * @implemented
2251  */
2252 LONG WINAPI
2254  IN LPCSTR lpSubKey OPTIONAL,
2255  IN LPCSTR lpValueName OPTIONAL,
2256  IN DWORD dwType,
2257  IN LPCVOID lpData OPTIONAL,
2258  IN DWORD cbData)
2259 {
2260  HANDLE KeyHandle, CurKey, SubKeyHandle = NULL;
2261  NTSTATUS Status;
2262  LONG Ret;
2263 
2264  Status = MapDefaultKey(&KeyHandle,
2265  hKey);
2266  if (!NT_SUCCESS(Status))
2267  {
2268  return RtlNtStatusToDosError(Status);
2269  }
2270 
2271  if (lpSubKey != NULL)
2272  {
2275 
2276  if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyName,
2277  (LPSTR)lpSubKey))
2278  {
2280  goto Cleanup;
2281  }
2282 
2283  InitializeObjectAttributes(&ObjectAttributes,
2284  &SubKeyName,
2286  KeyHandle,
2287  NULL);
2288 
2289  Status = NtOpenKey(&SubKeyHandle,
2290  KEY_SET_VALUE,
2291  &ObjectAttributes);
2292 
2293  RtlFreeUnicodeString(&SubKeyName);
2294 
2295  if (!NT_SUCCESS(Status))
2296  {
2297  Ret = RtlNtStatusToDosError(Status);
2298  goto Cleanup;
2299  }
2300 
2301  CurKey = SubKeyHandle;
2302  }
2303  else
2304  CurKey = KeyHandle;
2305 
2306  Ret = RegSetValueExA(CurKey,
2307  lpValueName,
2308  0,
2309  dwType,
2310  lpData,
2311  cbData);
2312 
2313  if (SubKeyHandle != NULL)
2314  {
2315  NtClose(SubKeyHandle);
2316  }
2317 
2318 Cleanup:
2319  ClosePredefKey(KeyHandle);
2320 
2321  return Ret;
2322 }
2323 
2324 
2325 /************************************************************************
2326  * RegDeleteValueA
2327  *
2328  * @implemented
2329  */
2330 LONG WINAPI
2332  LPCSTR lpValueName)
2333 {
2335  HANDLE KeyHandle;
2336  NTSTATUS Status;
2337 
2338  Status = MapDefaultKey(&KeyHandle,
2339  hKey);
2340  if (!NT_SUCCESS(Status))
2341  {
2342  return RtlNtStatusToDosError(Status);
2343  }
2344 
2346  (LPSTR)lpValueName);
2347  Status = NtDeleteValueKey(KeyHandle,
2348  &ValueName);
2349  RtlFreeUnicodeString (&ValueName);
2350 
2351  ClosePredefKey(KeyHandle);
2352 
2353  if (!NT_SUCCESS(Status))
2354  {
2355  return RtlNtStatusToDosError(Status);
2356  }
2357 
2358  return ERROR_SUCCESS;
2359 }
2360 
2361 
2362 /************************************************************************
2363  * RegDeleteValueW
2364  *
2365  * @implemented
2366  */
2367 LONG WINAPI
2369  LPCWSTR lpValueName)
2370 {
2372  NTSTATUS Status;
2373  HANDLE KeyHandle;
2374 
2375  Status = MapDefaultKey(&KeyHandle,
2376  hKey);
2377  if (!NT_SUCCESS(Status))
2378  {
2379  return RtlNtStatusToDosError(Status);
2380  }
2381 
2382  RtlInitUnicodeString(&ValueName,
2383  (LPWSTR)lpValueName);
2384 
2385  Status = NtDeleteValueKey(KeyHandle,
2386  &ValueName);
2387 
2388  ClosePredefKey(KeyHandle);
2389 
2390  if (!NT_SUCCESS(Status))
2391  {
2392  return RtlNtStatusToDosError(Status);
2393  }
2394 
2395  return ERROR_SUCCESS;
2396 }
2397 
2398 
2399 /************************************************************************
2400  * RegEnumKeyA
2401  *
2402  * @implemented
2403  */
2404 LONG WINAPI
2406  DWORD dwIndex,
2407  LPSTR lpName,
2408  DWORD cbName)
2409 {
2410  DWORD dwLength;
2411 
2412  dwLength = cbName;
2413  return RegEnumKeyExA(hKey,
2414  dwIndex,
2415  lpName,
2416  &dwLength,
2417  NULL,
2418  NULL,
2419  NULL,
2420  NULL);
2421 }
2422 
2423 
2424 /************************************************************************
2425  * RegEnumKeyW
2426  *
2427  * @implemented
2428  */
2429 LONG WINAPI
2431  DWORD dwIndex,
2432  LPWSTR lpName,
2433  DWORD cbName)
2434 {
2435  DWORD dwLength;
2436 
2437  dwLength = cbName;
2438  return RegEnumKeyExW(hKey,
2439  dwIndex,
2440  lpName,
2441  &dwLength,
2442  NULL,
2443  NULL,
2444  NULL,
2445  NULL);
2446 }
2447 
2448 
2449 /************************************************************************
2450  * RegEnumKeyExA
2451  *
2452  * @implemented
2453  */
2454 LONG
2455 WINAPI
2457  _In_ HKEY hKey,
2458  _In_ DWORD dwIndex,
2459  _Out_ LPSTR lpName,
2460  _Inout_ LPDWORD lpcbName,
2461  _Reserved_ LPDWORD lpReserved,
2462  _Out_opt_ LPSTR lpClass,
2463  _Inout_opt_ LPDWORD lpcbClass,
2464  _Out_opt_ PFILETIME lpftLastWriteTime)
2465 {
2466  WCHAR* NameBuffer = NULL;
2467  WCHAR* ClassBuffer = NULL;
2468  DWORD NameLength, ClassLength;
2469  LONG ErrorCode;
2470 
2471  /* Allocate our buffers */
2472  if (*lpcbName > 0)
2473  {
2474  NameLength = *lpcbName;
2475  NameBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, *lpcbName * sizeof(WCHAR));
2476  if (NameBuffer == NULL)
2477  {
2478  ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2479  goto Exit;
2480  }
2481  }
2482 
2483  if (lpClass)
2484  {
2485  if (*lpcbClass > 0)
2486  {
2487  ClassLength = *lpcbClass;
2488  ClassBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, *lpcbClass * sizeof(WCHAR));
2489  if (ClassBuffer == NULL)
2490  {
2491  ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2492  goto Exit;
2493  }
2494  }
2495  }
2496 
2497  /* Do the actual call */
2498  ErrorCode = RegEnumKeyExW(
2499  hKey,
2500  dwIndex,
2501  NameBuffer,
2502  lpcbName,
2503  lpReserved,
2504  ClassBuffer,
2505  lpcbClass,
2506  lpftLastWriteTime);
2507 
2508  if (ErrorCode != ERROR_SUCCESS)
2509  goto Exit;
2510 
2511  /* Convert the strings */
2512  RtlUnicodeToMultiByteN(lpName, *lpcbName, 0, NameBuffer, *lpcbName * sizeof(WCHAR));
2513  /* NULL terminate if we can */
2514  if (NameLength > *lpcbName)
2515  lpName[*lpcbName] = '\0';
2516 
2517  if (lpClass)
2518  {
2519  RtlUnicodeToMultiByteN(lpClass, *lpcbClass, 0, NameBuffer, *lpcbClass * sizeof(WCHAR));
2520  if (ClassLength > *lpcbClass)
2521  lpClass[*lpcbClass] = '\0';
2522  }
2523 
2524 Exit:
2525  if (NameBuffer)
2526  RtlFreeHeap(RtlGetProcessHeap(), 0, NameBuffer);
2527  if (ClassBuffer)
2528  RtlFreeHeap(RtlGetProcessHeap(), 0, ClassBuffer);
2529 
2530  return ErrorCode;
2531 }
2532 
2533 
2534 /************************************************************************
2535  * RegEnumKeyExW
2536  *
2537  * @implemented
2538  */
2539 LONG
2540 WINAPI
2542  _In_ HKEY hKey,
2543  _In_ DWORD dwIndex,
2545  _Inout_ LPDWORD lpcbName,
2546  _Reserved_ LPDWORD lpReserved,
2547  _Out_opt_ LPWSTR lpClass,
2548  _Inout_opt_ LPDWORD lpcbClass,
2549  _Out_opt_ PFILETIME lpftLastWriteTime)
2550 {
2551  union
2552  {
2554  KEY_BASIC_INFORMATION Basic;
2555  } *KeyInfo;
2556 
2557  ULONG BufferSize;
2558  ULONG ResultSize;
2559  ULONG NameLength;
2560  ULONG ClassLength = 0;
2561  HANDLE KeyHandle;
2563  NTSTATUS Status;
2564 
2565  Status = MapDefaultKey(&KeyHandle,
2566  hKey);
2567  if (!NT_SUCCESS(Status))
2568  {
2569  return RtlNtStatusToDosError(Status);
2570  }
2571 
2572  if (IsHKCRKey(KeyHandle))
2573  {
2574  ErrorCode = EnumHKCRKey(
2575  KeyHandle,
2576  dwIndex,
2577  lpName,
2578  lpcbName,
2579  lpReserved,
2580  lpClass,
2581  lpcbClass,
2582  lpftLastWriteTime);
2583  ClosePredefKey(KeyHandle);
2584  return ErrorCode;
2585  }
2586 
2587  if (*lpcbName > 0)
2588  {
2589  NameLength = min (*lpcbName - 1, REG_MAX_NAME_SIZE) * sizeof (WCHAR);
2590  }
2591  else
2592  {
2593  NameLength = 0;
2594  }
2595 
2596  if (lpClass)
2597  {
2598  if (*lpcbClass > 0)
2599  {
2600  ClassLength = min (*lpcbClass - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
2601  }
2602  else
2603  {
2604  ClassLength = 0;
2605  }
2606 
2607  BufferSize = ((sizeof(KEY_NODE_INFORMATION) + NameLength + 3) & ~3) + ClassLength;
2608  }
2609  else
2610  {
2611  BufferSize = sizeof(KEY_BASIC_INFORMATION) + NameLength;
2612  }
2613 
2614  KeyInfo = RtlAllocateHeap(ProcessHeap,
2615  0,
2616  BufferSize);
2617  if (KeyInfo == NULL)
2618  {
2619  ErrorCode = ERROR_OUTOFMEMORY;
2620  goto Cleanup;
2621  }
2622 
2623  Status = NtEnumerateKey(KeyHandle,
2624  (ULONG)dwIndex,
2626  KeyInfo,
2627  BufferSize,
2628  &ResultSize);
2629  TRACE("NtEnumerateKey() returned status 0x%X\n", Status);
2630  if (!NT_SUCCESS(Status))
2631  {
2632  ErrorCode = RtlNtStatusToDosError (Status);
2633  }
2634  else
2635  {
2636  if (lpClass == NULL)
2637  {
2638  if (KeyInfo->Basic.NameLength > NameLength)
2639  {
2640  ErrorCode = ERROR_MORE_DATA;
2641  }
2642  else
2643  {
2644  RtlCopyMemory(lpName,
2645  KeyInfo->Basic.Name,
2646  KeyInfo->Basic.NameLength);
2647  *lpcbName = (DWORD)(KeyInfo->Basic.NameLength / sizeof(WCHAR));
2648  lpName[*lpcbName] = 0;
2649  }
2650  }
2651  else
2652  {
2653  if (KeyInfo->Node.NameLength > NameLength ||
2654  KeyInfo->Node.ClassLength > ClassLength)
2655  {
2656  ErrorCode = ERROR_MORE_DATA;
2657  }
2658  else
2659  {
2660  RtlCopyMemory(lpName,
2661  KeyInfo->Node.Name,
2662  KeyInfo->Node.NameLength);
2663  *lpcbName = KeyInfo->Node.NameLength / sizeof(WCHAR);
2664  lpName[*lpcbName] = 0;
2665  RtlCopyMemory(lpClass,
2666  (PVOID)((ULONG_PTR)KeyInfo->Node.Name + KeyInfo->Node.ClassOffset),
2667  KeyInfo->Node.ClassLength);
2668  *lpcbClass = (DWORD)(KeyInfo->Node.ClassLength / sizeof(WCHAR));
2669  lpClass[*lpcbClass] = 0;
2670  }
2671  }
2672 
2673  if (ErrorCode == ERROR_SUCCESS && lpftLastWriteTime != NULL)
2674  {
2675  if (lpClass == NULL)
2676  {
2677  lpftLastWriteTime->dwLowDateTime = KeyInfo->Basic.LastWriteTime.u.LowPart;
2678  lpftLastWriteTime->dwHighDateTime = KeyInfo->Basic.LastWriteTime.u.HighPart;
2679  }
2680  else
2681  {
2682  lpftLastWriteTime->dwLowDateTime = KeyInfo->Node.LastWriteTime.u.LowPart;
2683  lpftLastWriteTime->dwHighDateTime = KeyInfo->Node.LastWriteTime.u.HighPart;
2684  }
2685  }
2686  }
2687 
2688  RtlFreeHeap(ProcessHeap,
2689  0,
2690  KeyInfo);
2691 
2692 Cleanup:
2693  ClosePredefKey(KeyHandle);
2694 
2695  return ErrorCode;
2696 }
2697 
2698 
2699 /************************************************************************
2700  * RegEnumValueA
2701  *
2702  * @implemented
2703  */
2704 LONG WINAPI
2706  _In_ HKEY hKey,
2707  _In_ DWORD dwIndex,
2708  _Out_ LPSTR lpName,
2709  _Inout_ LPDWORD lpcbName,
2710  _Reserved_ LPDWORD lpdwReserved,
2711  _Out_opt_ LPDWORD lpdwType,
2712  _Out_opt_ LPBYTE lpData,
2713  _Inout_opt_ LPDWORD lpcbData)
2714 {
2715  WCHAR* NameBuffer;
2716  DWORD NameBufferSize, NameLength;
2717  LONG ErrorCode;
2718  DWORD LocalType = REG_NONE;
2719  BOOL NameOverflow = FALSE;
2720 
2721  /* Do parameter checks now, once and for all. */
2722  if (!lpName || !lpcbName)
2723  return ERROR_INVALID_PARAMETER;
2724 
2725  if ((lpData && !lpcbData) || lpdwReserved)
2726  return ERROR_INVALID_PARAMETER;
2727 
2728  /* Get the size of the buffer we must use for the first call to RegEnumValueW */
2729  ErrorCode = RegQueryInfoKeyW(
2730  hKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &NameBufferSize, NULL, NULL, NULL);
2731  if (ErrorCode != ERROR_SUCCESS)
2732  return ErrorCode;
2733 
2734  /* Add space for the null terminator */
2735  NameBufferSize++;
2736 
2737  /* Allocate the buffer for the unicode name */
2738  NameBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, NameBufferSize * sizeof(WCHAR));
2739  if (NameBuffer == NULL)
2740  {
2741  return ERROR_NOT_ENOUGH_MEMORY;
2742  }
2743 
2744  /*
2745  * This code calls RegEnumValueW twice, because we need to know the type of the enumerated value.
2746  * So for the first call, we check if we overflow on the name, as we have no way of knowing if this
2747  * is an overflow on the data or on the name during the the second call. So the first time, we make the
2748  * call with the supplied value. This is merdique, but this is how it is.
2749  */
2750  NameLength = *lpcbName;
2751  ErrorCode = RegEnumValueW(
2752  hKey,
2753  dwIndex,
2754  NameBuffer,
2755  &NameLength,
2756  NULL,
2757  &LocalType,
2758  NULL,
2759  NULL);
2760  if (ErrorCode != ERROR_SUCCESS)
2761  {
2762  if (ErrorCode == ERROR_MORE_DATA)
2763  NameOverflow = TRUE;
2764  else
2765  goto Exit;
2766  }
2767 
2768  if (is_string(LocalType) && lpcbData)
2769  {
2770  /* We must allocate a buffer to get the unicode data */
2771  DWORD DataBufferSize = *lpcbData * sizeof(WCHAR);
2772  WCHAR* DataBuffer = NULL;
2773  DWORD DataLength = *lpcbData;
2774  LPSTR DataStr = (LPSTR)lpData;
2775 
2776  if (lpData)
2777  DataBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, *lpcbData * sizeof(WCHAR));
2778 
2779  /* Do the real call */
2780  ErrorCode = RegEnumValueW(
2781  hKey,
2782  dwIndex,
2783  NameBuffer,
2784  &NameBufferSize,
2785  lpdwReserved,
2786  lpdwType,
2787  (LPBYTE)DataBuffer,
2788  &DataBufferSize);
2789 
2790  *lpcbData = DataBufferSize / sizeof(WCHAR);
2791 
2792  if (ErrorCode != ERROR_SUCCESS)
2793  {
2794  RtlFreeHeap(RtlGetProcessHeap(), 0, DataBuffer);
2795  goto Exit;
2796  }
2797 
2798  /* Copy the data whatever the error code is */
2799  if (lpData)
2800  {
2801  /* Do the data conversion */
2802  RtlUnicodeToMultiByteN(DataStr, DataLength, 0, DataBuffer, DataBufferSize);
2803  /* NULL-terminate if there is enough room */
2804  if ((DataLength > *lpcbData) && (DataStr[*lpcbData - 1] != '\0'))
2805  DataStr[*lpcbData] = '\0';
2806  }
2807 
2808  RtlFreeHeap(RtlGetProcessHeap(), 0, DataBuffer);
2809  }
2810  else
2811  {
2812  /* No data conversion needed. Do the call with provided buffers */
2813  ErrorCode = RegEnumValueW(
2814  hKey,
2815  dwIndex,
2816  NameBuffer,
2817  &NameBufferSize,
2818  lpdwReserved,
2819  lpdwType,
2820  lpData,
2821  lpcbData);
2822 
2823  if (ErrorCode != ERROR_SUCCESS)
2824  {
2825  goto Exit;
2826  }
2827  }
2828 
2829  if (NameOverflow)
2830  {
2831  ErrorCode = ERROR_MORE_DATA;
2832  goto Exit;
2833  }
2834 
2835  /* Convert the name string */
2836  RtlUnicodeToMultiByteN(lpName, *lpcbName, lpcbName, NameBuffer, NameBufferSize * sizeof(WCHAR));
2837  ((PSTR)lpName)[*lpcbName] = '\0';
2838 
2839 Exit:
2840  if (NameBuffer)
2841  RtlFreeHeap(RtlGetProcessHeap(), 0, NameBuffer);
2842 
2843  return ErrorCode;
2844 }
2845 
2846 
2847 /******************************************************************************
2848  * RegEnumValueW [ADVAPI32.@]
2849  * @implemented
2850  *
2851  * PARAMS
2852  * hkey [I] Handle to key to query
2853  * index [I] Index of value to query
2854  * value [O] Value string
2855  * val_count [I/O] Size of value buffer (in wchars)
2856  * reserved [I] Reserved
2857  * type [O] Type code
2858  * data [O] Value data
2859  * count [I/O] Size of data buffer (in bytes)
2860  *
2861  * RETURNS
2862  * Success: ERROR_SUCCESS
2863  * Failure: nonzero error code from Winerror.h
2864  */
2865 LONG
2866 WINAPI
2868  _In_ HKEY hKey,
2869  _In_ DWORD index,
2870  _Out_ LPWSTR value,
2871  _Inout_ PDWORD val_count,
2876 {
2877  HANDLE KeyHandle;
2878  NTSTATUS status;
2879  ULONG total_size;
2880  char buffer[256], *buf_ptr = buffer;
2882  static const int info_size = FIELD_OFFSET( KEY_VALUE_FULL_INFORMATION, Name );
2883 
2884  TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
2885  hKey, index, value, val_count, reserved, type, data, count );
2886 
2887  if (!value || !val_count)
2888  return ERROR_INVALID_PARAMETER;
2889 
2890  if ((data && !count) || reserved)
2891  return ERROR_INVALID_PARAMETER;
2892 
2893  status = MapDefaultKey(&KeyHandle, hKey);
2894  if (!NT_SUCCESS(status))
2895  {
2896  return RtlNtStatusToDosError(status);
2897  }
2898 
2899  if (IsHKCRKey(KeyHandle))
2900  {
2902  KeyHandle,
2903  index,
2904  value,
2905  val_count,
2906  reserved,
2907  type,
2908  data,
2909  count);
2910  ClosePredefKey(KeyHandle);
2911  return ErrorCode;
2912  }
2913 
2914  total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR);
2915  if (data) total_size += *count;
2916  total_size = min( sizeof(buffer), total_size );
2917 
2918  status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
2919  buffer, total_size, &total_size );
2920  if (status && (status != STATUS_BUFFER_OVERFLOW) && (status != STATUS_BUFFER_TOO_SMALL)) goto done;
2921 
2922  if (value || data)
2923  {
2924  /* retry with a dynamically allocated buffer */
2925  while ((status == STATUS_BUFFER_OVERFLOW) || (status == STATUS_BUFFER_TOO_SMALL))
2926  {
2927  if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
2928  if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
2929  {
2930  status = ERROR_NOT_ENOUGH_MEMORY;
2931  goto done;
2932  }
2933  info = (KEY_VALUE_FULL_INFORMATION *)buf_ptr;
2934  status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
2935  buf_ptr, total_size, &total_size );
2936  }
2937 
2938  if (status) goto done;
2939 
2940  if (value)
2941  {
2942  if (info->NameLength/sizeof(WCHAR) >= *val_count)
2943  {
2944  status = STATUS_BUFFER_OVERFLOW;
2945  goto overflow;
2946  }
2947  memcpy( value, info->Name, info->NameLength );
2948  *val_count = info->NameLength / sizeof(WCHAR);
2949  value[*val_count] = 0;
2950  }
2951 
2952  if (data)
2953  {
2954  if (info->DataLength > *count)
2955  {
2956  status = STATUS_BUFFER_OVERFLOW;
2957  goto overflow;
2958  }
2959  memcpy( data, buf_ptr + info->DataOffset, info->DataLength );
2960  if (is_string(info->Type) && info->DataLength <= *count - sizeof(WCHAR))
2961  {
2962  /* if the type is REG_SZ and data is not 0-terminated
2963  * and there is enough space in the buffer NT appends a \0 */
2964  WCHAR *ptr = (WCHAR *)(data + info->DataLength);
2965  if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
2966  }
2967  }
2968  }
2969  else status = STATUS_SUCCESS;
2970 
2971  overflow:
2972  if (type) *type = info->Type;
2973  if (count) *count = info->DataLength;
2974 
2975  done:
2976  if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
2977  ClosePredefKey(KeyHandle);
2978  return RtlNtStatusToDosError(status);
2979 }
2980 
2981 
2982 /************************************************************************
2983  * RegFlushKey
2984  *
2985  * @implemented
2986  */
2987 LONG WINAPI
2989 {
2990  HANDLE KeyHandle;
2991  NTSTATUS Status;
2992 
2993  if (hKey == HKEY_PERFORMANCE_DATA)
2994  {
2995  return ERROR_SUCCESS;
2996  }
2997 
2998  Status = MapDefaultKey(&KeyHandle,
2999  hKey);
3000  if (!NT_SUCCESS(Status))
3001  {
3002  return RtlNtStatusToDosError(Status);
3003  }
3004 
3005  Status = NtFlushKey(KeyHandle);
3006 
3007  ClosePredefKey(KeyHandle);
3008 
3009  if (!NT_SUCCESS(Status))
3010  {
3011  return RtlNtStatusToDosError(Status);
3012  }
3013 
3014  return ERROR_SUCCESS;
3015 }
3016 
3017 
3018 /************************************************************************
3019  * RegGetKeySecurity
3020  *
3021  * @implemented
3022  */
3023 LONG WINAPI
3026  PSECURITY_DESCRIPTOR pSecurityDescriptor,
3027  LPDWORD lpcbSecurityDescriptor)
3028 {
3029  HANDLE KeyHandle;
3030  NTSTATUS Status;
3031 
3032  if (hKey == HKEY_PERFORMANCE_DATA)
3033  {
3034  return ERROR_INVALID_HANDLE;
3035  }
3036 
3037  Status = MapDefaultKey(&KeyHandle,
3038  hKey);
3039  if (!NT_SUCCESS(Status))
3040  {
3041  TRACE("MapDefaultKey() failed (Status %lx)\n", Status);
3042  return RtlNtStatusToDosError(Status);
3043  }
3044 
3045  Status = NtQuerySecurityObject(KeyHandle,
3046  SecurityInformation,
3047  pSecurityDescriptor,
3048  *lpcbSecurityDescriptor,
3049  lpcbSecurityDescriptor);
3050 
3051  ClosePredefKey(KeyHandle);
3052 
3053  if (!NT_SUCCESS(Status))
3054  {
3055  WARN("NtQuerySecurityObject() failed (Status %lx)\n", Status);
3056  return RtlNtStatusToDosError(Status);
3057  }
3058 
3059  return ERROR_SUCCESS;
3060 }
3061 
3062 
3063 /************************************************************************
3064  * RegLoadKeyA
3065  *
3066  * @implemented
3067  */
3068 LONG WINAPI
3070  LPCSTR lpSubKey,
3071  LPCSTR lpFile)
3072 {
3075  LONG ErrorCode;
3076 
3077  RtlInitEmptyUnicodeString(&KeyName, NULL, 0);
3078  RtlInitEmptyUnicodeString(&FileName, NULL, 0);
3079 
3080  if (lpSubKey)
3081  {
3082  if (!RtlCreateUnicodeStringFromAsciiz(&KeyName, lpSubKey))
3083  {
3084  ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
3085  goto Exit;
3086  }
3087  }
3088 
3089  if (lpFile)
3090  {
3091  if (!RtlCreateUnicodeStringFromAsciiz(&FileName, lpFile))
3092  {
3093  ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
3094  goto Exit;
3095  }
3096  }
3097 
3098  ErrorCode = RegLoadKeyW(hKey,
3099  KeyName.Buffer,
3100  FileName.Buffer);
3101 
3102 Exit:
3103  RtlFreeUnicodeString(&FileName);
3104  RtlFreeUnicodeString(&KeyName);
3105 
3106  return ErrorCode;
3107 }
3108 
3109 
3110 /************************************************************************
3111  * RegLoadKeyW
3112  *
3113  * @implemented
3114  */
3115 LONG WINAPI
3117  LPCWSTR lpSubKey,
3118  LPCWSTR lpFile)
3119 {
3120  OBJECT_ATTRIBUTES FileObjectAttributes;
3121  OBJECT_ATTRIBUTES KeyObjectAttributes;
3124  HANDLE KeyHandle;
3125  NTSTATUS Status;
3127 
3128  if (hKey == HKEY_PERFORMANCE_DATA)
3129  {
3130  return ERROR_INVALID_HANDLE;
3131  }
3132 
3133  Status = MapDefaultKey(&KeyHandle,
3134  hKey);
3135  if (!NT_SUCCESS(Status))
3136  {
3137  return RtlNtStatusToDosError(Status);
3138  }
3139 
3140  if (!RtlDosPathNameToNtPathName_U(lpFile,
3141  &FileName,
3142  NULL,
3143  NULL))
3144  {
3145  ErrorCode = ERROR_BAD_PATHNAME;
3146  goto Cleanup;
3147  }
3148 
3149  InitializeObjectAttributes(&FileObjectAttributes,
3150  &FileName,
3152  NULL,
3153  NULL);
3154 
3155  RtlInitUnicodeString(&KeyName,
3156  (LPWSTR)lpSubKey);
3157 
3158  InitializeObjectAttributes(&KeyObjectAttributes,
3159  &KeyName,
3161  KeyHandle,
3162  NULL);
3163 
3164  Status = NtLoadKey(&KeyObjectAttributes,
3165  &FileObjectAttributes);
3166 
3167  RtlFreeHeap(RtlGetProcessHeap(),
3168  0,
3169  FileName.Buffer);
3170 
3171  if (!NT_SUCCESS(Status))
3172  {
3173  ErrorCode = RtlNtStatusToDosError(Status);
3174  goto Cleanup;
3175  }
3176 
3177 Cleanup:
3178  ClosePredefKey(KeyHandle);
3179 
3180  return ErrorCode;
3181 }
3182 
3183 
3184 /************************************************************************
3185  * RegNotifyChangeKeyValue
3186  *
3187  * @unimplemented
3188  */
3189 LONG WINAPI
3191  BOOL bWatchSubtree,
3192  DWORD dwNotifyFilter,
3193  HANDLE hEvent,
3194  BOOL fAsynchronous)
3195 {
3197  HANDLE KeyHandle;
3198  NTSTATUS Status;
3200 
3201  if (hKey == HKEY_PERFORMANCE_DATA)
3202  {
3203  return ERROR_INVALID_HANDLE;
3204  }
3205 
3206  if ((fAsynchronous != FALSE) && (hEvent == NULL))
3207  {
3208  return ERROR_INVALID_PARAMETER;
3209  }
3210 
3211  Status = MapDefaultKey(&KeyHandle,
3212  hKey);
3213  if (!NT_SUCCESS(Status))
3214  {
3215  return RtlNtStatusToDosError(Status);
3216  }
3217 
3218  /* FIXME: Remote key handles must fail */
3219 
3220  Status = NtNotifyChangeKey(KeyHandle,
3221  hEvent,
3222  0,
3223  0,
3224  &IoStatusBlock,
3225  dwNotifyFilter,
3226  bWatchSubtree,
3227  0,
3228  0,
3229  fAsynchronous);
3230  if (!NT_SUCCESS(Status) && Status != STATUS_TIMEOUT)
3231  {
3232  ErrorCode = RtlNtStatusToDosError(Status);
3233  }
3234 
3235  ClosePredefKey(KeyHandle);
3236 
3237  return ErrorCode;
3238 }
3239 
3240 
3241 /************************************************************************
3242  * RegOpenCurrentUser
3243  *
3244  * @implemented
3245  */
3246 LONG WINAPI
3248  OUT PHKEY phkResult)
3249 {
3250  NTSTATUS Status;
3251 
3252  Status = RtlOpenCurrentUser((ACCESS_MASK)samDesired,
3253  (PHANDLE)phkResult);
3254  if (!NT_SUCCESS(Status))
3255  {
3256  /* NOTE - don't set the last error code! just return the error! */
3257  return RtlNtStatusToDosError(Status);
3258  }
3259 
3260  return ERROR_SUCCESS;
3261 }
3262 
3263 
3264 /************************************************************************
3265  * RegOpenKeyA
3266  *
3267  * 20050503 Fireball - imported from WINE
3268  *
3269  * @implemented
3270  */
3271 LONG WINAPI
3273  LPCSTR lpSubKey,
3274  PHKEY phkResult)
3275 {
3276  TRACE("RegOpenKeyA hKey 0x%x lpSubKey %s phkResult %p\n",
3277  hKey, lpSubKey, phkResult);
3278 
3279  if (!phkResult)
3280  return ERROR_INVALID_PARAMETER;
3281 
3282  if (!hKey && lpSubKey && phkResult)
3283  {
3284  return ERROR_INVALID_HANDLE;
3285  }
3286 
3287  if (!lpSubKey || !*lpSubKey)
3288  {
3289  *phkResult = hKey;
3290  return ERROR_SUCCESS;
3291  }
3292 
3293  return RegOpenKeyExA(hKey,
3294  lpSubKey,
3295  0,
3297  phkResult);
3298 }
3299 
3300 
3301 /************************************************************************
3302  * RegOpenKeyW
3303  *
3304  * 19981101 Ariadne
3305  * 19990525 EA
3306  * 20050503 Fireball - imported from WINE
3307  *
3308  * @implemented
3309  */
3310 LONG WINAPI
3312  LPCWSTR lpSubKey,
3313  PHKEY phkResult)
3314 {
3315  TRACE("RegOpenKeyW hKey 0x%x lpSubKey %S phkResult %p\n",
3316  hKey, lpSubKey, phkResult);
3317 
3318  if (!phkResult)
3319  return ERROR_INVALID_PARAMETER;
3320 
3321  if (!hKey && lpSubKey && phkResult)
3322  {
3323  return ERROR_INVALID_HANDLE;
3324  }
3325 
3326  if (!lpSubKey || !*lpSubKey)
3327  {
3328  *phkResult = hKey;
3329  return ERROR_SUCCESS;
3330  }
3331 
3332  return RegOpenKeyExW(hKey,
3333  lpSubKey,
3334  0,
3336  phkResult);
3337 }
3338 
3339 
3340 /************************************************************************
3341  * RegOpenKeyExA
3342  *
3343  * @implemented
3344  */
3345 LONG WINAPI
3347  _In_ HKEY hKey,
3348  _In_ LPCSTR lpSubKey,
3349  _In_ DWORD ulOptions,
3350  _In_ REGSAM samDesired,
3351  _Out_ PHKEY phkResult)
3352 {
3353  UNICODE_STRING SubKeyString;
3354  LONG ErrorCode;
3355 
3356  TRACE("RegOpenKeyExA hKey 0x%x lpSubKey %s ulOptions 0x%x samDesired 0x%x phkResult %p\n",
3357  hKey, lpSubKey, ulOptions, samDesired, phkResult);
3358 
3359  if (lpSubKey)
3360  {
3361  if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyString, lpSubKey))
3362  return ERROR_NOT_ENOUGH_MEMORY;
3363  }
3364  else
3365  RtlInitEmptyUnicodeString(&SubKeyString, NULL, 0);
3366 
3367  ErrorCode = RegOpenKeyExW(hKey, SubKeyString.Buffer, ulOptions, samDesired, phkResult);
3368 
3369  RtlFreeUnicodeString(&SubKeyString);
3370 
3371  return ErrorCode;
3372 }
3373 
3374 
3375 /************************************************************************
3376  * RegOpenKeyExW
3377  *
3378  * @implemented
3379  */
3380 LONG WINAPI
3382  LPCWSTR lpSubKey,
3383  DWORD ulOptions,
3384  REGSAM samDesired,
3385  PHKEY phkResult)
3386 {
3388  UNICODE_STRING SubKeyString;
3389  HANDLE KeyHandle;
3390  NTSTATUS Status;
3393 
3394  TRACE("RegOpenKeyExW hKey 0x%x lpSubKey %S ulOptions 0x%x samDesired 0x%x phkResult %p\n",
3395  hKey, lpSubKey, ulOptions, samDesired, phkResult);
3396  if (!phkResult)
3397  {
3398  return ERROR_INVALID_PARAMETER;
3399  }
3400 
3401  Status = MapDefaultKey(&KeyHandle, hKey);
3402  if (!NT_SUCCESS(Status))
3403  {
3404  return RtlNtStatusToDosError(Status);
3405  }
3406 
3407  if (IsHKCRKey(KeyHandle))
3408  {
3409  ErrorCode = OpenHKCRKey(KeyHandle, lpSubKey, ulOptions, samDesired, phkResult);
3410  ClosePredefKey(KeyHandle);
3411  return ErrorCode;
3412  }
3413 
3414  if (ulOptions & REG_OPTION_OPEN_LINK)
3415  Attributes |= OBJ_OPENLINK;
3416 
3417  if (lpSubKey != NULL)
3418  RtlInitUnicodeString(&SubKeyString, (LPWSTR)lpSubKey);
3419  else
3420  RtlInitUnicodeString(&SubKeyString, (LPWSTR)L"");
3421 
3422  InitializeObjectAttributes(&ObjectAttributes,
3423  &SubKeyString,
3424  Attributes,
3425  KeyHandle,
3426  NULL);
3427 
3428  Status = NtOpenKey((PHANDLE)phkResult,
3429  samDesired,
3430  &ObjectAttributes);
3431 
3432  if (Status == STATUS_DATATYPE_MISALIGNMENT)
3433  {
3434  HANDLE hAligned;
3435  UNICODE_STRING AlignedString;
3436 
3438  &SubKeyString,
3439  &AlignedString);
3440  if (NT_SUCCESS(Status))
3441  {
3442  /* Try again with aligned parameters */
3443  InitializeObjectAttributes(&ObjectAttributes,
3444  &AlignedString,
3445  Attributes,
3446  KeyHandle,
3447  NULL);
3448 
3449  Status = NtOpenKey(&hAligned,
3450  samDesired,
3451  &ObjectAttributes);
3452 
3453  RtlFreeUnicodeString(&AlignedString);
3454 
3455  if (NT_SUCCESS(Status))
3456  *phkResult = hAligned;
3457  }
3458  else
3459  {
3460  /* Restore the original error */
3462  }
3463  }
3464 
3465  if (!NT_SUCCESS(Status))
3466  {
3467  ErrorCode = RtlNtStatusToDosError(Status);
3468  }
3469 
3470 
3471  ClosePredefKey(KeyHandle);
3472 
3473  return ErrorCode;
3474 }
3475 
3476 
3477 /************************************************************************
3478  * RegOpenUserClassesRoot
3479  *
3480  * @implemented
3481  */
3482 LONG WINAPI
3484  IN DWORD dwOptions,
3485  IN REGSAM samDesired,
3486  OUT PHKEY phkResult)
3487 {
3488  const WCHAR UserClassesKeyPrefix[] = L"\\Registry\\User\\";
3489  const WCHAR UserClassesKeySuffix[] = L"_Classes";
3490  PTOKEN_USER TokenUserData;
3492  UNICODE_STRING UserSidString, UserClassesKeyRoot;
3494  NTSTATUS Status;
3495 
3496  /* check parameters */
3497  if (hToken == NULL || dwOptions != 0 || phkResult == NULL)
3498  {
3499  return ERROR_INVALID_PARAMETER;
3500  }
3501 
3502  /*
3503  * Get the user sid from the token
3504  */
3505 
3506 ReadTokenSid:
3507  /* determine how much memory we need */
3508  Status = NtQueryInformationToken(hToken,
3509  TokenUser,
3510  NULL,
3511  0,
3512  &RequiredLength);
3513  if (!NT_SUCCESS(Status) && (Status != STATUS_BUFFER_TOO_SMALL))
3514  {
3515  /* NOTE - as opposed to all other registry functions windows does indeed
3516  change the last error code in case the caller supplied a invalid
3517  handle for example! */
3518  return RtlNtStatusToDosError(Status);
3519  }
3520  RegInitialize(); /* HACK until delay-loading is implemented */
3521  TokenUserData = RtlAllocateHeap(ProcessHeap,
3522  0,
3523  RequiredLength);
3524  if (TokenUserData == NULL)
3525  {
3526  return ERROR_NOT_ENOUGH_MEMORY;
3527  }
3528 
3529  /* attempt to read the information */
3530  Status = NtQueryInformationToken(hToken,
3531  TokenUser,
3532  TokenUserData,
3533  RequiredLength,
3534  &RequiredLength);
3535  if (!NT_SUCCESS(Status))
3536  {
3537  RtlFreeHeap(ProcessHeap,
3538  0,
3539  TokenUserData);
3540  if (Status == STATUS_BUFFER_TOO_SMALL)
3541  {
3542  /* the information appears to have changed?! try again */
3543  goto ReadTokenSid;
3544  }
3545 
3546  /* NOTE - as opposed to all other registry functions windows does indeed
3547  change the last error code in case the caller supplied a invalid
3548  handle for example! */
3549  return RtlNtStatusToDosError(Status);
3550  }
3551 
3552  /*
3553  * Build the absolute path for the user's registry in the form
3554  * "\Registry\User<SID>_Classes"
3555  */
3556  Status = RtlConvertSidToUnicodeString(&UserSidString,
3557  TokenUserData->User.Sid,
3558  TRUE);
3559 
3560  /* we don't need the user data anymore, free it */
3561  RtlFreeHeap(ProcessHeap,
3562  0,
3563  TokenUserData);
3564 
3565  if (!NT_SUCCESS(Status))
3566  {
3567  return RtlNtStatusToDosError(Status);
3568  }
3569 
3570  /* allocate enough memory for the entire key string */
3571  UserClassesKeyRoot.Length = 0;
3572  UserClassesKeyRoot.MaximumLength = UserSidString.Length +
3573  sizeof(UserClassesKeyPrefix) +
3574  sizeof(UserClassesKeySuffix);
3575  UserClassesKeyRoot.Buffer = RtlAllocateHeap(ProcessHeap,
3576  0,
3577  UserClassesKeyRoot.MaximumLength);
3578  if (UserClassesKeyRoot.Buffer == NULL)
3579  {
3580  RtlFreeUnicodeString(&UserSidString);
3581  return RtlNtStatusToDosError(Status);
3582  }
3583 
3584  /* build the string */
3585  RtlAppendUnicodeToString(&UserClassesKeyRoot,
3586  UserClassesKeyPrefix);
3587  RtlAppendUnicodeStringToString(&UserClassesKeyRoot,
3588  &UserSidString);
3589  RtlAppendUnicodeToString(&UserClassesKeyRoot,
3590  UserClassesKeySuffix);
3591 
3592  TRACE("RegOpenUserClassesRoot: Absolute path: %wZ\n", &UserClassesKeyRoot);
3593 
3594  /*
3595  * Open the key
3596  */
3597  InitializeObjectAttributes(&ObjectAttributes,
3598  &UserClassesKeyRoot,
3600  NULL,
3601  NULL);
3602 
3603  Status = NtOpenKey((PHANDLE)phkResult,
3604  samDesired,
3605  &ObjectAttributes);
3606 
3607  RtlFreeUnicodeString(&UserSidString);
3608  RtlFreeUnicodeString(&UserClassesKeyRoot);
3609 
3610  if (!NT_SUCCESS(Status))
3611  {
3612  return RtlNtStatusToDosError(Status);
3613  }
3614 
3615  return ERROR_SUCCESS;
3616 }
3617 
3618 
3619 /************************************************************************
3620  * RegQueryInfoKeyA
3621  *
3622  * @implemented
3623  */
3624 LONG WINAPI
3626  LPSTR lpClass,
3627  LPDWORD lpcClass,
3628  LPDWORD lpReserved,
3629  LPDWORD lpcSubKeys,
3630  LPDWORD lpcMaxSubKeyLen,
3631  LPDWORD lpcMaxClassLen,
3632  LPDWORD lpcValues,
3633  LPDWORD lpcMaxValueNameLen,
3634  LPDWORD lpcMaxValueLen,
3635  LPDWORD lpcbSecurityDescriptor,
3636  PFILETIME lpftLastWriteTime)
3637 {
3638  WCHAR ClassName[MAX_PATH];
3641  LONG ErrorCode;
3642  NTSTATUS Status;
3643  DWORD cClass = 0;
3644 
3645  if ((lpClass) && (!lpcClass))
3646  {
3647  return ERROR_INVALID_PARAMETER;
3648  }
3649 
3650  RtlInitUnicodeString(&UnicodeString,
3651  NULL);
3652  if (lpClass != NULL)
3653  {
3654  RtlInitEmptyUnicodeString(&UnicodeString,
3655  ClassName,
3656  sizeof(ClassName));
3657  cClass = sizeof(ClassName) / sizeof(WCHAR);
3658  }
3659 
3660  ErrorCode = RegQueryInfoKeyW(hKey,
3661  UnicodeString.Buffer,
3662  &cClass,
3663  lpReserved,
3664  lpcSubKeys,
3665  lpcMaxSubKeyLen,
3666  lpcMaxClassLen,
3667  lpcValues,
3668  lpcMaxValueNameLen,
3669  lpcMaxValueLen,
3670  lpcbSecurityDescriptor,
3671  lpftLastWriteTime);
3672  if ((ErrorCode == ERROR_SUCCESS) && (lpClass != NULL))
3673  {
3674  if (*lpcClass == 0)
3675  {
3676  return ErrorCode;
3677  }
3678 
3679  RtlInitEmptyAnsiString(&AnsiString, lpClass, *lpcClass);
3680  UnicodeString.Length = cClass * sizeof(WCHAR);
3681  Status = RtlUnicodeStringToAnsiString(&AnsiString,
3682  &UnicodeString,
3683  FALSE);
3684  ErrorCode = RtlNtStatusToDosError(Status);
3685  cClass = AnsiString.Length;
3686  lpClass[cClass] = ANSI_NULL;
3687  }
3688 
3689  if (lpcClass != NULL)
3690  {
3691  *lpcClass = cClass;
3692  }
3693 
3694  return ErrorCode;
3695 }
3696 
3697 
3698 /************************************************************************
3699  * RegQueryInfoKeyW
3700  *
3701  * @implemented
3702  */
3703 LONG WINAPI
3705  LPWSTR lpClass,
3706  LPDWORD lpcClass,
3707  LPDWORD lpReserved,
3708  LPDWORD lpcSubKeys,
3709  LPDWORD lpcMaxSubKeyLen,
3710  LPDWORD lpcMaxClassLen,
3711  LPDWORD lpcValues,
3712  LPDWORD lpcMaxValueNameLen,
3713  LPDWORD lpcMaxValueLen,
3714  LPDWORD lpcbSecurityDescriptor,
3715  PFILETIME lpftLastWriteTime)
3716 {
3717  KEY_FULL_INFORMATION FullInfoBuffer;
3718  PKEY_FULL_INFORMATION FullInfo;
3719  ULONG FullInfoSize;
3720  ULONG ClassLength = 0;
3721  HANDLE KeyHandle;
3722  NTSTATUS Status;
3723  ULONG Length;
3725 
3726  if ((lpClass) && (!lpcClass))
3727  {
3728  return ERROR_INVALID_PARAMETER;
3729  }
3730 
3731  Status = MapDefaultKey(&KeyHandle,
3732  hKey);
3733  if (!NT_SUCCESS(Status))
3734  {
3735  return RtlNtStatusToDosError(Status);
3736  }
3737 
3738  if (lpClass != NULL)
3739  {
3740  if (*lpcClass > 0)
3741  {
3742  ClassLength = min(*lpcClass - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
3743  }
3744  else
3745  {
3746  ClassLength = 0;
3747  }
3748 
3749  FullInfoSize = sizeof(KEY_FULL_INFORMATION) + ((ClassLength + 3) & ~3);
3750  FullInfo = RtlAllocateHeap(ProcessHeap,
3751  0,
3752  FullInfoSize);
3753  if (FullInfo == NULL)
3754  {
3755  ErrorCode = ERROR_OUTOFMEMORY;
3756  goto Cleanup;
3757  }
3758  }
3759  else
3760  {
3761  FullInfoSize = sizeof(KEY_FULL_INFORMATION);
3762  FullInfo = &FullInfoBuffer;
3763  }
3764 
3765  if (lpcbSecurityDescriptor != NULL)
3766  *lpcbSecurityDescriptor = 0;
3767 
3768  Status = NtQueryKey(KeyHandle,
3770  FullInfo,
3771  FullInfoSize,
3772  &Length);
3773  TRACE("NtQueryKey() returned status 0x%X\n", Status);
3774  if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
3775  {
3776  ErrorCode = RtlNtStatusToDosError(Status);
3777  goto Cleanup;
3778  }
3779 
3780  TRACE("SubKeys %d\n", FullInfo->SubKeys);
3781  if (lpcSubKeys != NULL)
3782  {
3783  *lpcSubKeys = FullInfo->SubKeys;
3784  }
3785 
3786  TRACE("MaxNameLen %lu\n", FullInfo->MaxNameLen);
3787  if (lpcMaxSubKeyLen != NULL)
3788  {
3789  *lpcMaxSubKeyLen = FullInfo->MaxNameLen / sizeof(WCHAR);
3790  }
3791 
3792  TRACE("MaxClassLen %lu\n", FullInfo->MaxClassLen);
3793  if (lpcMaxClassLen != NULL)
3794  {
3795  *lpcMaxClassLen = FullInfo->MaxClassLen / sizeof(WCHAR);
3796  }
3797 
3798  TRACE("Values %lu\n", FullInfo->Values);
3799  if (lpcValues != NULL)
3800  {
3801  *lpcValues = FullInfo->Values;
3802  }
3803 
3804  TRACE("MaxValueNameLen %lu\n", FullInfo->MaxValueNameLen);
3805  if (lpcMaxValueNameLen != NULL)
3806  {
3807  *lpcMaxValueNameLen = FullInfo->MaxValueNameLen / sizeof(WCHAR);
3808  }
3809 
3810  TRACE("MaxValueDataLen %lu\n", FullInfo->MaxValueDataLen);
3811  if (lpcMaxValueLen != NULL)
3812  {
3813  *lpcMaxValueLen = FullInfo->MaxValueDataLen;
3814  }
3815 
3816  if (lpcbSecurityDescriptor != NULL)
3817  {
3818  Status = NtQuerySecurityObject(KeyHandle,
3822  NULL,
3823  0,
3824  lpcbSecurityDescriptor);
3825  TRACE("NtQuerySecurityObject() returned status 0x%X\n", Status);
3826  }
3827 
3828  if (lpftLastWriteTime != NULL)
3829  {
3830  lpftLastWriteTime->dwLowDateTime = FullInfo->LastWriteTime.u.LowPart;
3831  lpftLastWriteTime->dwHighDateTime = FullInfo->LastWriteTime.u.HighPart;
3832  }
3833 
3834  if (lpClass != NULL)
3835  {
3836  if (*lpcClass == 0)
3837  {
3838  goto Cleanup;
3839  }
3840 
3841  if (FullInfo->ClassLength > ClassLength)
3842  {
3843  ErrorCode = ERROR_INSUFFICIENT_BUFFER;
3844  }
3845  else
3846  {
3847  RtlCopyMemory(lpClass,
3848  FullInfo->Class,
3849  FullInfo->ClassLength);
3850  lpClass[FullInfo->ClassLength / sizeof(WCHAR)] = UNICODE_NULL;
3851  }
3852  }
3853 
3854  if (lpcClass != NULL)
3855  {
3856  *lpcClass = FullInfo->ClassLength / sizeof(WCHAR);
3857  }
3858 
3859 Cleanup:
3860  if (lpClass != NULL)
3861  {
3862  RtlFreeHeap(ProcessHeap,
3863  0,
3864  FullInfo);
3865  }
3866 
3867  ClosePredefKey(KeyHandle);
3868 
3869  return ErrorCode;
3870 }
3871 
3872 
3873 /************************************************************************
3874  * RegQueryMultipleValuesA
3875  *
3876  * @implemented
3877  */
3878 LONG WINAPI
3880  PVALENTA val_list,
3881  DWORD num_vals,
3882  LPSTR lpValueBuf,
3883  LPDWORD ldwTotsize)
3884 {
3885  ULONG i;
3886  DWORD maxBytes = *ldwTotsize;
3887  LPSTR bufptr = (LPSTR)lpValueBuf;
3888  LONG ErrorCode;
3889 
3890  if (maxBytes >= (1024*1024))
3891  return ERROR_MORE_DATA;
3892 
3893  *ldwTotsize = 0;
3894 
3895  TRACE("RegQueryMultipleValuesA(%p,%p,%ld,%p,%p=%ld)\n",
3896  hKey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize);
3897 
3898  for (i = 0; i < num_vals; i++)
3899  {
3900  val_list[i].ve_valuelen = 0;
3901  ErrorCode = RegQueryValueExA(hKey,
3902  val_list[i].ve_valuename,
3903  NULL,
3904  NULL,
3905  NULL,
3906  &val_list[i].ve_valuelen);
3907  if (ErrorCode != ERROR_SUCCESS)
3908  {
3909  return ErrorCode;
3910  }
3911 
3912  if (lpValueBuf != NULL && *ldwTotsize + val_list[i].ve_valuelen <= maxBytes)
3913  {
3914  ErrorCode = RegQueryValueExA(hKey,
3915  val_list[i].ve_valuename,
3916  NULL,
3917  &val_list[i].ve_type,
3918  (LPBYTE)bufptr,
3919  &val_list[i].ve_valuelen);
3920  if (ErrorCode != ERROR_SUCCESS)
3921  {
3922  return ErrorCode;
3923  }
3924 
3925  val_list[i].ve_valueptr = (DWORD_PTR)bufptr;
3926 
3927  bufptr += val_list[i].ve_valuelen;
3928  }
3929 
3930  *ldwTotsize += val_list[i].ve_valuelen;
3931  }
3932 
3933  return (lpValueBuf != NULL && *ldwTotsize <= maxBytes) ? ERROR_SUCCESS : ERROR_MORE_DATA;
3934 }
3935 
3936 
3937 /************************************************************************
3938  * RegQueryMultipleValuesW
3939  *
3940  * @implemented
3941  */
3942 LONG WINAPI
3944  PVALENTW val_list,
3945  DWORD num_vals,
3946  LPWSTR lpValueBuf,
3947  LPDWORD ldwTotsize)
3948 {
3949  ULONG i;
3950  DWORD maxBytes = *ldwTotsize;
3951  LPSTR bufptr = (LPSTR)lpValueBuf;
3952  LONG ErrorCode;
3953 
3954  if (maxBytes >= (1024*1024))
3955  return ERROR_MORE_DATA;
3956 
3957  *ldwTotsize = 0;
3958 
3959  TRACE("RegQueryMultipleValuesW(%p,%p,%ld,%p,%p=%ld)\n",
3960  hKey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize);
3961 
3962  for (i = 0; i < num_vals; i++)
3963  {
3964  val_list[i].ve_valuelen = 0;
3965  ErrorCode = RegQueryValueExW(hKey,
3966  val_list[i].ve_valuename,
3967  NULL,
3968  NULL,
3969  NULL,
3970  &val_list[i].ve_valuelen);
3971  if (ErrorCode != ERROR_SUCCESS)
3972  {
3973  return ErrorCode;
3974  }
3975 
3976  if (lpValueBuf != NULL && *ldwTotsize + val_list[i].ve_valuelen <= maxBytes)
3977  {
3978  ErrorCode = RegQueryValueExW(hKey,
3979  val_list[i].ve_valuename,
3980  NULL,
3981  &val_list[i].ve_type,
3982  (LPBYTE)bufptr,
3983  &val_list[i].ve_valuelen);
3984  if (ErrorCode != ERROR_SUCCESS)
3985  {
3986  return ErrorCode;
3987  }
3988 
3989  val_list[i].ve_valueptr = (DWORD_PTR)bufptr;
3990 
3991  bufptr += val_list[i].ve_valuelen;
3992  }
3993 
3994  *ldwTotsize += val_list[i].ve_valuelen;
3995  }
3996 
3997  return (lpValueBuf != NULL && *ldwTotsize <= maxBytes) ? ERROR_SUCCESS : ERROR_MORE_DATA;
3998 }
3999 
4000 
4001 /************************************************************************
4002  * RegQueryReflectionKey
4003  *
4004  * @unimplemented
4005  */
4006 LONG WINAPI
4008  OUT BOOL* bIsReflectionDisabled)
4009 {
4010  FIXME("RegQueryReflectionKey(0x%p, 0x%p) UNIMPLEMENTED!\n",
4011  hBase, bIsReflectionDisabled);
4013 }
4014 
4015 
4016 /******************************************************************************
4017  * RegQueryValueExA [ADVAPI32.@]
4018  *
4019  * Get the type and contents of a specified value under with a key.
4020  *
4021  * PARAMS
4022  * hkey [I] Handle of the key to query
4023  * name [I] Name of value under hkey to query
4024  * reserved [I] Reserved - must be NULL
4025  * type [O] Destination for the value type, or NULL if not required
4026  * data [O] Destination for the values contents, or NULL if not required
4027  * count [I/O] Size of data, updated with the number of bytes returned
4028  *
4029  * RETURNS
4030  * Success: ERROR_SUCCESS. *count is updated with the number of bytes copied to data.
4031  * Failure: ERROR_INVALID_HANDLE, if hkey is invalid.
4032  * ERROR_INVALID_PARAMETER, if any other parameter is invalid.
4033  * ERROR_MORE_DATA, if on input *count is too small to hold the contents.
4034  *
4035  * NOTES
4036  * MSDN states that if data is too small it is partially filled. In reality
4037  * it remains untouched.
4038  */
4039 LONG
4040 WINAPI
4042  _In_ HKEY hkeyorg,
4043  _In_ LPCSTR name,
4048 {
4050  DWORD DataLength;
4051  DWORD ErrorCode;
4052  DWORD BufferSize = 0;
4053  WCHAR* Buffer;
4054  CHAR* DataStr = (CHAR*)data;
4055  DWORD LocalType;
4056 
4057  /* Validate those parameters, the rest will be done with the first RegQueryValueExW call */
4058  if ((data && !count) || reserved)
4059  return ERROR_INVALID_PARAMETER;
4060 
4061  if (name)
4062  {
4063  if (!RtlCreateUnicodeStringFromAsciiz(&nameW, name))
4064  return ERROR_NOT_ENOUGH_MEMORY;
4065  }
4066  else
4067  RtlInitEmptyUnicodeString(&nameW, NULL, 0);
4068 
4069  ErrorCode = RegQueryValueExW(hkeyorg, nameW.Buffer, NULL, &LocalType, NULL, &BufferSize);
4070  if (ErrorCode != ERROR_SUCCESS)
4071  {
4072  if ((!data) && count)
4073  *count = 0;
4074  RtlFreeUnicodeString(&nameW);
4075  return ErrorCode;
4076  }
4077 
4078  /* See if we can directly handle the call without caring for conversion */
4079  if (!is_string(LocalType) || !count)
4080  {
4081  ErrorCode = RegQueryValueExW(hkeyorg, nameW.Buffer, reserved, type, data, count);
4082  RtlFreeUnicodeString(&nameW);
4083  return ErrorCode;
4084  }
4085 
4086  /* Allocate a unicode string to get the data */
4087  Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
4088  if (!Buffer)
4089  {
4090  RtlFreeUnicodeString(&nameW);
4091  return ERROR_NOT_ENOUGH_MEMORY;
4092  }
4093 
4094  ErrorCode = RegQueryValueExW(hkeyorg, nameW.Buffer, reserved, type, (LPBYTE)Buffer, &BufferSize);
4095  if (ErrorCode != ERROR_SUCCESS)
4096  {
4097  RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
4098  RtlFreeUnicodeString(&nameW);
4099  return ErrorCode;
4100  }
4101 
4102  /* We don't need this anymore */
4103  RtlFreeUnicodeString(&nameW);
4104 
4105  DataLength = *count;
4106  RtlUnicodeToMultiByteSize(count, Buffer, BufferSize);
4107 
4108  if ((!data) || (DataLength < *count))
4109  {
4110  RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
4111  return data ? ERROR_MORE_DATA : ERROR_SUCCESS;
4112  }
4113 
4114  /* We can finally do the conversion */
4115  RtlUnicodeToMultiByteN(DataStr, DataLength, NULL, Buffer, BufferSize);
4116 
4117  /* NULL-terminate if there is enough room */
4118  if ((DataLength > *count) && (DataStr[*count - 1] != '\0'))
4119  DataStr[*count] = '\0';
4120 
4121  RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
4122 
4123  return ERROR_SUCCESS;
4124 }
4125 
4126 
4127 /************************************************************************
4128  * RegQueryValueExW
4129  *
4130  * @implemented
4131  */
4132 LONG
4133 WINAPI
4135  _In_ HKEY hkeyorg,
4136  _In_ LPCWSTR name,
4138  _In_ LPDWORD type,
4139  _In_ LPBYTE data,
4140  _In_ LPDWORD count)
4141 {
4142  HANDLE hkey;
4143  NTSTATUS status;
4144  UNICODE_STRING name_str;
4145  DWORD total_size;
4146  char buffer[256], *buf_ptr = buffer;
4148  static const int info_size = offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data );
4149 
4150  TRACE("(%p,%s,%p,%p,%p,%p=%d)\n",
4151  hkeyorg, debugstr_w(name), reserved, type, data, count,
4152  (count && data) ? *count : 0 );
4153 
4154  if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
4155 
4156  status = MapDefaultKey(&hkey, hkeyorg);
4157  if (!NT_SUCCESS(status))
4158  {
4159  return RtlNtStatusToDosError(status);
4160  }
4161 
4162  if (IsHKCRKey(hkey))
4163  {
4164  LONG ErrorCode = QueryHKCRValue(hkey, name, reserved, type, data, count);
4165  ClosePredefKey(hkey);
4166  return ErrorCode;
4167  }
4168 
4169  RtlInitUnicodeString( &name_str, name );
4170 
4171  if (data)
4172  total_size = min( sizeof(buffer), *count + info_size );
4173  else
4174  total_size = info_size;
4175 
4176 
4177  status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation,
4178  buffer, total_size, &total_size );
4179 
4180  if (!NT_SUCCESS(status) && status != STATUS_BUFFER_OVERFLOW)
4181  {
4182  // NT: Valid handles with inexistant/null values or invalid (but not NULL) handles sets type to REG_NONE
4183  // On windows these conditions are likely to be side effects of the implementation...
4184  if (status == STATUS_INVALID_HANDLE && hkey)
4185  {
4186  if (type) *type = REG_NONE;
4187  if (count) *count = 0;
4188  }
4189  else if (status == STATUS_OBJECT_NAME_NOT_FOUND)
4190  {
4191  if (type) *type = REG_NONE;
4192  if (data == NULL && count) *count = 0;
4193  }
4194  goto done;
4195  }
4196 
4197  if (data)
4198  {
4199  /* retry with a dynamically allocated buffer */
4200  while (status == STATUS_BUFFER_OVERFLOW && total_size - info_size <= *count)
4201  {
4202  if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
4203  if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
4204  {
4205  ClosePredefKey(hkey);
4206  return ERROR_NOT_ENOUGH_MEMORY;
4207  }
4208  info = (KEY_VALUE_PARTIAL_INFORMATION *)buf_ptr;
4209  status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation,
4210  buf_ptr, total_size, &total_size );
4211  }
4212 
4213  if (NT_SUCCESS(status))
4214  {
4215  memcpy( data, buf_ptr + info_size, total_size - info_size );
4216  /* if the type is REG_SZ and data is not 0-terminated
4217  * and there is enough space in the buffer NT appends a \0 */
4218  if (is_string(info->Type) && total_size - info_size <= *count-sizeof(WCHAR))
4219  {
4220  WCHAR *ptr = (WCHAR *)(data + total_size - info_size);
4221  if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
4222  }
4223  }
4224  else if (status != STATUS_BUFFER_OVERFLOW) goto done;
4225  }
4226  else status = STATUS_SUCCESS;
4227 
4228  if (type) *type = info->Type;
4229  if (count) *count = total_size - info_size;
4230 
4231  done:
4232  if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
4233  ClosePredefKey(hkey);
4234  return RtlNtStatusToDosError(status);
4235 }
4236 
4237 
4238 /************************************************************************
4239  * RegQueryValueA
4240  *
4241  * @implemented
4242  */
4244 {
4245  DWORD ret;
4246  HKEY subkey = hkey;
4247 
4248  TRACE("(%p,%s,%p,%d)\n", hkey, debugstr_a(name), data, count ? *count : 0 );
4249 
4250  if (name && name[0])
4251  {
4252  if ((ret = RegOpenKeyA( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
4253  }
4254  ret = RegQueryValueExA( subkey, NULL, NULL, NULL, (LPBYTE)data, (LPDWORD)count );
4255  if (subkey != hkey) RegCloseKey( subkey );
4256  if (ret == ERROR_FILE_NOT_FOUND)
4257  {
4258  /* return empty string if default value not found */
4259  if (data) *data = 0;
4260  if (count) *count = 1;
4261  ret = ERROR_SUCCESS;
4262  }
4263  return ret;
4264 }
4265 
4266 
4267 /************************************************************************
4268  * RegQueryValueW
4269  *
4270  * @implemented
4271  */
4273 {
4274  DWORD ret;
4275  HKEY subkey = hkey;
4276 
4277  TRACE("(%p,%s,%p,%d)\n", hkey, debugstr_w(name), data, count ? *count : 0 );
4278  if (hkey == NULL)
4279  {
4280  return ERROR_INVALID_HANDLE;
4281  }
4282  if (name && name[0])
4283  {
4284  ret = RegOpenKeyW( hkey, name, &subkey);
4285  if (ret != ERROR_SUCCESS)
4286  {
4287  return ret;
4288  }
4289  }
4290 
4291  ret = RegQueryValueExW( subkey, NULL, NULL, NULL, (LPBYTE)data, (LPDWORD)count );
4292 
4293  if (subkey != hkey)
4294  {
4295  RegCloseKey( subkey );
4296  }
4297 
4298  if (ret == ERROR_FILE_NOT_FOUND)
4299  {
4300  /* return empty string if default value not found */
4301  if (data)
4302  *data = 0;
4303  if (count)
4304  *count = sizeof(WCHAR);
4305  ret = ERROR_SUCCESS;
4306  }
4307  return ret;
4308 }
4309 
4310 
4311 /************************************************************************
4312  * RegReplaceKeyA
4313  *
4314  * @implemented
4315  */
4316 LONG WINAPI
4318  LPCSTR lpSubKey,
4319  LPCSTR lpNewFile,
4320  LPCSTR lpOldFile)
4321 {
4322  UNICODE_STRING SubKey;
4323  UNICODE_STRING NewFile;
4324  UNICODE_STRING OldFile;
4325  LONG ErrorCode;
4326 
4327  RtlInitEmptyUnicodeString(&SubKey, NULL, 0);
4328  RtlInitEmptyUnicodeString(&OldFile, NULL, 0);
4329  RtlInitEmptyUnicodeString(&NewFile, NULL, 0);
4330 
4331  if (lpSubKey)
4332  {
4333  if (!RtlCreateUnicodeStringFromAsciiz(&SubKey, lpSubKey))
4334  {
4335  ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
4336  goto Exit;
4337  }
4338  }
4339 
4340  if (lpOldFile)
4341  {
4342  if (!RtlCreateUnicodeStringFromAsciiz(&OldFile, lpOldFile))
4343  {
4344  ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
4345  goto Exit;
4346  }
4347  }
4348 
4349  if (lpNewFile)
4350  {
4351  if (!RtlCreateUnicodeStringFromAsciiz(&NewFile, lpNewFile))
4352  {
4353  ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
4354  goto Exit;
4355  }
4356  }
4357 
4358  ErrorCode = RegReplaceKeyW(hKey,
4359  SubKey.Buffer,
4360  NewFile.Buffer,
4361  OldFile.Buffer);
4362 
4363 Exit:
4364  RtlFreeUnicodeString(&OldFile);
4365  RtlFreeUnicodeString(&NewFile);
4366  RtlFreeUnicodeString(&SubKey);
4367 
4368  return ErrorCode;
4369 }
4370 
4371 
4372 /************************************************************************
4373  * RegReplaceKeyW
4374  *
4375  * @unimplemented
4376  */
4377 LONG WINAPI
4379  LPCWSTR lpSubKey,
4380  LPCWSTR lpNewFile,
4381  LPCWSTR lpOldFile)
4382 {
4383  OBJECT_ATTRIBUTES KeyObjectAttributes;
4384  OBJECT_ATTRIBUTES NewObjectAttributes;
4385  OBJECT_ATTRIBUTES OldObjectAttributes;
4387  UNICODE_STRING NewFileName;
4388  UNICODE_STRING OldFileName;
4389  BOOLEAN CloseRealKey;
4390  HANDLE RealKeyHandle;
4391  HANDLE KeyHandle;
4392  NTSTATUS Status;
4394 
4395  if (hKey == HKEY_PERFORMANCE_DATA)
4396  {
4397  return ERROR_INVALID_HANDLE;
4398  }
4399 
4400  Status = MapDefaultKey(&KeyHandle,
4401  hKey);
4402  if (!NT_SUCCESS(Status))
4403  {
4404  return RtlNtStatusToDosError(Status);
4405  }
4406 
4407  /* Open the real key */
4408  if (lpSubKey != NULL && *lpSubKey != (WCHAR)0)
4409  {
4410  RtlInitUnicodeString(&SubKeyName,
4411  (PWSTR)lpSubKey);
4412  InitializeObjectAttributes(&KeyObjectAttributes,
4413  &SubKeyName,
4415  KeyHandle,
4416  NULL);
4417  Status = NtOpenKey(&RealKeyHandle,
4419  &KeyObjectAttributes);
4420  if (!NT_SUCCESS(Status))
4421  {
4422  ErrorCode = RtlNtStatusToDosError(Status);
4423  goto Cleanup;
4424  }
4425 
4426  CloseRealKey = TRUE;
4427  }
4428  else
4429  {
4430  RealKeyHandle = KeyHandle;
4431  CloseRealKey = FALSE;
4432  }
4433 
4434  /* Convert new file name */
4435  if (!RtlDosPathNameToNtPathName_U(lpNewFile,
4436  &NewFileName,
4437  NULL,
4438  NULL))
4439  {
4440  if (CloseRealKey)
4441  {
4442  NtClose(RealKeyHandle);
4443  }
4444 
4445  ErrorCode = ERROR_INVALID_PARAMETER;
4446  goto Cleanup;
4447  }
4448 
4449  InitializeObjectAttributes(&NewObjectAttributes,
4450  &NewFileName,
4452  NULL,
4453  NULL);
4454 
4455  /* Convert old file name */
4456  if (!RtlDosPathNameToNtPathName_U(lpOldFile,
4457  &OldFileName,
4458  NULL,
4459  NULL))
4460  {
4461  RtlFreeHeap(RtlGetProcessHeap (),
4462  0,
4463  NewFileName.Buffer);
4464  if (CloseRealKey)
4465  {
4466  NtClose(RealKeyHandle);
4467  }
4468 
4469  ErrorCode = ERROR_INVALID_PARAMETER;
4470  goto Cleanup;
4471  }
4472 
4473  InitializeObjectAttributes(&OldObjectAttributes,
4474  &OldFileName,
4476  NULL,
4477  NULL);
4478 
4479  Status = NtReplaceKey(&NewObjectAttributes,
4480  RealKeyHandle,
4481  &OldObjectAttributes);
4482 
4483  RtlFreeHeap(RtlGetProcessHeap(),
4484  0,
4485  OldFileName.Buffer);
4486  RtlFreeHeap(RtlGetProcessHeap(),
4487  0,
4488  NewFileName.Buffer);
4489 
4490  if (CloseRealKey)
4491  {
4492  NtClose(RealKeyHandle);
4493  }
4494 
4495  if (!NT_SUCCESS(Status))
4496  {
4497  return RtlNtStatusToDosError(Status);
4498  }
4499 
4500 Cleanup:
4501  ClosePredefKey(KeyHandle);
4502 
4503  return ErrorCode;
4504 }
4505 
4506 
4507 /************************************************************************
4508  * RegRestoreKeyA
4509  *
4510  * @implemented
4511  */
4512 LONG WINAPI
4514  LPCSTR lpFile,
4515  DWORD dwFlags)
4516 {
4518  LONG ErrorCode;
4519 
4520  if (lpFile)
4521  {
4522  if (!RtlCreateUnicodeStringFromAsciiz(&FileName, lpFile))
4523  return ERROR_NOT_ENOUGH_MEMORY;
4524  }
4525  else
4526  RtlInitEmptyUnicodeString(&FileName, NULL, 0);
4527 
4528  ErrorCode = RegRestoreKeyW(hKey,
4529  FileName.Buffer,
4530  dwFlags);
4531 
4532  RtlFreeUnicodeString(&FileName);
4533 
4534  return ErrorCode;
4535 }
4536 
4537 
4538 /************************************************************************
4539  * RegRestoreKeyW
4540  *
4541  * @implemented
4542  */
4543 LONG WINAPI
4545  LPCWSTR lpFile,
4546  DWORD dwFlags)
4547 {
4552  HANDLE KeyHandle;
4553  NTSTATUS Status;
4554 
4555  if (hKey == HKEY_PERFORMANCE_DATA)
4556  {
4557  return ERROR_INVALID_HANDLE;
4558  }
4559 
4560  Status = MapDefaultKey(&KeyHandle,
4561  hKey);
4562  if (!NT_SUCCESS(Status))
4563  {
4564  return RtlNtStatusToDosError(Status);
4565  }
4566 
4567  if (!RtlDosPathNameToNtPathName_U(lpFile,
4568  &FileName,
4569  NULL,
4570  NULL))
4571  {
4572  Status = STATUS_INVALID_PARAMETER;
4573  goto Cleanup;
4574  }
4575 
4576  InitializeObjectAttributes(&ObjectAttributes,
4577  &FileName,
4579  NULL,
4580  NULL);
4581 
4582  Status = NtOpenFile(&FileHandle,
4584  &ObjectAttributes,
4585  &IoStatusBlock,
4588  RtlFreeHeap(RtlGetProcessHeap(),
4589  0,
4590  FileName.Buffer);
4591  if (!NT_SUCCESS(Status))
4592  {
4593  goto Cleanup;
4594  }
4595 
4596  Status = NtRestoreKey(KeyHandle,
4597  FileHandle,
4598  (ULONG)dwFlags);
4599  NtClose (FileHandle);
4600 
4601 Cleanup:
4602  ClosePredefKey(KeyHandle);
4603 
4604  if (!NT_SUCCESS(Status))
4605  {
4606  return RtlNtStatusToDosError(Status);
4607  }
4608 
4609  return ERROR_SUCCESS;
4610 }
4611 
4612 
4613 /************************************************************************
4614  * RegSaveKeyA
4615  *
4616  * @implemented
4617  */
4618 LONG WINAPI
4620  LPCSTR lpFile,
4621  LPSECURITY_ATTRIBUTES lpSecurityAttributes)
4622 {
4624  LONG ErrorCode;
4625 
4626  if (lpFile)
4627  {
4628  if (!RtlCreateUnicodeStringFromAsciiz(&FileName, lpFile))
4629  return ERROR_NOT_ENOUGH_MEMORY;
4630  }
4631  else
4632  RtlInitEmptyUnicodeString(&FileName, NULL, 0);
4633 
4634  ErrorCode = RegSaveKeyW(hKey,
4635  FileName.Buffer,
4636  lpSecurityAttributes);
4637  RtlFreeUnicodeString(&FileName);
4638 
4639  return ErrorCode;
4640 }
4641 
4642 
4643 /************************************************************************
4644  * RegSaveKeyW
4645  *
4646  * @implemented
4647  */
4648 LONG WINAPI
4650  LPCWSTR lpFile,
4651  LPSECURITY_ATTRIBUTES lpSecurityAttributes)
4652 {
4658  HANDLE KeyHandle;
4659  NTSTATUS Status;
4660 
4661  Status = MapDefaultKey(&KeyHandle,
4662  hKey);
4663  if (!NT_SUCCESS(Status))
4664  {
4665  return RtlNtStatusToDosError(Status);
4666  }
4667 
4668  if (!RtlDosPathNameToNtPathName_U(lpFile,
4669  &FileName,
4670  NULL,
4671  NULL))
4672  {
4673  Status = STATUS_INVALID_PARAMETER;
4674  goto Cleanup;
4675  }
4676 
4677  if (lpSecurityAttributes != NULL)
4678  {
4679  SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
4680  }
4681 
4682  InitializeObjectAttributes(&ObjectAttributes,
4683  &FileName,
4685  NULL,
4686  SecurityDescriptor);
4687  Status = NtCreateFile(&FileHandle,
4689  &ObjectAttributes,
4690  &IoStatusBlock,
4691  NULL,
4694  FILE_CREATE,
4696  NULL,
4697  0);
4698  RtlFreeHeap(RtlGetProcessHeap(),
4699  0,
4700  FileName.Buffer);
4701  if (!NT_SUCCESS(Status))
4702  {
4703  goto Cleanup;
4704  }
4705 
4706  Status = NtSaveKey(KeyHandle,
4707  FileHandle);
4708  NtClose (FileHandle);
4709 
4710 Cleanup:
4711  ClosePredefKey(KeyHandle);
4712 
4713  if (!NT_SUCCESS(Status))
4714  {
4715  return RtlNtStatusToDosError(Status);
4716  }
4717 
4718  return ERROR_SUCCESS;
4719 }
4720 
4721 
4722 /************************************************************************
4723  * RegSaveKeyExA
4724  *
4725  * @implemented
4726  */
4727 LONG
4728 WINAPI
4730  LPCSTR lpFile,
4731  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
4732  DWORD Flags)
4733 {
4735  LONG ErrorCode;
4736 
4737  if (lpFile)
4738  {
4739  if (!RtlCreateUnicodeStringFromAsciiz(&FileName, lpFile))
4740  return ERROR_NOT_ENOUGH_MEMORY;
4741  }
4742  else
4743  RtlInitEmptyUnicodeString(&FileName, NULL, 0);
4744 
4745  ErrorCode = RegSaveKeyExW(hKey,
4746  FileName.Buffer,
4747  lpSecurityAttributes,
4748  Flags);
4749  RtlFreeUnicodeString(&FileName);
4750 
4751  return ErrorCode;
4752 }
4753 
4754 
4755 /************************************************************************
4756  * RegSaveKeyExW
4757  *
4758  * @unimplemented
4759  */
4760 LONG
4761 WINAPI
4763  LPCWSTR lpFile,
4764  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
4765  DWORD Flags)
4766 {
4767  switch (Flags)
4768  {
4769  case REG_STANDARD_FORMAT:
4770  case REG_LATEST_FORMAT:
4771  case REG_NO_COMPRESSION:
4772  break;
4773  default:
4774  return ERROR_INVALID_PARAMETER;
4775  }
4776 
4777  FIXME("RegSaveKeyExW(): Flags ignored!\n");
4778 
4779  return RegSaveKeyW(hKey,
4780  lpFile,
4781  lpSecurityAttributes);
4782 }
4783 
4784 
4785 /************************************************************************
4786  * RegSetKeySecurity
4787  *
4788  * @implemented
4789  */
4790 LONG WINAPI
4793  PSECURITY_DESCRIPTOR pSecurityDescriptor)
4794 {
4795  HANDLE KeyHandle;
4796  NTSTATUS Status;
4797 
4798  if (hKey == HKEY_PERFORMANCE_DATA)
4799  {
4800  return ERROR_INVALID_HANDLE;
4801  }
4802 
4803  Status = MapDefaultKey(&KeyHandle,
4804  hKey);
4805  if (!NT_SUCCESS(Status))
4806  {
4807  return RtlNtStatusToDosError(Status);
4808  }
4809 
4810  Status = NtSetSecurityObject(KeyHandle,
4811  SecurityInformation,
4812  pSecurityDescriptor);
4813 
4814  ClosePredefKey(KeyHandle);
4815 
4816  if (!NT_SUCCESS(Status))
4817  {
4818  return RtlNtStatusToDosError(Status);
4819  }
4820 
4821  return ERROR_SUCCESS;
4822 }
4823 
4824 
4825 /************************************************************************
4826  * RegSetValueExA
4827  *
4828  * @implemented
4829  */
4830 LONG WINAPI
4832  LPCSTR lpValueName,
4833  DWORD Reserved,
4834  DWORD dwType,
4835  CONST BYTE* lpData,
4836  DWORD cbData)
4837 {
4839  LPWSTR pValueName;
4842  LONG ErrorCode;
4843  LPBYTE pData;
4844  DWORD DataSize;
4845  NTSTATUS Status;
4846 
4847  /* Convert SubKey name to Unicode */
4848  if (lpValueName != NULL && lpValueName[0] != '\0')
4849  {
4850  BOOL bConverted;
4851  bConverted = RtlCreateUnicodeStringFromAsciiz(&ValueName,
4852  (PSTR)lpValueName);
4853  if(!bConverted)
4854  return ERROR_NOT_ENOUGH_MEMORY;
4855  }
4856  else
4857  {
4858  ValueName.Buffer = NULL;
4859  }
4860 
4861  pValueName = (LPWSTR)ValueName.Buffer;
4862 
4863 
4864  if (is_string(dwType) && (cbData != 0))
4865  {
4866  /* Convert ANSI string Data to Unicode */
4867  /* If last character NOT zero then increment length */
4868  LONG bNoNulledStr = ((lpData[cbData-1] != '\0') ? 1 : 0);
4869  AnsiString.Buffer = (PSTR)lpData;
4870  AnsiString.Length = cbData + bNoNulledStr;
4871  AnsiString.MaximumLength = cbData + bNoNulledStr;
4872  Status = RtlAnsiStringToUnicodeString(&Data,
4873  &AnsiString,
4874  TRUE);
4875 
4876  if (!NT_SUCCESS(Status))
4877  {
4878  if (pValueName != NULL)
4879  RtlFreeUnicodeString(&ValueName);
4880 
4881  return RtlNtStatusToDosError(Status);
4882  }
4883  pData = (LPBYTE)Data.Buffer;
4884  DataSize = cbData * sizeof(WCHAR);
4885  }
4886  else
4887  {
4888  Data.Buffer = NULL;
4889  pData = (LPBYTE)lpData;
4890  DataSize = cbData;
4891  }
4892 
4893  ErrorCode = RegSetValueExW(hKey,
4894  pValueName,
4895  Reserved,
4896  dwType,
4897  pData,
4898  DataSize);
4899 
4900  if (pValueName != NULL)
4901  RtlFreeUnicodeString(&ValueName);
4902 
4903  if (Data.Buffer != NULL)
4904  RtlFreeUnicodeString(&Data);
4905 
4906  return ErrorCode;
4907 }
4908 
4909 
4910 /************************************************************************
4911  * RegSetValueExW
4912  *
4913  * @implemented
4914  */
4915 LONG
4916 WINAPI
4918  _In_ HKEY hKey,
4919  _In_ LPCWSTR lpValueName,
4921  _In_ DWORD dwType,
4922  _In_ CONST BYTE* lpData,
4923  _In_ DWORD cbData)
4924 {
4926  HANDLE KeyHandle;
4927  NTSTATUS Status;
4928 
4929  Status = MapDefaultKey(&KeyHandle,
4930  hKey);
4931  if (!NT_SUCCESS(Status))
4932  {
4933  return RtlNtStatusToDosError(Status);
4934  }
4935 
4936  if (IsHKCRKey(KeyHandle))
4937  {
4938  LONG ErrorCode = SetHKCRValue(KeyHandle, lpValueName, Reserved, dwType, lpData, cbData);
4939  ClosePredefKey(KeyHandle);
4940  return ErrorCode;
4941  }
4942 
4943  if (is_string(dwType) && (cbData != 0))
4944  {
4945  PWSTR pwsData = (PWSTR)lpData;
4946 
4947  _SEH2_TRY
4948  {
4949  if((pwsData[cbData / sizeof(WCHAR) - 1] != L'\0') &&
4950  (pwsData[cbData / sizeof(WCHAR)] == L'\0'))
4951  {
4952  /* Increment length if last character is not zero and next is zero */
4953  cbData += sizeof(WCHAR);
4954  }
4955  }
4957  {
4958  ClosePredefKey(KeyHandle);
4959  return ERROR_NOACCESS;
4960  }
4961  _SEH2_END;
4962  }
4963 
4964  RtlInitUnicodeString(&ValueName, lpValueName);
4965 
4966  Status = NtSetValueKey(KeyHandle,
4967  &ValueName,
4968  0,
4969  dwType,
4970  (PVOID)lpData,
4971  (ULONG)cbData);
4972 
4973  ClosePredefKey(KeyHandle);
4974 
4975  if (!NT_SUCCESS(Status))
4976  {
4977  return RtlNtStatusToDosError(Status);
4978  }
4979 
4980  return ERROR_SUCCESS;
4981 }
4982 
4983 
4984 /************************************************************************
4985  * RegSetValueA
4986  *
4987  * @implemented
4988  */
4989 LONG WINAPI
4990 RegSetValueA(HKEY hKeyOriginal,
4991  LPCSTR lpSubKey,
4992  DWORD dwType,
4993  LPCSTR lpData,
4994  DWORD cbData)
4995 {
4996  HKEY subkey;
4997  HANDLE hKey;
4998  DWORD ret;
4999  NTSTATUS Status;
5000 
5001  TRACE("(%p,%s,%d,%s,%d)\n", hKeyOriginal, debugstr_a(lpSubKey), dwType, debugstr_a(lpData), cbData );
5002 
5003  if (dwType != REG_SZ || !lpData) return ERROR_INVALID_PARAMETER;
5004 
5005  Status = MapDefaultKey(&hKey, hKeyOriginal);
5006  if (!NT_SUCCESS(Status))
5007  {
5008  return RtlNtStatusToDosError (Status);
5009  }
5010  subkey = hKey;
5011 
5012  if (lpSubKey && lpSubKey[0]) /* need to create the subkey */
5013  {
5014  ret = RegCreateKeyA(hKey, lpSubKey, &subkey);
5015  if (ret != ERROR_SUCCESS)
5016  goto Cleanup;
5017  }
5018 
5019  ret = RegSetValueExA( subkey, NULL, 0, REG_SZ, (const BYTE*)lpData, strlen(lpData)+1 );
5020  if (subkey != hKey)
5021  RegCloseKey(subkey);
5022 
5023 Cleanup:
5024  ClosePredefKey(hKey);
5025 
5026  return ret;
5027 }
5028 
5029 
5030 /************************************************************************
5031  * RegSetValueW
5032  *
5033  * @implemented
5034  */
5035 LONG WINAPI
5036 RegSetValueW(HKEY hKeyOriginal,
5037  LPCWSTR lpSubKey,
5038  DWORD dwType,
5039  LPCWSTR lpData,
5040  DWORD cbData)
5041 {
5042  HKEY subkey;
5043  HANDLE hKey;
5044  DWORD ret;
5045  NTSTATUS Status;
5046 
5047  TRACE("(%p,%s,%d,%s,%d)\n", hKeyOriginal, debugstr_w(lpSubKey), dwType, debugstr_w(lpData), cbData );
5048 
5049  if (dwType != REG_SZ || !lpData)
5050  return ERROR_INVALID_PARAMETER;
5051 
5052  Status = MapDefaultKey(&hKey,
5053  hKeyOriginal);
5054  if (!NT_SUCCESS(Status))
5055  {
5056  return RtlNtStatusToDosError(Status);
5057  }
5058  subkey = hKey;
5059 
5060  if (lpSubKey && lpSubKey[0]) /* need to create the subkey */
5061  {
5062  ret = RegCreateKeyW(hKey, lpSubKey, &subkey);
5063  if (ret != ERROR_SUCCESS)
5064  goto Cleanup;
5065  }
5066 
5067  ret = RegSetValueExW( subkey, NULL, 0, REG_SZ, (const BYTE*)lpData,
5068  (wcslen( lpData ) + 1) * sizeof(WCHAR) );
5069  if (subkey != hKey)
5070  RegCloseKey(subkey);
5071 
5072 Cleanup:
5073  ClosePredefKey(hKey);
5074 
5075  return ret;
5076 }
5077 
5078 
5079 /************************************************************************
5080  * RegUnLoadKeyA
5081  *
5082  * @implemented
5083  */
5084 LONG WINAPI
5086  LPCSTR lpSubKey)
5087 {
5089  DWORD ErrorCode;
5090 
5091  if (lpSubKey)
5092  {
5093  if (!RtlCreateUnicodeStringFromAsciiz(&KeyName, lpSubKey))
5094  return ERROR_NOT_ENOUGH_MEMORY;
5095  }
5096  else
5097  RtlInitEmptyUnicodeString(&KeyName, NULL, 0);
5098 
5099  ErrorCode = RegUnLoadKeyW(hKey,
5100  KeyName.Buffer);
5101 
5102  RtlFreeUnicodeString (&KeyName);
5103 
5104  return ErrorCode;
5105 }
5106 
5107 
5108 /************************************************************************
5109  * RegUnLoadKeyW
5110  *
5111  * @implemented
5112  */
5113 LONG WINAPI
5115  LPCWSTR lpSubKey)
5116 {
5119  HANDLE KeyHandle;
5120  NTSTATUS Status;
5121 
5122  if (hKey == HKEY_PERFORMANCE_DATA)
5123  {
5124  return ERROR_INVALID_HANDLE;
5125  }
5126 
5127  Status = MapDefaultKey(&KeyHandle, hKey);
5128  if (!NT_SUCCESS(Status))
5129  {
5130  return RtlNtStatusToDosError(Status);
5131  }
5132 
5133  RtlInitUnicodeString(&KeyName,
5134  (LPWSTR)lpSubKey);
5135 
5136  InitializeObjectAttributes(&ObjectAttributes,
5137  &KeyName,
5139  KeyHandle,
5140  NULL);
5141 
5142  Status = NtUnloadKey(&ObjectAttributes);
5143 
5144  ClosePredefKey(KeyHandle);
5145 
5146  if (!NT_SUCCESS(Status))
5147  {
5148  return RtlNtStatusToDosError(Status);
5149  }
5150 
5151  return ERROR_SUCCESS;
5152 }
5153 
5154 /* EOF */
LSTATUS WINAPI RegGetValueW(HKEY hKey, LPCWSTR pszSubKey, LPCWSTR pszValue, DWORD dwFlags, LPDWORD pdwType, PVOID pvData, LPDWORD pcbData)
Definition: reg.c:1975
#define HKEY_USERS
Definition: winreg.h:13
LONG WINAPI RegDeleteKeyValueA(IN HKEY hKey, IN LPCSTR lpSubKey OPTIONAL, IN LPCSTR lpValueName OPTIONAL)
Definition: reg.c:1434
DWORD *typedef PVOID
Definition: winlogon.h:61
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
static NTSTATUS OpenClassesRootKey(PHANDLE KeyHandle)
#define FILE_GENERIC_READ
Definition: nt_native.h:653
LONG WINAPI RegSaveKeyExW(HKEY hKey, LPCWSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD Flags)
Definition: reg.c:4762
#define MAXIMUM_ALLOWED
Definition: nt_native.h:83
DWORD dwOptions
Definition: solitaire.cpp:23
LONG WINAPI RegOpenKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3272
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING KeyName
Definition: ndis.h:4693
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:4041
#define IN
Definition: typedefs.h:38
#define max(a, b)
Definition: svc.c:63
static VOID CloseDefaultKeys(VOID)
Definition: reg.c:216
Definition: get.c:139
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
static IN PWSTR
Definition: reg.c:123
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ NDIS_ERROR_CODE ErrorCode
Definition: ndis.h:4418
#define REG_STANDARD_FORMAT
Definition: cmtypes.h:97
*BytesInUnicodeString PWCH UnicodeString
Definition: rtlfuncs.h:1980
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
LSTATUS WINAPI RegQueryValueA(HKEY hkey, LPCSTR name, LPSTR data, LPLONG count)
Definition: reg.c:4243
LONG WINAPI RegOverridePredefKey(IN HKEY hKey, IN HKEY hNewHKey OPTIONAL)
Definition: reg.c:365
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:523
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:193
#define ERROR_SUCCESS
Definition: deptool.c:10
#define DWORD_PTR
Definition: treelist.c:76
static unsigned int bufptr
Definition: tncon.cpp:77
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ PNDIS_STRING SubKeyName
Definition: ndis.h:4705
#define KEY_SET_VALUE
Definition: nt_native.h:1017
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4693
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
LONG WINAPI RegDeleteKeyExA(_In_ HKEY hKey, _In_ LPCSTR lpSubKey, _In_ REGSAM samDesired, _In_ DWORD Reserved)
Definition: reg.c:1255
USHORT MaximumLength
Definition: env_spec_w32.h:370
FORCEINLINE void MakeHKCRKey(_Inout_ HKEY *hKey)
Definition: reg.h:20
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
LONG WINAPI RegUnLoadKeyA(HKEY hKey, LPCSTR lpSubKey)
Definition: reg.c:5085
#define REG_BINARY
Definition: nt_native.h:1496
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#define KEY_READ
Definition: nt_native.h:1023
_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:182
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
__wchar_t WCHAR
Definition: xmlstorage.h:180
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:3625
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
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:2182
DWORD dwMask
Definition: msvc.h:86
#define REG_OPTION_OPEN_LINK
Definition: nt_native.h:1070
#define HKEY_CURRENT_USER
Definition: winreg.h:11
unsigned char * LPBYTE
Definition: typedefs.h:52
char CHAR
Definition: xmlstorage.h:175
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:592
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3706
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
#define WARN(fmt,...)
Definition: debug.h:111
#define ERROR_INVALID_HANDLE
Definition: compat.h:88
NTSYSAPI NTSTATUS NTAPI RtlUnicodeToMultiByteSize(PULONG MbSize, PCWCH UnicodeString, ULONG UnicodeSize)
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:603
#define FILE_CREATE
Definition: from_kernel.h:55
struct _KEY_BASIC_INFORMATION KEY_BASIC_INFORMATION
LONG WINAPI RegDeleteKeyW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey)
Definition: reg.c:1240
_In_ LPCSTR lpName
Definition: winbase.h:2729
#define ERROR_DATATYPE_MISMATCH
Definition: winerror.h:987
LONG WINAPI RegSetValueW(HKEY hKeyOriginal, LPCWSTR lpSubKey, DWORD dwType, LPCWSTR lpData, DWORD cbData)
Definition: reg.c:5036
PVOID *typedef PWSTR
Definition: winlogon.h:66
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:2253
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
LONG WINAPI RegOpenKeyExA(_In_ HKEY hKey, _In_ LPCSTR lpSubKey, _In_ DWORD ulOptions, _In_ REGSAM samDesired, _Out_ PHKEY phkResult)
Definition: reg.c:3346
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define OBJ_OPENLINK
Definition: winternl.h:230
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define RRF_RT_REG_EXPAND_SZ
Definition: driver.c:576
#define RRF_RT_REG_SZ
Definition: driver.c:575
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
_In_ DWORD _Out_ PDWORD _In_opt_ PCSTR MachineName
Definition: setupapi.h:1286
#define ZeroMemory
Definition: winbase.h:1635
GLuint buffer
Definition: glext.h:5915
PVOID ULONG ULONG PULONG Data
Definition: oprghdlr.h:14
static BOOLEAN DllInitialized
Definition: reg.c:38
LONG WINAPI RegQueryMultipleValuesW(HKEY hKey, PVALENTW val_list, DWORD num_vals, LPWSTR lpValueBuf, LPDWORD ldwTotsize)
Definition: reg.c:3943
LONG WINAPI RegSetValueA(HKEY hKeyOriginal, LPCSTR lpSubKey, DWORD dwType, LPCSTR lpData, DWORD cbData)
Definition: reg.c:4990
#define GROUP_SECURITY_INFORMATION
Definition: setypes.h:124
DWORD ve_valueptr
Definition: winreg.h:80
uint16_t * PWCHAR
Definition: typedefs.h:54
BOOL WINAPI GetComputerNameW(LPWSTR lpBuffer, LPDWORD lpnSize)
Definition: compname.c:339
#define InsertTailList(ListHead, Entry)
LONG WINAPI RegFlushKey(HKEY hKey)
Definition: reg.c:2988
char * LPSTR
Definition: xmlstorage.h:182
#define RRF_RT_REG_MULTI_SZ
Definition: driver.c:579
#define HKEY_CURRENT_CONFIG
Definition: winreg.h:15
#define WCHAR
Definition: msvc.h:43
NTSTATUS NTAPI NtSaveKey(IN HANDLE KeyHandle, IN HANDLE FileHandle)
Definition: ntapi.c:1602
NTSTATUS NTAPI NtRestoreKey(IN HANDLE KeyHandle, IN HANDLE FileHandle, IN ULONG RestoreFlags)
Definition: ntapi.c:1592
NTSYSAPI PVOID WINAPI RtlReAllocateHeap(HANDLE, ULONG, PVOID, SIZE_T)
Definition: heap.c:2552
NTSTATUS NTAPI NtQueryKey(IN HANDLE KeyHandle, IN KEY_INFORMATION_CLASS KeyInformationClass, OUT PVOID KeyInformation, IN ULONG Length, OUT PULONG ResultLength)
Definition: ntapi.c:632
#define BufferSize
Definition: acefiex.h:377
LONG WINAPI RegDisableReflectionKey(IN HKEY hBase)
Definition: reg.c:1877
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
static NTSTATUS OpenUsersKey(PHANDLE KeyHandle)
Definition: reg.c:288
LONG WINAPI OpenHKCRKey(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ DWORD ulOptions, _In_ REGSAM samDesired, _In_ PHKEY phkResult)
Definition: hkcr.c:324
#define ERROR_BAD_NETPATH
Definition: winerror.h:145
DWORD DWORD
Definition: winlogon.h:84
_In_ ACCESS_MASK _In_ POBJECT_ATTRIBUTES _Reserved_ ULONG _In_opt_ PUNICODE_STRING _In_ ULONG _Out_opt_ PULONG Disposition
Definition: cmfuncs.h:50
LONG WINAPI RegDeleteTreeA(IN HKEY hKey, IN LPCSTR lpSubKey OPTIONAL)
Definition: reg.c:1849
#define STATUS_INVALID_HANDLE
Definition: ntstatus.h:231
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
struct TraceInfo Info
#define FILE_SHARE_READ
Definition: compat.h:125
#define _In_opt_
Definition: no_sal2.h:213
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:1094
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 STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:52
_SEH2_TRY
Definition: create.c:4250
LONG WINAPI RegDeleteKeyExW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ REGSAM samDesired, _In_ DWORD Reserved)
Definition: reg.c:1287
static HANDLE hEvent
Definition: comm.c:54
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define ERROR_INVALID_USER_BUFFER
Definition: winerror.h:1091
#define RRF_RT_REG_NONE
Definition: driver.c:574
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
_In_ PUNICODE_STRING ValueName
Definition: cmfuncs.h:264
BOOL RegCleanup(VOID)
Definition: reg.c:93
HANDLE FileHandle
Definition: stats.c:38
LONG WINAPI RegEnableReflectionKey(IN HKEY hBase)
Definition: reg.c:1890
LONG WINAPI QueryHKCRValue(_In_ HKEY hKey, _In_ LPCWSTR Name, _In_ LPDWORD Reserved, _In_ LPDWORD Type, _In_ LPBYTE Data, _In_ LPDWORD Count)
Definition: hkcr.c:458
LONG WINAPI DeleteHKCRKey(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ REGSAM RegSam, _In_ DWORD Reserved)
Definition: hkcr.c:395
DWORD dwHighDateTime
Definition: mapidefs.h:66
static IN IN IN PVOID
Definition: reg.c:122
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
GLenum GLclampf GLint i
Definition: glfuncs.h:14
#define ERROR_NOACCESS
Definition: winerror.h:578
LONG WINAPI RegSaveKeyA(HKEY hKey, LPCSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: reg.c:4619
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
static NTSTATUS MapDefaultKey(PHANDLE ParentKey, HKEY Key)
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
#define ANSI_NULL
static HANDLE ProcessHeap
Definition: reg.c:35
LONG WINAPI RegQueryMultipleValuesA(HKEY hKey, PVALENTA val_list, DWORD num_vals, LPSTR lpValueBuf, LPDWORD ldwTotsize)
Definition: reg.c:3879
LONG WINAPI RegDisablePredefinedCacheEx(VOID)
Definition: reg.c:348
long LONG
Definition: pedump.c:60
DWORD SECURITY_INFORMATION
Definition: ms-dtyp.idl:311
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
LONG WINAPI RegCopyTreeA(IN HKEY hKeySrc, IN LPCSTR lpSubKey OPTIONAL, IN HKEY hKeyDest)
Definition: reg.c:812
LONG WINAPI RegOpenKeyW(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3311
#define REG_MULTI_SZ
Definition: nt_native.h:1501
#define GENERIC_WRITE
Definition: nt_native.h:90
#define debugstr_w
Definition: kernel32.h:32
#define FIXME(fmt,...)
Definition: debug.h:110
static PVOID ptr
Definition: dispmode.c:27
LONG WINAPI EnumHKCRValue(_In_ HKEY hKey, _In_ DWORD dwIndex, _Out_ LPWSTR lpName, _Inout_ PDWORD lpcbName, _Reserved_ PDWORD lpReserved, _Out_opt_ PDWORD lpdwType, _Out_opt_ LPBYTE lpData, _Inout_opt_ PDWORD lpcbData)
Definition: hkcr.c:807
r reserved
Definition: btrfs.c:2640
LONG WINAPI RegSaveKeyExA(HKEY hKey, LPCSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD Flags)
Definition: reg.c:4729
UINTN * BufferSize
Definition: acefiex.h:370
struct _KEY_BASIC_INFORMATION * PKEY_BASIC_INFORMATION
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
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:2867
LONG WINAPI RegSetKeySecurity(HKEY hKey, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor)
Definition: reg.c:4791
_In_ ULONG _In_opt_ PVOID pvData
Definition: winddi.h:3748
LONG WINAPI RegConnectRegistryW(LPCWSTR lpMachineName, HKEY hKey, PHKEY phkResult)
Definition: reg.c:872
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
#define _Out_
Definition: no_sal2.h:323
DWORD WINAPI ExpandEnvironmentStringsA(IN LPCSTR lpSrc, IN LPSTR lpDst, IN DWORD nSize)
Definition: environ.c:399
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ SECURITY_INFORMATION SecurityInformation
Definition: fltkernel.h:1339
_Check_return_ _CRTIMP _CONST_RETURN wchar_t *__cdecl wcsrchr(_In_z_ const wchar_t *_Str, _In_ wchar_t _Ch)
#define REG_MAX_NAME_SIZE
Definition: reg.c:28
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeStringFromAsciiz(_Out_ PUNICODE_STRING Destination, _In_ PCSZ Source)
GLuint index
Definition: glext.h:6031
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToAnsiString(PANSI_STRING DestinationString, PUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
#define ERROR_UNSUPPORTED_TYPE
Definition: winerror.h:988
const char * LPCSTR
Definition: xmlstorage.h:183
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
LONG WINAPI RegCreateKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:1180
LSTATUS WINAPI RegGetValueA(HKEY hKey, LPCSTR pszSubKey, LPCSTR pszValue, DWORD dwFlags, LPDWORD pdwType, PVOID pvData, LPDWORD pcbData)
Definition: reg.c:2081
struct _KEY_NODE_INFORMATION KEY_NODE_INFORMATION
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define CONST
Definition: compiler.h:170
DWORD ve_valueptr
Definition: winreg.h:74
static NTSTATUS CreateNestedKey(PHKEY KeyHandle, POBJECT_ATTRIBUTES ObjectAttributes, PUNICODE_STRING ClassString, DWORD dwOptions, REGSAM samDesired, DWORD *lpdwDisposition)
Definition: reg.c:918
#define RRF_RT_DWORD
Definition: driver.c:581
LONG WINAPI RegRestoreKeyW(HKEY hKey, LPCWSTR lpFile, DWORD dwFlags)
Definition: reg.c:4544
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:585
static const WCHAR nameW[]
Definition: main.c:46
NTSTATUS NTAPI NtLoadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes, IN POBJECT_ATTRIBUTES FileObjectAttributes)
Definition: ntapi.c:1109
NTSYSAPI NTSTATUS NTAPI NtDeleteValueKey(IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName)
Definition: ntapi.c:994
#define GetPredefKeyIndex(HKey)
Definition: reg.c:50
NTSTATUS NTAPI NtReplaceKey(IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE Key, IN POBJECT_ATTRIBUTES ReplacedObjectAttributes)
Definition: ntapi.c:1582
#define KEY_WOW64_64KEY
Definition: cmtypes.h:46
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:4917
NTSTATUS RtlAppendUnicodeToString(IN PUNICODE_STRING Str1, IN PWSTR Str2)
Definition: string_lib.cpp:62
USHORT MaximumLength
Definition: env_spec_w32.h:377
#define _Out_opt_
Definition: no_sal2.h:339
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
_In_ HANDLE Handle
Definition: extypes.h:390
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
LONG WINAPI RegReplaceKeyW(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpNewFile, LPCWSTR lpOldFile)
Definition: reg.c:4378
unsigned char BOOLEAN
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)
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:1270
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 TRACE(s)
Definition: solgame.cpp:4
LONG WINAPI RegSaveKeyW(HKEY hKey, LPCWSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: reg.c:4649
unsigned int BOOL
Definition: ntddk_ex.h:94
LONG NTSTATUS
Definition: precomp.h:26
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:2705
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
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)
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4134
if(!(yy_init))
Definition: macro.lex.yy.c:717
#define RRF_ZEROONFAILURE
Definition: driver.c:584
LONG WINAPI RegGetKeySecurity(HKEY hKey, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, LPDWORD lpcbSecurityDescriptor)
Definition: reg.c:3024