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