Implement RegGetKeySecurity.
[reactos.git] / reactos / lib / advapi32 / reg / reg.c
1 /* $Id: reg.c,v 1.55 2004/09/13 08:51:40 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 return ERROR_INVALID_HANDLE;
1525 }
1526
1527 Status = MapDefaultKey(&KeyHandle,
1528 hKey);
1529 if (!NT_SUCCESS(Status))
1530 {
1531 ErrorCode = RtlNtStatusToDosError(Status);
1532 SetLastError(ErrorCode);
1533 return ErrorCode;
1534 }
1535
1536 Status = NtQuerySecurityObject(hKey,
1537 SecurityInformation,
1538 pSecurityDescriptor,
1539 *lpcbSecurityDescriptor,
1540 lpcbSecurityDescriptor);
1541 if (!NT_SUCCESS(Status))
1542 {
1543 ErrorCode = RtlNtStatusToDosError(Status);
1544 SetLastError(ErrorCode);
1545 return ErrorCode;
1546 }
1547
1548 return ERROR_SUCCESS;
1549 }
1550
1551
1552 /************************************************************************
1553 * RegLoadKeyA
1554 *
1555 * @implemented
1556 */
1557 LONG STDCALL
1558 RegLoadKeyA (HKEY hKey,
1559 LPCSTR lpSubKey,
1560 LPCSTR lpFile)
1561 {
1562 UNICODE_STRING FileName;
1563 UNICODE_STRING KeyName;
1564 LONG ErrorCode;
1565
1566 RtlCreateUnicodeStringFromAsciiz (&KeyName,
1567 (LPSTR)lpSubKey);
1568 RtlCreateUnicodeStringFromAsciiz (&FileName,
1569 (LPSTR)lpFile);
1570
1571 ErrorCode = RegLoadKeyW (hKey,
1572 KeyName.Buffer,
1573 FileName.Buffer);
1574
1575 RtlFreeUnicodeString (&FileName);
1576 RtlFreeUnicodeString (&KeyName);
1577
1578 return ErrorCode;
1579 }
1580
1581
1582 /************************************************************************
1583 * RegLoadKeyW
1584 *
1585 * @implemented
1586 */
1587 LONG STDCALL
1588 RegLoadKeyW (HKEY hKey,
1589 LPCWSTR lpSubKey,
1590 LPCWSTR lpFile)
1591 {
1592 OBJECT_ATTRIBUTES FileObjectAttributes;
1593 OBJECT_ATTRIBUTES KeyObjectAttributes;
1594 UNICODE_STRING FileName;
1595 UNICODE_STRING KeyName;
1596 HANDLE KeyHandle;
1597 LONG ErrorCode;
1598 NTSTATUS Status;
1599
1600 if (hKey == HKEY_PERFORMANCE_DATA)
1601 {
1602 return ERROR_INVALID_HANDLE;
1603 }
1604
1605 Status = MapDefaultKey (&KeyHandle,
1606 hKey);
1607 if (!NT_SUCCESS(Status))
1608 {
1609 ErrorCode = RtlNtStatusToDosError (Status);
1610 SetLastError (ErrorCode);
1611 return ErrorCode;
1612 }
1613
1614 if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFile,
1615 &FileName,
1616 NULL,
1617 NULL))
1618 {
1619 SetLastError (ERROR_BAD_PATHNAME);
1620 return ERROR_BAD_PATHNAME;
1621 }
1622
1623 InitializeObjectAttributes (&FileObjectAttributes,
1624 &FileName,
1625 OBJ_CASE_INSENSITIVE,
1626 NULL,
1627 NULL);
1628
1629 RtlInitUnicodeString (&KeyName,
1630 (LPWSTR)lpSubKey);
1631
1632 InitializeObjectAttributes (&KeyObjectAttributes,
1633 &KeyName,
1634 OBJ_CASE_INSENSITIVE,
1635 KeyHandle,
1636 NULL);
1637
1638 Status = NtLoadKey (&KeyObjectAttributes,
1639 &FileObjectAttributes);
1640
1641 RtlFreeUnicodeString (&FileName);
1642
1643 if (!NT_SUCCESS(Status))
1644 {
1645 ErrorCode = RtlNtStatusToDosError (Status);
1646 SetLastError (ErrorCode);
1647 return ErrorCode;
1648 }
1649
1650 return ERROR_SUCCESS;
1651 }
1652
1653
1654 /************************************************************************
1655 * RegNotifyChangeKeyValue
1656 *
1657 * @unimplemented
1658 */
1659 LONG STDCALL
1660 RegNotifyChangeKeyValue (HKEY hKey,
1661 BOOL bWatchSubtree,
1662 DWORD dwNotifyFilter,
1663 HANDLE hEvent,
1664 BOOL fAsynchronous)
1665 {
1666 IO_STATUS_BLOCK IoStatusBlock;
1667 HANDLE KeyHandle;
1668 NTSTATUS Status;
1669
1670 if (hKey == HKEY_PERFORMANCE_DATA)
1671 {
1672 return ERROR_INVALID_HANDLE;
1673 }
1674
1675 if (fAsynchronous == TRUE && hEvent == NULL)
1676 {
1677 return ERROR_INVALID_PARAMETER;
1678 }
1679
1680 Status = MapDefaultKey (&KeyHandle,
1681 hKey);
1682 if (!NT_SUCCESS(Status))
1683 {
1684 return RtlNtStatusToDosError (Status);
1685 }
1686
1687 /* FIXME: Remote key handles must fail */
1688
1689 Status = NtNotifyChangeKey (KeyHandle,
1690 hEvent,
1691 0,
1692 0,
1693 &IoStatusBlock,
1694 dwNotifyFilter,
1695 bWatchSubtree,
1696 0,
1697 0,
1698 fAsynchronous);
1699 if (!NT_SUCCESS(Status) && Status != STATUS_TIMEOUT)
1700 {
1701 return RtlNtStatusToDosError (Status);
1702 }
1703
1704 return ERROR_SUCCESS;
1705 }
1706
1707
1708 /************************************************************************
1709 * RegOpenKeyA
1710 *
1711 * @implemented
1712 */
1713 LONG STDCALL
1714 RegOpenKeyA (HKEY hKey,
1715 LPCSTR lpSubKey,
1716 PHKEY phkResult)
1717 {
1718 OBJECT_ATTRIBUTES ObjectAttributes;
1719 UNICODE_STRING SubKeyString;
1720 HANDLE KeyHandle;
1721 LONG ErrorCode;
1722 NTSTATUS Status;
1723
1724 Status = MapDefaultKey (&KeyHandle,
1725 hKey);
1726 if (!NT_SUCCESS(Status))
1727 {
1728 ErrorCode = RtlNtStatusToDosError (Status);
1729 SetLastError (ErrorCode);
1730 return ErrorCode;
1731 }
1732
1733 RtlCreateUnicodeStringFromAsciiz (&SubKeyString,
1734 (LPSTR)lpSubKey);
1735 InitializeObjectAttributes (&ObjectAttributes,
1736 &SubKeyString,
1737 OBJ_CASE_INSENSITIVE,
1738 KeyHandle,
1739 NULL);
1740 Status = NtOpenKey ((PHANDLE)phkResult,
1741 MAXIMUM_ALLOWED,
1742 &ObjectAttributes);
1743 RtlFreeUnicodeString (&SubKeyString);
1744 if (!NT_SUCCESS(Status))
1745 {
1746 ErrorCode = RtlNtStatusToDosError (Status);
1747 SetLastError (ErrorCode);
1748 return ErrorCode;
1749 }
1750
1751 return ERROR_SUCCESS;
1752 }
1753
1754
1755 /************************************************************************
1756 * RegOpenKeyW
1757 *
1758 * 19981101 Ariadne
1759 * 19990525 EA
1760 *
1761 * @implemented
1762 */
1763 LONG STDCALL
1764 RegOpenKeyW (HKEY hKey,
1765 LPCWSTR lpSubKey,
1766 PHKEY phkResult)
1767 {
1768 OBJECT_ATTRIBUTES ObjectAttributes;
1769 UNICODE_STRING SubKeyString;
1770 HANDLE KeyHandle;
1771 LONG ErrorCode;
1772 NTSTATUS Status;
1773
1774 Status = MapDefaultKey (&KeyHandle,
1775 hKey);
1776 if (!NT_SUCCESS(Status))
1777 {
1778 ErrorCode = RtlNtStatusToDosError (Status);
1779 SetLastError (ErrorCode);
1780 return ErrorCode;
1781 }
1782
1783 RtlInitUnicodeString (&SubKeyString,
1784 (LPWSTR)lpSubKey);
1785 InitializeObjectAttributes (&ObjectAttributes,
1786 &SubKeyString,
1787 OBJ_CASE_INSENSITIVE,
1788 KeyHandle,
1789 NULL);
1790 Status = NtOpenKey ((PHANDLE)phkResult,
1791 MAXIMUM_ALLOWED,
1792 &ObjectAttributes);
1793 if (!NT_SUCCESS(Status))
1794 {
1795 ErrorCode = RtlNtStatusToDosError (Status);
1796 SetLastError(ErrorCode);
1797 return ErrorCode;
1798 }
1799
1800 return ERROR_SUCCESS;
1801 }
1802
1803
1804 /************************************************************************
1805 * RegOpenKeyExA
1806 *
1807 * @implemented
1808 */
1809 LONG STDCALL
1810 RegOpenKeyExA (HKEY hKey,
1811 LPCSTR lpSubKey,
1812 DWORD ulOptions,
1813 REGSAM samDesired,
1814 PHKEY phkResult)
1815 {
1816 OBJECT_ATTRIBUTES ObjectAttributes;
1817 UNICODE_STRING SubKeyString;
1818 HANDLE KeyHandle;
1819 LONG ErrorCode;
1820 NTSTATUS Status;
1821
1822 Status = MapDefaultKey (&KeyHandle,
1823 hKey);
1824 if (!NT_SUCCESS(Status))
1825 {
1826 ErrorCode = RtlNtStatusToDosError (Status);
1827 SetLastError (ErrorCode);
1828 return ErrorCode;
1829 }
1830
1831 RtlCreateUnicodeStringFromAsciiz (&SubKeyString,
1832 (LPSTR)lpSubKey);
1833 InitializeObjectAttributes (&ObjectAttributes,
1834 &SubKeyString,
1835 OBJ_CASE_INSENSITIVE,
1836 KeyHandle,
1837 NULL);
1838 Status = NtOpenKey ((PHANDLE)phkResult,
1839 samDesired,
1840 &ObjectAttributes);
1841 RtlFreeUnicodeString (&SubKeyString);
1842 if (!NT_SUCCESS(Status))
1843 {
1844 ErrorCode = RtlNtStatusToDosError (Status);
1845 SetLastError (ErrorCode);
1846 return ErrorCode;
1847 }
1848
1849 return ERROR_SUCCESS;
1850 }
1851
1852
1853 /************************************************************************
1854 * RegOpenKeyExW
1855 *
1856 * @implemented
1857 */
1858 LONG STDCALL
1859 RegOpenKeyExW (HKEY hKey,
1860 LPCWSTR lpSubKey,
1861 DWORD ulOptions,
1862 REGSAM samDesired,
1863 PHKEY phkResult)
1864 {
1865 OBJECT_ATTRIBUTES ObjectAttributes;
1866 UNICODE_STRING SubKeyString;
1867 HANDLE KeyHandle;
1868 LONG ErrorCode;
1869 NTSTATUS Status;
1870
1871 Status = MapDefaultKey (&KeyHandle,
1872 hKey);
1873 if (!NT_SUCCESS(Status))
1874 {
1875 ErrorCode = RtlNtStatusToDosError (Status);
1876 SetLastError (ErrorCode);
1877 return ErrorCode;
1878 }
1879
1880 if (lpSubKey != NULL)
1881 {
1882 RtlInitUnicodeString (&SubKeyString,
1883 (LPWSTR)lpSubKey);
1884 }
1885 else
1886 {
1887 RtlInitUnicodeString (&SubKeyString,
1888 (LPWSTR)L"");
1889 }
1890 InitializeObjectAttributes (&ObjectAttributes,
1891 &SubKeyString,
1892 OBJ_CASE_INSENSITIVE,
1893 KeyHandle,
1894 NULL);
1895 Status = NtOpenKey ((PHANDLE)phkResult,
1896 samDesired,
1897 &ObjectAttributes);
1898 if (!NT_SUCCESS(Status))
1899 {
1900 ErrorCode = RtlNtStatusToDosError (Status);
1901 SetLastError (ErrorCode);
1902 return ErrorCode;
1903 }
1904
1905 return ERROR_SUCCESS;
1906 }
1907
1908
1909 /************************************************************************
1910 * RegQueryInfoKeyA
1911 *
1912 * @implemented
1913 */
1914 LONG STDCALL
1915 RegQueryInfoKeyA (HKEY hKey,
1916 LPSTR lpClass,
1917 LPDWORD lpcbClass,
1918 LPDWORD lpReserved,
1919 LPDWORD lpcSubKeys,
1920 LPDWORD lpcbMaxSubKeyLen,
1921 LPDWORD lpcbMaxClassLen,
1922 LPDWORD lpcValues,
1923 LPDWORD lpcbMaxValueNameLen,
1924 LPDWORD lpcbMaxValueLen,
1925 LPDWORD lpcbSecurityDescriptor,
1926 PFILETIME lpftLastWriteTime)
1927 {
1928 WCHAR ClassName[MAX_PATH];
1929 UNICODE_STRING UnicodeString;
1930 ANSI_STRING AnsiString;
1931 LONG ErrorCode;
1932
1933 RtlInitUnicodeString (&UnicodeString,
1934 NULL);
1935 if (lpClass != NULL)
1936 {
1937 UnicodeString.Buffer = &ClassName[0];
1938 UnicodeString.MaximumLength = sizeof(ClassName);
1939 AnsiString.MaximumLength = *lpcbClass;
1940 }
1941
1942 ErrorCode = RegQueryInfoKeyW (hKey,
1943 UnicodeString.Buffer,
1944 lpcbClass,
1945 lpReserved,
1946 lpcSubKeys,
1947 lpcbMaxSubKeyLen,
1948 lpcbMaxClassLen,
1949 lpcValues,
1950 lpcbMaxValueNameLen,
1951 lpcbMaxValueLen,
1952 lpcbSecurityDescriptor,
1953 lpftLastWriteTime);
1954 if ((ErrorCode == ERROR_SUCCESS) && (lpClass != NULL))
1955 {
1956 AnsiString.Buffer = lpClass;
1957 AnsiString.Length = 0;
1958 UnicodeString.Length = *lpcbClass * sizeof(WCHAR);
1959 RtlUnicodeStringToAnsiString (&AnsiString,
1960 &UnicodeString,
1961 FALSE);
1962 *lpcbClass = AnsiString.Length;
1963 lpClass[AnsiString.Length] = 0;
1964 }
1965
1966 return ErrorCode;
1967 }
1968
1969
1970 /************************************************************************
1971 * RegQueryInfoKeyW
1972 *
1973 * @implemented
1974 */
1975 LONG STDCALL
1976 RegQueryInfoKeyW (HKEY hKey,
1977 LPWSTR lpClass,
1978 LPDWORD lpcbClass,
1979 LPDWORD lpReserved,
1980 LPDWORD lpcSubKeys,
1981 LPDWORD lpcbMaxSubKeyLen,
1982 LPDWORD lpcbMaxClassLen,
1983 LPDWORD lpcValues,
1984 LPDWORD lpcbMaxValueNameLen,
1985 LPDWORD lpcbMaxValueLen,
1986 LPDWORD lpcbSecurityDescriptor,
1987 PFILETIME lpftLastWriteTime)
1988 {
1989 KEY_FULL_INFORMATION FullInfoBuffer;
1990 PKEY_FULL_INFORMATION FullInfo;
1991 ULONG FullInfoSize;
1992 ULONG ClassLength = 0;
1993 HANDLE KeyHandle;
1994 NTSTATUS Status;
1995 LONG ErrorCode = ERROR_SUCCESS;
1996 ULONG Length;
1997
1998 if ((lpClass) && (!lpcbClass))
1999 {
2000 SetLastError(ERROR_INVALID_PARAMETER);
2001 return ERROR_INVALID_PARAMETER;
2002 }
2003
2004 Status = MapDefaultKey (&KeyHandle,
2005 hKey);
2006 if (!NT_SUCCESS(Status))
2007 {
2008 ErrorCode = RtlNtStatusToDosError (Status);
2009 SetLastError (ErrorCode);
2010 return ErrorCode;
2011 }
2012
2013 if (lpClass != NULL)
2014 {
2015 if (*lpcbClass > 0)
2016 {
2017 ClassLength = min(*lpcbClass - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
2018 }
2019 else
2020 {
2021 ClassLength = 0;
2022 }
2023
2024 FullInfoSize = sizeof(KEY_FULL_INFORMATION) + ((ClassLength + 3) & ~3);
2025 FullInfo = RtlAllocateHeap (ProcessHeap,
2026 0,
2027 FullInfoSize);
2028 if (FullInfo == NULL)
2029 {
2030 SetLastError (ERROR_OUTOFMEMORY);
2031 return ERROR_OUTOFMEMORY;
2032 }
2033
2034 FullInfo->ClassLength = ClassLength;
2035 }
2036 else
2037 {
2038 FullInfoSize = sizeof(KEY_FULL_INFORMATION);
2039 FullInfo = &FullInfoBuffer;
2040 FullInfo->ClassLength = 0;
2041 }
2042 FullInfo->ClassOffset = FIELD_OFFSET(KEY_FULL_INFORMATION, Class);
2043
2044 Status = NtQueryKey (KeyHandle,
2045 KeyFullInformation,
2046 FullInfo,
2047 FullInfoSize,
2048 &Length);
2049 DPRINT("NtQueryKey() returned status 0x%X\n", Status);
2050 if (!NT_SUCCESS(Status))
2051 {
2052 if (lpClass != NULL)
2053 {
2054 RtlFreeHeap (ProcessHeap,
2055 0,
2056 FullInfo);
2057 }
2058
2059 ErrorCode = RtlNtStatusToDosError (Status);
2060 SetLastError (ErrorCode);
2061 return ErrorCode;
2062 }
2063
2064 DPRINT("SubKeys %d\n", FullInfo->SubKeys);
2065 if (lpcSubKeys != NULL)
2066 {
2067 *lpcSubKeys = FullInfo->SubKeys;
2068 }
2069
2070 DPRINT("MaxNameLen %lu\n", FullInfo->MaxNameLen);
2071 if (lpcbMaxSubKeyLen != NULL)
2072 {
2073 *lpcbMaxSubKeyLen = FullInfo->MaxNameLen / sizeof(WCHAR) + 1;
2074 }
2075
2076 DPRINT("MaxClassLen %lu\n", FullInfo->MaxClassLen);
2077 if (lpcbMaxClassLen != NULL)
2078 {
2079 *lpcbMaxClassLen = FullInfo->MaxClassLen / sizeof(WCHAR) + 1;
2080 }
2081
2082 DPRINT("Values %lu\n", FullInfo->Values);
2083 if (lpcValues != NULL)
2084 {
2085 *lpcValues = FullInfo->Values;
2086 }
2087
2088 DPRINT("MaxValueNameLen %lu\n", FullInfo->MaxValueNameLen);
2089 if (lpcbMaxValueNameLen != NULL)
2090 {
2091 *lpcbMaxValueNameLen = FullInfo->MaxValueNameLen / sizeof(WCHAR) + 1;
2092 }
2093
2094 DPRINT("MaxValueDataLen %lu\n", FullInfo->MaxValueDataLen);
2095 if (lpcbMaxValueLen != NULL)
2096 {
2097 *lpcbMaxValueLen = FullInfo->MaxValueDataLen;
2098 }
2099
2100 if (lpcbSecurityDescriptor != NULL)
2101 {
2102 /* FIXME */
2103 *lpcbSecurityDescriptor = 0;
2104 }
2105
2106 if (lpftLastWriteTime != NULL)
2107 {
2108 lpftLastWriteTime->dwLowDateTime = FullInfo->LastWriteTime.u.LowPart;
2109 lpftLastWriteTime->dwHighDateTime = FullInfo->LastWriteTime.u.HighPart;
2110 }
2111
2112 if (lpClass != NULL)
2113 {
2114 if (FullInfo->ClassLength > ClassLength)
2115 {
2116 ErrorCode = ERROR_BUFFER_OVERFLOW;
2117 }
2118 else
2119 {
2120 RtlCopyMemory (lpClass,
2121 FullInfo->Class,
2122 FullInfo->ClassLength);
2123 *lpcbClass = FullInfo->ClassLength / sizeof(WCHAR);
2124 lpClass[*lpcbClass] = 0;
2125 }
2126
2127 RtlFreeHeap (ProcessHeap,
2128 0,
2129 FullInfo);
2130 }
2131
2132 if (ErrorCode != ERROR_SUCCESS)
2133 {
2134 SetLastError (ErrorCode);
2135 }
2136
2137 return ErrorCode;
2138 }
2139
2140
2141 /************************************************************************
2142 * RegQueryMultipleValuesA
2143 *
2144 * @unimplemented
2145 */
2146 LONG STDCALL
2147 RegQueryMultipleValuesA (HKEY hKey,
2148 PVALENTA val_list,
2149 DWORD num_vals,
2150 LPSTR lpValueBuf,
2151 LPDWORD ldwTotsize)
2152 {
2153 UNIMPLEMENTED;
2154 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2155 return ERROR_CALL_NOT_IMPLEMENTED;
2156 }
2157
2158
2159 /************************************************************************
2160 * RegQueryMultipleValuesW
2161 *
2162 * @implemented
2163 */
2164 LONG STDCALL
2165 RegQueryMultipleValuesW (HKEY hKey,
2166 PVALENTW val_list,
2167 DWORD num_vals,
2168 LPWSTR lpValueBuf,
2169 LPDWORD ldwTotsize)
2170 {
2171 ULONG i;
2172 DWORD maxBytes = *ldwTotsize;
2173 LPSTR bufptr = (LPSTR)lpValueBuf;
2174 LONG ErrorCode;
2175
2176 if (maxBytes >= (1024*1024))
2177 return ERROR_TRANSFER_TOO_LONG;
2178
2179 *ldwTotsize = 0;
2180
2181 DPRINT ("RegQueryMultipleValuesW(%p,%p,%ld,%p,%p=%ld)\n",
2182 hKey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize);
2183
2184 for (i = 0; i < num_vals; ++i)
2185 {
2186 val_list[i].ve_valuelen = 0;
2187 ErrorCode = RegQueryValueExW (hKey,
2188 val_list[i].ve_valuename,
2189 NULL,
2190 NULL,
2191 NULL,
2192 &val_list[i].ve_valuelen);
2193 if (ErrorCode != ERROR_SUCCESS)
2194 {
2195 return ErrorCode;
2196 }
2197
2198 if (lpValueBuf != NULL && *ldwTotsize + val_list[i].ve_valuelen <= maxBytes)
2199 {
2200 ErrorCode = RegQueryValueExW (hKey,
2201 val_list[i].ve_valuename,
2202 NULL,
2203 &val_list[i].ve_type,
2204 bufptr,
2205 &val_list[i].ve_valuelen);
2206 if (ErrorCode != ERROR_SUCCESS)
2207 {
2208 return ErrorCode;
2209 }
2210
2211 val_list[i].ve_valueptr = (DWORD_PTR)bufptr;
2212
2213 bufptr += val_list[i].ve_valuelen;
2214 }
2215
2216 *ldwTotsize += val_list[i].ve_valuelen;
2217 }
2218
2219 return (lpValueBuf != NULL && *ldwTotsize <= maxBytes) ? ERROR_SUCCESS : ERROR_MORE_DATA;
2220 }
2221
2222
2223 /************************************************************************
2224 * RegQueryValueExW
2225 *
2226 * @implemented
2227 */
2228 LONG STDCALL
2229 RegQueryValueExW (HKEY hKey,
2230 LPCWSTR lpValueName,
2231 LPDWORD lpReserved,
2232 LPDWORD lpType,
2233 LPBYTE lpData,
2234 LPDWORD lpcbData)
2235 {
2236 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
2237 UNICODE_STRING ValueName;
2238 NTSTATUS Status;
2239 LONG ErrorCode = ERROR_SUCCESS;
2240 ULONG BufferSize;
2241 ULONG ResultSize;
2242 HANDLE KeyHandle;
2243 ULONG MaxCopy = lpcbData != NULL && lpData != NULL ? *lpcbData : 0;
2244
2245 DPRINT("hKey 0x%X lpValueName %S lpData 0x%X lpcbData %d\n",
2246 hKey, lpValueName, lpData, lpcbData ? *lpcbData : 0);
2247
2248 Status = MapDefaultKey (&KeyHandle,
2249 hKey);
2250 if (!NT_SUCCESS(Status))
2251 {
2252 ErrorCode = RtlNtStatusToDosError (Status);
2253 SetLastError (ErrorCode);
2254 return ErrorCode;
2255 }
2256
2257 if (lpData != NULL && lpcbData == NULL)
2258 {
2259 SetLastError (ERROR_INVALID_PARAMETER);
2260 return ERROR_INVALID_PARAMETER;
2261 }
2262
2263 RtlInitUnicodeString (&ValueName,
2264 lpValueName);
2265 BufferSize = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + MaxCopy;
2266 ValueInfo = RtlAllocateHeap (ProcessHeap,
2267 0,
2268 BufferSize);
2269 if (ValueInfo == NULL)
2270 {
2271 SetLastError(ERROR_OUTOFMEMORY);
2272 return ERROR_OUTOFMEMORY;
2273 }
2274
2275 Status = NtQueryValueKey (hKey,
2276 &ValueName,
2277 KeyValuePartialInformation,
2278 ValueInfo,
2279 BufferSize,
2280 &ResultSize);
2281 DPRINT("Status 0x%X\n", Status);
2282 if (Status == STATUS_BUFFER_TOO_SMALL)
2283 {
2284 /* Return ERROR_SUCCESS and the buffer space needed for a successful call */
2285 MaxCopy = 0;
2286 ErrorCode = lpData ? ERROR_MORE_DATA : ERROR_SUCCESS;
2287 }
2288 else if (!NT_SUCCESS(Status))
2289 {
2290 ErrorCode = RtlNtStatusToDosError (Status);
2291 SetLastError (ErrorCode);
2292 MaxCopy = 0;
2293 if (lpcbData != NULL)
2294 {
2295 ResultSize = sizeof(*ValueInfo) + *lpcbData;
2296 }
2297 }
2298
2299 if (lpType != NULL)
2300 {
2301 *lpType = ValueInfo->Type;
2302 }
2303
2304 if (NT_SUCCESS(Status) && lpData != NULL)
2305 {
2306 RtlMoveMemory (lpData,
2307 ValueInfo->Data,
2308 min(ValueInfo->DataLength, MaxCopy));
2309 }
2310
2311 if ((ValueInfo->Type == REG_SZ) ||
2312 (ValueInfo->Type == REG_MULTI_SZ) ||
2313 (ValueInfo->Type == REG_EXPAND_SZ))
2314 {
2315 if (lpData != NULL && MaxCopy > ValueInfo->DataLength)
2316 {
2317 ((PWSTR)lpData)[ValueInfo->DataLength / sizeof(WCHAR)] = 0;
2318 }
2319
2320 if (lpcbData != NULL)
2321 {
2322 *lpcbData = (ResultSize - sizeof(*ValueInfo));
2323 DPRINT("(string) Returning Size: %lu\n", *lpcbData);
2324 }
2325 }
2326 else
2327 {
2328 if (lpcbData != NULL)
2329 {
2330 *lpcbData = ResultSize - sizeof(*ValueInfo);
2331 DPRINT("(other) Returning Size: %lu\n", *lpcbData);
2332 }
2333 }
2334
2335 DPRINT("Type %d Size %d\n", ValueInfo->Type, ValueInfo->DataLength);
2336
2337 RtlFreeHeap (ProcessHeap,
2338 0,
2339 ValueInfo);
2340
2341 return ErrorCode;
2342 }
2343
2344
2345 /************************************************************************
2346 * RegQueryValueExA
2347 *
2348 * @implemented
2349 */
2350 LONG STDCALL
2351 RegQueryValueExA (HKEY hKey,
2352 LPCSTR lpValueName,
2353 LPDWORD lpReserved,
2354 LPDWORD lpType,
2355 LPBYTE lpData,
2356 LPDWORD lpcbData)
2357 {
2358 UNICODE_STRING ValueName;
2359 UNICODE_STRING ValueData;
2360 ANSI_STRING AnsiString;
2361 LONG ErrorCode;
2362 DWORD Length;
2363 DWORD Type;
2364
2365 if (lpData != NULL && lpcbData == NULL)
2366 {
2367 SetLastError(ERROR_INVALID_PARAMETER);
2368 return ERROR_INVALID_PARAMETER;
2369 }
2370
2371 if (lpData)
2372 {
2373 ValueData.Length = *lpcbData * sizeof(WCHAR);
2374 ValueData.MaximumLength = ValueData.Length + sizeof(WCHAR);
2375 ValueData.Buffer = RtlAllocateHeap (ProcessHeap,
2376 0,
2377 ValueData.MaximumLength);
2378 if (!ValueData.Buffer)
2379 {
2380 SetLastError(ERROR_OUTOFMEMORY);
2381 return ERROR_OUTOFMEMORY;
2382 }
2383 }
2384 else
2385 {
2386 ValueData.Buffer = NULL;
2387 ValueData.Length = 0;
2388 ValueData.MaximumLength = 0;
2389 }
2390
2391 RtlCreateUnicodeStringFromAsciiz (&ValueName,
2392 (LPSTR)lpValueName);
2393
2394 if (NULL != lpcbData)
2395 {
2396 Length = *lpcbData * sizeof(WCHAR);
2397 }
2398 ErrorCode = RegQueryValueExW (hKey,
2399 ValueName.Buffer,
2400 lpReserved,
2401 &Type,
2402 (LPBYTE)ValueData.Buffer,
2403 NULL == lpcbData ? NULL : &Length);
2404 DPRINT("ErrorCode %lu\n", ErrorCode);
2405
2406 if (ErrorCode == ERROR_SUCCESS ||
2407 ErrorCode == ERROR_MORE_DATA)
2408 {
2409 if (lpType != NULL)
2410 {
2411 *lpType = Type;
2412 }
2413
2414 if ((Type == REG_SZ) || (Type == REG_MULTI_SZ) || (Type == REG_EXPAND_SZ))
2415 {
2416 if (ErrorCode == ERROR_SUCCESS && ValueData.Buffer != NULL)
2417 {
2418 RtlInitAnsiString(&AnsiString, NULL);
2419 AnsiString.Buffer = lpData;
2420 AnsiString.MaximumLength = *lpcbData;
2421 ValueData.Length = Length;
2422 ValueData.MaximumLength = ValueData.Length + sizeof(WCHAR);
2423 RtlUnicodeStringToAnsiString(&AnsiString, &ValueData, FALSE);
2424 }
2425 Length = Length / sizeof(WCHAR);
2426 }
2427 else if (lpcbData != NULL)
2428 {
2429 Length = min(*lpcbData, Length);
2430 if (ErrorCode == ERROR_SUCCESS && ValueData.Buffer != NULL)
2431 {
2432 RtlMoveMemory(lpData, ValueData.Buffer, Length);
2433 }
2434 }
2435
2436 if (lpcbData != NULL)
2437 {
2438 *lpcbData = Length;
2439 }
2440 }
2441
2442 if (ValueData.Buffer != NULL)
2443 {
2444 RtlFreeHeap(ProcessHeap, 0, ValueData.Buffer);
2445 }
2446
2447 return ErrorCode;
2448 }
2449
2450
2451 /************************************************************************
2452 * RegQueryValueA
2453 *
2454 * @implemented
2455 */
2456 LONG STDCALL
2457 RegQueryValueA (HKEY hKey,
2458 LPCSTR lpSubKey,
2459 LPSTR lpValue,
2460 PLONG lpcbValue)
2461 {
2462 WCHAR SubKeyNameBuffer[MAX_PATH+1];
2463 UNICODE_STRING SubKeyName;
2464 UNICODE_STRING Value;
2465 ANSI_STRING AnsiString;
2466 LONG ValueSize;
2467 LONG ErrorCode;
2468
2469 if (lpValue != NULL &&
2470 lpcbValue == NULL)
2471 {
2472 SetLastError(ERROR_INVALID_PARAMETER);
2473 return ERROR_INVALID_PARAMETER;
2474 }
2475
2476 RtlInitUnicodeString (&SubKeyName,
2477 NULL);
2478 RtlInitUnicodeString (&Value,
2479 NULL);
2480 if (lpSubKey != NULL &&
2481 strlen(lpSubKey) != 0)
2482 {
2483 RtlInitAnsiString (&AnsiString,
2484 (LPSTR)lpSubKey);
2485 SubKeyName.Buffer = &SubKeyNameBuffer[0];
2486 SubKeyName.MaximumLength = sizeof(SubKeyNameBuffer);
2487 RtlAnsiStringToUnicodeString (&SubKeyName,
2488 &AnsiString,
2489 FALSE);
2490 }
2491
2492 if (lpValue != NULL)
2493 {
2494 ValueSize = *lpcbValue * sizeof(WCHAR);
2495 Value.MaximumLength = ValueSize;
2496 Value.Buffer = RtlAllocateHeap (ProcessHeap,
2497 0,
2498 ValueSize);
2499 if (Value.Buffer == NULL)
2500 {
2501 SetLastError(ERROR_OUTOFMEMORY);
2502 return ERROR_OUTOFMEMORY;
2503 }
2504 }
2505 else
2506 {
2507 ValueSize = 0;
2508 }
2509
2510 ErrorCode = RegQueryValueW (hKey,
2511 (LPCWSTR)SubKeyName.Buffer,
2512 Value.Buffer,
2513 &ValueSize);
2514 if (ErrorCode == ERROR_SUCCESS)
2515 {
2516 Value.Length = ValueSize;
2517 RtlInitAnsiString (&AnsiString,
2518 NULL);
2519 AnsiString.Buffer = lpValue;
2520 AnsiString.MaximumLength = *lpcbValue;
2521 RtlUnicodeStringToAnsiString (&AnsiString,
2522 &Value,
2523 FALSE);
2524 }
2525
2526 *lpcbValue = ValueSize;
2527 if (Value.Buffer != NULL)
2528 {
2529 RtlFreeHeap (ProcessHeap,
2530 0,
2531 Value.Buffer);
2532 }
2533
2534 return ErrorCode;
2535 }
2536
2537
2538 /************************************************************************
2539 * RegQueryValueW
2540 *
2541 * @implemented
2542 */
2543 LONG STDCALL
2544 RegQueryValueW (HKEY hKey,
2545 LPCWSTR lpSubKey,
2546 LPWSTR lpValue,
2547 PLONG lpcbValue)
2548 {
2549 OBJECT_ATTRIBUTES ObjectAttributes;
2550 UNICODE_STRING SubKeyString;
2551 HANDLE KeyHandle;
2552 HANDLE RealKey;
2553 LONG ErrorCode;
2554 BOOL CloseRealKey;
2555 NTSTATUS Status;
2556
2557 Status = MapDefaultKey (&KeyHandle,
2558 hKey);
2559 if (!NT_SUCCESS(Status))
2560 {
2561 ErrorCode = RtlNtStatusToDosError (Status);
2562 SetLastError (ErrorCode);
2563 return ErrorCode;
2564 }
2565
2566 if (lpSubKey != NULL &&
2567 wcslen(lpSubKey) != 0)
2568 {
2569 RtlInitUnicodeString (&SubKeyString,
2570 (LPWSTR)lpSubKey);
2571 InitializeObjectAttributes (&ObjectAttributes,
2572 &SubKeyString,
2573 OBJ_CASE_INSENSITIVE,
2574 KeyHandle,
2575 NULL);
2576 Status = NtOpenKey (&RealKey,
2577 KEY_ALL_ACCESS,
2578 &ObjectAttributes);
2579 if (!NT_SUCCESS(Status))
2580 {
2581 ErrorCode = RtlNtStatusToDosError (Status);
2582 SetLastError (ErrorCode);
2583 return ErrorCode;
2584 }
2585 CloseRealKey = TRUE;
2586 }
2587 else
2588 {
2589 RealKey = hKey;
2590 CloseRealKey = FALSE;
2591 }
2592
2593 ErrorCode = RegQueryValueExW (RealKey,
2594 NULL,
2595 NULL,
2596 NULL,
2597 (LPBYTE)lpValue,
2598 (LPDWORD)lpcbValue);
2599 if (CloseRealKey)
2600 {
2601 NtClose (RealKey);
2602 }
2603
2604 return ErrorCode;
2605 }
2606
2607
2608 /************************************************************************
2609 * RegReplaceKeyA
2610 *
2611 * @implemented
2612 */
2613 LONG STDCALL
2614 RegReplaceKeyA (HKEY hKey,
2615 LPCSTR lpSubKey,
2616 LPCSTR lpNewFile,
2617 LPCSTR lpOldFile)
2618 {
2619 UNICODE_STRING SubKey;
2620 UNICODE_STRING NewFile;
2621 UNICODE_STRING OldFile;
2622 LONG ErrorCode;
2623
2624 RtlCreateUnicodeStringFromAsciiz (&SubKey,
2625 (PCSZ)lpSubKey);
2626 RtlCreateUnicodeStringFromAsciiz (&OldFile,
2627 (PCSZ)lpOldFile);
2628 RtlCreateUnicodeStringFromAsciiz (&NewFile,
2629 (PCSZ)lpNewFile);
2630
2631 ErrorCode = RegReplaceKeyW (hKey,
2632 SubKey.Buffer,
2633 NewFile.Buffer,
2634 OldFile.Buffer);
2635
2636 RtlFreeUnicodeString (&OldFile);
2637 RtlFreeUnicodeString (&NewFile);
2638 RtlFreeUnicodeString (&SubKey);
2639
2640 return ErrorCode;
2641 }
2642
2643
2644 /************************************************************************
2645 * RegReplaceKeyW
2646 *
2647 * @unimplemented
2648 */
2649 LONG STDCALL
2650 RegReplaceKeyW (HKEY hKey,
2651 LPCWSTR lpSubKey,
2652 LPCWSTR lpNewFile,
2653 LPCWSTR lpOldFile)
2654 {
2655 OBJECT_ATTRIBUTES KeyObjectAttributes;
2656 OBJECT_ATTRIBUTES NewObjectAttributes;
2657 OBJECT_ATTRIBUTES OldObjectAttributes;
2658 UNICODE_STRING SubKeyName;
2659 UNICODE_STRING NewFileName;
2660 UNICODE_STRING OldFileName;
2661 BOOLEAN CloseRealKey;
2662 HANDLE RealKeyHandle;
2663 HANDLE KeyHandle;
2664 LONG ErrorCode;
2665 NTSTATUS Status;
2666
2667 if (hKey == HKEY_PERFORMANCE_DATA)
2668 {
2669 return ERROR_INVALID_HANDLE;
2670 }
2671
2672 Status = MapDefaultKey (&KeyHandle,
2673 hKey);
2674 if (!NT_SUCCESS(Status))
2675 {
2676 ErrorCode = RtlNtStatusToDosError (Status);
2677 SetLastError (ErrorCode);
2678 return ErrorCode;
2679 }
2680
2681 /* Open the real key */
2682 if (lpSubKey != NULL && *lpSubKey != (WCHAR)0)
2683 {
2684 RtlInitUnicodeString (&SubKeyName,
2685 (PWSTR)lpSubKey);
2686 InitializeObjectAttributes (&KeyObjectAttributes,
2687 &SubKeyName,
2688 OBJ_CASE_INSENSITIVE,
2689 KeyHandle,
2690 NULL);
2691 Status = NtOpenKey (&RealKeyHandle,
2692 KEY_ALL_ACCESS,
2693 &KeyObjectAttributes);
2694 if (!NT_SUCCESS(Status))
2695 {
2696 ErrorCode = RtlNtStatusToDosError (Status);
2697 SetLastError (ErrorCode);
2698 return ErrorCode;
2699 }
2700 CloseRealKey = TRUE;
2701 }
2702 else
2703 {
2704 RealKeyHandle = KeyHandle;
2705 CloseRealKey = FALSE;
2706 }
2707
2708 /* Convert new file name */
2709 if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpNewFile,
2710 &NewFileName,
2711 NULL,
2712 NULL))
2713 {
2714 if (CloseRealKey)
2715 {
2716 NtClose (RealKeyHandle);
2717 }
2718 SetLastError (ERROR_INVALID_PARAMETER);
2719 return ERROR_INVALID_PARAMETER;
2720 }
2721
2722 InitializeObjectAttributes (&NewObjectAttributes,
2723 &NewFileName,
2724 OBJ_CASE_INSENSITIVE,
2725 NULL,
2726 NULL);
2727
2728 /* Convert old file name */
2729 if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpOldFile,
2730 &OldFileName,
2731 NULL,
2732 NULL))
2733 {
2734 RtlFreeUnicodeString (&NewFileName);
2735 if (CloseRealKey)
2736 {
2737 NtClose (RealKeyHandle);
2738 }
2739 SetLastError (ERROR_INVALID_PARAMETER);
2740 return ERROR_INVALID_PARAMETER;
2741 }
2742
2743 InitializeObjectAttributes (&OldObjectAttributes,
2744 &OldFileName,
2745 OBJ_CASE_INSENSITIVE,
2746 NULL,
2747 NULL);
2748
2749 Status = NtReplaceKey (&NewObjectAttributes,
2750 RealKeyHandle,
2751 &OldObjectAttributes);
2752
2753 RtlFreeUnicodeString (&OldFileName);
2754 RtlFreeUnicodeString (&NewFileName);
2755
2756 if (CloseRealKey)
2757 {
2758 NtClose (RealKeyHandle);
2759 }
2760
2761 if (!NT_SUCCESS(Status))
2762 {
2763 ErrorCode = RtlNtStatusToDosError (Status);
2764 SetLastError (ErrorCode);
2765 return ErrorCode;
2766 }
2767
2768 return ERROR_SUCCESS;
2769 }
2770
2771
2772 /************************************************************************
2773 * RegRestoreKeyA
2774 *
2775 * @implemented
2776 */
2777 LONG STDCALL
2778 RegRestoreKeyA (HKEY hKey,
2779 LPCSTR lpFile,
2780 DWORD dwFlags)
2781 {
2782 UNICODE_STRING FileName;
2783 LONG ErrorCode;
2784
2785 RtlCreateUnicodeStringFromAsciiz (&FileName,
2786 (PCSZ)lpFile);
2787
2788 ErrorCode = RegRestoreKeyW (hKey,
2789 FileName.Buffer,
2790 dwFlags);
2791
2792 RtlFreeUnicodeString (&FileName);
2793
2794 return ErrorCode;
2795 }
2796
2797
2798 /************************************************************************
2799 * RegRestoreKeyW
2800 *
2801 * @implemented
2802 */
2803 LONG STDCALL
2804 RegRestoreKeyW (HKEY hKey,
2805 LPCWSTR lpFile,
2806 DWORD dwFlags)
2807 {
2808 OBJECT_ATTRIBUTES ObjectAttributes;
2809 IO_STATUS_BLOCK IoStatusBlock;
2810 UNICODE_STRING FileName;
2811 HANDLE FileHandle;
2812 HANDLE KeyHandle;
2813 LONG ErrorCode;
2814 NTSTATUS Status;
2815
2816 if (hKey == HKEY_PERFORMANCE_DATA)
2817 {
2818 return ERROR_INVALID_HANDLE;
2819 }
2820
2821 Status = MapDefaultKey (&KeyHandle,
2822 hKey);
2823 if (!NT_SUCCESS(Status))
2824 {
2825 ErrorCode = RtlNtStatusToDosError (Status);
2826 SetLastError (ErrorCode);
2827 return ErrorCode;
2828 }
2829
2830 if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFile,
2831 &FileName,
2832 NULL,
2833 NULL))
2834 {
2835 SetLastError (ERROR_INVALID_PARAMETER);
2836 return ERROR_INVALID_PARAMETER;
2837 }
2838
2839 InitializeObjectAttributes (&ObjectAttributes,
2840 &FileName,
2841 OBJ_CASE_INSENSITIVE,
2842 NULL,
2843 NULL);
2844
2845 Status = NtOpenFile (&FileHandle,
2846 FILE_GENERIC_READ,
2847 &ObjectAttributes,
2848 &IoStatusBlock,
2849 FILE_SHARE_READ,
2850 FILE_SYNCHRONOUS_IO_NONALERT);
2851 RtlFreeUnicodeString (&FileName);
2852 if (!NT_SUCCESS(Status))
2853 {
2854 ErrorCode = RtlNtStatusToDosError (Status);
2855 SetLastError (ErrorCode);
2856 return ErrorCode;
2857 }
2858
2859 Status = NtRestoreKey (KeyHandle,
2860 FileHandle,
2861 (ULONG)dwFlags);
2862 NtClose (FileHandle);
2863 if (!NT_SUCCESS(Status))
2864 {
2865 ErrorCode = RtlNtStatusToDosError (Status);
2866 SetLastError (ErrorCode);
2867 return ErrorCode;
2868 }
2869
2870 return ERROR_SUCCESS;
2871 }
2872
2873
2874 /************************************************************************
2875 * RegSaveKeyA
2876 *
2877 * @implemented
2878 */
2879 LONG STDCALL
2880 RegSaveKeyA (HKEY hKey,
2881 LPCSTR lpFile,
2882 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
2883 {
2884 UNICODE_STRING FileName;
2885 LONG ErrorCode;
2886
2887 RtlCreateUnicodeStringFromAsciiz (&FileName,
2888 (LPSTR)lpFile);
2889 ErrorCode = RegSaveKeyW (hKey,
2890 FileName.Buffer,
2891 lpSecurityAttributes);
2892 RtlFreeUnicodeString (&FileName);
2893
2894 return ErrorCode;
2895 }
2896
2897
2898 /************************************************************************
2899 * RegSaveKeyW
2900 *
2901 * @implemented
2902 */
2903 LONG STDCALL
2904 RegSaveKeyW (HKEY hKey,
2905 LPCWSTR lpFile,
2906 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
2907 {
2908 PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
2909 OBJECT_ATTRIBUTES ObjectAttributes;
2910 UNICODE_STRING FileName;
2911 IO_STATUS_BLOCK IoStatusBlock;
2912 HANDLE FileHandle;
2913 HANDLE KeyHandle;
2914 NTSTATUS Status;
2915 LONG ErrorCode;
2916
2917 Status = MapDefaultKey (&KeyHandle,
2918 hKey);
2919 if (!NT_SUCCESS(Status))
2920 {
2921 ErrorCode = RtlNtStatusToDosError (Status);
2922 SetLastError (ErrorCode);
2923 return ErrorCode;
2924 }
2925
2926 if (!RtlDosPathNameToNtPathName_U ((PWSTR)lpFile,
2927 &FileName,
2928 NULL,
2929 NULL))
2930 {
2931 SetLastError (ERROR_INVALID_PARAMETER);
2932 return ERROR_INVALID_PARAMETER;
2933 }
2934
2935 if (lpSecurityAttributes != NULL)
2936 {
2937 SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
2938 }
2939
2940 InitializeObjectAttributes (&ObjectAttributes,
2941 &FileName,
2942 OBJ_CASE_INSENSITIVE,
2943 NULL,
2944 SecurityDescriptor);
2945 Status = NtCreateFile (&FileHandle,
2946 GENERIC_WRITE | SYNCHRONIZE,
2947 &ObjectAttributes,
2948 &IoStatusBlock,
2949 NULL,
2950 FILE_ATTRIBUTE_NORMAL,
2951 FILE_SHARE_READ,
2952 FILE_CREATE,
2953 FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
2954 NULL,
2955 0);
2956 RtlFreeUnicodeString (&FileName);
2957 if (!NT_SUCCESS(Status))
2958 {
2959 ErrorCode = RtlNtStatusToDosError (Status);
2960 SetLastError (ErrorCode);
2961 return ErrorCode;
2962 }
2963
2964 Status = NtSaveKey (KeyHandle,
2965 FileHandle);
2966 NtClose (FileHandle);
2967 if (!NT_SUCCESS(Status))
2968 {
2969 ErrorCode = RtlNtStatusToDosError (Status);
2970 SetLastError (ErrorCode);
2971 return ErrorCode;
2972 }
2973
2974 return ERROR_SUCCESS;
2975 }
2976
2977
2978 /************************************************************************
2979 * RegSetKeySecurity
2980 *
2981 * @implemented
2982 */
2983 LONG STDCALL
2984 RegSetKeySecurity (HKEY hKey,
2985 SECURITY_INFORMATION SecurityInformation,
2986 PSECURITY_DESCRIPTOR pSecurityDescriptor)
2987 {
2988 HANDLE KeyHandle;
2989 LONG ErrorCode;
2990 NTSTATUS Status;
2991
2992 if (hKey == HKEY_PERFORMANCE_DATA)
2993 {
2994 return ERROR_INVALID_HANDLE;
2995 }
2996
2997 Status = MapDefaultKey (&KeyHandle,
2998 hKey);
2999 if (!NT_SUCCESS(Status))
3000 {
3001 ErrorCode = RtlNtStatusToDosError (Status);
3002 SetLastError (ErrorCode);
3003 return ErrorCode;
3004 }
3005
3006 Status = NtSetSecurityObject (KeyHandle,
3007 SecurityInformation,
3008 pSecurityDescriptor);
3009 if (!NT_SUCCESS(Status))
3010 {
3011 ErrorCode = RtlNtStatusToDosError (Status);
3012 SetLastError (ErrorCode);
3013 return ErrorCode;
3014 }
3015
3016 return ERROR_SUCCESS;
3017 }
3018
3019
3020 /************************************************************************
3021 * RegSetValueExA
3022 *
3023 * @implemented
3024 */
3025 LONG STDCALL
3026 RegSetValueExA (HKEY hKey,
3027 LPCSTR lpValueName,
3028 DWORD Reserved,
3029 DWORD dwType,
3030 CONST BYTE* lpData,
3031 DWORD cbData)
3032 {
3033 UNICODE_STRING ValueName;
3034 LPWSTR pValueName;
3035 ANSI_STRING AnsiString;
3036 UNICODE_STRING Data;
3037 LONG ErrorCode;
3038 LPBYTE pData;
3039 DWORD DataSize;
3040
3041 if (lpData == NULL)
3042 {
3043 SetLastError (ERROR_INVALID_PARAMETER);
3044 return ERROR_INVALID_PARAMETER;
3045 }
3046
3047 if (lpValueName != NULL &&
3048 strlen(lpValueName) != 0)
3049 {
3050 RtlCreateUnicodeStringFromAsciiz (&ValueName,
3051 (PSTR)lpValueName);
3052 pValueName = (LPWSTR)ValueName.Buffer;
3053 }
3054 else
3055 {
3056 pValueName = NULL;
3057 }
3058
3059 if ((dwType == REG_SZ) ||
3060 (dwType == REG_MULTI_SZ) ||
3061 (dwType == REG_EXPAND_SZ))
3062 {
3063 RtlInitAnsiString (&AnsiString,
3064 NULL);
3065 AnsiString.Buffer = (PSTR)lpData;
3066 AnsiString.Length = cbData;
3067 AnsiString.MaximumLength = cbData;
3068 RtlAnsiStringToUnicodeString (&Data,
3069 &AnsiString,
3070 TRUE);
3071 pData = (LPBYTE)Data.Buffer;
3072 DataSize = cbData * sizeof(WCHAR);
3073 }
3074 else
3075 {
3076 RtlInitUnicodeString (&Data,
3077 NULL);
3078 pData = (LPBYTE)lpData;
3079 DataSize = cbData;
3080 }
3081
3082 ErrorCode = RegSetValueExW (hKey,
3083 pValueName,
3084 Reserved,
3085 dwType,
3086 pData,
3087 DataSize);
3088 if (pValueName != NULL)
3089 {
3090 RtlFreeHeap (ProcessHeap,
3091 0,
3092 ValueName.Buffer);
3093 }
3094
3095 if (Data.Buffer != NULL)
3096 {
3097 RtlFreeHeap (ProcessHeap,
3098 0,
3099 Data.Buffer);
3100 }
3101
3102 return ErrorCode;
3103 }
3104
3105
3106 /************************************************************************
3107 * RegSetValueExW
3108 *
3109 * @implemented
3110 */
3111 LONG STDCALL
3112 RegSetValueExW (HKEY hKey,
3113 LPCWSTR lpValueName,
3114 DWORD Reserved,
3115 DWORD dwType,
3116 CONST BYTE* lpData,
3117 DWORD cbData)
3118 {
3119 UNICODE_STRING ValueName;
3120 PUNICODE_STRING pValueName;
3121 HANDLE KeyHandle;
3122 NTSTATUS Status;
3123 LONG ErrorCode;
3124
3125 Status = MapDefaultKey (&KeyHandle,
3126 hKey);
3127 if (!NT_SUCCESS(Status))
3128 {
3129 ErrorCode = RtlNtStatusToDosError (Status);
3130 SetLastError (ErrorCode);
3131 return ErrorCode;
3132 }
3133
3134 if (lpValueName != NULL)
3135 {
3136 RtlInitUnicodeString (&ValueName,
3137 lpValueName);
3138 }
3139 else
3140 {
3141 RtlInitUnicodeString (&ValueName, L"");
3142 }
3143 pValueName = &ValueName;
3144
3145 Status = NtSetValueKey (KeyHandle,
3146 pValueName,
3147 0,
3148 dwType,
3149 (PVOID)lpData,
3150 (ULONG)cbData);
3151 if (!NT_SUCCESS(Status))
3152 {
3153 ErrorCode = RtlNtStatusToDosError (Status);
3154 SetLastError (ErrorCode);
3155 return ErrorCode;
3156 }
3157
3158 return ERROR_SUCCESS;
3159 }
3160
3161
3162 /************************************************************************
3163 * RegSetValueA
3164 *
3165 * @implemented
3166 */
3167 LONG STDCALL
3168 RegSetValueA (HKEY hKey,
3169 LPCSTR lpSubKey,
3170 DWORD dwType,
3171 LPCSTR lpData,
3172 DWORD cbData)
3173 {
3174 WCHAR SubKeyNameBuffer[MAX_PATH+1];
3175 UNICODE_STRING SubKeyName;
3176 UNICODE_STRING Data;
3177 ANSI_STRING AnsiString;
3178 LONG DataSize;
3179 LONG ErrorCode;
3180
3181 if (lpData == NULL)
3182 {
3183 SetLastError (ERROR_INVALID_PARAMETER);
3184 return ERROR_INVALID_PARAMETER;
3185 }
3186
3187 RtlInitUnicodeString (&SubKeyName, NULL);
3188 RtlInitUnicodeString (&Data, NULL);
3189 if (lpSubKey != NULL && (strlen(lpSubKey) != 0))
3190 {
3191 RtlInitAnsiString (&AnsiString, (LPSTR)lpSubKey);
3192 SubKeyName.Buffer = &SubKeyNameBuffer[0];
3193 SubKeyName.MaximumLength = sizeof(SubKeyNameBuffer);
3194 RtlAnsiStringToUnicodeString (&SubKeyName, &AnsiString, FALSE);
3195 }
3196
3197 DataSize = cbData * sizeof(WCHAR);
3198 Data.MaximumLength = DataSize;
3199 Data.Buffer = RtlAllocateHeap (ProcessHeap,
3200 0,
3201 DataSize);
3202 if (Data.Buffer == NULL)
3203 {
3204 SetLastError (ERROR_OUTOFMEMORY);
3205 return ERROR_OUTOFMEMORY;
3206 }
3207
3208 ErrorCode = RegSetValueW (hKey,
3209 (LPCWSTR)SubKeyName.Buffer,
3210 dwType,
3211 Data.Buffer,
3212 DataSize);
3213
3214 RtlFreeHeap (ProcessHeap,
3215 0,
3216 Data.Buffer);
3217
3218 return ErrorCode;
3219 }
3220
3221
3222 /************************************************************************
3223 * RegSetValueW
3224 *
3225 * @implemented
3226 */
3227 LONG STDCALL
3228 RegSetValueW (HKEY hKey,
3229 LPCWSTR lpSubKey,
3230 DWORD dwType,
3231 LPCWSTR lpData,
3232 DWORD cbData)
3233 {
3234 OBJECT_ATTRIBUTES ObjectAttributes;
3235 UNICODE_STRING SubKeyString;
3236 HANDLE KeyHandle;
3237 HANDLE RealKey;
3238 LONG ErrorCode;
3239 BOOL CloseRealKey;
3240 NTSTATUS Status;
3241
3242 Status = MapDefaultKey (&KeyHandle,
3243 hKey);
3244 if (!NT_SUCCESS(Status))
3245 {
3246 ErrorCode = RtlNtStatusToDosError (Status);
3247 SetLastError (ErrorCode);
3248 return ErrorCode;
3249 }
3250
3251 if ((lpSubKey) && (wcslen(lpSubKey) != 0))
3252 {
3253 RtlInitUnicodeString (&SubKeyString,
3254 (LPWSTR)lpSubKey);
3255 InitializeObjectAttributes (&ObjectAttributes,
3256 &SubKeyString,
3257 OBJ_CASE_INSENSITIVE,
3258 KeyHandle,
3259 NULL);
3260 Status = NtOpenKey (&RealKey,
3261 KEY_ALL_ACCESS,
3262 &ObjectAttributes);
3263 if (!NT_SUCCESS(Status))
3264 {
3265 ErrorCode = RtlNtStatusToDosError (Status);
3266 SetLastError (ErrorCode);
3267 return ErrorCode;
3268 }
3269 CloseRealKey = TRUE;
3270 }
3271 else
3272 {
3273 RealKey = hKey;
3274 CloseRealKey = FALSE;
3275 }
3276
3277 ErrorCode = RegSetValueExW (RealKey,
3278 NULL,
3279 0,
3280 dwType,
3281 (LPBYTE)lpData,
3282 cbData);
3283 if (CloseRealKey == TRUE)
3284 {
3285 NtClose (RealKey);
3286 }
3287
3288 return ErrorCode;
3289 }
3290
3291
3292 /************************************************************************
3293 * RegUnLoadKeyA
3294 *
3295 * @implemented
3296 */
3297 LONG STDCALL
3298 RegUnLoadKeyA (HKEY hKey,
3299 LPCSTR lpSubKey)
3300 {
3301 UNICODE_STRING KeyName;
3302 DWORD ErrorCode;
3303
3304 RtlCreateUnicodeStringFromAsciiz (&KeyName,
3305 (LPSTR)lpSubKey);
3306
3307 ErrorCode = RegUnLoadKeyW (hKey,
3308 KeyName.Buffer);
3309
3310 RtlFreeUnicodeString (&KeyName);
3311
3312 return ErrorCode;
3313 }
3314
3315
3316 /************************************************************************
3317 * RegUnLoadKeyW
3318 *
3319 * @implemented
3320 */
3321 LONG STDCALL
3322 RegUnLoadKeyW (HKEY hKey,
3323 LPCWSTR lpSubKey)
3324 {
3325 OBJECT_ATTRIBUTES ObjectAttributes;
3326 UNICODE_STRING KeyName;
3327 HANDLE KeyHandle;
3328 DWORD ErrorCode;
3329 NTSTATUS Status;
3330
3331 if (hKey == HKEY_PERFORMANCE_DATA)
3332 return ERROR_INVALID_HANDLE;
3333
3334 Status = MapDefaultKey (&KeyHandle, hKey);
3335 if (!NT_SUCCESS(Status))
3336 {
3337 ErrorCode = RtlNtStatusToDosError (Status);
3338 SetLastError (ErrorCode);
3339 return ErrorCode;
3340 }
3341
3342 RtlInitUnicodeString (&KeyName,
3343 (LPWSTR)lpSubKey);
3344
3345 InitializeObjectAttributes (&ObjectAttributes,
3346 &KeyName,
3347 OBJ_CASE_INSENSITIVE,
3348 KeyHandle,
3349 NULL);
3350
3351 Status = NtUnloadKey (&ObjectAttributes);
3352
3353 if (!NT_SUCCESS(Status))
3354 {
3355 ErrorCode = RtlNtStatusToDosError (Status);
3356 SetLastError (ErrorCode);
3357 return ErrorCode;
3358 }
3359
3360 return ERROR_SUCCESS;
3361 }
3362
3363 /* EOF */