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