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