- Fix a typo in RegGetKeySecurity().
[reactos.git] / reactos / lib / advapi32 / reg / reg.c
1 /* $Id: reg.c,v 1.56 2004/09/13 11:41:26 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 /* FIXME */
2107 *lpcbSecurityDescriptor = 0;
2108 }
2109
2110 if (lpftLastWriteTime != NULL)
2111 {
2112 lpftLastWriteTime->dwLowDateTime = FullInfo->LastWriteTime.u.LowPart;
2113 lpftLastWriteTime->dwHighDateTime = FullInfo->LastWriteTime.u.HighPart;
2114 }
2115
2116 if (lpClass != NULL)
2117 {
2118 if (FullInfo->ClassLength > ClassLength)
2119 {
2120 ErrorCode = ERROR_BUFFER_OVERFLOW;
2121 }
2122 else
2123 {
2124 RtlCopyMemory (lpClass,
2125 FullInfo->Class,
2126 FullInfo->ClassLength);
2127 *lpcbClass = FullInfo->ClassLength / sizeof(WCHAR);
2128 lpClass[*lpcbClass] = 0;
2129 }
2130
2131 RtlFreeHeap (ProcessHeap,
2132 0,
2133 FullInfo);
2134 }
2135
2136 if (ErrorCode != ERROR_SUCCESS)
2137 {
2138 SetLastError (ErrorCode);
2139 }
2140
2141 return ErrorCode;
2142 }
2143
2144
2145 /************************************************************************
2146 * RegQueryMultipleValuesA
2147 *
2148 * @unimplemented
2149 */
2150 LONG STDCALL
2151 RegQueryMultipleValuesA (HKEY hKey,
2152 PVALENTA val_list,
2153 DWORD num_vals,
2154 LPSTR lpValueBuf,
2155 LPDWORD ldwTotsize)
2156 {
2157 UNIMPLEMENTED;
2158 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2159 return ERROR_CALL_NOT_IMPLEMENTED;
2160 }
2161
2162
2163 /************************************************************************
2164 * RegQueryMultipleValuesW
2165 *
2166 * @implemented
2167 */
2168 LONG STDCALL
2169 RegQueryMultipleValuesW (HKEY hKey,
2170 PVALENTW val_list,
2171 DWORD num_vals,
2172 LPWSTR lpValueBuf,
2173 LPDWORD ldwTotsize)
2174 {
2175 ULONG i;
2176 DWORD maxBytes = *ldwTotsize;
2177 LPSTR bufptr = (LPSTR)lpValueBuf;
2178 LONG ErrorCode;
2179
2180 if (maxBytes >= (1024*1024))
2181 return ERROR_TRANSFER_TOO_LONG;
2182
2183 *ldwTotsize = 0;
2184
2185 DPRINT ("RegQueryMultipleValuesW(%p,%p,%ld,%p,%p=%ld)\n",
2186 hKey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize);
2187
2188 for (i = 0; i < num_vals; ++i)
2189 {
2190 val_list[i].ve_valuelen = 0;
2191 ErrorCode = RegQueryValueExW (hKey,
2192 val_list[i].ve_valuename,
2193 NULL,
2194 NULL,
2195 NULL,
2196 &val_list[i].ve_valuelen);
2197 if (ErrorCode != ERROR_SUCCESS)
2198 {
2199 return ErrorCode;
2200 }
2201
2202 if (lpValueBuf != NULL && *ldwTotsize + val_list[i].ve_valuelen <= maxBytes)
2203 {
2204 ErrorCode = RegQueryValueExW (hKey,
2205 val_list[i].ve_valuename,
2206 NULL,
2207 &val_list[i].ve_type,
2208 bufptr,
2209 &val_list[i].ve_valuelen);
2210 if (ErrorCode != ERROR_SUCCESS)
2211 {
2212 return ErrorCode;
2213 }
2214
2215 val_list[i].ve_valueptr = (DWORD_PTR)bufptr;
2216
2217 bufptr += val_list[i].ve_valuelen;
2218 }
2219
2220 *ldwTotsize += val_list[i].ve_valuelen;
2221 }
2222
2223 return (lpValueBuf != NULL && *ldwTotsize <= maxBytes) ? ERROR_SUCCESS : ERROR_MORE_DATA;
2224 }
2225
2226
2227 /************************************************************************
2228 * RegQueryValueExW
2229 *
2230 * @implemented
2231 */
2232 LONG STDCALL
2233 RegQueryValueExW (HKEY hKey,
2234 LPCWSTR lpValueName,
2235 LPDWORD lpReserved,
2236 LPDWORD lpType,
2237 LPBYTE lpData,
2238 LPDWORD lpcbData)
2239 {
2240 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
2241 UNICODE_STRING ValueName;
2242 NTSTATUS Status;
2243 LONG ErrorCode = ERROR_SUCCESS;
2244 ULONG BufferSize;
2245 ULONG ResultSize;
2246 HANDLE KeyHandle;
2247 ULONG MaxCopy = lpcbData != NULL && lpData != NULL ? *lpcbData : 0;
2248
2249 DPRINT("hKey 0x%X lpValueName %S lpData 0x%X lpcbData %d\n",
2250 hKey, lpValueName, lpData, lpcbData ? *lpcbData : 0);
2251
2252 Status = MapDefaultKey (&KeyHandle,
2253 hKey);
2254 if (!NT_SUCCESS(Status))
2255 {
2256 ErrorCode = RtlNtStatusToDosError (Status);
2257 SetLastError (ErrorCode);
2258 return ErrorCode;
2259 }
2260
2261 if (lpData != NULL && lpcbData == NULL)
2262 {
2263 SetLastError (ERROR_INVALID_PARAMETER);
2264 return ERROR_INVALID_PARAMETER;
2265 }
2266
2267 RtlInitUnicodeString (&ValueName,
2268 lpValueName);
2269 BufferSize = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + MaxCopy;
2270 ValueInfo = RtlAllocateHeap (ProcessHeap,
2271 0,
2272 BufferSize);
2273 if (ValueInfo == NULL)
2274 {
2275 SetLastError(ERROR_OUTOFMEMORY);
2276 return ERROR_OUTOFMEMORY;
2277 }
2278
2279 Status = NtQueryValueKey (hKey,
2280 &ValueName,
2281 KeyValuePartialInformation,
2282 ValueInfo,
2283 BufferSize,
2284 &ResultSize);
2285 DPRINT("Status 0x%X\n", Status);
2286 if (Status == STATUS_BUFFER_TOO_SMALL)
2287 {
2288 /* Return ERROR_SUCCESS and the buffer space needed for a successful call */
2289 MaxCopy = 0;
2290 ErrorCode = lpData ? ERROR_MORE_DATA : ERROR_SUCCESS;
2291 }
2292 else if (!NT_SUCCESS(Status))
2293 {
2294 ErrorCode = RtlNtStatusToDosError (Status);
2295 SetLastError (ErrorCode);
2296 MaxCopy = 0;
2297 if (lpcbData != NULL)
2298 {
2299 ResultSize = sizeof(*ValueInfo) + *lpcbData;
2300 }
2301 }
2302
2303 if (lpType != NULL)
2304 {
2305 *lpType = ValueInfo->Type;
2306 }
2307
2308 if (NT_SUCCESS(Status) && lpData != NULL)
2309 {
2310 RtlMoveMemory (lpData,
2311 ValueInfo->Data,
2312 min(ValueInfo->DataLength, MaxCopy));
2313 }
2314
2315 if ((ValueInfo->Type == REG_SZ) ||
2316 (ValueInfo->Type == REG_MULTI_SZ) ||
2317 (ValueInfo->Type == REG_EXPAND_SZ))
2318 {
2319 if (lpData != NULL && MaxCopy > ValueInfo->DataLength)
2320 {
2321 ((PWSTR)lpData)[ValueInfo->DataLength / sizeof(WCHAR)] = 0;
2322 }
2323
2324 if (lpcbData != NULL)
2325 {
2326 *lpcbData = (ResultSize - sizeof(*ValueInfo));
2327 DPRINT("(string) Returning Size: %lu\n", *lpcbData);
2328 }
2329 }
2330 else
2331 {
2332 if (lpcbData != NULL)
2333 {
2334 *lpcbData = ResultSize - sizeof(*ValueInfo);
2335 DPRINT("(other) Returning Size: %lu\n", *lpcbData);
2336 }
2337 }
2338
2339 DPRINT("Type %d Size %d\n", ValueInfo->Type, ValueInfo->DataLength);
2340
2341 RtlFreeHeap (ProcessHeap,
2342 0,
2343 ValueInfo);
2344
2345 return ErrorCode;
2346 }
2347
2348
2349 /************************************************************************
2350 * RegQueryValueExA
2351 *
2352 * @implemented
2353 */
2354 LONG STDCALL
2355 RegQueryValueExA (HKEY hKey,
2356 LPCSTR lpValueName,
2357 LPDWORD lpReserved,
2358 LPDWORD lpType,
2359 LPBYTE lpData,
2360 LPDWORD lpcbData)
2361 {
2362 UNICODE_STRING ValueName;
2363 UNICODE_STRING ValueData;
2364 ANSI_STRING AnsiString;
2365 LONG ErrorCode;
2366 DWORD Length;
2367 DWORD Type;
2368
2369 if (lpData != NULL && lpcbData == NULL)
2370 {
2371 SetLastError(ERROR_INVALID_PARAMETER);
2372 return ERROR_INVALID_PARAMETER;
2373 }
2374
2375 if (lpData)
2376 {
2377 ValueData.Length = *lpcbData * sizeof(WCHAR);
2378 ValueData.MaximumLength = ValueData.Length + sizeof(WCHAR);
2379 ValueData.Buffer = RtlAllocateHeap (ProcessHeap,
2380 0,
2381 ValueData.MaximumLength);
2382 if (!ValueData.Buffer)
2383 {
2384 SetLastError(ERROR_OUTOFMEMORY);
2385 return ERROR_OUTOFMEMORY;
2386 }
2387 }
2388 else
2389 {
2390 ValueData.Buffer = NULL;
2391 ValueData.Length = 0;
2392 ValueData.MaximumLength = 0;
2393 }
2394
2395 RtlCreateUnicodeStringFromAsciiz (&ValueName,
2396 (LPSTR)lpValueName);
2397
2398 if (NULL != lpcbData)
2399 {
2400 Length = *lpcbData * sizeof(WCHAR);
2401 }
2402 ErrorCode = RegQueryValueExW (hKey,
2403 ValueName.Buffer,
2404 lpReserved,
2405 &Type,
2406 (LPBYTE)ValueData.Buffer,
2407 NULL == lpcbData ? NULL : &Length);
2408 DPRINT("ErrorCode %lu\n", ErrorCode);
2409
2410 if (ErrorCode == ERROR_SUCCESS ||
2411 ErrorCode == ERROR_MORE_DATA)
2412 {
2413 if (lpType != NULL)
2414 {
2415 *lpType = Type;
2416 }
2417
2418 if ((Type == REG_SZ) || (Type == REG_MULTI_SZ) || (Type == REG_EXPAND_SZ))
2419 {
2420 if (ErrorCode == ERROR_SUCCESS && ValueData.Buffer != NULL)
2421 {
2422 RtlInitAnsiString(&AnsiString, NULL);
2423 AnsiString.Buffer = lpData;
2424 AnsiString.MaximumLength = *lpcbData;
2425 ValueData.Length = Length;
2426 ValueData.MaximumLength = ValueData.Length + sizeof(WCHAR);
2427 RtlUnicodeStringToAnsiString(&AnsiString, &ValueData, FALSE);
2428 }
2429 Length = Length / sizeof(WCHAR);
2430 }
2431 else if (lpcbData != NULL)
2432 {
2433 Length = min(*lpcbData, Length);
2434 if (ErrorCode == ERROR_SUCCESS && ValueData.Buffer != NULL)
2435 {
2436 RtlMoveMemory(lpData, ValueData.Buffer, Length);
2437 }
2438 }
2439
2440 if (lpcbData != NULL)
2441 {
2442 *lpcbData = Length;
2443 }
2444 }
2445
2446 if (ValueData.Buffer != NULL)
2447 {
2448 RtlFreeHeap(ProcessHeap, 0, ValueData.Buffer);
2449 }
2450
2451 return ErrorCode;
2452 }
2453
2454
2455 /************************************************************************
2456 * RegQueryValueA
2457 *
2458 * @implemented
2459 */
2460 LONG STDCALL
2461 RegQueryValueA (HKEY hKey,
2462 LPCSTR lpSubKey,
2463 LPSTR lpValue,
2464 PLONG lpcbValue)
2465 {
2466 WCHAR SubKeyNameBuffer[MAX_PATH+1];
2467 UNICODE_STRING SubKeyName;
2468 UNICODE_STRING Value;
2469 ANSI_STRING AnsiString;
2470 LONG ValueSize;
2471 LONG ErrorCode;
2472
2473 if (lpValue != NULL &&
2474 lpcbValue == NULL)
2475 {
2476 SetLastError(ERROR_INVALID_PARAMETER);
2477 return ERROR_INVALID_PARAMETER;
2478 }
2479
2480 RtlInitUnicodeString (&SubKeyName,
2481 NULL);
2482 RtlInitUnicodeString (&Value,
2483 NULL);
2484 if (lpSubKey != NULL &&
2485 strlen(lpSubKey) != 0)
2486 {
2487 RtlInitAnsiString (&AnsiString,
2488 (LPSTR)lpSubKey);
2489 SubKeyName.Buffer = &SubKeyNameBuffer[0];
2490 SubKeyName.MaximumLength = sizeof(SubKeyNameBuffer);
2491 RtlAnsiStringToUnicodeString (&SubKeyName,
2492 &AnsiString,
2493 FALSE);
2494 }
2495
2496 if (lpValue != NULL)
2497 {
2498 ValueSize = *lpcbValue * sizeof(WCHAR);
2499 Value.MaximumLength = ValueSize;
2500 Value.Buffer = RtlAllocateHeap (ProcessHeap,
2501 0,
2502 ValueSize);
2503 if (Value.Buffer == NULL)
2504 {
2505 SetLastError(ERROR_OUTOFMEMORY);
2506 return ERROR_OUTOFMEMORY;
2507 }
2508 }
2509 else
2510 {
2511 ValueSize = 0;
2512 }
2513
2514 ErrorCode = RegQueryValueW (hKey,
2515 (LPCWSTR)SubKeyName.Buffer,
2516 Value.Buffer,
2517 &ValueSize);
2518 if (ErrorCode == ERROR_SUCCESS)
2519 {
2520 Value.Length = ValueSize;
2521 RtlInitAnsiString (&AnsiString,
2522 NULL);
2523 AnsiString.Buffer = lpValue;
2524 AnsiString.MaximumLength = *lpcbValue;
2525 RtlUnicodeStringToAnsiString (&AnsiString,
2526 &Value,
2527 FALSE);
2528 }
2529
2530 *lpcbValue = ValueSize;
2531 if (Value.Buffer != NULL)
2532 {
2533 RtlFreeHeap (ProcessHeap,
2534 0,
2535 Value.Buffer);
2536 }
2537
2538 return ErrorCode;
2539 }
2540
2541
2542 /************************************************************************
2543 * RegQueryValueW
2544 *
2545 * @implemented
2546 */
2547 LONG STDCALL
2548 RegQueryValueW (HKEY hKey,
2549 LPCWSTR lpSubKey,
2550 LPWSTR lpValue,
2551 PLONG lpcbValue)
2552 {
2553 OBJECT_ATTRIBUTES ObjectAttributes;
2554 UNICODE_STRING SubKeyString;
2555 HANDLE KeyHandle;
2556 HANDLE RealKey;
2557 LONG ErrorCode;
2558 BOOL CloseRealKey;
2559 NTSTATUS Status;
2560
2561 Status = MapDefaultKey (&KeyHandle,
2562 hKey);
2563 if (!NT_SUCCESS(Status))
2564 {
2565 ErrorCode = RtlNtStatusToDosError (Status);
2566 SetLastError (ErrorCode);
2567 return ErrorCode;
2568 }
2569
2570 if (lpSubKey != NULL &&
2571 wcslen(lpSubKey) != 0)
2572 {
2573 RtlInitUnicodeString (&SubKeyString,
2574 (LPWSTR)lpSubKey);
2575 InitializeObjectAttributes (&ObjectAttributes,
2576 &SubKeyString,
2577 OBJ_CASE_INSENSITIVE,
2578 KeyHandle,
2579 NULL);
2580 Status = NtOpenKey (&RealKey,
2581 KEY_ALL_ACCESS,
2582 &ObjectAttributes);
2583 if (!NT_SUCCESS(Status))
2584 {
2585 ErrorCode = RtlNtStatusToDosError (Status);
2586 SetLastError (ErrorCode);
2587 return ErrorCode;
2588 }
2589 CloseRealKey = TRUE;
2590 }
2591 else
2592 {
2593 RealKey = hKey;
2594 CloseRealKey = FALSE;
2595 }
2596
2597 ErrorCode = RegQueryValueExW (RealKey,
2598 NULL,
2599 NULL,
2600 NULL,
2601 (LPBYTE)lpValue,
2602 (LPDWORD)lpcbValue);
2603 if (CloseRealKey)
2604 {
2605 NtClose (RealKey);
2606 }
2607
2608 return ErrorCode;
2609 }
2610
2611
2612 /************************************************************************
2613 * RegReplaceKeyA
2614 *
2615 * @implemented
2616 */
2617 LONG STDCALL
2618 RegReplaceKeyA (HKEY hKey,
2619 LPCSTR lpSubKey,
2620 LPCSTR lpNewFile,
2621 LPCSTR lpOldFile)
2622 {
2623 UNICODE_STRING SubKey;
2624 UNICODE_STRING NewFile;
2625 UNICODE_STRING OldFile;
2626 LONG ErrorCode;
2627
2628 RtlCreateUnicodeStringFromAsciiz (&SubKey,
2629 (PCSZ)lpSubKey);
2630 RtlCreateUnicodeStringFromAsciiz (&OldFile,
2631 (PCSZ)lpOldFile);
2632 RtlCreateUnicodeStringFromAsciiz (&NewFile,
2633 (PCSZ)lpNewFile);
2634
2635 ErrorCode = RegReplaceKeyW (hKey,
2636 SubKey.Buffer,
2637 NewFile.Buffer,
2638 OldFile.Buffer);
2639
2640 RtlFreeUnicodeString (&OldFile);
2641 RtlFreeUnicodeString (&NewFile);
2642 RtlFreeUnicodeString (&SubKey);
2643
2644 return ErrorCode;
2645 }
2646
2647
2648 /************************************************************************
2649 * RegReplaceKeyW
2650 *
2651 * @unimplemented
2652 */
2653 LONG STDCALL
2654 RegReplaceKeyW (HKEY hKey,
2655 LPCWSTR lpSubKey,
2656 LPCWSTR lpNewFile,
2657 LPCWSTR lpOldFile)
2658 {
2659 OBJECT_ATTRIBUTES KeyObjectAttributes;
2660 OBJECT_ATTRIBUTES NewObjectAttributes;
2661 OBJECT_ATTRIBUTES OldObjectAttributes;
2662 UNICODE_STRING SubKeyName;
2663 UNICODE_STRING NewFileName;
2664 UNICODE_STRING OldFileName;
2665 BOOLEAN CloseRealKey;
2666 HANDLE RealKeyHandle;
2667 HANDLE KeyHandle;
2668 LONG ErrorCode;
2669 NTSTATUS Status;
2670
2671 if (hKey == HKEY_PERFORMANCE_DATA)
2672 {
2673 return ERROR_INVALID_HANDLE;
2674 }
2675
2676 Status = MapDefaultKey (&KeyHandle,
2677 hKey);
2678 if (!NT_SUCCESS(Status))
2679 {
2680 ErrorCode = RtlNtStatusToDosError (Status);
2681 SetLastError (ErrorCode);
2682 return ErrorCode;
2683 }
2684
2685 /* Open the real key */
2686 if (lpSubKey != NULL && *lpSubKey != (WCHAR)0)
2687 {
2688 RtlInitUnicodeString (&SubKeyName,
2689 (PWSTR)lpSubKey);
2690 InitializeObjectAttributes (&KeyObjectAttributes,
2691 &SubKeyName,
2692 OBJ_CASE_INSENSITIVE,
2693 KeyHandle,
2694 NULL);
2695 Status = NtOpenKey (&RealKeyHandle,
2696 KEY_ALL_ACCESS,
2697 &KeyObjectAttributes);
2698 if (!NT_SUCCESS(Status))
2699 {
2700 ErrorCode = RtlNtStatusToDosError (Status);
2701 SetLastError (ErrorCode);
2702 return ErrorCode;
2703 }
2704 CloseRealKey = TRUE;
2705 }
2706 else
2707 {
2708 RealKeyHandle = KeyHandle;
2709 CloseRealKey = FALSE;
2710 }
2711
2712 /* Convert new file name */
2713 if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpNewFile,
2714 &NewFileName,
2715 NULL,
2716 NULL))
2717 {
2718 if (CloseRealKey)
2719 {
2720 NtClose (RealKeyHandle);
2721 }
2722 SetLastError (ERROR_INVALID_PARAMETER);
2723 return ERROR_INVALID_PARAMETER;
2724 }
2725
2726 InitializeObjectAttributes (&NewObjectAttributes,
2727 &NewFileName,
2728 OBJ_CASE_INSENSITIVE,
2729 NULL,
2730 NULL);
2731
2732 /* Convert old file name */
2733 if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpOldFile,
2734 &OldFileName,
2735 NULL,
2736 NULL))
2737 {
2738 RtlFreeUnicodeString (&NewFileName);
2739 if (CloseRealKey)
2740 {
2741 NtClose (RealKeyHandle);
2742 }
2743 SetLastError (ERROR_INVALID_PARAMETER);
2744 return ERROR_INVALID_PARAMETER;
2745 }
2746
2747 InitializeObjectAttributes (&OldObjectAttributes,
2748 &OldFileName,
2749 OBJ_CASE_INSENSITIVE,
2750 NULL,
2751 NULL);
2752
2753 Status = NtReplaceKey (&NewObjectAttributes,
2754 RealKeyHandle,
2755 &OldObjectAttributes);
2756
2757 RtlFreeUnicodeString (&OldFileName);
2758 RtlFreeUnicodeString (&NewFileName);
2759
2760 if (CloseRealKey)
2761 {
2762 NtClose (RealKeyHandle);
2763 }
2764
2765 if (!NT_SUCCESS(Status))
2766 {
2767 ErrorCode = RtlNtStatusToDosError (Status);
2768 SetLastError (ErrorCode);
2769 return ErrorCode;
2770 }
2771
2772 return ERROR_SUCCESS;
2773 }
2774
2775
2776 /************************************************************************
2777 * RegRestoreKeyA
2778 *
2779 * @implemented
2780 */
2781 LONG STDCALL
2782 RegRestoreKeyA (HKEY hKey,
2783 LPCSTR lpFile,
2784 DWORD dwFlags)
2785 {
2786 UNICODE_STRING FileName;
2787 LONG ErrorCode;
2788
2789 RtlCreateUnicodeStringFromAsciiz (&FileName,
2790 (PCSZ)lpFile);
2791
2792 ErrorCode = RegRestoreKeyW (hKey,
2793 FileName.Buffer,
2794 dwFlags);
2795
2796 RtlFreeUnicodeString (&FileName);
2797
2798 return ErrorCode;
2799 }
2800
2801
2802 /************************************************************************
2803 * RegRestoreKeyW
2804 *
2805 * @implemented
2806 */
2807 LONG STDCALL
2808 RegRestoreKeyW (HKEY hKey,
2809 LPCWSTR lpFile,
2810 DWORD dwFlags)
2811 {
2812 OBJECT_ATTRIBUTES ObjectAttributes;
2813 IO_STATUS_BLOCK IoStatusBlock;
2814 UNICODE_STRING FileName;
2815 HANDLE FileHandle;
2816 HANDLE KeyHandle;
2817 LONG ErrorCode;
2818 NTSTATUS Status;
2819
2820 if (hKey == HKEY_PERFORMANCE_DATA)
2821 {
2822 return ERROR_INVALID_HANDLE;
2823 }
2824
2825 Status = MapDefaultKey (&KeyHandle,
2826 hKey);
2827 if (!NT_SUCCESS(Status))
2828 {
2829 ErrorCode = RtlNtStatusToDosError (Status);
2830 SetLastError (ErrorCode);
2831 return ErrorCode;
2832 }
2833
2834 if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFile,
2835 &FileName,
2836 NULL,
2837 NULL))
2838 {
2839 SetLastError (ERROR_INVALID_PARAMETER);
2840 return ERROR_INVALID_PARAMETER;
2841 }
2842
2843 InitializeObjectAttributes (&ObjectAttributes,
2844 &FileName,
2845 OBJ_CASE_INSENSITIVE,
2846 NULL,
2847 NULL);
2848
2849 Status = NtOpenFile (&FileHandle,
2850 FILE_GENERIC_READ,
2851 &ObjectAttributes,
2852 &IoStatusBlock,
2853 FILE_SHARE_READ,
2854 FILE_SYNCHRONOUS_IO_NONALERT);
2855 RtlFreeUnicodeString (&FileName);
2856 if (!NT_SUCCESS(Status))
2857 {
2858 ErrorCode = RtlNtStatusToDosError (Status);
2859 SetLastError (ErrorCode);
2860 return ErrorCode;
2861 }
2862
2863 Status = NtRestoreKey (KeyHandle,
2864 FileHandle,
2865 (ULONG)dwFlags);
2866 NtClose (FileHandle);
2867 if (!NT_SUCCESS(Status))
2868 {
2869 ErrorCode = RtlNtStatusToDosError (Status);
2870 SetLastError (ErrorCode);
2871 return ErrorCode;
2872 }
2873
2874 return ERROR_SUCCESS;
2875 }
2876
2877
2878 /************************************************************************
2879 * RegSaveKeyA
2880 *
2881 * @implemented
2882 */
2883 LONG STDCALL
2884 RegSaveKeyA (HKEY hKey,
2885 LPCSTR lpFile,
2886 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
2887 {
2888 UNICODE_STRING FileName;
2889 LONG ErrorCode;
2890
2891 RtlCreateUnicodeStringFromAsciiz (&FileName,
2892 (LPSTR)lpFile);
2893 ErrorCode = RegSaveKeyW (hKey,
2894 FileName.Buffer,
2895 lpSecurityAttributes);
2896 RtlFreeUnicodeString (&FileName);
2897
2898 return ErrorCode;
2899 }
2900
2901
2902 /************************************************************************
2903 * RegSaveKeyW
2904 *
2905 * @implemented
2906 */
2907 LONG STDCALL
2908 RegSaveKeyW (HKEY hKey,
2909 LPCWSTR lpFile,
2910 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
2911 {
2912 PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
2913 OBJECT_ATTRIBUTES ObjectAttributes;
2914 UNICODE_STRING FileName;
2915 IO_STATUS_BLOCK IoStatusBlock;
2916 HANDLE FileHandle;
2917 HANDLE KeyHandle;
2918 NTSTATUS Status;
2919 LONG ErrorCode;
2920
2921 Status = MapDefaultKey (&KeyHandle,
2922 hKey);
2923 if (!NT_SUCCESS(Status))
2924 {
2925 ErrorCode = RtlNtStatusToDosError (Status);
2926 SetLastError (ErrorCode);
2927 return ErrorCode;
2928 }
2929
2930 if (!RtlDosPathNameToNtPathName_U ((PWSTR)lpFile,
2931 &FileName,
2932 NULL,
2933 NULL))
2934 {
2935 SetLastError (ERROR_INVALID_PARAMETER);
2936 return ERROR_INVALID_PARAMETER;
2937 }
2938
2939 if (lpSecurityAttributes != NULL)
2940 {
2941 SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
2942 }
2943
2944 InitializeObjectAttributes (&ObjectAttributes,
2945 &FileName,
2946 OBJ_CASE_INSENSITIVE,
2947 NULL,
2948 SecurityDescriptor);
2949 Status = NtCreateFile (&FileHandle,
2950 GENERIC_WRITE | SYNCHRONIZE,
2951 &ObjectAttributes,
2952 &IoStatusBlock,
2953 NULL,
2954 FILE_ATTRIBUTE_NORMAL,
2955 FILE_SHARE_READ,
2956 FILE_CREATE,
2957 FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
2958 NULL,
2959 0);
2960 RtlFreeUnicodeString (&FileName);
2961 if (!NT_SUCCESS(Status))
2962 {
2963 ErrorCode = RtlNtStatusToDosError (Status);
2964 SetLastError (ErrorCode);
2965 return ErrorCode;
2966 }
2967
2968 Status = NtSaveKey (KeyHandle,
2969 FileHandle);
2970 NtClose (FileHandle);
2971 if (!NT_SUCCESS(Status))
2972 {
2973 ErrorCode = RtlNtStatusToDosError (Status);
2974 SetLastError (ErrorCode);
2975 return ErrorCode;
2976 }
2977
2978 return ERROR_SUCCESS;
2979 }
2980
2981
2982 /************************************************************************
2983 * RegSetKeySecurity
2984 *
2985 * @implemented
2986 */
2987 LONG STDCALL
2988 RegSetKeySecurity (HKEY hKey,
2989 SECURITY_INFORMATION SecurityInformation,
2990 PSECURITY_DESCRIPTOR pSecurityDescriptor)
2991 {
2992 HANDLE KeyHandle;
2993 LONG ErrorCode;
2994 NTSTATUS Status;
2995
2996 if (hKey == HKEY_PERFORMANCE_DATA)
2997 {
2998 SetLastError(ERROR_INVALID_HANDLE);
2999 return ERROR_INVALID_HANDLE;
3000 }
3001
3002 Status = MapDefaultKey (&KeyHandle,
3003 hKey);
3004 if (!NT_SUCCESS(Status))
3005 {
3006 ErrorCode = RtlNtStatusToDosError (Status);
3007 SetLastError (ErrorCode);
3008 return ErrorCode;
3009 }
3010
3011 Status = NtSetSecurityObject (KeyHandle,
3012 SecurityInformation,
3013 pSecurityDescriptor);
3014 if (!NT_SUCCESS(Status))
3015 {
3016 ErrorCode = RtlNtStatusToDosError (Status);
3017 SetLastError (ErrorCode);
3018 return ErrorCode;
3019 }
3020
3021 return ERROR_SUCCESS;
3022 }
3023
3024
3025 /************************************************************************
3026 * RegSetValueExA
3027 *
3028 * @implemented
3029 */
3030 LONG STDCALL
3031 RegSetValueExA (HKEY hKey,
3032 LPCSTR lpValueName,
3033 DWORD Reserved,
3034 DWORD dwType,
3035 CONST BYTE* lpData,
3036 DWORD cbData)
3037 {
3038 UNICODE_STRING ValueName;
3039 LPWSTR pValueName;
3040 ANSI_STRING AnsiString;
3041 UNICODE_STRING Data;
3042 LONG ErrorCode;
3043 LPBYTE pData;
3044 DWORD DataSize;
3045
3046 if (lpData == NULL)
3047 {
3048 SetLastError (ERROR_INVALID_PARAMETER);
3049 return ERROR_INVALID_PARAMETER;
3050 }
3051
3052 if (lpValueName != NULL &&
3053 strlen(lpValueName) != 0)
3054 {
3055 RtlCreateUnicodeStringFromAsciiz (&ValueName,
3056 (PSTR)lpValueName);
3057 pValueName = (LPWSTR)ValueName.Buffer;
3058 }
3059 else
3060 {
3061 pValueName = NULL;
3062 }
3063
3064 if ((dwType == REG_SZ) ||
3065 (dwType == REG_MULTI_SZ) ||
3066 (dwType == REG_EXPAND_SZ))
3067 {
3068 RtlInitAnsiString (&AnsiString,
3069 NULL);
3070 AnsiString.Buffer = (PSTR)lpData;
3071 AnsiString.Length = cbData;
3072 AnsiString.MaximumLength = cbData;
3073 RtlAnsiStringToUnicodeString (&Data,
3074 &AnsiString,
3075 TRUE);
3076 pData = (LPBYTE)Data.Buffer;
3077 DataSize = cbData * sizeof(WCHAR);
3078 }
3079 else
3080 {
3081 RtlInitUnicodeString (&Data,
3082 NULL);
3083 pData = (LPBYTE)lpData;
3084 DataSize = cbData;
3085 }
3086
3087 ErrorCode = RegSetValueExW (hKey,
3088 pValueName,
3089 Reserved,
3090 dwType,
3091 pData,
3092 DataSize);
3093 if (pValueName != NULL)
3094 {
3095 RtlFreeHeap (ProcessHeap,
3096 0,
3097 ValueName.Buffer);
3098 }
3099
3100 if (Data.Buffer != NULL)
3101 {
3102 RtlFreeHeap (ProcessHeap,
3103 0,
3104 Data.Buffer);
3105 }
3106
3107 return ErrorCode;
3108 }
3109
3110
3111 /************************************************************************
3112 * RegSetValueExW
3113 *
3114 * @implemented
3115 */
3116 LONG STDCALL
3117 RegSetValueExW (HKEY hKey,
3118 LPCWSTR lpValueName,
3119 DWORD Reserved,
3120 DWORD dwType,
3121 CONST BYTE* lpData,
3122 DWORD cbData)
3123 {
3124 UNICODE_STRING ValueName;
3125 PUNICODE_STRING pValueName;
3126 HANDLE KeyHandle;
3127 NTSTATUS Status;
3128 LONG ErrorCode;
3129
3130 Status = MapDefaultKey (&KeyHandle,
3131 hKey);
3132 if (!NT_SUCCESS(Status))
3133 {
3134 ErrorCode = RtlNtStatusToDosError (Status);
3135 SetLastError (ErrorCode);
3136 return ErrorCode;
3137 }
3138
3139 if (lpValueName != NULL)
3140 {
3141 RtlInitUnicodeString (&ValueName,
3142 lpValueName);
3143 }
3144 else
3145 {
3146 RtlInitUnicodeString (&ValueName, L"");
3147 }
3148 pValueName = &ValueName;
3149
3150 Status = NtSetValueKey (KeyHandle,
3151 pValueName,
3152 0,
3153 dwType,
3154 (PVOID)lpData,
3155 (ULONG)cbData);
3156 if (!NT_SUCCESS(Status))
3157 {
3158 ErrorCode = RtlNtStatusToDosError (Status);
3159 SetLastError (ErrorCode);
3160 return ErrorCode;
3161 }
3162
3163 return ERROR_SUCCESS;
3164 }
3165
3166
3167 /************************************************************************
3168 * RegSetValueA
3169 *
3170 * @implemented
3171 */
3172 LONG STDCALL
3173 RegSetValueA (HKEY hKey,
3174 LPCSTR lpSubKey,
3175 DWORD dwType,
3176 LPCSTR lpData,
3177 DWORD cbData)
3178 {
3179 WCHAR SubKeyNameBuffer[MAX_PATH+1];
3180 UNICODE_STRING SubKeyName;
3181 UNICODE_STRING Data;
3182 ANSI_STRING AnsiString;
3183 LONG DataSize;
3184 LONG ErrorCode;
3185
3186 if (lpData == NULL)
3187 {
3188 SetLastError (ERROR_INVALID_PARAMETER);
3189 return ERROR_INVALID_PARAMETER;
3190 }
3191
3192 RtlInitUnicodeString (&SubKeyName, NULL);
3193 RtlInitUnicodeString (&Data, NULL);
3194 if (lpSubKey != NULL && (strlen(lpSubKey) != 0))
3195 {
3196 RtlInitAnsiString (&AnsiString, (LPSTR)lpSubKey);
3197 SubKeyName.Buffer = &SubKeyNameBuffer[0];
3198 SubKeyName.MaximumLength = sizeof(SubKeyNameBuffer);
3199 RtlAnsiStringToUnicodeString (&SubKeyName, &AnsiString, FALSE);
3200 }
3201
3202 DataSize = cbData * sizeof(WCHAR);
3203 Data.MaximumLength = DataSize;
3204 Data.Buffer = RtlAllocateHeap (ProcessHeap,
3205 0,
3206 DataSize);
3207 if (Data.Buffer == NULL)
3208 {
3209 SetLastError (ERROR_OUTOFMEMORY);
3210 return ERROR_OUTOFMEMORY;
3211 }
3212
3213 ErrorCode = RegSetValueW (hKey,
3214 (LPCWSTR)SubKeyName.Buffer,
3215 dwType,
3216 Data.Buffer,
3217 DataSize);
3218
3219 RtlFreeHeap (ProcessHeap,
3220 0,
3221 Data.Buffer);
3222
3223 return ErrorCode;
3224 }
3225
3226
3227 /************************************************************************
3228 * RegSetValueW
3229 *
3230 * @implemented
3231 */
3232 LONG STDCALL
3233 RegSetValueW (HKEY hKey,
3234 LPCWSTR lpSubKey,
3235 DWORD dwType,
3236 LPCWSTR lpData,
3237 DWORD cbData)
3238 {
3239 OBJECT_ATTRIBUTES ObjectAttributes;
3240 UNICODE_STRING SubKeyString;
3241 HANDLE KeyHandle;
3242 HANDLE RealKey;
3243 LONG ErrorCode;
3244 BOOL CloseRealKey;
3245 NTSTATUS Status;
3246
3247 Status = MapDefaultKey (&KeyHandle,
3248 hKey);
3249 if (!NT_SUCCESS(Status))
3250 {
3251 ErrorCode = RtlNtStatusToDosError (Status);
3252 SetLastError (ErrorCode);
3253 return ErrorCode;
3254 }
3255
3256 if ((lpSubKey) && (wcslen(lpSubKey) != 0))
3257 {
3258 RtlInitUnicodeString (&SubKeyString,
3259 (LPWSTR)lpSubKey);
3260 InitializeObjectAttributes (&ObjectAttributes,
3261 &SubKeyString,
3262 OBJ_CASE_INSENSITIVE,
3263 KeyHandle,
3264 NULL);
3265 Status = NtOpenKey (&RealKey,
3266 KEY_ALL_ACCESS,
3267 &ObjectAttributes);
3268 if (!NT_SUCCESS(Status))
3269 {
3270 ErrorCode = RtlNtStatusToDosError (Status);
3271 SetLastError (ErrorCode);
3272 return ErrorCode;
3273 }
3274 CloseRealKey = TRUE;
3275 }
3276 else
3277 {
3278 RealKey = hKey;
3279 CloseRealKey = FALSE;
3280 }
3281
3282 ErrorCode = RegSetValueExW (RealKey,
3283 NULL,
3284 0,
3285 dwType,
3286 (LPBYTE)lpData,
3287 cbData);
3288 if (CloseRealKey == TRUE)
3289 {
3290 NtClose (RealKey);
3291 }
3292
3293 return ErrorCode;
3294 }
3295
3296
3297 /************************************************************************
3298 * RegUnLoadKeyA
3299 *
3300 * @implemented
3301 */
3302 LONG STDCALL
3303 RegUnLoadKeyA (HKEY hKey,
3304 LPCSTR lpSubKey)
3305 {
3306 UNICODE_STRING KeyName;
3307 DWORD ErrorCode;
3308
3309 RtlCreateUnicodeStringFromAsciiz (&KeyName,
3310 (LPSTR)lpSubKey);
3311
3312 ErrorCode = RegUnLoadKeyW (hKey,
3313 KeyName.Buffer);
3314
3315 RtlFreeUnicodeString (&KeyName);
3316
3317 return ErrorCode;
3318 }
3319
3320
3321 /************************************************************************
3322 * RegUnLoadKeyW
3323 *
3324 * @implemented
3325 */
3326 LONG STDCALL
3327 RegUnLoadKeyW (HKEY hKey,
3328 LPCWSTR lpSubKey)
3329 {
3330 OBJECT_ATTRIBUTES ObjectAttributes;
3331 UNICODE_STRING KeyName;
3332 HANDLE KeyHandle;
3333 DWORD ErrorCode;
3334 NTSTATUS Status;
3335
3336 if (hKey == HKEY_PERFORMANCE_DATA)
3337 {
3338 SetLastError(ERROR_INVALID_HANDLE);
3339 return ERROR_INVALID_HANDLE;
3340 }
3341
3342 Status = MapDefaultKey (&KeyHandle, hKey);
3343 if (!NT_SUCCESS(Status))
3344 {
3345 ErrorCode = RtlNtStatusToDosError (Status);
3346 SetLastError (ErrorCode);
3347 return ErrorCode;
3348 }
3349
3350 RtlInitUnicodeString (&KeyName,
3351 (LPWSTR)lpSubKey);
3352
3353 InitializeObjectAttributes (&ObjectAttributes,
3354 &KeyName,
3355 OBJ_CASE_INSENSITIVE,
3356 KeyHandle,
3357 NULL);
3358
3359 Status = NtUnloadKey (&ObjectAttributes);
3360
3361 if (!NT_SUCCESS(Status))
3362 {
3363 ErrorCode = RtlNtStatusToDosError (Status);
3364 SetLastError (ErrorCode);
3365 return ErrorCode;
3366 }
3367
3368 return ERROR_SUCCESS;
3369 }
3370
3371 /* EOF */