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