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