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