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