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