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