RegQueryInfoKeyW returns correct security descriptor size.
[reactos.git] / reactos / lib / advapi32 / reg / reg.c
1 /* $Id: reg.c,v 1.57 2004/09/13 14:42:37 ekohl Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/advapi32/reg/reg.c
6 * PURPOSE: Registry functions
7 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
8 * UPDATE HISTORY:
9 * Created 01/11/98
10 * 19990309 EA Stubs
11 */
12
13 /* INCLUDES *****************************************************************/
14
15 #include "advapi32.h"
16 #define NDEBUG
17 #include <debug.h>
18
19 /* DEFINES ******************************************************************/
20
21 #define MAX_DEFAULT_HANDLES 6
22 #define REG_MAX_NAME_SIZE 256
23 #define REG_MAX_DATA_SIZE 2048
24
25 /* GLOBALS ******************************************************************/
26
27 static CRITICAL_SECTION HandleTableCS;
28 static HANDLE DefaultHandleTable[MAX_DEFAULT_HANDLES];
29 static HANDLE ProcessHeap;
30
31 /* PROTOTYPES ***************************************************************/
32
33 static NTSTATUS MapDefaultKey (PHANDLE ParentKey, HKEY Key);
34 static VOID CloseDefaultKeys(VOID);
35
36 static NTSTATUS OpenClassesRootKey(PHANDLE KeyHandle);
37 static NTSTATUS OpenLocalMachineKey (PHANDLE KeyHandle);
38 static NTSTATUS OpenUsersKey (PHANDLE KeyHandle);
39 static NTSTATUS OpenCurrentConfigKey(PHANDLE KeyHandle);
40
41
42 /* FUNCTIONS ****************************************************************/
43
44 /************************************************************************
45 * RegInitDefaultHandles
46 */
47 BOOL
48 RegInitialize (VOID)
49 {
50 DPRINT("RegInitialize()\n");
51
52 ProcessHeap = RtlGetProcessHeap();
53 RtlZeroMemory (DefaultHandleTable,
54 MAX_DEFAULT_HANDLES * sizeof(HANDLE));
55 RtlInitializeCriticalSection (&HandleTableCS);
56
57 return TRUE;
58 }
59
60
61 /************************************************************************
62 * RegInit
63 */
64 BOOL
65 RegCleanup (VOID)
66 {
67 DPRINT("RegCleanup()\n");
68
69 CloseDefaultKeys ();
70 RtlDeleteCriticalSection (&HandleTableCS);
71
72 return TRUE;
73 }
74
75
76 static NTSTATUS
77 MapDefaultKey (PHANDLE RealKey,
78 HKEY Key)
79 {
80 PHANDLE Handle;
81 ULONG Index;
82 NTSTATUS Status = STATUS_SUCCESS;
83
84 DPRINT("MapDefaultKey (Key %x)\n", Key);
85
86 if (((ULONG)Key & 0xF0000000) != 0x80000000)
87 {
88 *RealKey = (HANDLE)Key;
89 return STATUS_SUCCESS;
90 }
91
92 /* Handle special cases here */
93 Index = (ULONG)Key & 0x0FFFFFFF;
94 if (Index >= MAX_DEFAULT_HANDLES)
95 {
96 return STATUS_INVALID_PARAMETER;
97 }
98
99 RtlEnterCriticalSection (&HandleTableCS);
100 Handle = &DefaultHandleTable[Index];
101 if (*Handle == NULL)
102 {
103 /* create/open the default handle */
104 switch (Index)
105 {
106 case 0: /* HKEY_CLASSES_ROOT */
107 Status = OpenClassesRootKey (Handle);
108 break;
109
110 case 1: /* HKEY_CURRENT_USER */
111 Status = RtlOpenCurrentUser (MAXIMUM_ALLOWED,
112 Handle);
113 break;
114
115 case 2: /* HKEY_LOCAL_MACHINE */
116 Status = OpenLocalMachineKey (Handle);
117 break;
118
119 case 3: /* HKEY_USERS */
120 Status = OpenUsersKey (Handle);
121 break;
122 #if 0
123 case 4: /* HKEY_PERFORMANCE_DATA */
124 Status = OpenPerformanceDataKey (Handle);
125 break;
126 #endif
127 case 5: /* HKEY_CURRENT_CONFIG */
128 Status = OpenCurrentConfigKey (Handle);
129 break;
130
131 case 6: /* HKEY_DYN_DATA */
132 Status = STATUS_NOT_IMPLEMENTED;
133 break;
134
135 default:
136 DPRINT("MapDefaultHandle() no handle creator\n");
137 Status = STATUS_INVALID_PARAMETER;
138 }
139 }
140 RtlLeaveCriticalSection (&HandleTableCS);
141
142 if (NT_SUCCESS(Status))
143 {
144 *RealKey = *Handle;
145 }
146
147 return Status;
148 }
149
150
151 static VOID
152 CloseDefaultKeys (VOID)
153 {
154 ULONG i;
155
156 RtlEnterCriticalSection (&HandleTableCS);
157 for (i = 0; i < MAX_DEFAULT_HANDLES; i++)
158 {
159 if (DefaultHandleTable[i] != NULL)
160 {
161 NtClose (DefaultHandleTable[i]);
162 DefaultHandleTable[i] = NULL;
163 }
164 }
165 RtlLeaveCriticalSection (&HandleTableCS);
166 }
167
168
169 static NTSTATUS
170 OpenClassesRootKey (PHANDLE KeyHandle)
171 {
172 OBJECT_ATTRIBUTES Attributes;
173 UNICODE_STRING KeyName = ROS_STRING_INITIALIZER(L"\\Registry\\Machine\\Software\\CLASSES");
174
175 DPRINT("OpenClassesRootKey()\n");
176
177 InitializeObjectAttributes (&Attributes,
178 &KeyName,
179 OBJ_CASE_INSENSITIVE,
180 NULL,
181 NULL);
182 return NtOpenKey (KeyHandle,
183 MAXIMUM_ALLOWED,
184 &Attributes);
185 }
186
187
188 static NTSTATUS
189 OpenLocalMachineKey (PHANDLE KeyHandle)
190 {
191 OBJECT_ATTRIBUTES Attributes;
192 UNICODE_STRING KeyName = ROS_STRING_INITIALIZER(L"\\Registry\\Machine");
193 NTSTATUS Status;
194
195 DPRINT("OpenLocalMachineKey()\n");
196
197 InitializeObjectAttributes (&Attributes,
198 &KeyName,
199 OBJ_CASE_INSENSITIVE,
200 NULL,
201 NULL);
202 Status = NtOpenKey (KeyHandle,
203 MAXIMUM_ALLOWED,
204 &Attributes);
205
206 DPRINT("NtOpenKey(%wZ) => %08x\n", &KeyName, Status);
207 return Status;
208 }
209
210
211 static NTSTATUS
212 OpenUsersKey (PHANDLE KeyHandle)
213 {
214 OBJECT_ATTRIBUTES Attributes;
215 UNICODE_STRING KeyName = ROS_STRING_INITIALIZER(L"\\Registry\\User");
216
217 DPRINT("OpenUsersKey()\n");
218
219 InitializeObjectAttributes (&Attributes,
220 &KeyName,
221 OBJ_CASE_INSENSITIVE,
222 NULL,
223 NULL);
224 return NtOpenKey (KeyHandle,
225 KEY_ALL_ACCESS,
226 &Attributes);
227 }
228
229
230 static NTSTATUS
231 OpenCurrentConfigKey (PHANDLE KeyHandle)
232 {
233 OBJECT_ATTRIBUTES Attributes;
234 UNICODE_STRING KeyName =
235 ROS_STRING_INITIALIZER(L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current");
236
237 DPRINT("OpenCurrentConfigKey()\n");
238
239 InitializeObjectAttributes (&Attributes,
240 &KeyName,
241 OBJ_CASE_INSENSITIVE,
242 NULL,
243 NULL);
244 return NtOpenKey (KeyHandle,
245 MAXIMUM_ALLOWED,
246 &Attributes);
247 }
248
249
250 /************************************************************************
251 * RegCloseKey
252 *
253 * @implemented
254 */
255 LONG STDCALL
256 RegCloseKey (HKEY hKey)
257 {
258 LONG ErrorCode;
259 NTSTATUS Status;
260
261 /* don't close null handle or a pseudo handle */
262 if ((!hKey) || (((ULONG)hKey & 0xF0000000) == 0x80000000))
263 {
264 return ERROR_INVALID_HANDLE;
265 }
266
267 Status = NtClose (hKey);
268 if (!NT_SUCCESS(Status))
269 {
270 ErrorCode = RtlNtStatusToDosError (Status);
271 SetLastError (ErrorCode);
272 return ErrorCode;
273 }
274
275 return ERROR_SUCCESS;
276 }
277
278
279 /************************************************************************
280 * RegConnectRegistryA
281 *
282 * @unimplemented
283 */
284 LONG STDCALL
285 RegConnectRegistryA (LPCSTR lpMachineName,
286 HKEY hKey,
287 PHKEY phkResult)
288 {
289 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
290 return ERROR_CALL_NOT_IMPLEMENTED;
291 }
292
293
294 /************************************************************************
295 * RegConnectRegistryW
296 *
297 * @unimplemented
298 */
299 LONG STDCALL
300 RegConnectRegistryW (LPCWSTR lpMachineName,
301 HKEY hKey,
302 PHKEY phkResult)
303 {
304 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
305 return ERROR_CALL_NOT_IMPLEMENTED;
306 }
307
308
309 /************************************************************************
310 * CreateNestedKey
311 *
312 * Create key and all necessary intermediate keys
313 */
314 static NTSTATUS
315 CreateNestedKey(PHKEY KeyHandle,
316 POBJECT_ATTRIBUTES ObjectAttributes,
317 PUNICODE_STRING ClassString,
318 DWORD dwOptions,
319 REGSAM samDesired,
320 DWORD *lpdwDisposition)
321 {
322 OBJECT_ATTRIBUTES LocalObjectAttributes;
323 UNICODE_STRING LocalKeyName;
324 ULONG Disposition;
325 NTSTATUS Status;
326 ULONG FullNameLength;
327 ULONG Length;
328 PWCHAR Ptr;
329 HANDLE LocalKeyHandle;
330
331 Status = NtCreateKey((PHANDLE) KeyHandle,
332 samDesired,
333 ObjectAttributes,
334 0,
335 ClassString,
336 dwOptions,
337 (PULONG)lpdwDisposition);
338 DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", ObjectAttributes->ObjectName, Status);
339 if (Status != STATUS_OBJECT_NAME_NOT_FOUND)
340 return Status;
341
342 /* Copy object attributes */
343 RtlCopyMemory (&LocalObjectAttributes,
344 ObjectAttributes,
345 sizeof(OBJECT_ATTRIBUTES));
346 RtlCreateUnicodeString (&LocalKeyName,
347 ObjectAttributes->ObjectName->Buffer);
348 LocalObjectAttributes.ObjectName = &LocalKeyName;
349 FullNameLength = LocalKeyName.Length / sizeof(WCHAR);
350
351 /* Remove the last part of the key name and try to create the key again. */
352 while (Status == STATUS_OBJECT_NAME_NOT_FOUND)
353 {
354 Ptr = wcsrchr (LocalKeyName.Buffer, '\\');
355 if (Ptr == NULL || Ptr == LocalKeyName.Buffer)
356 {
357 Status = STATUS_UNSUCCESSFUL;
358 break;
359 }
360 *Ptr = (WCHAR)0;
361 LocalKeyName.Length = wcslen (LocalKeyName.Buffer) * sizeof(WCHAR);
362
363 Status = NtCreateKey (&LocalKeyHandle,
364 KEY_ALL_ACCESS,
365 &LocalObjectAttributes,
366 0,
367 NULL,
368 0,
369 &Disposition);
370 DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName, Status);
371 }
372
373 if (!NT_SUCCESS(Status))
374 {
375 RtlFreeUnicodeString (&LocalKeyName);
376 return Status;
377 }
378
379 /* Add removed parts of the key name and create them too. */
380 Length = wcslen (LocalKeyName.Buffer);
381 while (TRUE)
382 {
383 NtClose (LocalKeyHandle);
384
385 LocalKeyName.Buffer[Length] = L'\\';
386 Length = wcslen (LocalKeyName.Buffer);
387 LocalKeyName.Length = Length * sizeof(WCHAR);
388
389 if (Length == FullNameLength)
390 {
391 Status = NtCreateKey((PHANDLE) KeyHandle,
392 samDesired,
393 ObjectAttributes,
394 0,
395 ClassString,
396 dwOptions,
397 (PULONG)lpdwDisposition);
398 break;
399 }
400 Status = NtCreateKey (&LocalKeyHandle,
401 KEY_ALL_ACCESS,
402 &LocalObjectAttributes,
403 0,
404 NULL,
405 0,
406 &Disposition);
407 DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName, Status);
408 if (!NT_SUCCESS(Status))
409 break;
410 }
411
412 RtlFreeUnicodeString (&LocalKeyName);
413
414 return Status;
415 }
416
417
418 /************************************************************************
419 * RegCreateKeyExA
420 *
421 * @implemented
422 */
423 LONG STDCALL
424 RegCreateKeyExA (HKEY hKey,
425 LPCSTR lpSubKey,
426 DWORD Reserved,
427 LPSTR lpClass,
428 DWORD dwOptions,
429 REGSAM samDesired,
430 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
431 PHKEY phkResult,
432 LPDWORD lpdwDisposition)
433 {
434 UNICODE_STRING SubKeyString;
435 UNICODE_STRING ClassString;
436 OBJECT_ATTRIBUTES Attributes;
437 HANDLE ParentKey;
438 LONG ErrorCode;
439 NTSTATUS Status;
440
441 DPRINT("RegCreateKeyExA() called\n");
442
443 /* get the real parent key */
444 Status = MapDefaultKey (&ParentKey,
445 hKey);
446 if (!NT_SUCCESS(Status))
447 {
448 ErrorCode = RtlNtStatusToDosError (Status);
449 SetLastError (ErrorCode);
450 return ErrorCode;
451 }
452 DPRINT("ParentKey %x\n", (ULONG)ParentKey);
453
454 if (lpClass != NULL)
455 {
456 RtlCreateUnicodeStringFromAsciiz (&ClassString,
457 lpClass);
458 }
459 RtlCreateUnicodeStringFromAsciiz (&SubKeyString,
460 (LPSTR)lpSubKey);
461 InitializeObjectAttributes (&Attributes,
462 &SubKeyString,
463 OBJ_CASE_INSENSITIVE,
464 (HANDLE)ParentKey,
465 (PSECURITY_DESCRIPTOR)lpSecurityAttributes);
466 Status = CreateNestedKey(phkResult,
467 &Attributes,
468 (lpClass == NULL)? NULL : &ClassString,
469 dwOptions,
470 samDesired,
471 lpdwDisposition);
472 RtlFreeUnicodeString (&SubKeyString);
473 if (lpClass != NULL)
474 {
475 RtlFreeUnicodeString (&ClassString);
476 }
477 DPRINT("Status %x\n", Status);
478 if (!NT_SUCCESS(Status))
479 {
480 ErrorCode = RtlNtStatusToDosError (Status);
481 SetLastError (ErrorCode);
482 return ErrorCode;
483 }
484
485 return ERROR_SUCCESS;
486 }
487
488
489 /************************************************************************
490 * RegCreateKeyExW
491 *
492 * @implemented
493 */
494 LONG STDCALL
495 RegCreateKeyExW (HKEY hKey,
496 LPCWSTR lpSubKey,
497 DWORD Reserved,
498 LPWSTR lpClass,
499 DWORD dwOptions,
500 REGSAM samDesired,
501 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
502 PHKEY phkResult,
503 LPDWORD lpdwDisposition)
504 {
505 UNICODE_STRING SubKeyString;
506 UNICODE_STRING ClassString;
507 OBJECT_ATTRIBUTES Attributes;
508 HANDLE ParentKey;
509 LONG ErrorCode;
510 NTSTATUS Status;
511
512 DPRINT("RegCreateKeyExW() called\n");
513
514 /* get the real parent key */
515 Status = MapDefaultKey (&ParentKey,
516 hKey);
517 if (!NT_SUCCESS(Status))
518 {
519 ErrorCode = RtlNtStatusToDosError(Status);
520 SetLastError (ErrorCode);
521 return ErrorCode;
522 }
523 DPRINT("ParentKey %x\n", (ULONG)ParentKey);
524
525 RtlInitUnicodeString (&ClassString,
526 lpClass);
527 RtlInitUnicodeString (&SubKeyString,
528 lpSubKey);
529 InitializeObjectAttributes (&Attributes,
530 &SubKeyString,
531 OBJ_CASE_INSENSITIVE,
532 (HANDLE)ParentKey,
533 (PSECURITY_DESCRIPTOR)lpSecurityAttributes);
534 Status = CreateNestedKey(phkResult,
535 &Attributes,
536 (lpClass == NULL)? NULL : &ClassString,
537 dwOptions,
538 samDesired,
539 lpdwDisposition);
540 DPRINT("Status %x\n", Status);
541 if (!NT_SUCCESS(Status))
542 {
543 ErrorCode = RtlNtStatusToDosError (Status);
544 SetLastError (ErrorCode);
545 return ErrorCode;
546 }
547
548 return ERROR_SUCCESS;
549 }
550
551
552 /************************************************************************
553 * RegCreateKeyA
554 *
555 * @implemented
556 */
557 LONG STDCALL
558 RegCreateKeyA (HKEY hKey,
559 LPCSTR lpSubKey,
560 PHKEY phkResult)
561 {
562 return RegCreateKeyExA (hKey,
563 lpSubKey,
564 0,
565 NULL,
566 0,
567 KEY_ALL_ACCESS,
568 NULL,
569 phkResult,
570 NULL);
571 }
572
573
574 /************************************************************************
575 * RegCreateKeyW
576 *
577 * @implemented
578 */
579 LONG STDCALL
580 RegCreateKeyW (HKEY hKey,
581 LPCWSTR lpSubKey,
582 PHKEY phkResult)
583 {
584 return RegCreateKeyExW (hKey,
585 lpSubKey,
586 0,
587 NULL,
588 0,
589 KEY_ALL_ACCESS,
590 NULL,
591 phkResult,
592 NULL);
593 }
594
595
596 /************************************************************************
597 * RegDeleteKeyA
598 *
599 * @implemented
600 */
601 LONG STDCALL
602 RegDeleteKeyA (HKEY hKey,
603 LPCSTR lpSubKey)
604 {
605 OBJECT_ATTRIBUTES ObjectAttributes;
606 UNICODE_STRING SubKeyName;
607 HANDLE ParentKey;
608 HANDLE TargetKey;
609 NTSTATUS Status;
610 LONG ErrorCode;
611
612 Status = MapDefaultKey (&ParentKey,
613 hKey);
614 if (!NT_SUCCESS(Status))
615 {
616 ErrorCode = RtlNtStatusToDosError (Status);
617 SetLastError (ErrorCode);
618 return ErrorCode;
619 }
620
621 RtlCreateUnicodeStringFromAsciiz (&SubKeyName,
622 (LPSTR)lpSubKey);
623 InitializeObjectAttributes(&ObjectAttributes,
624 &SubKeyName,
625 OBJ_CASE_INSENSITIVE,
626 (HANDLE)ParentKey,
627 NULL);
628
629 Status = NtOpenKey (&TargetKey,
630 DELETE,
631 &ObjectAttributes);
632 RtlFreeUnicodeString (&SubKeyName);
633 if (!NT_SUCCESS(Status))
634 {
635 ErrorCode = RtlNtStatusToDosError (Status);
636 SetLastError (ErrorCode);
637 return ErrorCode;
638 }
639
640 Status = NtDeleteKey (TargetKey);
641 NtClose (TargetKey);
642 if (!NT_SUCCESS(Status))
643 {
644 ErrorCode = RtlNtStatusToDosError(Status);
645 SetLastError (ErrorCode);
646 return ErrorCode;
647 }
648
649 return ERROR_SUCCESS;
650 }
651
652
653 /************************************************************************
654 * RegDeleteKeyW
655 *
656 * @implemented
657 */
658 LONG STDCALL
659 RegDeleteKeyW (HKEY hKey,
660 LPCWSTR lpSubKey)
661 {
662 OBJECT_ATTRIBUTES ObjectAttributes;
663 UNICODE_STRING SubKeyName;
664 HANDLE ParentKey;
665 HANDLE TargetKey;
666 NTSTATUS Status;
667 LONG ErrorCode;
668
669 Status = MapDefaultKey (&ParentKey,
670 hKey);
671 if (!NT_SUCCESS(Status))
672 {
673 ErrorCode = RtlNtStatusToDosError (Status);
674 SetLastError (ErrorCode);
675 return ErrorCode;
676 }
677
678 RtlInitUnicodeString (&SubKeyName,
679 (LPWSTR)lpSubKey);
680 InitializeObjectAttributes (&ObjectAttributes,
681 &SubKeyName,
682 OBJ_CASE_INSENSITIVE,
683 (HANDLE)ParentKey,
684 NULL);
685 Status = NtOpenKey (&TargetKey,
686 DELETE,
687 &ObjectAttributes);
688 if (!NT_SUCCESS(Status))
689 {
690 ErrorCode = RtlNtStatusToDosError (Status);
691 SetLastError (ErrorCode);
692 return ErrorCode;
693 }
694
695 Status = NtDeleteKey (TargetKey);
696 NtClose (TargetKey);
697 if (!NT_SUCCESS(Status))
698 {
699 ErrorCode = RtlNtStatusToDosError (Status);
700 SetLastError (ErrorCode);
701 return ErrorCode;
702 }
703
704 return ERROR_SUCCESS;
705 }
706
707
708 /************************************************************************
709 * RegDeleteValueA
710 *
711 * @implemented
712 */
713 LONG STDCALL
714 RegDeleteValueA (HKEY hKey,
715 LPCSTR lpValueName)
716 {
717 UNICODE_STRING ValueName;
718 HANDLE KeyHandle;
719 LONG ErrorCode;
720 NTSTATUS Status;
721
722 Status = MapDefaultKey (&KeyHandle,
723 hKey);
724 if (!NT_SUCCESS(Status))
725 {
726 ErrorCode = RtlNtStatusToDosError (Status);
727 SetLastError (ErrorCode);
728 return ErrorCode;
729 }
730
731 RtlCreateUnicodeStringFromAsciiz (&ValueName,
732 (LPSTR)lpValueName);
733 Status = NtDeleteValueKey (KeyHandle,
734 &ValueName);
735 RtlFreeUnicodeString (&ValueName);
736 if (!NT_SUCCESS(Status))
737 {
738 ErrorCode = RtlNtStatusToDosError (Status);
739 SetLastError (ErrorCode);
740 return ErrorCode;
741 }
742
743 return ERROR_SUCCESS;
744 }
745
746
747 /************************************************************************
748 * RegDeleteValueW
749 *
750 * @implemented
751 */
752 LONG STDCALL
753 RegDeleteValueW (HKEY hKey,
754 LPCWSTR lpValueName)
755 {
756 UNICODE_STRING ValueName;
757 NTSTATUS Status;
758 LONG ErrorCode;
759 HANDLE KeyHandle;
760
761 Status = MapDefaultKey (&KeyHandle,
762 hKey);
763 if (!NT_SUCCESS(Status))
764 {
765 ErrorCode = RtlNtStatusToDosError (Status);
766 SetLastError (ErrorCode);
767 return ErrorCode;
768 }
769
770 RtlInitUnicodeString (&ValueName,
771 (LPWSTR)lpValueName);
772
773 Status = NtDeleteValueKey (KeyHandle,
774 &ValueName);
775 if (!NT_SUCCESS(Status))
776 {
777 ErrorCode = RtlNtStatusToDosError (Status);
778 SetLastError (ErrorCode);
779 return ErrorCode;
780 }
781
782 return ERROR_SUCCESS;
783 }
784
785
786 /************************************************************************
787 * RegEnumKeyA
788 *
789 * @implemented
790 */
791 LONG STDCALL
792 RegEnumKeyA (HKEY hKey,
793 DWORD dwIndex,
794 LPSTR lpName,
795 DWORD cbName)
796 {
797 DWORD dwLength;
798
799 dwLength = cbName;
800 return RegEnumKeyExA (hKey,
801 dwIndex,
802 lpName,
803 &dwLength,
804 NULL,
805 NULL,
806 NULL,
807 NULL);
808 }
809
810
811 /************************************************************************
812 * RegEnumKeyW
813 *
814 * @implemented
815 */
816 LONG STDCALL
817 RegEnumKeyW (HKEY hKey,
818 DWORD dwIndex,
819 LPWSTR lpName,
820 DWORD cbName)
821 {
822 DWORD dwLength;
823
824 dwLength = cbName;
825 return RegEnumKeyExW (hKey,
826 dwIndex,
827 lpName,
828 &dwLength,
829 NULL,
830 NULL,
831 NULL,
832 NULL);
833 }
834
835
836 /************************************************************************
837 * RegEnumKeyExA
838 *
839 * @implemented
840 */
841 LONG STDCALL
842 RegEnumKeyExA (HKEY hKey,
843 DWORD dwIndex,
844 LPSTR lpName,
845 LPDWORD lpcbName,
846 LPDWORD lpReserved,
847 LPSTR lpClass,
848 LPDWORD lpcbClass,
849 PFILETIME lpftLastWriteTime)
850 {
851 union
852 {
853 KEY_NODE_INFORMATION Node;
854 KEY_BASIC_INFORMATION Basic;
855 } *KeyInfo;
856
857 UNICODE_STRING StringU;
858 ANSI_STRING StringA;
859 LONG ErrorCode = ERROR_SUCCESS;
860 DWORD NameLength;
861 DWORD ClassLength = 0;
862 DWORD BufferSize;
863 DWORD ResultSize;
864 HANDLE KeyHandle;
865 NTSTATUS Status;
866
867 DPRINT("RegEnumKeyExA(hKey 0x%x, dwIndex %d, lpName 0x%x, *lpcbName %d, lpClass 0x%x, lpcbClass %d)\n",
868 hKey, dwIndex, lpName, *lpcbName, lpClass, lpcbClass ? *lpcbClass : 0);
869
870 if ((lpClass) && (!lpcbClass))
871 {
872 SetLastError (ERROR_INVALID_PARAMETER);
873 return ERROR_INVALID_PARAMETER;
874 }
875
876 Status = MapDefaultKey(&KeyHandle,
877 hKey);
878 if (!NT_SUCCESS(Status))
879 {
880 ErrorCode = RtlNtStatusToDosError (Status);
881 SetLastError (ErrorCode);
882 return ErrorCode;
883 }
884
885 if (*lpcbName > 0)
886 {
887 NameLength = min (*lpcbName - 1 , REG_MAX_NAME_SIZE) * sizeof (WCHAR);
888 }
889 else
890 {
891 NameLength = 0;
892 }
893
894 if (lpClass)
895 {
896 if (*lpcbClass > 0)
897 {
898 ClassLength = min (*lpcbClass -1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
899 }
900 else
901 {
902 ClassLength = 0;
903 }
904
905 /* The class name should start at a dword boundary */
906 BufferSize = ((sizeof(KEY_NODE_INFORMATION) + NameLength + 3) & ~3) + ClassLength;
907 }
908 else
909 {
910 BufferSize = sizeof(KEY_BASIC_INFORMATION) + NameLength;
911 }
912
913 KeyInfo = RtlAllocateHeap (ProcessHeap,
914 0,
915 BufferSize);
916 if (KeyInfo == NULL)
917 {
918 SetLastError (ERROR_OUTOFMEMORY);
919 return ERROR_OUTOFMEMORY;
920 }
921
922 Status = NtEnumerateKey (KeyHandle,
923 (ULONG)dwIndex,
924 lpClass == NULL ? KeyBasicInformation : KeyNodeInformation,
925 KeyInfo,
926 BufferSize,
927 &ResultSize);
928 DPRINT("NtEnumerateKey() returned status 0x%X\n", Status);
929 if (!NT_SUCCESS(Status))
930 {
931 ErrorCode = RtlNtStatusToDosError (Status);
932 }
933 else
934 {
935 if (lpClass == NULL)
936 {
937 if (KeyInfo->Basic.NameLength > NameLength)
938 {
939 ErrorCode = ERROR_BUFFER_OVERFLOW;
940 }
941 else
942 {
943 StringU.Buffer = KeyInfo->Basic.Name;
944 StringU.Length = KeyInfo->Basic.NameLength;
945 StringU.MaximumLength = KeyInfo->Basic.NameLength;
946 }
947 }
948 else
949 {
950 if (KeyInfo->Node.NameLength > NameLength ||
951 KeyInfo->Node.ClassLength > ClassLength)
952 {
953 ErrorCode = ERROR_BUFFER_OVERFLOW;
954 }
955 else
956 {
957 StringA.Buffer = lpClass;
958 StringA.Length = 0;
959 StringA.MaximumLength = *lpcbClass;
960 StringU.Buffer = (PWCHAR)((ULONG_PTR)KeyInfo->Node.Name + KeyInfo->Node.ClassOffset);
961 StringU.Length = KeyInfo->Node.ClassLength;
962 StringU.MaximumLength = KeyInfo->Node.ClassLength;
963 RtlUnicodeStringToAnsiString (&StringA, &StringU, FALSE);
964 lpClass[StringA.Length] = 0;
965 *lpcbClass = StringA.Length;
966 StringU.Buffer = KeyInfo->Node.Name;
967 StringU.Length = KeyInfo->Node.NameLength;
968 StringU.MaximumLength = KeyInfo->Node.NameLength;
969 }
970 }
971
972 if (ErrorCode == ERROR_SUCCESS)
973 {
974 StringA.Buffer = lpName;
975 StringA.Length = 0;
976 StringA.MaximumLength = *lpcbName;
977 RtlUnicodeStringToAnsiString (&StringA, &StringU, FALSE);
978 lpName[StringA.Length] = 0;
979 *lpcbName = StringA.Length;
980 if (lpftLastWriteTime != NULL)
981 {
982 if (lpClass == NULL)
983 {
984 lpftLastWriteTime->dwLowDateTime = KeyInfo->Basic.LastWriteTime.u.LowPart;
985 lpftLastWriteTime->dwHighDateTime = KeyInfo->Basic.LastWriteTime.u.HighPart;
986 }
987 else
988 {
989 lpftLastWriteTime->dwLowDateTime = KeyInfo->Node.LastWriteTime.u.LowPart;
990 lpftLastWriteTime->dwHighDateTime = KeyInfo->Node.LastWriteTime.u.HighPart;
991 }
992 }
993 }
994 }
995
996 DPRINT("Key Namea0 Length %d\n", StringU.Length);
997 DPRINT("Key Namea1 Length %d\n", NameLength);
998 DPRINT("Key Namea Length %d\n", *lpcbName);
999 DPRINT("Key Namea %s\n", lpName);
1000
1001 RtlFreeHeap (ProcessHeap,
1002 0,
1003 KeyInfo);
1004
1005 if (ErrorCode != ERROR_SUCCESS)
1006 {
1007 SetLastError(ErrorCode);
1008 }
1009
1010 return ErrorCode;
1011 }
1012
1013
1014 /************************************************************************
1015 * RegEnumKeyExW
1016 *
1017 * @implemented
1018 */
1019 LONG STDCALL
1020 RegEnumKeyExW (HKEY hKey,
1021 DWORD dwIndex,
1022 LPWSTR lpName,
1023 LPDWORD lpcbName,
1024 LPDWORD lpReserved,
1025 LPWSTR lpClass,
1026 LPDWORD lpcbClass,
1027 PFILETIME lpftLastWriteTime)
1028 {
1029 union
1030 {
1031 KEY_NODE_INFORMATION Node;
1032 KEY_BASIC_INFORMATION Basic;
1033 } *KeyInfo;
1034
1035 ULONG BufferSize;
1036 ULONG ResultSize;
1037 ULONG NameLength;
1038 ULONG ClassLength = 0;
1039 HANDLE KeyHandle;
1040 LONG ErrorCode = ERROR_SUCCESS;
1041 NTSTATUS Status;
1042
1043 Status = MapDefaultKey(&KeyHandle,
1044 hKey);
1045 if (!NT_SUCCESS(Status))
1046 {
1047 ErrorCode = RtlNtStatusToDosError (Status);
1048 SetLastError (ErrorCode);
1049 return ErrorCode;
1050 }
1051
1052 if (*lpcbName > 0)
1053 {
1054 NameLength = min (*lpcbName - 1, REG_MAX_NAME_SIZE) * sizeof (WCHAR);
1055 }
1056 else
1057 {
1058 NameLength = 0;
1059 }
1060
1061 if (lpClass)
1062 {
1063 if (*lpcbClass > 0)
1064 {
1065 ClassLength = min (*lpcbClass - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
1066 }
1067 else
1068 {
1069 ClassLength = 0;
1070 }
1071
1072 BufferSize = ((sizeof(KEY_NODE_INFORMATION) + NameLength + 3) & ~3) + ClassLength;
1073 }
1074 else
1075 {
1076 BufferSize = sizeof(KEY_BASIC_INFORMATION) + NameLength;
1077 }
1078
1079 KeyInfo = RtlAllocateHeap (ProcessHeap,
1080 0,
1081 BufferSize);
1082 if (KeyInfo == NULL)
1083 {
1084 SetLastError (ERROR_OUTOFMEMORY);
1085 return ERROR_OUTOFMEMORY;
1086 }
1087
1088 Status = NtEnumerateKey (KeyHandle,
1089 (ULONG)dwIndex,
1090 lpClass ? KeyNodeInformation : KeyBasicInformation,
1091 KeyInfo,
1092 BufferSize,
1093 &ResultSize);
1094 DPRINT("NtEnumerateKey() returned status 0x%X\n", Status);
1095 if (!NT_SUCCESS(Status))
1096 {
1097 ErrorCode = RtlNtStatusToDosError (Status);
1098 }
1099 else
1100 {
1101 if (lpClass == NULL)
1102 {
1103 if (KeyInfo->Basic.NameLength > NameLength)
1104 {
1105 ErrorCode = ERROR_BUFFER_OVERFLOW;
1106 }
1107 else
1108 {
1109 RtlCopyMemory (lpName,
1110 KeyInfo->Basic.Name,
1111 KeyInfo->Basic.NameLength);
1112 *lpcbName = (DWORD)(KeyInfo->Basic.NameLength / sizeof(WCHAR));
1113 lpName[*lpcbName] = 0;
1114 }
1115 }
1116 else
1117 {
1118 if (KeyInfo->Node.NameLength > NameLength ||
1119 KeyInfo->Node.ClassLength > ClassLength)
1120 {
1121 ErrorCode = ERROR_BUFFER_OVERFLOW;
1122 }
1123 else
1124 {
1125 RtlCopyMemory (lpName,
1126 KeyInfo->Node.Name,
1127 KeyInfo->Node.NameLength);
1128 *lpcbName = KeyInfo->Node.NameLength / sizeof(WCHAR);
1129 lpName[*lpcbName] = 0;
1130 RtlCopyMemory (lpClass,
1131 (PVOID)((ULONG_PTR)KeyInfo->Node.Name + KeyInfo->Node.ClassOffset),
1132 KeyInfo->Node.ClassLength);
1133 *lpcbClass = (DWORD)(KeyInfo->Node.ClassLength / sizeof(WCHAR));
1134 lpClass[*lpcbClass] = 0;
1135 }
1136 }
1137
1138 if (ErrorCode == ERROR_SUCCESS && lpftLastWriteTime != NULL)
1139 {
1140 if (lpClass == NULL)
1141 {
1142 lpftLastWriteTime->dwLowDateTime = KeyInfo->Basic.LastWriteTime.u.LowPart;
1143 lpftLastWriteTime->dwHighDateTime = KeyInfo->Basic.LastWriteTime.u.HighPart;
1144 }
1145 else
1146 {
1147 lpftLastWriteTime->dwLowDateTime = KeyInfo->Node.LastWriteTime.u.LowPart;
1148 lpftLastWriteTime->dwHighDateTime = KeyInfo->Node.LastWriteTime.u.HighPart;
1149 }
1150 }
1151 }
1152
1153 RtlFreeHeap (ProcessHeap,
1154 0,
1155 KeyInfo);
1156
1157 if (ErrorCode != ERROR_SUCCESS)
1158 {
1159 SetLastError(ErrorCode);
1160 }
1161
1162 return ErrorCode;
1163 }
1164
1165
1166 /************************************************************************
1167 * RegEnumValueA
1168 *
1169 * @implemented
1170 */
1171 LONG STDCALL
1172 RegEnumValueA (HKEY hKey,
1173 DWORD dwIndex,
1174 LPSTR lpValueName,
1175 LPDWORD lpcbValueName,
1176 LPDWORD lpReserved,
1177 LPDWORD lpType,
1178 LPBYTE lpData,
1179 LPDWORD lpcbData)
1180 {
1181 union
1182 {
1183 KEY_VALUE_FULL_INFORMATION Full;
1184 KEY_VALUE_BASIC_INFORMATION Basic;
1185 } *ValueInfo;
1186
1187 ULONG NameLength;
1188 ULONG BufferSize;
1189 ULONG DataLength = 0;
1190 ULONG ResultSize;
1191 HANDLE KeyHandle;
1192 LONG ErrorCode;
1193 NTSTATUS Status;
1194 UNICODE_STRING StringU;
1195 ANSI_STRING StringA;
1196 BOOL IsStringType;
1197
1198 ErrorCode = ERROR_SUCCESS;
1199
1200 Status = MapDefaultKey (&KeyHandle,
1201 hKey);
1202 if (!NT_SUCCESS(Status))
1203 {
1204 ErrorCode = RtlNtStatusToDosError (Status);
1205 SetLastError (ErrorCode);
1206 return ErrorCode;
1207 }
1208
1209 if (*lpcbValueName > 0)
1210 {
1211 NameLength = min (*lpcbValueName - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
1212 }
1213 else
1214 {
1215 NameLength = 0;
1216 }
1217
1218 if (lpData)
1219 {
1220 DataLength = min (*lpcbData * sizeof(WCHAR), REG_MAX_DATA_SIZE);
1221 BufferSize = ((sizeof(KEY_VALUE_FULL_INFORMATION) + NameLength + 3) & ~3) + DataLength;
1222 }
1223 else
1224 {
1225 BufferSize = sizeof(KEY_VALUE_BASIC_INFORMATION) + NameLength;
1226 }
1227
1228 ValueInfo = RtlAllocateHeap (ProcessHeap,
1229 0,
1230 BufferSize);
1231 if (ValueInfo == NULL)
1232 {
1233 SetLastError(ERROR_OUTOFMEMORY);
1234 return ERROR_OUTOFMEMORY;
1235 }
1236
1237 Status = NtEnumerateValueKey (KeyHandle,
1238 (ULONG)dwIndex,
1239 lpData ? KeyValueFullInformation : KeyValueBasicInformation,
1240 ValueInfo,
1241 BufferSize,
1242 &ResultSize);
1243
1244 DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status);
1245 if (!NT_SUCCESS(Status))
1246 {
1247 ErrorCode = RtlNtStatusToDosError (Status);
1248 }
1249 else
1250 {
1251 if (lpData)
1252 {
1253 IsStringType = (ValueInfo->Full.Type == REG_SZ) ||
1254 (ValueInfo->Full.Type == REG_MULTI_SZ) ||
1255 (ValueInfo->Full.Type == REG_EXPAND_SZ);
1256 if (ValueInfo->Full.NameLength > NameLength ||
1257 (!IsStringType && ValueInfo->Full.DataLength > *lpcbData) ||
1258 ValueInfo->Full.DataLength > DataLength)
1259 {
1260 ErrorCode = ERROR_BUFFER_OVERFLOW;
1261 }
1262 else
1263 {
1264 if (IsStringType)
1265 {
1266 StringU.Buffer = (PWCHAR)((ULONG_PTR)ValueInfo + ValueInfo->Full.DataOffset);
1267 StringU.Length = ValueInfo->Full.DataLength;
1268 StringU.MaximumLength = DataLength;
1269 StringA.Buffer = (PCHAR)lpData;
1270 StringA.Length = 0;
1271 StringA.MaximumLength = *lpcbData;
1272 RtlUnicodeStringToAnsiString (&StringA,
1273 &StringU,
1274 FALSE);
1275 *lpcbData = StringA.Length;
1276 }
1277 else
1278 {
1279 RtlCopyMemory (lpData,
1280 (PVOID)((ULONG_PTR)ValueInfo + ValueInfo->Full.DataOffset),
1281 ValueInfo->Full.DataLength);
1282 *lpcbData = ValueInfo->Full.DataLength;
1283 }
1284
1285 StringU.Buffer = ValueInfo->Full.Name;
1286 StringU.Length = ValueInfo->Full.NameLength;
1287 StringU.MaximumLength = NameLength;
1288 }
1289 }
1290 else
1291 {
1292 if (ValueInfo->Basic.NameLength > NameLength)
1293 {
1294 ErrorCode = ERROR_BUFFER_OVERFLOW;
1295 }
1296 else
1297 {
1298 StringU.Buffer = ValueInfo->Basic.Name;
1299 StringU.Length = ValueInfo->Basic.NameLength;
1300 StringU.MaximumLength = NameLength;
1301 }
1302 }
1303
1304 if (ErrorCode == ERROR_SUCCESS)
1305 {
1306 StringA.Buffer = (PCHAR)lpValueName;
1307 StringA.Length = 0;
1308 StringA.MaximumLength = *lpcbValueName;
1309 RtlUnicodeStringToAnsiString (&StringA,
1310 &StringU,
1311 FALSE);
1312 StringA.Buffer[StringA.Length] = 0;
1313 *lpcbValueName = StringA.Length;
1314 if (lpType)
1315 {
1316 *lpType = lpData ? ValueInfo->Full.Type : ValueInfo->Basic.Type;
1317 }
1318 }
1319 }
1320
1321 RtlFreeHeap (ProcessHeap,
1322 0,
1323 ValueInfo);
1324 if (ErrorCode != ERROR_SUCCESS)
1325 {
1326 SetLastError(ErrorCode);
1327 }
1328
1329 return ErrorCode;
1330 }
1331
1332
1333 /************************************************************************
1334 * RegEnumValueW
1335 *
1336 * @implemented
1337 */
1338 LONG STDCALL
1339 RegEnumValueW (HKEY hKey,
1340 DWORD dwIndex,
1341 LPWSTR lpValueName,
1342 LPDWORD lpcbValueName,
1343 LPDWORD lpReserved,
1344 LPDWORD lpType,
1345 LPBYTE lpData,
1346 LPDWORD lpcbData)
1347 {
1348 union
1349 {
1350 KEY_VALUE_FULL_INFORMATION Full;
1351 KEY_VALUE_BASIC_INFORMATION Basic;
1352 } *ValueInfo;
1353
1354 ULONG NameLength;
1355 ULONG BufferSize;
1356 ULONG DataLength = 0;
1357 ULONG ResultSize;
1358 HANDLE KeyHandle;
1359 LONG ErrorCode;
1360 NTSTATUS Status;
1361
1362 ErrorCode = ERROR_SUCCESS;
1363
1364 Status = MapDefaultKey (&KeyHandle,
1365 hKey);
1366 if (!NT_SUCCESS(Status))
1367 {
1368 ErrorCode = RtlNtStatusToDosError (Status);
1369 SetLastError (ErrorCode);
1370 return ErrorCode;
1371 }
1372
1373 if (*lpcbValueName > 0)
1374 {
1375 NameLength = min (*lpcbValueName - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
1376 }
1377 else
1378 {
1379 NameLength = 0;
1380 }
1381
1382 if (lpData)
1383 {
1384 DataLength = min(*lpcbData, REG_MAX_DATA_SIZE);
1385 BufferSize = ((sizeof(KEY_VALUE_FULL_INFORMATION) + NameLength + 3) & ~3) + DataLength;
1386 }
1387 else
1388 {
1389 BufferSize = sizeof(KEY_VALUE_BASIC_INFORMATION) + NameLength;
1390 }
1391 ValueInfo = RtlAllocateHeap (ProcessHeap,
1392 0,
1393 BufferSize);
1394 if (ValueInfo == NULL)
1395 {
1396 SetLastError (ERROR_OUTOFMEMORY);
1397 return ERROR_OUTOFMEMORY;
1398 }
1399 Status = NtEnumerateValueKey (KeyHandle,
1400 (ULONG)dwIndex,
1401 lpData ? KeyValueFullInformation : KeyValueBasicInformation,
1402 ValueInfo,
1403 BufferSize,
1404 &ResultSize);
1405
1406 DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status);
1407 if (!NT_SUCCESS(Status))
1408 {
1409 ErrorCode = RtlNtStatusToDosError (Status);
1410 }
1411 else
1412 {
1413 if (lpData)
1414 {
1415 if (ValueInfo->Full.DataLength > DataLength ||
1416 ValueInfo->Full.NameLength > NameLength)
1417 {
1418 ErrorCode = ERROR_BUFFER_OVERFLOW;
1419 }
1420 else
1421 {
1422 RtlCopyMemory (lpValueName,
1423 ValueInfo->Full.Name,
1424 ValueInfo->Full.NameLength);
1425 *lpcbValueName = (DWORD)(ValueInfo->Full.NameLength / sizeof(WCHAR));
1426 lpValueName[*lpcbValueName] = 0;
1427 RtlCopyMemory (lpData,
1428 (PVOID)((ULONG_PTR)ValueInfo + ValueInfo->Full.DataOffset),
1429 ValueInfo->Full.DataLength);
1430 *lpcbData = (DWORD)ValueInfo->Full.DataLength;
1431 }
1432 }
1433 else
1434 {
1435 if (ValueInfo->Basic.NameLength > NameLength)
1436 {
1437 ErrorCode = ERROR_BUFFER_OVERFLOW;
1438 }
1439 else
1440 {
1441 RtlCopyMemory (lpValueName,
1442 ValueInfo->Basic.Name,
1443 ValueInfo->Basic.NameLength);
1444 *lpcbValueName = (DWORD)(ValueInfo->Basic.NameLength / sizeof(WCHAR));
1445 lpValueName[*lpcbValueName] = 0;
1446 }
1447 *lpcbData = (DWORD)ValueInfo->Full.DataLength;
1448 }
1449
1450 if (ErrorCode == ERROR_SUCCESS && lpType != NULL)
1451 {
1452 *lpType = lpData ? ValueInfo->Full.Type : ValueInfo->Basic.Type;
1453 }
1454 }
1455
1456 RtlFreeHeap (ProcessHeap,
1457 0,
1458 ValueInfo);
1459
1460 if (ErrorCode != ERROR_SUCCESS)
1461 {
1462 SetLastError (ErrorCode);
1463 }
1464
1465 return ErrorCode;
1466 }
1467
1468
1469 /************************************************************************
1470 * RegFlushKey
1471 *
1472 * @implemented
1473 */
1474 LONG STDCALL
1475 RegFlushKey(HKEY hKey)
1476 {
1477 HANDLE KeyHandle;
1478 LONG ErrorCode;
1479 NTSTATUS Status;
1480
1481 if (hKey == HKEY_PERFORMANCE_DATA)
1482 {
1483 return ERROR_SUCCESS;
1484 }
1485
1486 Status = MapDefaultKey (&KeyHandle,
1487 hKey);
1488 if (!NT_SUCCESS(Status))
1489 {
1490 ErrorCode = RtlNtStatusToDosError (Status);
1491 SetLastError (ErrorCode);
1492 return ErrorCode;
1493 }
1494
1495 Status = NtFlushKey (KeyHandle);
1496 if (!NT_SUCCESS(Status))
1497 {
1498 ErrorCode = RtlNtStatusToDosError (Status);
1499 SetLastError (ErrorCode);
1500 return ErrorCode;
1501 }
1502
1503 return ERROR_SUCCESS;
1504 }
1505
1506
1507 /************************************************************************
1508 * RegGetKeySecurity
1509 *
1510 * @implemented
1511 */
1512 LONG STDCALL
1513 RegGetKeySecurity(HKEY hKey,
1514 SECURITY_INFORMATION SecurityInformation,
1515 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1516 LPDWORD lpcbSecurityDescriptor)
1517 {
1518 HANDLE KeyHandle;
1519 LONG ErrorCode;
1520 NTSTATUS Status;
1521
1522 if (hKey == HKEY_PERFORMANCE_DATA)
1523 {
1524 SetLastError(ERROR_INVALID_HANDLE);
1525 return ERROR_INVALID_HANDLE;
1526 }
1527
1528 Status = MapDefaultKey(&KeyHandle,
1529 hKey);
1530 if (!NT_SUCCESS(Status))
1531 {
1532 DPRINT("MapDefaultKey() failed (Status %lx)\n", Status);
1533 ErrorCode = RtlNtStatusToDosError(Status);
1534 SetLastError(ErrorCode);
1535 return ErrorCode;
1536 }
1537
1538 Status = NtQuerySecurityObject(KeyHandle,
1539 SecurityInformation,
1540 pSecurityDescriptor,
1541 *lpcbSecurityDescriptor,
1542 lpcbSecurityDescriptor);
1543 if (!NT_SUCCESS(Status))
1544 {
1545 DPRINT("NtQuerySecurityObject() failed (Status %lx)\n", Status);
1546 ErrorCode = RtlNtStatusToDosError(Status);
1547 SetLastError(ErrorCode);
1548 return ErrorCode;
1549 }
1550
1551 return ERROR_SUCCESS;
1552 }
1553
1554
1555 /************************************************************************
1556 * RegLoadKeyA
1557 *
1558 * @implemented
1559 */
1560 LONG STDCALL
1561 RegLoadKeyA (HKEY hKey,
1562 LPCSTR lpSubKey,
1563 LPCSTR lpFile)
1564 {
1565 UNICODE_STRING FileName;
1566 UNICODE_STRING KeyName;
1567 LONG ErrorCode;
1568
1569 RtlCreateUnicodeStringFromAsciiz (&KeyName,
1570 (LPSTR)lpSubKey);
1571 RtlCreateUnicodeStringFromAsciiz (&FileName,
1572 (LPSTR)lpFile);
1573
1574 ErrorCode = RegLoadKeyW (hKey,
1575 KeyName.Buffer,
1576 FileName.Buffer);
1577
1578 RtlFreeUnicodeString (&FileName);
1579 RtlFreeUnicodeString (&KeyName);
1580
1581 return ErrorCode;
1582 }
1583
1584
1585 /************************************************************************
1586 * RegLoadKeyW
1587 *
1588 * @implemented
1589 */
1590 LONG STDCALL
1591 RegLoadKeyW (HKEY hKey,
1592 LPCWSTR lpSubKey,
1593 LPCWSTR lpFile)
1594 {
1595 OBJECT_ATTRIBUTES FileObjectAttributes;
1596 OBJECT_ATTRIBUTES KeyObjectAttributes;
1597 UNICODE_STRING FileName;
1598 UNICODE_STRING KeyName;
1599 HANDLE KeyHandle;
1600 LONG ErrorCode;
1601 NTSTATUS Status;
1602
1603 if (hKey == HKEY_PERFORMANCE_DATA)
1604 {
1605 SetLastError(ERROR_INVALID_HANDLE);
1606 return ERROR_INVALID_HANDLE;
1607 }
1608
1609 Status = MapDefaultKey (&KeyHandle,
1610 hKey);
1611 if (!NT_SUCCESS(Status))
1612 {
1613 ErrorCode = RtlNtStatusToDosError (Status);
1614 SetLastError (ErrorCode);
1615 return ErrorCode;
1616 }
1617
1618 if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFile,
1619 &FileName,
1620 NULL,
1621 NULL))
1622 {
1623 SetLastError (ERROR_BAD_PATHNAME);
1624 return ERROR_BAD_PATHNAME;
1625 }
1626
1627 InitializeObjectAttributes (&FileObjectAttributes,
1628 &FileName,
1629 OBJ_CASE_INSENSITIVE,
1630 NULL,
1631 NULL);
1632
1633 RtlInitUnicodeString (&KeyName,
1634 (LPWSTR)lpSubKey);
1635
1636 InitializeObjectAttributes (&KeyObjectAttributes,
1637 &KeyName,
1638 OBJ_CASE_INSENSITIVE,
1639 KeyHandle,
1640 NULL);
1641
1642 Status = NtLoadKey (&KeyObjectAttributes,
1643 &FileObjectAttributes);
1644
1645 RtlFreeUnicodeString (&FileName);
1646
1647 if (!NT_SUCCESS(Status))
1648 {
1649 ErrorCode = RtlNtStatusToDosError (Status);
1650 SetLastError (ErrorCode);
1651 return ErrorCode;
1652 }
1653
1654 return ERROR_SUCCESS;
1655 }
1656
1657
1658 /************************************************************************
1659 * RegNotifyChangeKeyValue
1660 *
1661 * @unimplemented
1662 */
1663 LONG STDCALL
1664 RegNotifyChangeKeyValue (HKEY hKey,
1665 BOOL bWatchSubtree,
1666 DWORD dwNotifyFilter,
1667 HANDLE hEvent,
1668 BOOL fAsynchronous)
1669 {
1670 IO_STATUS_BLOCK IoStatusBlock;
1671 HANDLE KeyHandle;
1672 NTSTATUS Status;
1673
1674 if (hKey == HKEY_PERFORMANCE_DATA)
1675 {
1676 return ERROR_INVALID_HANDLE;
1677 }
1678
1679 if (fAsynchronous == TRUE && hEvent == NULL)
1680 {
1681 return ERROR_INVALID_PARAMETER;
1682 }
1683
1684 Status = MapDefaultKey (&KeyHandle,
1685 hKey);
1686 if (!NT_SUCCESS(Status))
1687 {
1688 return RtlNtStatusToDosError (Status);
1689 }
1690
1691 /* FIXME: Remote key handles must fail */
1692
1693 Status = NtNotifyChangeKey (KeyHandle,
1694 hEvent,
1695 0,
1696 0,
1697 &IoStatusBlock,
1698 dwNotifyFilter,
1699 bWatchSubtree,
1700 0,
1701 0,
1702 fAsynchronous);
1703 if (!NT_SUCCESS(Status) && Status != STATUS_TIMEOUT)
1704 {
1705 return RtlNtStatusToDosError (Status);
1706 }
1707
1708 return ERROR_SUCCESS;
1709 }
1710
1711
1712 /************************************************************************
1713 * RegOpenKeyA
1714 *
1715 * @implemented
1716 */
1717 LONG STDCALL
1718 RegOpenKeyA (HKEY hKey,
1719 LPCSTR lpSubKey,
1720 PHKEY phkResult)
1721 {
1722 OBJECT_ATTRIBUTES ObjectAttributes;
1723 UNICODE_STRING SubKeyString;
1724 HANDLE KeyHandle;
1725 LONG ErrorCode;
1726 NTSTATUS Status;
1727
1728 Status = MapDefaultKey (&KeyHandle,
1729 hKey);
1730 if (!NT_SUCCESS(Status))
1731 {
1732 ErrorCode = RtlNtStatusToDosError (Status);
1733 SetLastError (ErrorCode);
1734 return ErrorCode;
1735 }
1736
1737 RtlCreateUnicodeStringFromAsciiz (&SubKeyString,
1738 (LPSTR)lpSubKey);
1739 InitializeObjectAttributes (&ObjectAttributes,
1740 &SubKeyString,
1741 OBJ_CASE_INSENSITIVE,
1742 KeyHandle,
1743 NULL);
1744 Status = NtOpenKey ((PHANDLE)phkResult,
1745 MAXIMUM_ALLOWED,
1746 &ObjectAttributes);
1747 RtlFreeUnicodeString (&SubKeyString);
1748 if (!NT_SUCCESS(Status))
1749 {
1750 ErrorCode = RtlNtStatusToDosError (Status);
1751 SetLastError (ErrorCode);
1752 return ErrorCode;
1753 }
1754
1755 return ERROR_SUCCESS;
1756 }
1757
1758
1759 /************************************************************************
1760 * RegOpenKeyW
1761 *
1762 * 19981101 Ariadne
1763 * 19990525 EA
1764 *
1765 * @implemented
1766 */
1767 LONG STDCALL
1768 RegOpenKeyW (HKEY hKey,
1769 LPCWSTR lpSubKey,
1770 PHKEY phkResult)
1771 {
1772 OBJECT_ATTRIBUTES ObjectAttributes;
1773 UNICODE_STRING SubKeyString;
1774 HANDLE KeyHandle;
1775 LONG ErrorCode;
1776 NTSTATUS Status;
1777
1778 Status = MapDefaultKey (&KeyHandle,
1779 hKey);
1780 if (!NT_SUCCESS(Status))
1781 {
1782 ErrorCode = RtlNtStatusToDosError (Status);
1783 SetLastError (ErrorCode);
1784 return ErrorCode;
1785 }
1786
1787 RtlInitUnicodeString (&SubKeyString,
1788 (LPWSTR)lpSubKey);
1789 InitializeObjectAttributes (&ObjectAttributes,
1790 &SubKeyString,
1791 OBJ_CASE_INSENSITIVE,
1792 KeyHandle,
1793 NULL);
1794 Status = NtOpenKey ((PHANDLE)phkResult,
1795 MAXIMUM_ALLOWED,
1796 &ObjectAttributes);
1797 if (!NT_SUCCESS(Status))
1798 {
1799 ErrorCode = RtlNtStatusToDosError (Status);
1800 SetLastError(ErrorCode);
1801 return ErrorCode;
1802 }
1803
1804 return ERROR_SUCCESS;
1805 }
1806
1807
1808 /************************************************************************
1809 * RegOpenKeyExA
1810 *
1811 * @implemented
1812 */
1813 LONG STDCALL
1814 RegOpenKeyExA (HKEY hKey,
1815 LPCSTR lpSubKey,
1816 DWORD ulOptions,
1817 REGSAM samDesired,
1818 PHKEY phkResult)
1819 {
1820 OBJECT_ATTRIBUTES ObjectAttributes;
1821 UNICODE_STRING SubKeyString;
1822 HANDLE KeyHandle;
1823 LONG ErrorCode;
1824 NTSTATUS Status;
1825
1826 Status = MapDefaultKey (&KeyHandle,
1827 hKey);
1828 if (!NT_SUCCESS(Status))
1829 {
1830 ErrorCode = RtlNtStatusToDosError (Status);
1831 SetLastError (ErrorCode);
1832 return ErrorCode;
1833 }
1834
1835 RtlCreateUnicodeStringFromAsciiz (&SubKeyString,
1836 (LPSTR)lpSubKey);
1837 InitializeObjectAttributes (&ObjectAttributes,
1838 &SubKeyString,
1839 OBJ_CASE_INSENSITIVE,
1840 KeyHandle,
1841 NULL);
1842 Status = NtOpenKey ((PHANDLE)phkResult,
1843 samDesired,
1844 &ObjectAttributes);
1845 RtlFreeUnicodeString (&SubKeyString);
1846 if (!NT_SUCCESS(Status))
1847 {
1848 ErrorCode = RtlNtStatusToDosError (Status);
1849 SetLastError (ErrorCode);
1850 return ErrorCode;
1851 }
1852
1853 return ERROR_SUCCESS;
1854 }
1855
1856
1857 /************************************************************************
1858 * RegOpenKeyExW
1859 *
1860 * @implemented
1861 */
1862 LONG STDCALL
1863 RegOpenKeyExW (HKEY hKey,
1864 LPCWSTR lpSubKey,
1865 DWORD ulOptions,
1866 REGSAM samDesired,
1867 PHKEY phkResult)
1868 {
1869 OBJECT_ATTRIBUTES ObjectAttributes;
1870 UNICODE_STRING SubKeyString;
1871 HANDLE KeyHandle;
1872 LONG ErrorCode;
1873 NTSTATUS Status;
1874
1875 Status = MapDefaultKey (&KeyHandle,
1876 hKey);
1877 if (!NT_SUCCESS(Status))
1878 {
1879 ErrorCode = RtlNtStatusToDosError (Status);
1880 SetLastError (ErrorCode);
1881 return ErrorCode;
1882 }
1883
1884 if (lpSubKey != NULL)
1885 {
1886 RtlInitUnicodeString (&SubKeyString,
1887 (LPWSTR)lpSubKey);
1888 }
1889 else
1890 {
1891 RtlInitUnicodeString (&SubKeyString,
1892 (LPWSTR)L"");
1893 }
1894 InitializeObjectAttributes (&ObjectAttributes,
1895 &SubKeyString,
1896 OBJ_CASE_INSENSITIVE,
1897 KeyHandle,
1898 NULL);
1899 Status = NtOpenKey ((PHANDLE)phkResult,
1900 samDesired,
1901 &ObjectAttributes);
1902 if (!NT_SUCCESS(Status))
1903 {
1904 ErrorCode = RtlNtStatusToDosError (Status);
1905 SetLastError (ErrorCode);
1906 return ErrorCode;
1907 }
1908
1909 return ERROR_SUCCESS;
1910 }
1911
1912
1913 /************************************************************************
1914 * RegQueryInfoKeyA
1915 *
1916 * @implemented
1917 */
1918 LONG STDCALL
1919 RegQueryInfoKeyA (HKEY hKey,
1920 LPSTR lpClass,
1921 LPDWORD lpcbClass,
1922 LPDWORD lpReserved,
1923 LPDWORD lpcSubKeys,
1924 LPDWORD lpcbMaxSubKeyLen,
1925 LPDWORD lpcbMaxClassLen,
1926 LPDWORD lpcValues,
1927 LPDWORD lpcbMaxValueNameLen,
1928 LPDWORD lpcbMaxValueLen,
1929 LPDWORD lpcbSecurityDescriptor,
1930 PFILETIME lpftLastWriteTime)
1931 {
1932 WCHAR ClassName[MAX_PATH];
1933 UNICODE_STRING UnicodeString;
1934 ANSI_STRING AnsiString;
1935 LONG ErrorCode;
1936
1937 RtlInitUnicodeString (&UnicodeString,
1938 NULL);
1939 if (lpClass != NULL)
1940 {
1941 UnicodeString.Buffer = &ClassName[0];
1942 UnicodeString.MaximumLength = sizeof(ClassName);
1943 AnsiString.MaximumLength = *lpcbClass;
1944 }
1945
1946 ErrorCode = RegQueryInfoKeyW (hKey,
1947 UnicodeString.Buffer,
1948 lpcbClass,
1949 lpReserved,
1950 lpcSubKeys,
1951 lpcbMaxSubKeyLen,
1952 lpcbMaxClassLen,
1953 lpcValues,
1954 lpcbMaxValueNameLen,
1955 lpcbMaxValueLen,
1956 lpcbSecurityDescriptor,
1957 lpftLastWriteTime);
1958 if ((ErrorCode == ERROR_SUCCESS) && (lpClass != NULL))
1959 {
1960 AnsiString.Buffer = lpClass;
1961 AnsiString.Length = 0;
1962 UnicodeString.Length = *lpcbClass * sizeof(WCHAR);
1963 RtlUnicodeStringToAnsiString (&AnsiString,
1964 &UnicodeString,
1965 FALSE);
1966 *lpcbClass = AnsiString.Length;
1967 lpClass[AnsiString.Length] = 0;
1968 }
1969
1970 return ErrorCode;
1971 }
1972
1973
1974 /************************************************************************
1975 * RegQueryInfoKeyW
1976 *
1977 * @implemented
1978 */
1979 LONG STDCALL
1980 RegQueryInfoKeyW (HKEY hKey,
1981 LPWSTR lpClass,
1982 LPDWORD lpcbClass,
1983 LPDWORD lpReserved,
1984 LPDWORD lpcSubKeys,
1985 LPDWORD lpcbMaxSubKeyLen,
1986 LPDWORD lpcbMaxClassLen,
1987 LPDWORD lpcValues,
1988 LPDWORD lpcbMaxValueNameLen,
1989 LPDWORD lpcbMaxValueLen,
1990 LPDWORD lpcbSecurityDescriptor,
1991 PFILETIME lpftLastWriteTime)
1992 {
1993 KEY_FULL_INFORMATION FullInfoBuffer;
1994 PKEY_FULL_INFORMATION FullInfo;
1995 ULONG FullInfoSize;
1996 ULONG ClassLength = 0;
1997 HANDLE KeyHandle;
1998 NTSTATUS Status;
1999 LONG ErrorCode = ERROR_SUCCESS;
2000 ULONG Length;
2001
2002 if ((lpClass) && (!lpcbClass))
2003 {
2004 SetLastError(ERROR_INVALID_PARAMETER);
2005 return ERROR_INVALID_PARAMETER;
2006 }
2007
2008 Status = MapDefaultKey (&KeyHandle,
2009 hKey);
2010 if (!NT_SUCCESS(Status))
2011 {
2012 ErrorCode = RtlNtStatusToDosError (Status);
2013 SetLastError (ErrorCode);
2014 return ErrorCode;
2015 }
2016
2017 if (lpClass != NULL)
2018 {
2019 if (*lpcbClass > 0)
2020 {
2021 ClassLength = min(*lpcbClass - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
2022 }
2023 else
2024 {
2025 ClassLength = 0;
2026 }
2027
2028 FullInfoSize = sizeof(KEY_FULL_INFORMATION) + ((ClassLength + 3) & ~3);
2029 FullInfo = RtlAllocateHeap (ProcessHeap,
2030 0,
2031 FullInfoSize);
2032 if (FullInfo == NULL)
2033 {
2034 SetLastError (ERROR_OUTOFMEMORY);
2035 return ERROR_OUTOFMEMORY;
2036 }
2037
2038 FullInfo->ClassLength = ClassLength;
2039 }
2040 else
2041 {
2042 FullInfoSize = sizeof(KEY_FULL_INFORMATION);
2043 FullInfo = &FullInfoBuffer;
2044 FullInfo->ClassLength = 0;
2045 }
2046 FullInfo->ClassOffset = FIELD_OFFSET(KEY_FULL_INFORMATION, Class);
2047
2048 Status = NtQueryKey (KeyHandle,
2049 KeyFullInformation,
2050 FullInfo,
2051 FullInfoSize,
2052 &Length);
2053 DPRINT("NtQueryKey() returned status 0x%X\n", Status);
2054 if (!NT_SUCCESS(Status))
2055 {
2056 if (lpClass != NULL)
2057 {
2058 RtlFreeHeap (ProcessHeap,
2059 0,
2060 FullInfo);
2061 }
2062
2063 ErrorCode = RtlNtStatusToDosError (Status);
2064 SetLastError (ErrorCode);
2065 return ErrorCode;
2066 }
2067
2068 DPRINT("SubKeys %d\n", FullInfo->SubKeys);
2069 if (lpcSubKeys != NULL)
2070 {
2071 *lpcSubKeys = FullInfo->SubKeys;
2072 }
2073
2074 DPRINT("MaxNameLen %lu\n", FullInfo->MaxNameLen);
2075 if (lpcbMaxSubKeyLen != NULL)
2076 {
2077 *lpcbMaxSubKeyLen = FullInfo->MaxNameLen / sizeof(WCHAR) + 1;
2078 }
2079
2080 DPRINT("MaxClassLen %lu\n", FullInfo->MaxClassLen);
2081 if (lpcbMaxClassLen != NULL)
2082 {
2083 *lpcbMaxClassLen = FullInfo->MaxClassLen / sizeof(WCHAR) + 1;
2084 }
2085
2086 DPRINT("Values %lu\n", FullInfo->Values);
2087 if (lpcValues != NULL)
2088 {
2089 *lpcValues = FullInfo->Values;
2090 }
2091
2092 DPRINT("MaxValueNameLen %lu\n", FullInfo->MaxValueNameLen);
2093 if (lpcbMaxValueNameLen != NULL)
2094 {
2095 *lpcbMaxValueNameLen = FullInfo->MaxValueNameLen / sizeof(WCHAR) + 1;
2096 }
2097
2098 DPRINT("MaxValueDataLen %lu\n", FullInfo->MaxValueDataLen);
2099 if (lpcbMaxValueLen != NULL)
2100 {
2101 *lpcbMaxValueLen = FullInfo->MaxValueDataLen;
2102 }
2103
2104 if (lpcbSecurityDescriptor != NULL)
2105 {
2106 Status = NtQuerySecurityObject(KeyHandle,
2107 OWNER_SECURITY_INFORMATION |
2108 GROUP_SECURITY_INFORMATION |
2109 DACL_SECURITY_INFORMATION,
2110 NULL,
2111 0,
2112 lpcbSecurityDescriptor);
2113 if (!NT_SUCCESS(Status))
2114 {
2115 if (lpClass != NULL)
2116 {
2117 RtlFreeHeap(ProcessHeap,
2118 0,
2119 FullInfo);
2120 }
2121
2122 ErrorCode = RtlNtStatusToDosError(Status);
2123 SetLastError(ErrorCode);
2124 return ErrorCode;
2125 }
2126 }
2127
2128 if (lpftLastWriteTime != NULL)
2129 {
2130 lpftLastWriteTime->dwLowDateTime = FullInfo->LastWriteTime.u.LowPart;
2131 lpftLastWriteTime->dwHighDateTime = FullInfo->LastWriteTime.u.HighPart;
2132 }
2133
2134 if (lpClass != NULL)
2135 {
2136 if (FullInfo->ClassLength > ClassLength)
2137 {
2138 ErrorCode = ERROR_BUFFER_OVERFLOW;
2139 }
2140 else
2141 {
2142 RtlCopyMemory (lpClass,
2143 FullInfo->Class,
2144 FullInfo->ClassLength);
2145 *lpcbClass = FullInfo->ClassLength / sizeof(WCHAR);
2146 lpClass[*lpcbClass] = 0;
2147 }
2148
2149 RtlFreeHeap (ProcessHeap,
2150 0,
2151 FullInfo);
2152 }
2153
2154 if (ErrorCode != ERROR_SUCCESS)
2155 {
2156 SetLastError (ErrorCode);
2157 }
2158
2159 return ErrorCode;
2160 }
2161
2162
2163 /************************************************************************
2164 * RegQueryMultipleValuesA
2165 *
2166 * @unimplemented
2167 */
2168 LONG STDCALL
2169 RegQueryMultipleValuesA (HKEY hKey,
2170 PVALENTA val_list,
2171 DWORD num_vals,
2172 LPSTR lpValueBuf,
2173 LPDWORD ldwTotsize)
2174 {
2175 UNIMPLEMENTED;
2176 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2177 return ERROR_CALL_NOT_IMPLEMENTED;
2178 }
2179
2180
2181 /************************************************************************
2182 * RegQueryMultipleValuesW
2183 *
2184 * @implemented
2185 */
2186 LONG STDCALL
2187 RegQueryMultipleValuesW (HKEY hKey,
2188 PVALENTW val_list,
2189 DWORD num_vals,
2190 LPWSTR lpValueBuf,
2191 LPDWORD ldwTotsize)
2192 {
2193 ULONG i;
2194 DWORD maxBytes = *ldwTotsize;
2195 LPSTR bufptr = (LPSTR)lpValueBuf;
2196 LONG ErrorCode;
2197
2198 if (maxBytes >= (1024*1024))
2199 return ERROR_TRANSFER_TOO_LONG;
2200
2201 *ldwTotsize = 0;
2202
2203 DPRINT ("RegQueryMultipleValuesW(%p,%p,%ld,%p,%p=%ld)\n",
2204 hKey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize);
2205
2206 for (i = 0; i < num_vals; ++i)
2207 {
2208 val_list[i].ve_valuelen = 0;
2209 ErrorCode = RegQueryValueExW (hKey,
2210 val_list[i].ve_valuename,
2211 NULL,
2212 NULL,
2213 NULL,
2214 &val_list[i].ve_valuelen);
2215 if (ErrorCode != ERROR_SUCCESS)
2216 {
2217 return ErrorCode;
2218 }
2219
2220 if (lpValueBuf != NULL && *ldwTotsize + val_list[i].ve_valuelen <= maxBytes)
2221 {
2222 ErrorCode = RegQueryValueExW (hKey,
2223 val_list[i].ve_valuename,
2224 NULL,
2225 &val_list[i].ve_type,
2226 bufptr,
2227 &val_list[i].ve_valuelen);
2228 if (ErrorCode != ERROR_SUCCESS)
2229 {
2230 return ErrorCode;
2231 }
2232
2233 val_list[i].ve_valueptr = (DWORD_PTR)bufptr;
2234
2235 bufptr += val_list[i].ve_valuelen;
2236 }
2237
2238 *ldwTotsize += val_list[i].ve_valuelen;
2239 }
2240
2241 return (lpValueBuf != NULL && *ldwTotsize <= maxBytes) ? ERROR_SUCCESS : ERROR_MORE_DATA;
2242 }
2243
2244
2245 /************************************************************************
2246 * RegQueryValueExW
2247 *
2248 * @implemented
2249 */
2250 LONG STDCALL
2251 RegQueryValueExW (HKEY hKey,
2252 LPCWSTR lpValueName,
2253 LPDWORD lpReserved,
2254 LPDWORD lpType,
2255 LPBYTE lpData,
2256 LPDWORD lpcbData)
2257 {
2258 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
2259 UNICODE_STRING ValueName;
2260 NTSTATUS Status;
2261 LONG ErrorCode = ERROR_SUCCESS;
2262 ULONG BufferSize;
2263 ULONG ResultSize;
2264 HANDLE KeyHandle;
2265 ULONG MaxCopy = lpcbData != NULL && lpData != NULL ? *lpcbData : 0;
2266
2267 DPRINT("hKey 0x%X lpValueName %S lpData 0x%X lpcbData %d\n",
2268 hKey, lpValueName, lpData, lpcbData ? *lpcbData : 0);
2269
2270 Status = MapDefaultKey (&KeyHandle,
2271 hKey);
2272 if (!NT_SUCCESS(Status))
2273 {
2274 ErrorCode = RtlNtStatusToDosError (Status);
2275 SetLastError (ErrorCode);
2276 return ErrorCode;
2277 }
2278
2279 if (lpData != NULL && lpcbData == NULL)
2280 {
2281 SetLastError (ERROR_INVALID_PARAMETER);
2282 return ERROR_INVALID_PARAMETER;
2283 }
2284
2285 RtlInitUnicodeString (&ValueName,
2286 lpValueName);
2287 BufferSize = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + MaxCopy;
2288 ValueInfo = RtlAllocateHeap (ProcessHeap,
2289 0,
2290 BufferSize);
2291 if (ValueInfo == NULL)
2292 {
2293 SetLastError(ERROR_OUTOFMEMORY);
2294 return ERROR_OUTOFMEMORY;
2295 }
2296
2297 Status = NtQueryValueKey (hKey,
2298 &ValueName,
2299 KeyValuePartialInformation,
2300 ValueInfo,
2301 BufferSize,
2302 &ResultSize);
2303 DPRINT("Status 0x%X\n", Status);
2304 if (Status == STATUS_BUFFER_TOO_SMALL)
2305 {
2306 /* Return ERROR_SUCCESS and the buffer space needed for a successful call */
2307 MaxCopy = 0;
2308 ErrorCode = lpData ? ERROR_MORE_DATA : ERROR_SUCCESS;
2309 }
2310 else if (!NT_SUCCESS(Status))
2311 {
2312 ErrorCode = RtlNtStatusToDosError (Status);
2313 SetLastError (ErrorCode);
2314 MaxCopy = 0;
2315 if (lpcbData != NULL)
2316 {
2317 ResultSize = sizeof(*ValueInfo) + *lpcbData;
2318 }
2319 }
2320
2321 if (lpType != NULL)
2322 {
2323 *lpType = ValueInfo->Type;
2324 }
2325
2326 if (NT_SUCCESS(Status) && lpData != NULL)
2327 {
2328 RtlMoveMemory (lpData,
2329 ValueInfo->Data,
2330 min(ValueInfo->DataLength, MaxCopy));
2331 }
2332
2333 if ((ValueInfo->Type == REG_SZ) ||
2334 (ValueInfo->Type == REG_MULTI_SZ) ||
2335 (ValueInfo->Type == REG_EXPAND_SZ))
2336 {
2337 if (lpData != NULL && MaxCopy > ValueInfo->DataLength)
2338 {
2339 ((PWSTR)lpData)[ValueInfo->DataLength / sizeof(WCHAR)] = 0;
2340 }
2341
2342 if (lpcbData != NULL)
2343 {
2344 *lpcbData = (ResultSize - sizeof(*ValueInfo));
2345 DPRINT("(string) Returning Size: %lu\n", *lpcbData);
2346 }
2347 }
2348 else
2349 {
2350 if (lpcbData != NULL)
2351 {
2352 *lpcbData = ResultSize - sizeof(*ValueInfo);
2353 DPRINT("(other) Returning Size: %lu\n", *lpcbData);
2354 }
2355 }
2356
2357 DPRINT("Type %d Size %d\n", ValueInfo->Type, ValueInfo->DataLength);
2358
2359 RtlFreeHeap (ProcessHeap,
2360 0,
2361 ValueInfo);
2362
2363 return ErrorCode;
2364 }
2365
2366
2367 /************************************************************************
2368 * RegQueryValueExA
2369 *
2370 * @implemented
2371 */
2372 LONG STDCALL
2373 RegQueryValueExA (HKEY hKey,
2374 LPCSTR lpValueName,
2375 LPDWORD lpReserved,
2376 LPDWORD lpType,
2377 LPBYTE lpData,
2378 LPDWORD lpcbData)
2379 {
2380 UNICODE_STRING ValueName;
2381 UNICODE_STRING ValueData;
2382 ANSI_STRING AnsiString;
2383 LONG ErrorCode;
2384 DWORD Length;
2385 DWORD Type;
2386
2387 if (lpData != NULL && lpcbData == NULL)
2388 {
2389 SetLastError(ERROR_INVALID_PARAMETER);
2390 return ERROR_INVALID_PARAMETER;
2391 }
2392
2393 if (lpData)
2394 {
2395 ValueData.Length = *lpcbData * sizeof(WCHAR);
2396 ValueData.MaximumLength = ValueData.Length + sizeof(WCHAR);
2397 ValueData.Buffer = RtlAllocateHeap (ProcessHeap,
2398 0,
2399 ValueData.MaximumLength);
2400 if (!ValueData.Buffer)
2401 {
2402 SetLastError(ERROR_OUTOFMEMORY);
2403 return ERROR_OUTOFMEMORY;
2404 }
2405 }
2406 else
2407 {
2408 ValueData.Buffer = NULL;
2409 ValueData.Length = 0;
2410 ValueData.MaximumLength = 0;
2411 }
2412
2413 RtlCreateUnicodeStringFromAsciiz (&ValueName,
2414 (LPSTR)lpValueName);
2415
2416 if (NULL != lpcbData)
2417 {
2418 Length = *lpcbData * sizeof(WCHAR);
2419 }
2420 ErrorCode = RegQueryValueExW (hKey,
2421 ValueName.Buffer,
2422 lpReserved,
2423 &Type,
2424 (LPBYTE)ValueData.Buffer,
2425 NULL == lpcbData ? NULL : &Length);
2426 DPRINT("ErrorCode %lu\n", ErrorCode);
2427
2428 if (ErrorCode == ERROR_SUCCESS ||
2429 ErrorCode == ERROR_MORE_DATA)
2430 {
2431 if (lpType != NULL)
2432 {
2433 *lpType = Type;
2434 }
2435
2436 if ((Type == REG_SZ) || (Type == REG_MULTI_SZ) || (Type == REG_EXPAND_SZ))
2437 {
2438 if (ErrorCode == ERROR_SUCCESS && ValueData.Buffer != NULL)
2439 {
2440 RtlInitAnsiString(&AnsiString, NULL);
2441 AnsiString.Buffer = lpData;
2442 AnsiString.MaximumLength = *lpcbData;
2443 ValueData.Length = Length;
2444 ValueData.MaximumLength = ValueData.Length + sizeof(WCHAR);
2445 RtlUnicodeStringToAnsiString(&AnsiString, &ValueData, FALSE);
2446 }
2447 Length = Length / sizeof(WCHAR);
2448 }
2449 else if (lpcbData != NULL)
2450 {
2451 Length = min(*lpcbData, Length);
2452 if (ErrorCode == ERROR_SUCCESS && ValueData.Buffer != NULL)
2453 {
2454 RtlMoveMemory(lpData, ValueData.Buffer, Length);
2455 }
2456 }
2457
2458 if (lpcbData != NULL)
2459 {
2460 *lpcbData = Length;
2461 }
2462 }
2463
2464 if (ValueData.Buffer != NULL)
2465 {
2466 RtlFreeHeap(ProcessHeap, 0, ValueData.Buffer);
2467 }
2468
2469 return ErrorCode;
2470 }
2471
2472
2473 /************************************************************************
2474 * RegQueryValueA
2475 *
2476 * @implemented
2477 */
2478 LONG STDCALL
2479 RegQueryValueA (HKEY hKey,
2480 LPCSTR lpSubKey,
2481 LPSTR lpValue,
2482 PLONG lpcbValue)
2483 {
2484 WCHAR SubKeyNameBuffer[MAX_PATH+1];
2485 UNICODE_STRING SubKeyName;
2486 UNICODE_STRING Value;
2487 ANSI_STRING AnsiString;
2488 LONG ValueSize;
2489 LONG ErrorCode;
2490
2491 if (lpValue != NULL &&
2492 lpcbValue == NULL)
2493 {
2494 SetLastError(ERROR_INVALID_PARAMETER);
2495 return ERROR_INVALID_PARAMETER;
2496 }
2497
2498 RtlInitUnicodeString (&SubKeyName,
2499 NULL);
2500 RtlInitUnicodeString (&Value,
2501 NULL);
2502 if (lpSubKey != NULL &&
2503 strlen(lpSubKey) != 0)
2504 {
2505 RtlInitAnsiString (&AnsiString,
2506 (LPSTR)lpSubKey);
2507 SubKeyName.Buffer = &SubKeyNameBuffer[0];
2508 SubKeyName.MaximumLength = sizeof(SubKeyNameBuffer);
2509 RtlAnsiStringToUnicodeString (&SubKeyName,
2510 &AnsiString,
2511 FALSE);
2512 }
2513
2514 if (lpValue != NULL)
2515 {
2516 ValueSize = *lpcbValue * sizeof(WCHAR);
2517 Value.MaximumLength = ValueSize;
2518 Value.Buffer = RtlAllocateHeap (ProcessHeap,
2519 0,
2520 ValueSize);
2521 if (Value.Buffer == NULL)
2522 {
2523 SetLastError(ERROR_OUTOFMEMORY);
2524 return ERROR_OUTOFMEMORY;
2525 }
2526 }
2527 else
2528 {
2529 ValueSize = 0;
2530 }
2531
2532 ErrorCode = RegQueryValueW (hKey,
2533 (LPCWSTR)SubKeyName.Buffer,
2534 Value.Buffer,
2535 &ValueSize);
2536 if (ErrorCode == ERROR_SUCCESS)
2537 {
2538 Value.Length = ValueSize;
2539 RtlInitAnsiString (&AnsiString,
2540 NULL);
2541 AnsiString.Buffer = lpValue;
2542 AnsiString.MaximumLength = *lpcbValue;
2543 RtlUnicodeStringToAnsiString (&AnsiString,
2544 &Value,
2545 FALSE);
2546 }
2547
2548 *lpcbValue = ValueSize;
2549 if (Value.Buffer != NULL)
2550 {
2551 RtlFreeHeap (ProcessHeap,
2552 0,
2553 Value.Buffer);
2554 }
2555
2556 return ErrorCode;
2557 }
2558
2559
2560 /************************************************************************
2561 * RegQueryValueW
2562 *
2563 * @implemented
2564 */
2565 LONG STDCALL
2566 RegQueryValueW (HKEY hKey,
2567 LPCWSTR lpSubKey,
2568 LPWSTR lpValue,
2569 PLONG lpcbValue)
2570 {
2571 OBJECT_ATTRIBUTES ObjectAttributes;
2572 UNICODE_STRING SubKeyString;
2573 HANDLE KeyHandle;
2574 HANDLE RealKey;
2575 LONG ErrorCode;
2576 BOOL CloseRealKey;
2577 NTSTATUS Status;
2578
2579 Status = MapDefaultKey (&KeyHandle,
2580 hKey);
2581 if (!NT_SUCCESS(Status))
2582 {
2583 ErrorCode = RtlNtStatusToDosError (Status);
2584 SetLastError (ErrorCode);
2585 return ErrorCode;
2586 }
2587
2588 if (lpSubKey != NULL &&
2589 wcslen(lpSubKey) != 0)
2590 {
2591 RtlInitUnicodeString (&SubKeyString,
2592 (LPWSTR)lpSubKey);
2593 InitializeObjectAttributes (&ObjectAttributes,
2594 &SubKeyString,
2595 OBJ_CASE_INSENSITIVE,
2596 KeyHandle,
2597 NULL);
2598 Status = NtOpenKey (&RealKey,
2599 KEY_ALL_ACCESS,
2600 &ObjectAttributes);
2601 if (!NT_SUCCESS(Status))
2602 {
2603 ErrorCode = RtlNtStatusToDosError (Status);
2604 SetLastError (ErrorCode);
2605 return ErrorCode;
2606 }
2607 CloseRealKey = TRUE;
2608 }
2609 else
2610 {
2611 RealKey = hKey;
2612 CloseRealKey = FALSE;
2613 }
2614
2615 ErrorCode = RegQueryValueExW (RealKey,
2616 NULL,
2617 NULL,
2618 NULL,
2619 (LPBYTE)lpValue,
2620 (LPDWORD)lpcbValue);
2621 if (CloseRealKey)
2622 {
2623 NtClose (RealKey);
2624 }
2625
2626 return ErrorCode;
2627 }
2628
2629
2630 /************************************************************************
2631 * RegReplaceKeyA
2632 *
2633 * @implemented
2634 */
2635 LONG STDCALL
2636 RegReplaceKeyA (HKEY hKey,
2637 LPCSTR lpSubKey,
2638 LPCSTR lpNewFile,
2639 LPCSTR lpOldFile)
2640 {
2641 UNICODE_STRING SubKey;
2642 UNICODE_STRING NewFile;
2643 UNICODE_STRING OldFile;
2644 LONG ErrorCode;
2645
2646 RtlCreateUnicodeStringFromAsciiz (&SubKey,
2647 (PCSZ)lpSubKey);
2648 RtlCreateUnicodeStringFromAsciiz (&OldFile,
2649 (PCSZ)lpOldFile);
2650 RtlCreateUnicodeStringFromAsciiz (&NewFile,
2651 (PCSZ)lpNewFile);
2652
2653 ErrorCode = RegReplaceKeyW (hKey,
2654 SubKey.Buffer,
2655 NewFile.Buffer,
2656 OldFile.Buffer);
2657
2658 RtlFreeUnicodeString (&OldFile);
2659 RtlFreeUnicodeString (&NewFile);
2660 RtlFreeUnicodeString (&SubKey);
2661
2662 return ErrorCode;
2663 }
2664
2665
2666 /************************************************************************
2667 * RegReplaceKeyW
2668 *
2669 * @unimplemented
2670 */
2671 LONG STDCALL
2672 RegReplaceKeyW (HKEY hKey,
2673 LPCWSTR lpSubKey,
2674 LPCWSTR lpNewFile,
2675 LPCWSTR lpOldFile)
2676 {
2677 OBJECT_ATTRIBUTES KeyObjectAttributes;
2678 OBJECT_ATTRIBUTES NewObjectAttributes;
2679 OBJECT_ATTRIBUTES OldObjectAttributes;
2680 UNICODE_STRING SubKeyName;
2681 UNICODE_STRING NewFileName;
2682 UNICODE_STRING OldFileName;
2683 BOOLEAN CloseRealKey;
2684 HANDLE RealKeyHandle;
2685 HANDLE KeyHandle;
2686 LONG ErrorCode;
2687 NTSTATUS Status;
2688
2689 if (hKey == HKEY_PERFORMANCE_DATA)
2690 {
2691 return ERROR_INVALID_HANDLE;
2692 }
2693
2694 Status = MapDefaultKey (&KeyHandle,
2695 hKey);
2696 if (!NT_SUCCESS(Status))
2697 {
2698 ErrorCode = RtlNtStatusToDosError (Status);
2699 SetLastError (ErrorCode);
2700 return ErrorCode;
2701 }
2702
2703 /* Open the real key */
2704 if (lpSubKey != NULL && *lpSubKey != (WCHAR)0)
2705 {
2706 RtlInitUnicodeString (&SubKeyName,
2707 (PWSTR)lpSubKey);
2708 InitializeObjectAttributes (&KeyObjectAttributes,
2709 &SubKeyName,
2710 OBJ_CASE_INSENSITIVE,
2711 KeyHandle,
2712 NULL);
2713 Status = NtOpenKey (&RealKeyHandle,
2714 KEY_ALL_ACCESS,
2715 &KeyObjectAttributes);
2716 if (!NT_SUCCESS(Status))
2717 {
2718 ErrorCode = RtlNtStatusToDosError (Status);
2719 SetLastError (ErrorCode);
2720 return ErrorCode;
2721 }
2722 CloseRealKey = TRUE;
2723 }
2724 else
2725 {
2726 RealKeyHandle = KeyHandle;
2727 CloseRealKey = FALSE;
2728 }
2729
2730 /* Convert new file name */
2731 if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpNewFile,
2732 &NewFileName,
2733 NULL,
2734 NULL))
2735 {
2736 if (CloseRealKey)
2737 {
2738 NtClose (RealKeyHandle);
2739 }
2740 SetLastError (ERROR_INVALID_PARAMETER);
2741 return ERROR_INVALID_PARAMETER;
2742 }
2743
2744 InitializeObjectAttributes (&NewObjectAttributes,
2745 &NewFileName,
2746 OBJ_CASE_INSENSITIVE,
2747 NULL,
2748 NULL);
2749
2750 /* Convert old file name */
2751 if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpOldFile,
2752 &OldFileName,
2753 NULL,
2754 NULL))
2755 {
2756 RtlFreeUnicodeString (&NewFileName);
2757 if (CloseRealKey)
2758 {
2759 NtClose (RealKeyHandle);
2760 }
2761 SetLastError (ERROR_INVALID_PARAMETER);
2762 return ERROR_INVALID_PARAMETER;
2763 }
2764
2765 InitializeObjectAttributes (&OldObjectAttributes,
2766 &OldFileName,
2767 OBJ_CASE_INSENSITIVE,
2768 NULL,
2769 NULL);
2770
2771 Status = NtReplaceKey (&NewObjectAttributes,
2772 RealKeyHandle,
2773 &OldObjectAttributes);
2774
2775 RtlFreeUnicodeString (&OldFileName);
2776 RtlFreeUnicodeString (&NewFileName);
2777
2778 if (CloseRealKey)
2779 {
2780 NtClose (RealKeyHandle);
2781 }
2782
2783 if (!NT_SUCCESS(Status))
2784 {
2785 ErrorCode = RtlNtStatusToDosError (Status);
2786 SetLastError (ErrorCode);
2787 return ErrorCode;
2788 }
2789
2790 return ERROR_SUCCESS;
2791 }
2792
2793
2794 /************************************************************************
2795 * RegRestoreKeyA
2796 *
2797 * @implemented
2798 */
2799 LONG STDCALL
2800 RegRestoreKeyA (HKEY hKey,
2801 LPCSTR lpFile,
2802 DWORD dwFlags)
2803 {
2804 UNICODE_STRING FileName;
2805 LONG ErrorCode;
2806
2807 RtlCreateUnicodeStringFromAsciiz (&FileName,
2808 (PCSZ)lpFile);
2809
2810 ErrorCode = RegRestoreKeyW (hKey,
2811 FileName.Buffer,
2812 dwFlags);
2813
2814 RtlFreeUnicodeString (&FileName);
2815
2816 return ErrorCode;
2817 }
2818
2819
2820 /************************************************************************
2821 * RegRestoreKeyW
2822 *
2823 * @implemented
2824 */
2825 LONG STDCALL
2826 RegRestoreKeyW (HKEY hKey,
2827 LPCWSTR lpFile,
2828 DWORD dwFlags)
2829 {
2830 OBJECT_ATTRIBUTES ObjectAttributes;
2831 IO_STATUS_BLOCK IoStatusBlock;
2832 UNICODE_STRING FileName;
2833 HANDLE FileHandle;
2834 HANDLE KeyHandle;
2835 LONG ErrorCode;
2836 NTSTATUS Status;
2837
2838 if (hKey == HKEY_PERFORMANCE_DATA)
2839 {
2840 return ERROR_INVALID_HANDLE;
2841 }
2842
2843 Status = MapDefaultKey (&KeyHandle,
2844 hKey);
2845 if (!NT_SUCCESS(Status))
2846 {
2847 ErrorCode = RtlNtStatusToDosError (Status);
2848 SetLastError (ErrorCode);
2849 return ErrorCode;
2850 }
2851
2852 if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFile,
2853 &FileName,
2854 NULL,
2855 NULL))
2856 {
2857 SetLastError (ERROR_INVALID_PARAMETER);
2858 return ERROR_INVALID_PARAMETER;
2859 }
2860
2861 InitializeObjectAttributes (&ObjectAttributes,
2862 &FileName,
2863 OBJ_CASE_INSENSITIVE,
2864 NULL,
2865 NULL);
2866
2867 Status = NtOpenFile (&FileHandle,
2868 FILE_GENERIC_READ,
2869 &ObjectAttributes,
2870 &IoStatusBlock,
2871 FILE_SHARE_READ,
2872 FILE_SYNCHRONOUS_IO_NONALERT);
2873 RtlFreeUnicodeString (&FileName);
2874 if (!NT_SUCCESS(Status))
2875 {
2876 ErrorCode = RtlNtStatusToDosError (Status);
2877 SetLastError (ErrorCode);
2878 return ErrorCode;
2879 }
2880
2881 Status = NtRestoreKey (KeyHandle,
2882 FileHandle,
2883 (ULONG)dwFlags);
2884 NtClose (FileHandle);
2885 if (!NT_SUCCESS(Status))
2886 {
2887 ErrorCode = RtlNtStatusToDosError (Status);
2888 SetLastError (ErrorCode);
2889 return ErrorCode;
2890 }
2891
2892 return ERROR_SUCCESS;
2893 }
2894
2895
2896 /************************************************************************
2897 * RegSaveKeyA
2898 *
2899 * @implemented
2900 */
2901 LONG STDCALL
2902 RegSaveKeyA (HKEY hKey,
2903 LPCSTR lpFile,
2904 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
2905 {
2906 UNICODE_STRING FileName;
2907 LONG ErrorCode;
2908
2909 RtlCreateUnicodeStringFromAsciiz (&FileName,
2910 (LPSTR)lpFile);
2911 ErrorCode = RegSaveKeyW (hKey,
2912 FileName.Buffer,
2913 lpSecurityAttributes);
2914 RtlFreeUnicodeString (&FileName);
2915
2916 return ErrorCode;
2917 }
2918
2919
2920 /************************************************************************
2921 * RegSaveKeyW
2922 *
2923 * @implemented
2924 */
2925 LONG STDCALL
2926 RegSaveKeyW (HKEY hKey,
2927 LPCWSTR lpFile,
2928 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
2929 {
2930 PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
2931 OBJECT_ATTRIBUTES ObjectAttributes;
2932 UNICODE_STRING FileName;
2933 IO_STATUS_BLOCK IoStatusBlock;
2934 HANDLE FileHandle;
2935 HANDLE KeyHandle;
2936 NTSTATUS Status;
2937 LONG ErrorCode;
2938
2939 Status = MapDefaultKey (&KeyHandle,
2940 hKey);
2941 if (!NT_SUCCESS(Status))
2942 {
2943 ErrorCode = RtlNtStatusToDosError (Status);
2944 SetLastError (ErrorCode);
2945 return ErrorCode;
2946 }
2947
2948 if (!RtlDosPathNameToNtPathName_U ((PWSTR)lpFile,
2949 &FileName,
2950 NULL,
2951 NULL))
2952 {
2953 SetLastError (ERROR_INVALID_PARAMETER);
2954 return ERROR_INVALID_PARAMETER;
2955 }
2956
2957 if (lpSecurityAttributes != NULL)
2958 {
2959 SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
2960 }
2961
2962 InitializeObjectAttributes (&ObjectAttributes,
2963 &FileName,
2964 OBJ_CASE_INSENSITIVE,
2965 NULL,
2966 SecurityDescriptor);
2967 Status = NtCreateFile (&FileHandle,
2968 GENERIC_WRITE | SYNCHRONIZE,
2969 &ObjectAttributes,
2970 &IoStatusBlock,
2971 NULL,
2972 FILE_ATTRIBUTE_NORMAL,
2973 FILE_SHARE_READ,
2974 FILE_CREATE,
2975 FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
2976 NULL,
2977 0);
2978 RtlFreeUnicodeString (&FileName);
2979 if (!NT_SUCCESS(Status))
2980 {
2981 ErrorCode = RtlNtStatusToDosError (Status);
2982 SetLastError (ErrorCode);
2983 return ErrorCode;
2984 }
2985
2986 Status = NtSaveKey (KeyHandle,
2987 FileHandle);
2988 NtClose (FileHandle);
2989 if (!NT_SUCCESS(Status))
2990 {
2991 ErrorCode = RtlNtStatusToDosError (Status);
2992 SetLastError (ErrorCode);
2993 return ErrorCode;
2994 }
2995
2996 return ERROR_SUCCESS;
2997 }
2998
2999
3000 /************************************************************************
3001 * RegSetKeySecurity
3002 *
3003 * @implemented
3004 */
3005 LONG STDCALL
3006 RegSetKeySecurity (HKEY hKey,
3007 SECURITY_INFORMATION SecurityInformation,
3008 PSECURITY_DESCRIPTOR pSecurityDescriptor)
3009 {
3010 HANDLE KeyHandle;
3011 LONG ErrorCode;
3012 NTSTATUS Status;
3013
3014 if (hKey == HKEY_PERFORMANCE_DATA)
3015 {
3016 SetLastError(ERROR_INVALID_HANDLE);
3017 return ERROR_INVALID_HANDLE;
3018 }
3019
3020 Status = MapDefaultKey (&KeyHandle,
3021 hKey);
3022 if (!NT_SUCCESS(Status))
3023 {
3024 ErrorCode = RtlNtStatusToDosError (Status);
3025 SetLastError (ErrorCode);
3026 return ErrorCode;
3027 }
3028
3029 Status = NtSetSecurityObject (KeyHandle,
3030 SecurityInformation,
3031 pSecurityDescriptor);
3032 if (!NT_SUCCESS(Status))
3033 {
3034 ErrorCode = RtlNtStatusToDosError (Status);
3035 SetLastError (ErrorCode);
3036 return ErrorCode;
3037 }
3038
3039 return ERROR_SUCCESS;
3040 }
3041
3042
3043 /************************************************************************
3044 * RegSetValueExA
3045 *
3046 * @implemented
3047 */
3048 LONG STDCALL
3049 RegSetValueExA (HKEY hKey,
3050 LPCSTR lpValueName,
3051 DWORD Reserved,
3052 DWORD dwType,
3053 CONST BYTE* lpData,
3054 DWORD cbData)
3055 {
3056 UNICODE_STRING ValueName;
3057 LPWSTR pValueName;
3058 ANSI_STRING AnsiString;
3059 UNICODE_STRING Data;
3060 LONG ErrorCode;
3061 LPBYTE pData;
3062 DWORD DataSize;
3063
3064 if (lpData == NULL)
3065 {
3066 SetLastError (ERROR_INVALID_PARAMETER);
3067 return ERROR_INVALID_PARAMETER;
3068 }
3069
3070 if (lpValueName != NULL &&
3071 strlen(lpValueName) != 0)
3072 {
3073 RtlCreateUnicodeStringFromAsciiz (&ValueName,
3074 (PSTR)lpValueName);
3075 pValueName = (LPWSTR)ValueName.Buffer;
3076 }
3077 else
3078 {
3079 pValueName = NULL;
3080 }
3081
3082 if ((dwType == REG_SZ) ||
3083 (dwType == REG_MULTI_SZ) ||
3084 (dwType == REG_EXPAND_SZ))
3085 {
3086 RtlInitAnsiString (&AnsiString,
3087 NULL);
3088 AnsiString.Buffer = (PSTR)lpData;
3089 AnsiString.Length = cbData;
3090 AnsiString.MaximumLength = cbData;
3091 RtlAnsiStringToUnicodeString (&Data,
3092 &AnsiString,
3093 TRUE);
3094 pData = (LPBYTE)Data.Buffer;
3095 DataSize = cbData * sizeof(WCHAR);
3096 }
3097 else
3098 {
3099 RtlInitUnicodeString (&Data,
3100 NULL);
3101 pData = (LPBYTE)lpData;
3102 DataSize = cbData;
3103 }
3104
3105 ErrorCode = RegSetValueExW (hKey,
3106 pValueName,
3107 Reserved,
3108 dwType,
3109 pData,
3110 DataSize);
3111 if (pValueName != NULL)
3112 {
3113 RtlFreeHeap (ProcessHeap,
3114 0,
3115 ValueName.Buffer);
3116 }
3117
3118 if (Data.Buffer != NULL)
3119 {
3120 RtlFreeHeap (ProcessHeap,
3121 0,
3122 Data.Buffer);
3123 }
3124
3125 return ErrorCode;
3126 }
3127
3128
3129 /************************************************************************
3130 * RegSetValueExW
3131 *
3132 * @implemented
3133 */
3134 LONG STDCALL
3135 RegSetValueExW (HKEY hKey,
3136 LPCWSTR lpValueName,
3137 DWORD Reserved,
3138 DWORD dwType,
3139 CONST BYTE* lpData,
3140 DWORD cbData)
3141 {
3142 UNICODE_STRING ValueName;
3143 PUNICODE_STRING pValueName;
3144 HANDLE KeyHandle;
3145 NTSTATUS Status;
3146 LONG ErrorCode;
3147
3148 Status = MapDefaultKey (&KeyHandle,
3149 hKey);
3150 if (!NT_SUCCESS(Status))
3151 {
3152 ErrorCode = RtlNtStatusToDosError (Status);
3153 SetLastError (ErrorCode);
3154 return ErrorCode;
3155 }
3156
3157 if (lpValueName != NULL)
3158 {
3159 RtlInitUnicodeString (&ValueName,
3160 lpValueName);
3161 }
3162 else
3163 {
3164 RtlInitUnicodeString (&ValueName, L"");
3165 }
3166 pValueName = &ValueName;
3167
3168 Status = NtSetValueKey (KeyHandle,
3169 pValueName,
3170 0,
3171 dwType,
3172 (PVOID)lpData,
3173 (ULONG)cbData);
3174 if (!NT_SUCCESS(Status))
3175 {
3176 ErrorCode = RtlNtStatusToDosError (Status);
3177 SetLastError (ErrorCode);
3178 return ErrorCode;
3179 }
3180
3181 return ERROR_SUCCESS;
3182 }
3183
3184
3185 /************************************************************************
3186 * RegSetValueA
3187 *
3188 * @implemented
3189 */
3190 LONG STDCALL
3191 RegSetValueA (HKEY hKey,
3192 LPCSTR lpSubKey,
3193 DWORD dwType,
3194 LPCSTR lpData,
3195 DWORD cbData)
3196 {
3197 WCHAR SubKeyNameBuffer[MAX_PATH+1];
3198 UNICODE_STRING SubKeyName;
3199 UNICODE_STRING Data;
3200 ANSI_STRING AnsiString;
3201 LONG DataSize;
3202 LONG ErrorCode;
3203
3204 if (lpData == NULL)
3205 {
3206 SetLastError (ERROR_INVALID_PARAMETER);
3207 return ERROR_INVALID_PARAMETER;
3208 }
3209
3210 RtlInitUnicodeString (&SubKeyName, NULL);
3211 RtlInitUnicodeString (&Data, NULL);
3212 if (lpSubKey != NULL && (strlen(lpSubKey) != 0))
3213 {
3214 RtlInitAnsiString (&AnsiString, (LPSTR)lpSubKey);
3215 SubKeyName.Buffer = &SubKeyNameBuffer[0];
3216 SubKeyName.MaximumLength = sizeof(SubKeyNameBuffer);
3217 RtlAnsiStringToUnicodeString (&SubKeyName, &AnsiString, FALSE);
3218 }
3219
3220 DataSize = cbData * sizeof(WCHAR);
3221 Data.MaximumLength = DataSize;
3222 Data.Buffer = RtlAllocateHeap (ProcessHeap,
3223 0,
3224 DataSize);
3225 if (Data.Buffer == NULL)
3226 {
3227 SetLastError (ERROR_OUTOFMEMORY);
3228 return ERROR_OUTOFMEMORY;
3229 }
3230
3231 ErrorCode = RegSetValueW (hKey,
3232 (LPCWSTR)SubKeyName.Buffer,
3233 dwType,
3234 Data.Buffer,
3235 DataSize);
3236
3237 RtlFreeHeap (ProcessHeap,
3238 0,
3239 Data.Buffer);
3240
3241 return ErrorCode;
3242 }
3243
3244
3245 /************************************************************************
3246 * RegSetValueW
3247 *
3248 * @implemented
3249 */
3250 LONG STDCALL
3251 RegSetValueW (HKEY hKey,
3252 LPCWSTR lpSubKey,
3253 DWORD dwType,
3254 LPCWSTR lpData,
3255 DWORD cbData)
3256 {
3257 OBJECT_ATTRIBUTES ObjectAttributes;
3258 UNICODE_STRING SubKeyString;
3259 HANDLE KeyHandle;
3260 HANDLE RealKey;
3261 LONG ErrorCode;
3262 BOOL CloseRealKey;
3263 NTSTATUS Status;
3264
3265 Status = MapDefaultKey (&KeyHandle,
3266 hKey);
3267 if (!NT_SUCCESS(Status))
3268 {
3269 ErrorCode = RtlNtStatusToDosError (Status);
3270 SetLastError (ErrorCode);
3271 return ErrorCode;
3272 }
3273
3274 if ((lpSubKey) && (wcslen(lpSubKey) != 0))
3275 {
3276 RtlInitUnicodeString (&SubKeyString,
3277 (LPWSTR)lpSubKey);
3278 InitializeObjectAttributes (&ObjectAttributes,
3279 &SubKeyString,
3280 OBJ_CASE_INSENSITIVE,
3281 KeyHandle,
3282 NULL);
3283 Status = NtOpenKey (&RealKey,
3284 KEY_ALL_ACCESS,
3285 &ObjectAttributes);
3286 if (!NT_SUCCESS(Status))
3287 {
3288 ErrorCode = RtlNtStatusToDosError (Status);
3289 SetLastError (ErrorCode);
3290 return ErrorCode;
3291 }
3292 CloseRealKey = TRUE;
3293 }
3294 else
3295 {
3296 RealKey = hKey;
3297 CloseRealKey = FALSE;
3298 }
3299
3300 ErrorCode = RegSetValueExW (RealKey,
3301 NULL,
3302 0,
3303 dwType,
3304 (LPBYTE)lpData,
3305 cbData);
3306 if (CloseRealKey == TRUE)
3307 {
3308 NtClose (RealKey);
3309 }
3310
3311 return ErrorCode;
3312 }
3313
3314
3315 /************************************************************************
3316 * RegUnLoadKeyA
3317 *
3318 * @implemented
3319 */
3320 LONG STDCALL
3321 RegUnLoadKeyA (HKEY hKey,
3322 LPCSTR lpSubKey)
3323 {
3324 UNICODE_STRING KeyName;
3325 DWORD ErrorCode;
3326
3327 RtlCreateUnicodeStringFromAsciiz (&KeyName,
3328 (LPSTR)lpSubKey);
3329
3330 ErrorCode = RegUnLoadKeyW (hKey,
3331 KeyName.Buffer);
3332
3333 RtlFreeUnicodeString (&KeyName);
3334
3335 return ErrorCode;
3336 }
3337
3338
3339 /************************************************************************
3340 * RegUnLoadKeyW
3341 *
3342 * @implemented
3343 */
3344 LONG STDCALL
3345 RegUnLoadKeyW (HKEY hKey,
3346 LPCWSTR lpSubKey)
3347 {
3348 OBJECT_ATTRIBUTES ObjectAttributes;
3349 UNICODE_STRING KeyName;
3350 HANDLE KeyHandle;
3351 DWORD ErrorCode;
3352 NTSTATUS Status;
3353
3354 if (hKey == HKEY_PERFORMANCE_DATA)
3355 {
3356 SetLastError(ERROR_INVALID_HANDLE);
3357 return ERROR_INVALID_HANDLE;
3358 }
3359
3360 Status = MapDefaultKey (&KeyHandle, hKey);
3361 if (!NT_SUCCESS(Status))
3362 {
3363 ErrorCode = RtlNtStatusToDosError (Status);
3364 SetLastError (ErrorCode);
3365 return ErrorCode;
3366 }
3367
3368 RtlInitUnicodeString (&KeyName,
3369 (LPWSTR)lpSubKey);
3370
3371 InitializeObjectAttributes (&ObjectAttributes,
3372 &KeyName,
3373 OBJ_CASE_INSENSITIVE,
3374 KeyHandle,
3375 NULL);
3376
3377 Status = NtUnloadKey (&ObjectAttributes);
3378
3379 if (!NT_SUCCESS(Status))
3380 {
3381 ErrorCode = RtlNtStatusToDosError (Status);
3382 SetLastError (ErrorCode);
3383 return ErrorCode;
3384 }
3385
3386 return ERROR_SUCCESS;
3387 }
3388
3389 /* EOF */