Implemented RegSaveKey[A/W]().
[reactos.git] / reactos / lib / advapi32 / reg / reg.c
1 /* $Id: reg.c,v 1.14 2001/09/03 23:11:59 ekohl Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/advapi32/reg/reg.c
6 * PURPOSE: Registry functions
7 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
8 * UPDATE HISTORY:
9 * Created 01/11/98
10 * 19990309 EA Stubs
11 */
12 #include <ddk/ntddk.h>
13 #include <ntdll/rtl.h>
14 #include <windows.h>
15 #include <wchar.h>
16
17 #define NDEBUG
18 #include <debug.h>
19
20 #define CHECK_STATUS \
21 { \
22 if (!NT_SUCCESS(Status)) \
23 { \
24 LONG _ErrorCode = RtlNtStatusToDosError(Status); \
25 SetLastError(_ErrorCode); \
26 return _ErrorCode; \
27 } \
28 }
29
30 /* GLOBALS *******************************************************************/
31
32 #define MAX_DEFAULT_HANDLES 6
33
34 static CRITICAL_SECTION HandleTableCS;
35 static HANDLE DefaultHandleTable[MAX_DEFAULT_HANDLES];
36
37
38 /* PROTOTYPES ****************************************************************/
39
40 static NTSTATUS MapDefaultKey (PHKEY 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 inline RegiTerminateWideString(LPWSTR String, DWORD Length)
52 {
53 LPWSTR AfterString = String + Length;
54 *AfterString = 0;
55 }
56
57 /************************************************************************
58 * RegInitDefaultHandles
59 */
60
61 BOOL
62 RegInitialize (VOID)
63 {
64 DPRINT("RegInitialize()\n");
65
66 RtlZeroMemory (DefaultHandleTable,
67 MAX_DEFAULT_HANDLES * sizeof(HANDLE));
68
69 RtlInitializeCriticalSection(&HandleTableCS);
70 return TRUE;
71 }
72
73
74 /************************************************************************
75 * RegInit
76 */
77 BOOL
78 RegCleanup(VOID)
79 {
80 DPRINT("RegCleanup()\n");
81
82 CloseDefaultKeys();
83 RtlDeleteCriticalSection(&HandleTableCS);
84 return TRUE;
85 }
86
87
88 static NTSTATUS
89 MapDefaultKey(PHKEY RealKey,
90 HKEY Key)
91 {
92 PHANDLE Handle;
93 ULONG Index;
94 NTSTATUS Status = STATUS_SUCCESS;
95
96 DPRINT("MapDefaultKey (Key %x)\n", Key);
97
98 if (((ULONG)Key & 0xF0000000) != 0x80000000)
99 {
100 *RealKey = Key;
101 return STATUS_SUCCESS;
102 }
103
104 /* Handle special cases here */
105 Index = (ULONG)Key & 0x0FFFFFFF;
106
107 if (Index >= MAX_DEFAULT_HANDLES)
108 return STATUS_INVALID_PARAMETER;
109
110 RtlEnterCriticalSection(&HandleTableCS);
111
112 Handle = &DefaultHandleTable[Index];
113 if (*Handle == NULL)
114 {
115 /* create/open the default handle */
116 switch (Index)
117 {
118 case 0: /* HKEY_CLASSES_ROOT */
119 Status = OpenClassesRootKey(Handle);
120 break;
121
122 case 1: /* HKEY_CURRENT_USER */
123 Status = RtlOpenCurrentUser(KEY_ALL_ACCESS,
124 Handle);
125 break;
126
127 case 2: /* HKEY_LOCAL_MACHINE */
128 Status = OpenLocalMachineKey(Handle);
129 break;
130
131 case 3: /* HKEY_USERS */
132 Status = OpenUsersKey(Handle);
133 break;
134 #if 0
135 case 4: /* HKEY_PERFORMANCE_DATA */
136 Status = OpenPerformanceDataKey(Handle);
137 break;
138 #endif
139 case 5: /* HKEY_CURRENT_CONFIG */
140 Status = OpenCurrentConfigKey(Handle);
141 break;
142
143 default:
144 DPRINT("MapDefaultHandle() no handle creator\n");
145 Status = STATUS_INVALID_PARAMETER;
146 }
147 }
148
149 RtlLeaveCriticalSection(&HandleTableCS);
150
151 if (NT_SUCCESS(Status))
152 {
153 *RealKey = (HKEY)*Handle;
154 }
155
156 return Status;
157 }
158
159
160 static VOID
161 CloseDefaultKeys(VOID)
162 {
163 ULONG i;
164
165 RtlEnterCriticalSection(&HandleTableCS);
166
167 for (i = 0; i < MAX_DEFAULT_HANDLES; i++)
168 {
169 if (DefaultHandleTable[i] != NULL)
170 {
171 NtClose (DefaultHandleTable[i]);
172 DefaultHandleTable[i] = NULL;
173 }
174 }
175
176 RtlLeaveCriticalSection(&HandleTableCS);
177 }
178
179
180 static NTSTATUS
181 OpenClassesRootKey(PHANDLE KeyHandle)
182 {
183 OBJECT_ATTRIBUTES Attributes;
184 UNICODE_STRING KeyName;
185
186 DPRINT("OpenClassesRootKey()\n");
187
188 RtlInitUnicodeString(&KeyName,
189 L"\\Registry\\Machine\\Software\\CLASSES");
190
191 InitializeObjectAttributes(&Attributes,
192 &KeyName,
193 OBJ_CASE_INSENSITIVE,
194 NULL,
195 NULL);
196
197 return(NtOpenKey(KeyHandle,
198 KEY_ALL_ACCESS,
199 &Attributes));
200 }
201
202
203 static NTSTATUS
204 OpenLocalMachineKey(PHANDLE KeyHandle)
205 {
206 OBJECT_ATTRIBUTES Attributes;
207 UNICODE_STRING KeyName;
208
209 DPRINT("OpenLocalMachineKey()\n");
210
211 RtlInitUnicodeString(&KeyName,
212 L"\\Registry\\Machine");
213
214 InitializeObjectAttributes(&Attributes,
215 &KeyName,
216 OBJ_CASE_INSENSITIVE,
217 NULL,
218 NULL);
219
220 return(NtOpenKey(KeyHandle,
221 KEY_ALL_ACCESS,
222 &Attributes));
223 }
224
225
226 static NTSTATUS
227 OpenUsersKey(PHANDLE KeyHandle)
228 {
229 OBJECT_ATTRIBUTES Attributes;
230 UNICODE_STRING KeyName;
231
232 DPRINT("OpenUsersKey()\n");
233
234 RtlInitUnicodeString(&KeyName,
235 L"\\Registry\\User");
236
237 InitializeObjectAttributes(&Attributes,
238 &KeyName,
239 OBJ_CASE_INSENSITIVE,
240 NULL,
241 NULL);
242
243 return(NtOpenKey(KeyHandle,
244 KEY_ALL_ACCESS,
245 &Attributes));
246 }
247
248
249 static NTSTATUS
250 OpenCurrentConfigKey(PHANDLE KeyHandle)
251 {
252 OBJECT_ATTRIBUTES Attributes;
253 UNICODE_STRING KeyName;
254
255 DPRINT("OpenCurrentConfigKey()\n");
256
257 RtlInitUnicodeString(&KeyName,
258 L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current");
259
260 InitializeObjectAttributes(&Attributes,
261 &KeyName,
262 OBJ_CASE_INSENSITIVE,
263 NULL,
264 NULL);
265
266 return(NtOpenKey(KeyHandle,
267 KEY_ALL_ACCESS,
268 &Attributes));
269 }
270
271 /************************************************************************
272 * RegCloseKey
273 */
274 LONG STDCALL
275 RegCloseKey(HKEY hKey)
276 {
277 NTSTATUS Status;
278
279 /* don't close null handle or a pseudo handle */
280 if ((!hKey) || (((ULONG)hKey & 0xF0000000) == 0x80000000))
281 return ERROR_INVALID_HANDLE;
282
283 Status = NtClose (hKey);
284 if (!NT_SUCCESS(Status))
285 {
286 LONG ErrorCode = RtlNtStatusToDosError(Status);
287
288 SetLastError (ErrorCode);
289 return ErrorCode;
290 }
291
292 return ERROR_SUCCESS;
293 }
294
295
296 /************************************************************************
297 * RegConnectRegistryA
298 */
299 LONG STDCALL
300 RegConnectRegistryA(LPSTR 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 * RegConnectRegistryW
311 */
312 LONG STDCALL
313 RegConnectRegistryW(LPWSTR lpMachineName,
314 HKEY hKey,
315 PHKEY phkResult)
316 {
317 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
318 return ERROR_CALL_NOT_IMPLEMENTED;
319 }
320
321
322 /************************************************************************
323 * RegCreateKeyA
324 */
325 LONG STDCALL
326 RegCreateKeyA(HKEY hKey,
327 LPCSTR lpSubKey,
328 PHKEY phkResult)
329 {
330 return(RegCreateKeyExA(hKey,
331 lpSubKey,
332 0,
333 NULL,
334 0,
335 KEY_ALL_ACCESS,
336 NULL,
337 phkResult,
338 NULL));
339 }
340
341
342 /************************************************************************
343 * RegCreateKeyW
344 */
345 LONG STDCALL
346 RegCreateKeyW(HKEY hKey,
347 LPCWSTR lpSubKey,
348 PHKEY phkResult)
349 {
350 return(RegCreateKeyExW(hKey,
351 lpSubKey,
352 0,
353 NULL,
354 0,
355 KEY_ALL_ACCESS,
356 NULL,
357 phkResult,
358 NULL));
359 }
360
361
362 /************************************************************************
363 * RegCreateKeyExA
364 */
365 LONG STDCALL
366 RegCreateKeyExA(HKEY hKey,
367 LPCSTR lpSubKey,
368 DWORD Reserved,
369 LPSTR lpClass,
370 DWORD dwOptions,
371 REGSAM samDesired,
372 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
373 PHKEY phkResult,
374 LPDWORD lpdwDisposition)
375 {
376 UNICODE_STRING SubKeyString;
377 UNICODE_STRING ClassString;
378 OBJECT_ATTRIBUTES Attributes;
379 NTSTATUS Status;
380 HKEY ParentKey;
381
382 DPRINT("RegCreateKeyExW() called\n");
383
384 /* get the real parent key */
385 Status = MapDefaultKey(&ParentKey,
386 hKey);
387 if (!NT_SUCCESS(Status))
388 {
389 LONG ErrorCode = RtlNtStatusToDosError(Status);
390
391 SetLastError(ErrorCode);
392 return(ErrorCode);
393 }
394
395 DPRINT("ParentKey %x\n", (ULONG)ParentKey);
396
397 if (lpClass != NULL)
398 RtlCreateUnicodeStringFromAsciiz(&ClassString,
399 lpClass);
400 RtlCreateUnicodeStringFromAsciiz(&SubKeyString,
401 (LPSTR)lpSubKey);
402
403 InitializeObjectAttributes(&Attributes,
404 &SubKeyString,
405 OBJ_CASE_INSENSITIVE,
406 (HANDLE)ParentKey,
407 (PSECURITY_DESCRIPTOR)lpSecurityAttributes);
408
409 Status = NtCreateKey(phkResult,
410 samDesired,
411 &Attributes,
412 0,
413 (lpClass == NULL)? NULL : &ClassString,
414 dwOptions,
415 (PULONG)lpdwDisposition);
416
417 RtlFreeUnicodeString(&SubKeyString);
418 if (lpClass != NULL)
419 RtlFreeUnicodeString(&ClassString);
420
421 DPRINT("Status %x\n", Status);
422 if (!NT_SUCCESS(Status))
423 {
424 LONG ErrorCode = RtlNtStatusToDosError(Status);
425
426 SetLastError (ErrorCode);
427 return ErrorCode;
428 }
429
430 return(ERROR_SUCCESS);
431 }
432
433
434 /************************************************************************
435 * RegCreateKeyExW
436 */
437 LONG STDCALL
438 RegCreateKeyExW(HKEY hKey,
439 LPCWSTR lpSubKey,
440 DWORD Reserved,
441 LPWSTR lpClass,
442 DWORD dwOptions,
443 REGSAM samDesired,
444 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
445 PHKEY phkResult,
446 LPDWORD lpdwDisposition)
447 {
448 UNICODE_STRING SubKeyString;
449 UNICODE_STRING ClassString;
450 OBJECT_ATTRIBUTES Attributes;
451 NTSTATUS Status;
452 HKEY ParentKey;
453
454 DPRINT("RegCreateKeyExW() called\n");
455
456 /* get the real parent key */
457 Status = MapDefaultKey (&ParentKey, hKey);
458 if (!NT_SUCCESS(Status))
459 {
460 LONG ErrorCode = RtlNtStatusToDosError(Status);
461
462 SetLastError (ErrorCode);
463 return ErrorCode;
464 }
465
466 DPRINT("ParentKey %x\n", (ULONG)ParentKey);
467
468 RtlInitUnicodeString (&ClassString, lpClass);
469 RtlInitUnicodeString (&SubKeyString, lpSubKey);
470
471 InitializeObjectAttributes (&Attributes,
472 &SubKeyString,
473 OBJ_CASE_INSENSITIVE,
474 (HANDLE)ParentKey,
475 (PSECURITY_DESCRIPTOR)lpSecurityAttributes);
476
477 Status = NtCreateKey (phkResult,
478 samDesired,
479 &Attributes,
480 0,
481 (lpClass == NULL)? NULL : &ClassString,
482 dwOptions,
483 (PULONG)lpdwDisposition);
484 DPRINT("Status %x\n", Status);
485 if (!NT_SUCCESS(Status))
486 {
487 LONG ErrorCode = RtlNtStatusToDosError(Status);
488
489 SetLastError (ErrorCode);
490 return ErrorCode;
491 }
492
493 return ERROR_SUCCESS;
494 }
495
496
497 /************************************************************************
498 * RegDeleteKeyA
499 */
500 LONG
501 STDCALL
502 RegDeleteKeyA(
503 HKEY hKey,
504 LPCSTR lpSubKey
505 )
506 {
507 OBJECT_ATTRIBUTES ObjectAttributes;
508 UNICODE_STRING SubKeyStringW;
509 ANSI_STRING SubKeyStringA;
510 HANDLE ParentKey;
511 HANDLE TargetKey;
512 NTSTATUS Status;
513 LONG ErrorCode;
514
515 Status = MapDefaultKey(&ParentKey,
516 hKey);
517 if (!NT_SUCCESS(Status))
518 {
519 ErrorCode = RtlNtStatusToDosError(Status);
520
521 SetLastError (ErrorCode);
522 return ErrorCode;
523 }
524
525 RtlInitAnsiString(&SubKeyStringA,
526 (LPSTR)lpSubKey);
527 RtlAnsiStringToUnicodeString(&SubKeyStringW,
528 &SubKeyStringA,
529 TRUE);
530
531 InitializeObjectAttributes (&ObjectAttributes,
532 &SubKeyStringW,
533 OBJ_CASE_INSENSITIVE,
534 (HANDLE)ParentKey,
535 NULL);
536
537 Status = NtOpenKey (&TargetKey,
538 DELETE,
539 &ObjectAttributes);
540
541 RtlFreeUnicodeString (&SubKeyStringW);
542
543 if (!NT_SUCCESS(Status))
544 {
545 ErrorCode = RtlNtStatusToDosError(Status);
546
547 SetLastError (ErrorCode);
548 return ErrorCode;
549 }
550
551 Status = NtDeleteKey(TargetKey);
552
553 NtClose(TargetKey);
554
555 if (!NT_SUCCESS(Status))
556 {
557 ErrorCode = RtlNtStatusToDosError(Status);
558
559 SetLastError (ErrorCode);
560 return ErrorCode;
561 }
562 return ERROR_SUCCESS;
563 }
564
565
566 /************************************************************************
567 * RegDeleteKeyW
568 */
569 LONG
570 STDCALL
571 RegDeleteKeyW(
572 HKEY hKey,
573 LPCWSTR lpSubKey
574 )
575 {
576 OBJECT_ATTRIBUTES ObjectAttributes;
577 UNICODE_STRING SubKeyString;
578 HANDLE ParentKey;
579 HANDLE TargetKey;
580 NTSTATUS Status;
581 LONG ErrorCode;
582
583 Status = MapDefaultKey(&ParentKey,
584 hKey);
585 if (!NT_SUCCESS(Status))
586 {
587 ErrorCode = RtlNtStatusToDosError(Status);
588
589 SetLastError (ErrorCode);
590 return ErrorCode;
591 }
592
593 RtlInitUnicodeString(&SubKeyString,
594 (LPWSTR)lpSubKey);
595
596 InitializeObjectAttributes (&ObjectAttributes,
597 &SubKeyString,
598 OBJ_CASE_INSENSITIVE,
599 (HANDLE)ParentKey,
600 NULL);
601
602 Status = NtOpenKey (&TargetKey,
603 DELETE,
604 &ObjectAttributes);
605 if (!NT_SUCCESS(Status))
606 {
607 ErrorCode = RtlNtStatusToDosError(Status);
608
609 SetLastError (ErrorCode);
610 return ErrorCode;
611 }
612
613 Status = NtDeleteKey(TargetKey);
614
615 NtClose(TargetKey);
616
617 if (!NT_SUCCESS(Status))
618 {
619 ErrorCode = RtlNtStatusToDosError(Status);
620
621 SetLastError (ErrorCode);
622 return ErrorCode;
623 }
624 return ERROR_SUCCESS;
625 }
626
627
628 /************************************************************************
629 * RegDeleteValueA
630 */
631 LONG
632 STDCALL
633 RegDeleteValueA(
634 HKEY hKey,
635 LPCSTR lpValueName
636 )
637 {
638 UNICODE_STRING ValueNameW;
639 ANSI_STRING ValueNameA;
640 NTSTATUS Status;
641 LONG ErrorCode;
642 HANDLE KeyHandle;
643
644 Status = MapDefaultKey(&KeyHandle,
645 hKey);
646 if (!NT_SUCCESS(Status))
647 {
648 ErrorCode = RtlNtStatusToDosError(Status);
649
650 SetLastError (ErrorCode);
651 return ErrorCode;
652 }
653
654 RtlInitAnsiString(&ValueNameA,
655 (LPSTR)lpValueName);
656 RtlAnsiStringToUnicodeString(&ValueNameW,
657 &ValueNameA,
658 TRUE);
659
660 Status = NtDeleteValueKey(KeyHandle,
661 &ValueNameW);
662
663 RtlFreeUnicodeString (&ValueNameW);
664
665 if (!NT_SUCCESS(Status))
666 {
667 ErrorCode = RtlNtStatusToDosError(Status);
668
669 SetLastError (ErrorCode);
670 return ErrorCode;
671 }
672
673 return ERROR_SUCCESS;
674 }
675
676
677 /************************************************************************
678 * RegDeleteValueW
679 */
680 LONG
681 STDCALL
682 RegDeleteValueW(
683 HKEY hKey,
684 LPCWSTR lpValueName
685 )
686 {
687 UNICODE_STRING ValueName;
688 NTSTATUS Status;
689 LONG ErrorCode;
690 HANDLE KeyHandle;
691
692 Status = MapDefaultKey(&KeyHandle,
693 hKey);
694 if (!NT_SUCCESS(Status))
695 {
696 ErrorCode = RtlNtStatusToDosError(Status);
697
698 SetLastError (ErrorCode);
699 return ErrorCode;
700 }
701
702 RtlInitUnicodeString(&ValueName,
703 (LPWSTR)lpValueName);
704
705 Status = NtDeleteValueKey(KeyHandle,
706 &ValueName);
707 if (!NT_SUCCESS(Status))
708 {
709 ErrorCode = RtlNtStatusToDosError(Status);
710
711 SetLastError (ErrorCode);
712 return ErrorCode;
713 }
714
715 return ERROR_SUCCESS;
716 }
717
718
719 /************************************************************************
720 * RegEnumKeyA
721 */
722 LONG
723 STDCALL
724 RegEnumKeyA(
725 HKEY hKey,
726 DWORD dwIndex,
727 LPSTR lpName,
728 DWORD cbName
729 )
730 {
731 DWORD dwLength = cbName;
732
733 return RegEnumKeyExA(hKey,
734 dwIndex,
735 lpName,
736 &dwLength,
737 NULL,
738 NULL,
739 NULL,
740 NULL);
741 }
742
743
744 /************************************************************************
745 * RegEnumKeyExA
746 */
747 LONG
748 STDCALL
749 RegEnumKeyExA(
750 HKEY hKey,
751 DWORD dwIndex,
752 LPSTR lpName,
753 LPDWORD lpcbName,
754 LPDWORD lpReserved,
755 LPSTR lpClass,
756 LPDWORD lpcbClass,
757 PFILETIME lpftLastWriteTime
758 )
759 {
760 WCHAR Name[MAX_PATH+1];
761 UNICODE_STRING UnicodeStringName;
762 WCHAR Class[MAX_PATH+1];
763 UNICODE_STRING UnicodeStringClass;
764 ANSI_STRING AnsiString;
765 LONG ErrorCode;
766 DWORD NameLength;
767 DWORD ClassLength;
768
769 DPRINT("hKey 0x%x dwIndex %d lpName 0x%x *lpcbName %d lpClass 0x%x lpcbClass %d\n",
770 hKey, dwIndex, lpName, *lpcbName, lpClass, lpcbClass);
771
772 if ((lpClass) && (!lpcbClass))
773 {
774 SetLastError(ERROR_INVALID_PARAMETER);
775 return ERROR_INVALID_PARAMETER;
776 }
777
778 RtlInitUnicodeString(&UnicodeStringName, NULL);
779 UnicodeStringName.Buffer = &Name[0];
780 UnicodeStringName.MaximumLength = sizeof(Name);
781
782 RtlInitUnicodeString(&UnicodeStringClass, NULL);
783
784 if (lpClass)
785 {
786 UnicodeStringClass.Buffer = &Class[0];
787 UnicodeStringClass.MaximumLength = sizeof(Class);
788 ClassLength = *lpcbClass;
789 }
790 else
791 {
792 ClassLength = 0;
793 }
794
795 NameLength = *lpcbName;
796
797 ErrorCode = RegEnumKeyExW(
798 hKey,
799 dwIndex,
800 UnicodeStringName.Buffer,
801 &NameLength,
802 lpReserved,
803 UnicodeStringClass.Buffer,
804 &ClassLength,
805 lpftLastWriteTime);
806
807 if (ErrorCode != ERROR_SUCCESS)
808 return ErrorCode;
809
810 UnicodeStringName.Length = NameLength * sizeof(WCHAR);
811 UnicodeStringClass.Length = ClassLength * sizeof(WCHAR);
812
813 RtlInitAnsiString(&AnsiString, NULL);
814 AnsiString.Buffer = lpName;
815 AnsiString.MaximumLength = *lpcbName;
816 RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeStringName, FALSE);
817 *lpcbName = AnsiString.Length;
818
819 DPRINT("Key Namea0 Length %d\n", UnicodeStringName.Length);
820 DPRINT("Key Namea1 Length %d\n", NameLength);
821 DPRINT("Key Namea Length %d\n", *lpcbName);
822 DPRINT("Key Namea %s\n", lpName);
823
824 if (lpClass)
825 {
826 RtlInitAnsiString(&AnsiString, NULL);
827 AnsiString.Buffer = lpClass;
828 AnsiString.MaximumLength = *lpcbClass;
829 RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeStringClass, FALSE);
830 *lpcbClass = AnsiString.Length;
831 }
832
833 return ERROR_SUCCESS;
834 }
835
836
837 /************************************************************************
838 * RegEnumKeyExW
839 */
840 LONG
841 STDCALL
842 RegEnumKeyExW(
843 HKEY hKey,
844 DWORD dwIndex,
845 LPWSTR lpName,
846 LPDWORD lpcbName,
847 LPDWORD lpReserved,
848 LPWSTR lpClass,
849 LPDWORD lpcbClass,
850 PFILETIME lpftLastWriteTime
851 )
852 {
853 PKEY_NODE_INFORMATION KeyInfo;
854 NTSTATUS Status;
855 DWORD dwError = ERROR_SUCCESS;
856 ULONG BufferSize;
857 ULONG ResultSize;
858 HANDLE KeyHandle;
859
860 Status = MapDefaultKey(&KeyHandle, hKey);
861 if (!NT_SUCCESS(Status))
862 {
863 dwError = RtlNtStatusToDosError(Status);
864 SetLastError (dwError);
865 return dwError;
866 }
867
868 BufferSize = sizeof (KEY_NODE_INFORMATION) + *lpcbName * sizeof(WCHAR);
869 if (lpClass)
870 BufferSize += *lpcbClass;
871 KeyInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
872
873 /* We don't know the exact size of the data returned, so call
874 NtEnumerateKey() with a buffer size determined from parameters
875 to this function. If that call fails with a status code of
876 STATUS_BUFFER_OVERFLOW, allocate a new buffer and try again */
877 while (TRUE) {
878 KeyInfo = RtlAllocateHeap(
879 RtlGetProcessHeap(),
880 0,
881 BufferSize);
882 if (KeyInfo == NULL)
883 {
884 SetLastError(ERROR_OUTOFMEMORY);
885 return ERROR_OUTOFMEMORY;
886 }
887
888 Status = NtEnumerateKey(
889 KeyHandle,
890 (ULONG)dwIndex,
891 KeyNodeInformation,
892 KeyInfo,
893 BufferSize,
894 &ResultSize);
895
896 DPRINT("NtEnumerateKey() returned status 0x%X\n", Status);
897
898 if (Status == STATUS_BUFFER_OVERFLOW)
899 {
900 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
901 BufferSize = ResultSize;
902 continue;
903 }
904
905 if (!NT_SUCCESS(Status))
906 {
907 dwError = RtlNtStatusToDosError(Status);
908 SetLastError(dwError);
909 break;
910 }
911 else
912 {
913 if ((lpClass) && (*lpcbClass != 0) && (KeyInfo->ClassLength > *lpcbClass))
914 {
915 dwError = ERROR_MORE_DATA;
916 SetLastError(dwError);
917 break;
918 }
919
920 RtlMoveMemory(lpName, KeyInfo->Name, KeyInfo->NameLength);
921 *lpcbName = (DWORD)(KeyInfo->NameLength / sizeof(WCHAR));
922 RegiTerminateWideString(lpName, *lpcbName);
923
924 if (lpClass)
925 {
926 RtlMoveMemory(lpClass,
927 (PVOID)((ULONG_PTR)KeyInfo->Name + KeyInfo->ClassOffset),
928 KeyInfo->ClassLength);
929 *lpcbClass = (DWORD)(KeyInfo->ClassLength / sizeof(WCHAR));
930 }
931
932 if (lpftLastWriteTime)
933 {
934 /* FIXME: Fill lpftLastWriteTime */
935 }
936
937 break;
938 }
939 }
940
941 RtlFreeHeap (RtlGetProcessHeap(), 0, KeyInfo);
942
943 return dwError;
944 }
945
946
947 /************************************************************************
948 * RegEnumKeyW
949 */
950 LONG
951 STDCALL
952 RegEnumKeyW(
953 HKEY hKey,
954 DWORD dwIndex,
955 LPWSTR lpName,
956 DWORD cbName
957 )
958 {
959 DWORD dwLength = cbName;
960
961 return RegEnumKeyExW(hKey,
962 dwIndex,
963 lpName,
964 &dwLength,
965 NULL,
966 NULL,
967 NULL,
968 NULL);
969 }
970
971
972 /************************************************************************
973 * RegEnumValueA
974 */
975 LONG
976 STDCALL
977 RegEnumValueA(
978 HKEY hKey,
979 DWORD dwIndex,
980 LPSTR lpValueName,
981 LPDWORD lpcbValueName,
982 LPDWORD lpReserved,
983 LPDWORD lpType,
984 LPBYTE lpData,
985 LPDWORD lpcbData
986 )
987 {
988 WCHAR ValueName[MAX_PATH+1];
989 UNICODE_STRING UnicodeString;
990 ANSI_STRING AnsiString;
991 LONG ErrorCode;
992 DWORD ValueNameLength;
993
994 RtlInitUnicodeString(&UnicodeString, NULL);
995 UnicodeString.Buffer = &ValueName[0];
996 UnicodeString.MaximumLength = sizeof(ValueName);
997
998 ValueNameLength = *lpcbValueName;
999
1000 ErrorCode = RegEnumValueW(
1001 hKey,
1002 dwIndex,
1003 UnicodeString.Buffer,
1004 &ValueNameLength,
1005 lpReserved,
1006 lpType,
1007 lpData,
1008 lpcbData);
1009
1010 if (ErrorCode != ERROR_SUCCESS)
1011 return ErrorCode;
1012
1013 UnicodeString.Length = ValueNameLength * sizeof(WCHAR);
1014
1015 RtlInitAnsiString(&AnsiString, NULL);
1016 AnsiString.Buffer = lpValueName;
1017 AnsiString.MaximumLength = *lpcbValueName;
1018 RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE);
1019 *lpcbValueName = AnsiString.Length;
1020
1021 return ERROR_SUCCESS;
1022 }
1023
1024
1025 /************************************************************************
1026 * RegEnumValueW
1027 */
1028 LONG
1029 STDCALL
1030 RegEnumValueW(
1031 HKEY hKey,
1032 DWORD dwIndex,
1033 LPWSTR lpValueName,
1034 LPDWORD lpcbValueName,
1035 LPDWORD lpReserved,
1036 LPDWORD lpType,
1037 LPBYTE lpData,
1038 LPDWORD lpcbData
1039 )
1040 {
1041 PKEY_VALUE_FULL_INFORMATION ValueInfo;
1042 NTSTATUS Status;
1043 DWORD dwError = ERROR_SUCCESS;
1044 ULONG BufferSize;
1045 ULONG ResultSize;
1046 HANDLE KeyHandle;
1047
1048 Status = MapDefaultKey(&KeyHandle, hKey);
1049 if (!NT_SUCCESS(Status))
1050 {
1051 dwError = RtlNtStatusToDosError(Status);
1052 SetLastError(dwError);
1053 return(dwError);
1054 }
1055
1056 BufferSize = sizeof (KEY_VALUE_FULL_INFORMATION) +
1057 *lpcbValueName * sizeof(WCHAR);
1058 if (lpcbData)
1059 BufferSize += *lpcbData;
1060
1061 /* We don't know the exact size of the data returned, so call
1062 NtEnumerateValueKey() with a buffer size determined from parameters
1063 to this function. If that call fails with a status code of
1064 STATUS_BUFFER_OVERFLOW, allocate a new buffer and try again */
1065 while (TRUE) {
1066 ValueInfo = RtlAllocateHeap(
1067 RtlGetProcessHeap(),
1068 0,
1069 BufferSize);
1070 if (ValueInfo == NULL)
1071 {
1072 SetLastError(ERROR_OUTOFMEMORY);
1073 return ERROR_OUTOFMEMORY;
1074 }
1075
1076 Status = NtEnumerateValueKey(
1077 KeyHandle,
1078 (ULONG)dwIndex,
1079 KeyValueFullInformation,
1080 ValueInfo,
1081 BufferSize,
1082 &ResultSize);
1083
1084 DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status);
1085
1086 if (Status == STATUS_BUFFER_OVERFLOW)
1087 {
1088 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo);
1089 BufferSize = ResultSize;
1090 continue;
1091 }
1092
1093 if (!NT_SUCCESS(Status))
1094 {
1095 dwError = RtlNtStatusToDosError(Status);
1096 SetLastError(dwError);
1097 break;
1098 }
1099 else
1100 {
1101 if ((lpData) && (*lpcbData != 0) && (ValueInfo->DataLength > *lpcbData))
1102 {
1103 dwError = ERROR_MORE_DATA;
1104 SetLastError(dwError);
1105 break;
1106 }
1107
1108 memcpy(lpValueName, ValueInfo->Name, ValueInfo->NameLength);
1109 *lpcbValueName = (DWORD)(ValueInfo->NameLength / sizeof(WCHAR));
1110 RegiTerminateWideString(lpValueName, *lpcbValueName);
1111
1112 if (lpType)
1113 *lpType = ValueInfo->Type;
1114
1115 if (lpData)
1116 {
1117 memcpy(lpData,
1118 (PVOID)((ULONG_PTR)ValueInfo->Name + ValueInfo->DataOffset),
1119 ValueInfo->DataLength);
1120 *lpcbData = (DWORD)ValueInfo->DataLength;
1121 }
1122
1123 break;
1124 }
1125 }
1126
1127 RtlFreeHeap (RtlGetProcessHeap(), 0, ValueInfo);
1128
1129 return dwError;
1130 }
1131
1132
1133 /************************************************************************
1134 * RegFlushKey
1135 */
1136 LONG STDCALL
1137 RegFlushKey(HKEY hKey)
1138 {
1139 HANDLE KeyHandle;
1140 NTSTATUS Status;
1141 LONG ErrorCode;
1142
1143 if (hKey == HKEY_PERFORMANCE_DATA)
1144 return(ERROR_SUCCESS);
1145
1146 Status = MapDefaultKey(&KeyHandle,
1147 hKey);
1148 if (!NT_SUCCESS(Status))
1149 {
1150 ErrorCode = RtlNtStatusToDosError(Status);
1151
1152 SetLastError(ErrorCode);
1153 return(ErrorCode);
1154 }
1155
1156 Status = NtFlushKey(KeyHandle);
1157 if (!NT_SUCCESS(Status))
1158 {
1159 ErrorCode = RtlNtStatusToDosError(Status);
1160
1161 SetLastError(ErrorCode);
1162 return(ErrorCode);
1163 }
1164
1165 return(ERROR_SUCCESS);
1166 }
1167
1168
1169 /************************************************************************
1170 * RegGetKeySecurity
1171 */
1172 LONG
1173 STDCALL
1174 RegGetKeySecurity (
1175 HKEY hKey,
1176 SECURITY_INFORMATION SecurityInformation,
1177 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1178 LPDWORD lpcbSecurityDescriptor
1179 )
1180 {
1181 UNIMPLEMENTED;
1182 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1183 return ERROR_CALL_NOT_IMPLEMENTED;
1184 }
1185
1186
1187 /************************************************************************
1188 * RegLoadKeyA
1189 */
1190 LONG
1191 STDCALL
1192 RegLoadKey(
1193 HKEY hKey,
1194 LPCSTR lpSubKey,
1195 LPCSTR lpFile
1196 )
1197 {
1198 UNIMPLEMENTED;
1199 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1200 return ERROR_CALL_NOT_IMPLEMENTED;
1201 }
1202
1203
1204 /************************************************************************
1205 * RegLoadKeyW
1206 */
1207 LONG
1208 STDCALL
1209 RegLoadKeyW(
1210 HKEY hKey,
1211 LPCWSTR lpSubKey,
1212 LPCWSTR lpFile
1213 )
1214 {
1215 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1216 return ERROR_CALL_NOT_IMPLEMENTED;
1217 }
1218
1219
1220 /************************************************************************
1221 * RegNotifyChangeKeyValue
1222 */
1223 LONG
1224 STDCALL
1225 RegNotifyChangeKeyValue(
1226 HKEY hKey,
1227 BOOL bWatchSubtree,
1228 DWORD dwNotifyFilter,
1229 HANDLE hEvent,
1230 BOOL fAsynchronous
1231 )
1232 {
1233 UNIMPLEMENTED;
1234 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1235 return ERROR_CALL_NOT_IMPLEMENTED;
1236 }
1237
1238
1239
1240 /************************************************************************
1241 * RegOpenKeyA
1242 */
1243 LONG STDCALL
1244 RegOpenKeyA(HKEY hKey,
1245 LPCSTR lpSubKey,
1246 PHKEY phkResult)
1247 {
1248 OBJECT_ATTRIBUTES ObjectAttributes;
1249 UNICODE_STRING SubKeyString;
1250 HANDLE KeyHandle;
1251 LONG ErrorCode;
1252 NTSTATUS Status;
1253
1254 Status = MapDefaultKey(&KeyHandle,
1255 hKey);
1256 if (!NT_SUCCESS(Status))
1257 {
1258 ErrorCode = RtlNtStatusToDosError(Status);
1259
1260 SetLastError(ErrorCode);
1261 return(ErrorCode);
1262 }
1263
1264 RtlCreateUnicodeStringFromAsciiz(&SubKeyString,
1265 (LPSTR)lpSubKey);
1266
1267 InitializeObjectAttributes(&ObjectAttributes,
1268 &SubKeyString,
1269 OBJ_CASE_INSENSITIVE,
1270 KeyHandle,
1271 NULL);
1272
1273 Status = NtOpenKey(phkResult,
1274 KEY_ALL_ACCESS,
1275 &ObjectAttributes);
1276
1277 RtlFreeUnicodeString(&SubKeyString);
1278
1279 if (!NT_SUCCESS(Status))
1280 {
1281 ErrorCode = RtlNtStatusToDosError(Status);
1282
1283 SetLastError(ErrorCode);
1284 return(ErrorCode);
1285 }
1286 return(ERROR_SUCCESS);
1287 }
1288
1289
1290 /************************************************************************
1291 * RegOpenKeyW
1292 *
1293 * 19981101 Ariadne
1294 * 19990525 EA
1295 */
1296 LONG
1297 STDCALL
1298 RegOpenKeyW (
1299 HKEY hKey,
1300 LPCWSTR lpSubKey,
1301 PHKEY phkResult
1302 )
1303 {
1304 NTSTATUS errCode;
1305 UNICODE_STRING SubKeyString;
1306 OBJECT_ATTRIBUTES ObjectAttributes;
1307 HANDLE KeyHandle;
1308 LONG ErrorCode;
1309
1310 errCode = MapDefaultKey(&KeyHandle,
1311 hKey);
1312 if (!NT_SUCCESS(errCode))
1313 {
1314 ErrorCode = RtlNtStatusToDosError(errCode);
1315
1316 SetLastError (ErrorCode);
1317 return ErrorCode;
1318 }
1319
1320 RtlInitUnicodeString(&SubKeyString,
1321 (LPWSTR)lpSubKey);
1322
1323 InitializeObjectAttributes(&ObjectAttributes,
1324 &SubKeyString,
1325 OBJ_CASE_INSENSITIVE,
1326 KeyHandle,
1327 NULL);
1328
1329 errCode = NtOpenKey(
1330 phkResult,
1331 KEY_ALL_ACCESS,
1332 & ObjectAttributes
1333 );
1334 if ( !NT_SUCCESS(errCode) )
1335 {
1336 ErrorCode = RtlNtStatusToDosError(errCode);
1337
1338 SetLastError(ErrorCode);
1339 return ErrorCode;
1340 }
1341 return ERROR_SUCCESS;
1342 }
1343
1344
1345 /************************************************************************
1346 * RegOpenKeyExA
1347 */
1348 LONG STDCALL
1349 RegOpenKeyExA(HKEY hKey,
1350 LPCSTR lpSubKey,
1351 DWORD ulOptions,
1352 REGSAM samDesired,
1353 PHKEY phkResult)
1354 {
1355 OBJECT_ATTRIBUTES ObjectAttributes;
1356 UNICODE_STRING SubKeyString;
1357 HANDLE KeyHandle;
1358 LONG ErrorCode;
1359 NTSTATUS Status;
1360
1361 Status = MapDefaultKey(&KeyHandle,
1362 hKey);
1363 if (!NT_SUCCESS(Status))
1364 {
1365 ErrorCode = RtlNtStatusToDosError(Status);
1366
1367 SetLastError(ErrorCode);
1368 return(ErrorCode);
1369 }
1370
1371 RtlCreateUnicodeStringFromAsciiz(&SubKeyString,
1372 (LPSTR)lpSubKey);
1373
1374 InitializeObjectAttributes(&ObjectAttributes,
1375 &SubKeyString,
1376 OBJ_CASE_INSENSITIVE,
1377 KeyHandle,
1378 NULL);
1379
1380 Status = NtOpenKey(phkResult,
1381 samDesired,
1382 &ObjectAttributes);
1383
1384 RtlFreeUnicodeString(&SubKeyString);
1385
1386 if (!NT_SUCCESS(Status))
1387 {
1388 ErrorCode = RtlNtStatusToDosError(Status);
1389
1390 SetLastError(ErrorCode);
1391 return(ErrorCode);
1392 }
1393
1394 return(ERROR_SUCCESS);
1395 }
1396
1397
1398 /************************************************************************
1399 * RegOpenKeyExW
1400 */
1401 LONG STDCALL
1402 RegOpenKeyExW(HKEY hKey,
1403 LPCWSTR lpSubKey,
1404 DWORD ulOptions,
1405 REGSAM samDesired,
1406 PHKEY phkResult)
1407 {
1408 OBJECT_ATTRIBUTES ObjectAttributes;
1409 UNICODE_STRING SubKeyString;
1410 HANDLE KeyHandle;
1411 LONG ErrorCode;
1412 NTSTATUS Status;
1413
1414 Status = MapDefaultKey(&KeyHandle,
1415 hKey);
1416 if (!NT_SUCCESS(Status))
1417 {
1418 ErrorCode = RtlNtStatusToDosError(Status);
1419
1420 SetLastError (ErrorCode);
1421 return(ErrorCode);
1422 }
1423
1424 RtlInitUnicodeString(&SubKeyString,
1425 (LPWSTR)lpSubKey);
1426
1427 InitializeObjectAttributes(&ObjectAttributes,
1428 &SubKeyString,
1429 OBJ_CASE_INSENSITIVE,
1430 KeyHandle,
1431 NULL);
1432
1433 Status = NtOpenKey(phkResult,
1434 samDesired,
1435 &ObjectAttributes);
1436 if (!NT_SUCCESS(Status))
1437 {
1438 ErrorCode = RtlNtStatusToDosError(Status);
1439
1440 SetLastError(ErrorCode);
1441 return(ErrorCode);
1442 }
1443 return(ERROR_SUCCESS);
1444 }
1445
1446
1447 /************************************************************************
1448 * RegQueryInfoKeyA
1449 */
1450 LONG
1451 STDCALL
1452 RegQueryInfoKeyA(
1453 HKEY hKey,
1454 LPSTR lpClass,
1455 LPDWORD lpcbClass,
1456 LPDWORD lpReserved,
1457 LPDWORD lpcSubKeys,
1458 LPDWORD lpcbMaxSubKeyLen,
1459 LPDWORD lpcbMaxClassLen,
1460 LPDWORD lpcValues,
1461 LPDWORD lpcbMaxValueNameLen,
1462 LPDWORD lpcbMaxValueLen,
1463 LPDWORD lpcbSecurityDescriptor,
1464 PFILETIME lpftLastWriteTime
1465 )
1466 {
1467 WCHAR ClassName[MAX_PATH];
1468 UNICODE_STRING UnicodeString;
1469 ANSI_STRING AnsiString;
1470 LONG ErrorCode;
1471
1472 RtlInitUnicodeString(&UnicodeString, NULL);
1473
1474 if (lpClass)
1475 {
1476 UnicodeString.Buffer = &ClassName[0];
1477 UnicodeString.MaximumLength = sizeof(ClassName);
1478 }
1479
1480 ErrorCode = RegQueryInfoKeyW(
1481 hKey,
1482 UnicodeString.Buffer,
1483 lpcbClass,
1484 lpReserved,
1485 lpcSubKeys,
1486 lpcbMaxSubKeyLen,
1487 lpcbMaxClassLen,
1488 lpcValues,
1489 lpcbMaxValueNameLen,
1490 lpcbMaxValueLen,
1491 lpcbSecurityDescriptor,
1492 lpftLastWriteTime);
1493
1494 if ((ErrorCode == ERROR_SUCCESS) && (lpClass))
1495 {
1496 RtlInitAnsiString(&AnsiString, NULL);
1497 AnsiString.Buffer = lpClass;
1498 AnsiString.MaximumLength = *lpcbClass;
1499 RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE);
1500 *lpcbClass = AnsiString.Length;
1501 }
1502
1503 return ErrorCode;
1504 }
1505
1506
1507 /************************************************************************
1508 * RegQueryInfoKeyW
1509 */
1510 LONG
1511 STDCALL
1512 RegQueryInfoKeyW(
1513 HKEY hKey,
1514 LPWSTR lpClass,
1515 LPDWORD lpcbClass,
1516 LPDWORD lpReserved,
1517 LPDWORD lpcSubKeys,
1518 LPDWORD lpcbMaxSubKeyLen,
1519 LPDWORD lpcbMaxClassLen,
1520 LPDWORD lpcValues,
1521 LPDWORD lpcbMaxValueNameLen,
1522 LPDWORD lpcbMaxValueLen,
1523 LPDWORD lpcbSecurityDescriptor,
1524 PFILETIME lpftLastWriteTime
1525 )
1526 {
1527 KEY_FULL_INFORMATION FullInfoBuffer;
1528 PKEY_FULL_INFORMATION FullInfo;
1529 ULONG FullInfoSize;
1530 HANDLE KeyHandle;
1531 NTSTATUS Status;
1532 LONG ErrorCode;
1533 ULONG Length;
1534
1535 if ((lpClass) && (!lpcbClass))
1536 {
1537 SetLastError(ERROR_INVALID_PARAMETER);
1538 return ERROR_INVALID_PARAMETER;
1539 }
1540
1541 Status = MapDefaultKey(&KeyHandle, hKey);
1542 CHECK_STATUS;
1543
1544 if (lpClass)
1545 {
1546 FullInfoSize = sizeof(KEY_FULL_INFORMATION) + *lpcbClass;
1547 FullInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, FullInfoSize);
1548 if (!FullInfo)
1549 {
1550 SetLastError(ERROR_OUTOFMEMORY);
1551 return ERROR_OUTOFMEMORY;
1552 }
1553
1554 FullInfo->ClassLength = *lpcbClass;
1555 }
1556 else
1557 {
1558 FullInfoSize = sizeof(KEY_FULL_INFORMATION);
1559 FullInfo = &FullInfoBuffer;
1560 FullInfo->ClassLength = 1;
1561 }
1562
1563 FullInfo->ClassOffset = FIELD_OFFSET(KEY_FULL_INFORMATION, Class);
1564
1565 Status = NtQueryKey(
1566 KeyHandle,
1567 KeyFullInformation,
1568 FullInfo,
1569 FullInfoSize,
1570 &Length);
1571
1572 if (!NT_SUCCESS(Status))
1573 {
1574 if (lpClass)
1575 {
1576 RtlFreeHeap(RtlGetProcessHeap(), 0, FullInfo);
1577 }
1578
1579 ErrorCode = RtlNtStatusToDosError(Status);
1580 SetLastError(ErrorCode);
1581 return ErrorCode;
1582 }
1583
1584 if (lpcSubKeys)
1585 {
1586 *lpcSubKeys = FullInfo->SubKeys;
1587 }
1588
1589 if (lpcbMaxSubKeyLen)
1590 {
1591 *lpcbMaxSubKeyLen = FullInfo->MaxNameLen;
1592 }
1593
1594 if (lpcbMaxClassLen)
1595 {
1596 *lpcbMaxClassLen = FullInfo->MaxClassLen;
1597 }
1598
1599 if (lpcValues)
1600 {
1601 *lpcValues = FullInfo->Values;
1602 }
1603
1604 if (lpcbMaxValueNameLen)
1605 {
1606 *lpcbMaxValueNameLen = FullInfo->MaxValueNameLen;
1607 }
1608
1609 if (lpcbMaxValueLen)
1610 {
1611 *lpcbMaxValueLen = FullInfo->MaxValueDataLen;
1612 }
1613
1614 if (lpcbSecurityDescriptor)
1615 {
1616 *lpcbSecurityDescriptor = 0;
1617 /* FIXME */
1618 }
1619
1620 if (lpftLastWriteTime != NULL)
1621 {
1622 lpftLastWriteTime->dwLowDateTime = FullInfo->LastWriteTime.u.LowPart;
1623 lpftLastWriteTime->dwHighDateTime = FullInfo->LastWriteTime.u.HighPart;
1624 }
1625
1626 if (lpClass)
1627 {
1628 wcsncpy(lpClass, FullInfo->Class, *lpcbClass);
1629 RtlFreeHeap(RtlGetProcessHeap(), 0, FullInfo);
1630 }
1631
1632 SetLastError(ERROR_SUCCESS);
1633 return ERROR_SUCCESS;
1634 }
1635
1636
1637 /************************************************************************
1638 * RegQueryMultipleValuesA
1639 */
1640 LONG
1641 STDCALL
1642 RegQueryMultipleValuesA(
1643 HKEY hKey,
1644 PVALENT val_list,
1645 DWORD num_vals,
1646 LPSTR lpValueBuf,
1647 LPDWORD ldwTotsize
1648 )
1649 {
1650 UNIMPLEMENTED;
1651 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1652 return ERROR_CALL_NOT_IMPLEMENTED;
1653 }
1654
1655
1656 /************************************************************************
1657 * RegQueryMultipleValuesW
1658 */
1659 LONG
1660 STDCALL
1661 RegQueryMultipleValuesW(
1662 HKEY hKey,
1663 PVALENT val_list,
1664 DWORD num_vals,
1665 LPWSTR lpValueBuf,
1666 LPDWORD ldwTotsize
1667 )
1668 {
1669 UNIMPLEMENTED;
1670 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1671 return ERROR_CALL_NOT_IMPLEMENTED;
1672 }
1673
1674
1675 /************************************************************************
1676 * RegQueryValueA
1677 */
1678 LONG
1679 STDCALL
1680 RegQueryValueA(
1681 HKEY hKey,
1682 LPCSTR lpSubKey,
1683 LPSTR lpValue,
1684 PLONG lpcbValue
1685 )
1686 {
1687 WCHAR SubKeyNameBuffer[MAX_PATH+1];
1688 UNICODE_STRING SubKeyName;
1689 UNICODE_STRING Value;
1690 ANSI_STRING AnsiString;
1691 LONG ValueSize;
1692 LONG ErrorCode;
1693
1694 if ((lpValue) && (!lpcbValue))
1695 {
1696 SetLastError(ERROR_INVALID_PARAMETER);
1697 return ERROR_INVALID_PARAMETER;
1698 }
1699
1700 RtlInitUnicodeString(&SubKeyName, NULL);
1701 RtlInitUnicodeString(&Value, NULL);
1702
1703 if ((lpSubKey) && (strlen(lpSubKey) != 0))
1704 {
1705 RtlInitAnsiString(&AnsiString, (LPSTR)lpSubKey);
1706 SubKeyName.Buffer = &SubKeyNameBuffer[0];
1707 SubKeyName.MaximumLength = sizeof(SubKeyNameBuffer);
1708 RtlAnsiStringToUnicodeString(&SubKeyName, &AnsiString, FALSE);
1709 }
1710
1711 if (lpValue)
1712 {
1713 ValueSize = *lpcbValue * sizeof(WCHAR);
1714 Value.MaximumLength = ValueSize;
1715 Value.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, ValueSize);
1716 if (!Value.Buffer)
1717 {
1718 SetLastError(ERROR_OUTOFMEMORY);
1719 return ERROR_OUTOFMEMORY;
1720 }
1721 }
1722 else
1723 {
1724 ValueSize = 0;
1725 }
1726
1727 ErrorCode = RegQueryValueW(
1728 hKey,
1729 (LPCWSTR)SubKeyName.Buffer,
1730 Value.Buffer,
1731 &ValueSize);
1732
1733 if (ErrorCode == ERROR_SUCCESS)
1734 {
1735 Value.Length = ValueSize;
1736 RtlInitAnsiString(&AnsiString, NULL);
1737 AnsiString.Buffer = lpValue;
1738 AnsiString.MaximumLength = *lpcbValue;
1739 RtlUnicodeStringToAnsiString(&AnsiString, &Value, FALSE);
1740 }
1741
1742 *lpcbValue = ValueSize;
1743
1744 if (Value.Buffer)
1745 {
1746 RtlFreeHeap(RtlGetProcessHeap(), 0, Value.Buffer);
1747 }
1748
1749 return ErrorCode;
1750 }
1751
1752
1753 /************************************************************************
1754 * RegQueryValueExA
1755 */
1756 LONG
1757 STDCALL
1758 RegQueryValueExA(
1759 HKEY hKey,
1760 LPSTR lpValueName,
1761 LPDWORD lpReserved,
1762 LPDWORD lpType,
1763 LPBYTE lpData,
1764 LPDWORD lpcbData
1765 )
1766 {
1767 WCHAR ValueNameBuffer[MAX_PATH+1];
1768 UNICODE_STRING ValueName;
1769 UNICODE_STRING ValueData;
1770 ANSI_STRING AnsiString;
1771 LONG ErrorCode;
1772 DWORD ResultSize;
1773 DWORD Type;
1774
1775 /* FIXME: HKEY_PERFORMANCE_DATA is special, see MS SDK */
1776
1777 if ((lpData) && (!lpcbData))
1778 {
1779 SetLastError(ERROR_INVALID_PARAMETER);
1780 return ERROR_INVALID_PARAMETER;
1781 }
1782
1783 RtlInitUnicodeString(&ValueData, NULL);
1784
1785 if (lpData)
1786 {
1787 ValueData.MaximumLength = *lpcbData * sizeof(WCHAR);
1788 ValueData.Buffer = RtlAllocateHeap(
1789 RtlGetProcessHeap(),
1790 0,
1791 ValueData.MaximumLength);
1792 if (!ValueData.Buffer)
1793 {
1794 SetLastError(ERROR_OUTOFMEMORY);
1795 return ERROR_OUTOFMEMORY;
1796 }
1797 }
1798
1799 RtlInitAnsiString(&AnsiString, (LPSTR)lpValueName);
1800 RtlInitUnicodeString(&ValueName, NULL);
1801 ValueName.Buffer = &ValueNameBuffer[0];
1802 ValueName.MaximumLength = sizeof(ValueNameBuffer);
1803 RtlAnsiStringToUnicodeString(&ValueName, &AnsiString, FALSE);
1804
1805 if (lpcbData)
1806 {
1807 ResultSize = *lpcbData;
1808 }
1809 else
1810 {
1811 ResultSize = 0;
1812 }
1813
1814 ErrorCode = RegQueryValueExW(
1815 hKey,
1816 ValueName.Buffer,
1817 lpReserved,
1818 &Type,
1819 (LPBYTE)ValueData.Buffer,
1820 &ResultSize);
1821
1822 if ((ErrorCode == ERROR_SUCCESS) && (ValueData.Buffer != NULL))
1823 {
1824 if (lpType)
1825 {
1826 *lpType = Type;
1827 }
1828
1829 if ((Type == REG_SZ) || (Type == REG_MULTI_SZ) || (Type == REG_EXPAND_SZ))
1830 {
1831 ValueData.Length = ResultSize;
1832 RtlInitAnsiString(&AnsiString, NULL);
1833 AnsiString.Buffer = lpData;
1834 AnsiString.MaximumLength = *lpcbData;
1835 RtlUnicodeStringToAnsiString(&AnsiString, &ValueData, FALSE);
1836 }
1837 else
1838 {
1839 RtlMoveMemory(lpData, ValueData.Buffer, ResultSize);
1840 }
1841 }
1842
1843 if (lpcbData)
1844 {
1845 *lpcbData = ResultSize;
1846 }
1847
1848 if (ValueData.Buffer)
1849 {
1850 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueData.Buffer);
1851 }
1852
1853 return ErrorCode;
1854 }
1855
1856
1857 /************************************************************************
1858 * RegQueryValueExW
1859 */
1860 LONG
1861 STDCALL
1862 RegQueryValueExW(
1863 HKEY hKey,
1864 LPWSTR lpValueName,
1865 LPDWORD lpReserved,
1866 LPDWORD lpType,
1867 LPBYTE lpData,
1868 LPDWORD lpcbData
1869 )
1870 {
1871 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
1872 UNICODE_STRING ValueName;
1873 NTSTATUS Status;
1874 DWORD dwError = ERROR_SUCCESS;
1875 ULONG BufferSize;
1876 ULONG ResultSize;
1877 HANDLE KeyHandle;
1878
1879 DPRINT("hKey 0x%X lpValueName %S lpData 0x%X lpcbData %d\n",
1880 hKey, lpValueName, lpData, lpcbData ? *lpcbData : 0);
1881
1882 Status = MapDefaultKey(&KeyHandle, hKey);
1883 if (!NT_SUCCESS(Status))
1884 {
1885 dwError = RtlNtStatusToDosError(Status);
1886 SetLastError(dwError);
1887 return(dwError);
1888 }
1889
1890 if ((lpData) && (!lpcbData))
1891 {
1892 SetLastError(ERROR_INVALID_PARAMETER);
1893 return ERROR_INVALID_PARAMETER;
1894 }
1895
1896 RtlInitUnicodeString (&ValueName,
1897 lpValueName);
1898
1899 BufferSize = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + *lpcbData;
1900 ValueInfo = RtlAllocateHeap (RtlGetProcessHeap(),
1901 0,
1902 BufferSize);
1903 if (ValueInfo == NULL)
1904 {
1905 SetLastError(ERROR_OUTOFMEMORY);
1906 return ERROR_OUTOFMEMORY;
1907 }
1908
1909 Status = NtQueryValueKey (hKey,
1910 &ValueName,
1911 KeyValuePartialInformation,
1912 ValueInfo,
1913 BufferSize,
1914 &ResultSize);
1915
1916 DPRINT("Status 0x%X\n", Status);
1917
1918 if (Status == STATUS_BUFFER_TOO_SMALL)
1919 {
1920 /* Return ERROR_SUCCESS and the buffer space needed for a successful call */
1921 dwError = ERROR_SUCCESS;
1922 }
1923 else if (!NT_SUCCESS(Status))
1924 {
1925 dwError = RtlNtStatusToDosError(Status);
1926 SetLastError(dwError);
1927 }
1928 else
1929 {
1930 if (lpType)
1931 {
1932 *lpType = ValueInfo->Type;
1933 }
1934
1935 RtlMoveMemory(lpData, ValueInfo->Data, ValueInfo->DataLength);
1936 if ((ValueInfo->Type == REG_SZ) ||
1937 (ValueInfo->Type == REG_MULTI_SZ) ||
1938 (ValueInfo->Type == REG_EXPAND_SZ))
1939 {
1940 ((PWSTR)lpData)[ValueInfo->DataLength / sizeof(WCHAR)] = 0;
1941 }
1942 }
1943
1944 DPRINT("Type %d ResultSize %d\n", ValueInfo->Type, ResultSize);
1945
1946 *lpcbData = (DWORD)ResultSize;
1947
1948 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo);
1949
1950 return dwError;
1951 }
1952
1953
1954 /************************************************************************
1955 * RegQueryValueW
1956 */
1957 LONG
1958 STDCALL
1959 RegQueryValueW(
1960 HKEY hKey,
1961 LPCWSTR lpSubKey,
1962 LPWSTR lpValue,
1963 PLONG lpcbValue
1964 )
1965 {
1966 NTSTATUS errCode;
1967 UNICODE_STRING SubKeyString;
1968 OBJECT_ATTRIBUTES ObjectAttributes;
1969 HANDLE KeyHandle;
1970 HANDLE RealKey;
1971 LONG ErrorCode;
1972 BOOL CloseRealKey;
1973
1974 errCode = MapDefaultKey(&KeyHandle, hKey);
1975 if (!NT_SUCCESS(errCode))
1976 {
1977 ErrorCode = RtlNtStatusToDosError(errCode);
1978 SetLastError (ErrorCode);
1979 return ErrorCode;
1980 }
1981
1982 if ((lpSubKey) && (wcslen(lpSubKey) != 0))
1983 {
1984
1985 RtlInitUnicodeString(&SubKeyString,
1986 (LPWSTR)lpSubKey);
1987
1988 InitializeObjectAttributes(&ObjectAttributes,
1989 &SubKeyString,
1990 OBJ_CASE_INSENSITIVE,
1991 KeyHandle,
1992 NULL);
1993
1994 errCode = NtOpenKey(
1995 &RealKey,
1996 KEY_ALL_ACCESS,
1997 & ObjectAttributes
1998 );
1999 if ( !NT_SUCCESS(errCode) )
2000 {
2001 ErrorCode = RtlNtStatusToDosError(errCode);
2002 SetLastError(ErrorCode);
2003 return ErrorCode;
2004 }
2005 CloseRealKey = TRUE;
2006 }
2007 else
2008 {
2009 RealKey = hKey;
2010 CloseRealKey = FALSE;
2011 }
2012
2013 ErrorCode = RegQueryValueExW(
2014 RealKey,
2015 NULL,
2016 NULL,
2017 NULL,
2018 (LPBYTE)lpValue,
2019 (LPDWORD)lpcbValue);
2020
2021 if (CloseRealKey)
2022 {
2023 NtClose(RealKey);
2024 }
2025
2026 return ErrorCode;
2027 }
2028
2029
2030 /************************************************************************
2031 * RegReplaceKeyA
2032 */
2033 LONG
2034 STDCALL
2035 RegReplaceKeyA(
2036 HKEY hKey,
2037 LPCSTR lpSubKey,
2038 LPCSTR lpNewFile,
2039 LPCSTR lpOldFile
2040 )
2041 {
2042 UNIMPLEMENTED;
2043 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2044 return ERROR_CALL_NOT_IMPLEMENTED;
2045 }
2046
2047
2048 /************************************************************************
2049 * RegReplaceKeyW
2050 */
2051 LONG
2052 STDCALL
2053 RegReplaceKeyW(
2054 HKEY hKey,
2055 LPCWSTR lpSubKey,
2056 LPCWSTR lpNewFile,
2057 LPCWSTR lpOldFile
2058 )
2059 {
2060 UNIMPLEMENTED;
2061 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2062 return ERROR_CALL_NOT_IMPLEMENTED;
2063 }
2064
2065
2066 /************************************************************************
2067 * RegRestoreKeyA
2068 */
2069 LONG
2070 STDCALL
2071 RegRestoreKeyA(
2072 HKEY hKey,
2073 LPCSTR lpFile,
2074 DWORD dwFlags
2075 )
2076 {
2077 UNIMPLEMENTED;
2078 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2079 return ERROR_CALL_NOT_IMPLEMENTED;
2080 }
2081
2082
2083 /************************************************************************
2084 * RegRestoreKeyW
2085 */
2086 LONG
2087 STDCALL
2088 RegRestoreKeyW(
2089 HKEY hKey,
2090 LPCWSTR lpFile,
2091 DWORD dwFlags
2092 )
2093 {
2094 UNIMPLEMENTED;
2095 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2096 return ERROR_CALL_NOT_IMPLEMENTED;
2097 }
2098
2099
2100 /************************************************************************
2101 * RegSaveKeyA
2102 */
2103 LONG STDCALL
2104 RegSaveKeyA(HKEY hKey,
2105 LPCSTR lpFile,
2106 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
2107 {
2108 UNICODE_STRING FileName;
2109 LONG ErrorCode;
2110
2111 RtlCreateUnicodeStringFromAsciiz(&FileName,
2112 (LPSTR)lpFile);
2113 ErrorCode = RegSaveKeyW(hKey,
2114 FileName.Buffer,
2115 lpSecurityAttributes);
2116 RtlFreeUnicodeString(&FileName);
2117
2118 return(ErrorCode);
2119 }
2120
2121
2122 /************************************************************************
2123 * RegSaveKeyW
2124 */
2125 LONG STDCALL
2126 RegSaveKeyW(HKEY hKey,
2127 LPCWSTR lpFile,
2128 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
2129 {
2130 PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
2131 OBJECT_ATTRIBUTES ObjectAttributes;
2132 UNICODE_STRING NtName;
2133 IO_STATUS_BLOCK IoStatusBlock;
2134 HANDLE FileHandle;
2135 HANDLE KeyHandle;
2136 NTSTATUS Status;
2137 LONG ErrorCode;
2138
2139 Status = MapDefaultKey(&KeyHandle,
2140 hKey);
2141 if (!NT_SUCCESS(Status))
2142 {
2143 ErrorCode = RtlNtStatusToDosError(Status);
2144 SetLastError(ErrorCode);
2145 return(ErrorCode);
2146 }
2147
2148 if (!RtlDosPathNameToNtPathName_U((LPWSTR)lpFile,
2149 &NtName,
2150 NULL,
2151 NULL))
2152 {
2153 SetLastError(ERROR_INVALID_PARAMETER);
2154 return(ERROR_INVALID_PARAMETER);
2155 }
2156
2157 if (lpSecurityAttributes != NULL)
2158 SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
2159
2160 InitializeObjectAttributes(&ObjectAttributes,
2161 &NtName,
2162 OBJ_CASE_INSENSITIVE,
2163 NULL,
2164 SecurityDescriptor);
2165
2166 Status = NtCreateFile(&FileHandle,
2167 GENERIC_WRITE | SYNCHRONIZE,
2168 &ObjectAttributes,
2169 &IoStatusBlock,
2170 NULL,
2171 FILE_ATTRIBUTE_NORMAL,
2172 FILE_SHARE_READ,
2173 FILE_CREATE,
2174 FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
2175 NULL,
2176 0);
2177 RtlFreeUnicodeString(&NtName);
2178 if (!NT_SUCCESS(Status))
2179 {
2180 ErrorCode = RtlNtStatusToDosError(Status);
2181 SetLastError(ErrorCode);
2182 return(ErrorCode);
2183 }
2184
2185 Status = NtSaveKey(KeyHandle,
2186 FileHandle);
2187 NtClose(FileHandle);
2188 if (!NT_SUCCESS(Status))
2189 {
2190 ErrorCode = RtlNtStatusToDosError(Status);
2191 SetLastError(ErrorCode);
2192 return(ErrorCode);
2193 }
2194
2195 return(ERROR_SUCCESS);
2196 }
2197
2198
2199 /************************************************************************
2200 * RegSetKeySecurity
2201 */
2202 LONG
2203 STDCALL
2204 RegSetKeySecurity(
2205 HKEY hKey,
2206 SECURITY_INFORMATION SecurityInformation, /* FIXME: ULONG? */
2207 PSECURITY_DESCRIPTOR pSecurityDescriptor
2208 )
2209 {
2210 UNIMPLEMENTED;
2211 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2212 return ERROR_CALL_NOT_IMPLEMENTED;
2213 }
2214
2215
2216 /************************************************************************
2217 * RegSetValueA
2218 */
2219 LONG
2220 STDCALL
2221 RegSetValueA(
2222 HKEY hKey,
2223 LPCSTR lpSubKey,
2224 DWORD dwType,
2225 LPCSTR lpData,
2226 DWORD cbData
2227 )
2228 {
2229 WCHAR SubKeyNameBuffer[MAX_PATH+1];
2230 UNICODE_STRING SubKeyName;
2231 UNICODE_STRING Data;
2232 ANSI_STRING AnsiString;
2233 LONG DataSize;
2234 LONG ErrorCode;
2235
2236 if (!lpData)
2237 {
2238 SetLastError(ERROR_INVALID_PARAMETER);
2239 return ERROR_INVALID_PARAMETER;
2240 }
2241
2242 RtlInitUnicodeString(&SubKeyName, NULL);
2243 RtlInitUnicodeString(&Data, NULL);
2244
2245 if ((lpSubKey) && (strlen(lpSubKey) != 0))
2246 {
2247 RtlInitAnsiString(&AnsiString, (LPSTR)lpSubKey);
2248 SubKeyName.Buffer = &SubKeyNameBuffer[0];
2249 SubKeyName.MaximumLength = sizeof(SubKeyNameBuffer);
2250 RtlAnsiStringToUnicodeString(&SubKeyName, &AnsiString, FALSE);
2251 }
2252
2253 DataSize = cbData * sizeof(WCHAR);
2254 Data.MaximumLength = DataSize;
2255 Data.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, DataSize);
2256 if (!Data.Buffer)
2257 {
2258 SetLastError(ERROR_OUTOFMEMORY);
2259 return ERROR_OUTOFMEMORY;
2260 }
2261
2262 ErrorCode = RegSetValueW(
2263 hKey,
2264 (LPCWSTR)SubKeyName.Buffer,
2265 dwType,
2266 Data.Buffer,
2267 DataSize);
2268
2269 RtlFreeHeap(RtlGetProcessHeap(), 0, Data.Buffer);
2270
2271 return ErrorCode;
2272 }
2273
2274
2275 /************************************************************************
2276 * RegSetValueExA
2277 */
2278 LONG
2279 STDCALL
2280 RegSetValueExA(
2281 HKEY hKey,
2282 LPCSTR lpValueName,
2283 DWORD Reserved,
2284 DWORD dwType,
2285 CONST BYTE *lpData,
2286 DWORD cbData
2287 )
2288 {
2289 UNICODE_STRING ValueName;
2290 LPWSTR pValueName;
2291 ANSI_STRING AnsiString;
2292 UNICODE_STRING Data;
2293 LONG ErrorCode;
2294 LPBYTE pData;
2295 DWORD DataSize;
2296
2297 if (!lpData)
2298 {
2299 SetLastError(ERROR_INVALID_PARAMETER);
2300 return ERROR_INVALID_PARAMETER;
2301 }
2302
2303 if ((lpValueName) && (strlen(lpValueName) != 0))
2304 {
2305 RtlCreateUnicodeStringFromAsciiz(&ValueName, (LPSTR)lpValueName);
2306 pValueName = (LPWSTR)ValueName.Buffer;
2307 }
2308 else
2309 {
2310 pValueName = NULL;
2311 }
2312
2313 if ((dwType == REG_SZ) || (dwType == REG_MULTI_SZ) || (dwType == REG_EXPAND_SZ))
2314 {
2315 RtlInitAnsiString(&AnsiString, NULL);
2316 AnsiString.Buffer = (LPSTR)lpData;
2317 AnsiString.Length = cbData;
2318 AnsiString.MaximumLength = cbData;
2319 RtlAnsiStringToUnicodeString(&Data, &AnsiString, TRUE);
2320 pData = (LPBYTE)Data.Buffer;
2321 DataSize = cbData * sizeof(WCHAR);
2322 }
2323 else
2324 {
2325 RtlInitUnicodeString(&Data, NULL);
2326 pData = (LPBYTE)lpData;
2327 DataSize = cbData;
2328 }
2329
2330 ErrorCode = RegSetValueExW(
2331 hKey,
2332 pValueName,
2333 Reserved,
2334 dwType,
2335 pData,
2336 DataSize);
2337
2338 if (pValueName)
2339 {
2340 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueName.Buffer);
2341 }
2342
2343 if (Data.Buffer)
2344 {
2345 RtlFreeHeap(RtlGetProcessHeap(), 0, Data.Buffer);
2346 }
2347
2348 return ErrorCode;
2349 }
2350
2351
2352 /************************************************************************
2353 * RegSetValueExW
2354 */
2355 LONG
2356 STDCALL
2357 RegSetValueExW(
2358 HKEY hKey,
2359 LPCWSTR lpValueName,
2360 DWORD Reserved,
2361 DWORD dwType,
2362 CONST BYTE *lpData,
2363 DWORD cbData
2364 )
2365 {
2366 UNICODE_STRING ValueName;
2367 PUNICODE_STRING pValueName;
2368 HANDLE KeyHandle;
2369 NTSTATUS Status;
2370 LONG ErrorCode;
2371
2372 Status = MapDefaultKey(&KeyHandle, hKey);
2373 if (!NT_SUCCESS(Status))
2374 {
2375 ErrorCode = RtlNtStatusToDosError(Status);
2376 SetLastError(ErrorCode);
2377 return ErrorCode;
2378 }
2379
2380 if (lpValueName)
2381 {
2382 RtlInitUnicodeString(&ValueName, lpValueName);
2383 pValueName = &ValueName;
2384 }
2385 else
2386 {
2387 pValueName = NULL;
2388 }
2389
2390 Status = NtSetValueKey(
2391 KeyHandle,
2392 pValueName,
2393 0,
2394 dwType,
2395 (PVOID)lpData,
2396 (ULONG)cbData);
2397 if (!NT_SUCCESS(Status))
2398 {
2399 LONG ErrorCode = RtlNtStatusToDosError(Status);
2400 SetLastError (ErrorCode);
2401 return ErrorCode;
2402 }
2403
2404 return ERROR_SUCCESS;
2405 }
2406
2407
2408 /************************************************************************
2409 * RegSetValueW
2410 */
2411 LONG
2412 STDCALL
2413 RegSetValueW(
2414 HKEY hKey,
2415 LPCWSTR lpSubKey,
2416 DWORD dwType,
2417 LPCWSTR lpData,
2418 DWORD cbData
2419 )
2420 {
2421 NTSTATUS errCode;
2422 UNICODE_STRING SubKeyString;
2423 OBJECT_ATTRIBUTES ObjectAttributes;
2424 HANDLE KeyHandle;
2425 HANDLE RealKey;
2426 LONG ErrorCode;
2427 BOOL CloseRealKey;
2428
2429 errCode = MapDefaultKey(&KeyHandle, hKey);
2430 if (!NT_SUCCESS(errCode))
2431 {
2432 ErrorCode = RtlNtStatusToDosError(errCode);
2433 SetLastError (ErrorCode);
2434 return ErrorCode;
2435 }
2436
2437 if ((lpSubKey) && (wcslen(lpSubKey) != 0))
2438 {
2439
2440 RtlInitUnicodeString(&SubKeyString,
2441 (LPWSTR)lpSubKey);
2442
2443 InitializeObjectAttributes(&ObjectAttributes,
2444 &SubKeyString,
2445 OBJ_CASE_INSENSITIVE,
2446 KeyHandle,
2447 NULL);
2448
2449 errCode = NtOpenKey(
2450 &RealKey,
2451 KEY_ALL_ACCESS,
2452 & ObjectAttributes
2453 );
2454 if ( !NT_SUCCESS(errCode) )
2455 {
2456 ErrorCode = RtlNtStatusToDosError(errCode);
2457 SetLastError(ErrorCode);
2458 return ErrorCode;
2459 }
2460 CloseRealKey = TRUE;
2461 }
2462 else
2463 {
2464 RealKey = hKey;
2465 CloseRealKey = FALSE;
2466 }
2467
2468 ErrorCode = RegSetValueExW(
2469 RealKey,
2470 NULL,
2471 0,
2472 dwType,
2473 (LPBYTE)lpData,
2474 cbData);
2475
2476 if (CloseRealKey)
2477 {
2478 NtClose(RealKey);
2479 }
2480
2481 return ErrorCode;
2482 }
2483
2484
2485 /************************************************************************
2486 * RegUnLoadKeyA
2487 */
2488 LONG
2489 STDCALL
2490 RegUnLoadKeyA(
2491 HKEY hKey,
2492 LPCSTR lpSubKey
2493 )
2494 {
2495 UNIMPLEMENTED;
2496 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2497 return ERROR_CALL_NOT_IMPLEMENTED;
2498 }
2499
2500
2501 /************************************************************************
2502 * RegUnLoadKeyW
2503 */
2504 LONG
2505 STDCALL
2506 RegUnLoadKeyW(
2507 HKEY hKey,
2508 LPCWSTR lpSubKey
2509 )
2510 {
2511 UNIMPLEMENTED;
2512 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2513 return ERROR_CALL_NOT_IMPLEMENTED;
2514 }
2515
2516 /* EOF */