Zero memory for value info in RegQueryValueExW, otherwise we will return invalid...
[reactos.git] / reactos / lib / advapi32 / reg / reg.c
1 /* $Id: reg.c,v 1.36 2003/12/23 22:00:54 navaraf 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 HEAP_ZERO_MEMORY,
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 }
2146 else if (!NT_SUCCESS(Status))
2147 {
2148 ErrorCode = RtlNtStatusToDosError (Status);
2149 SetLastError (ErrorCode);
2150 }
2151 else
2152 {
2153 if (lpType != NULL)
2154 {
2155 *lpType = ValueInfo->Type;
2156 }
2157 RtlMoveMemory (lpData,
2158 ValueInfo->Data,
2159 ValueInfo->DataLength);
2160 if ((ValueInfo->Type == REG_SZ) ||
2161 (ValueInfo->Type == REG_MULTI_SZ) ||
2162 (ValueInfo->Type == REG_EXPAND_SZ))
2163 {
2164 ((PWSTR)lpData)[ValueInfo->DataLength / sizeof(WCHAR)] = 0;
2165 }
2166 }
2167 DPRINT("Type %d Size %d\n", ValueInfo->Type, ValueInfo->DataLength);
2168
2169 if (NULL != lpcbData)
2170 {
2171 *lpcbData = (DWORD)ValueInfo->DataLength;
2172 }
2173 RtlFreeHeap (ProcessHeap,
2174 0,
2175 ValueInfo);
2176
2177 return ErrorCode;
2178 }
2179
2180
2181 /************************************************************************
2182 * RegQueryValueExA
2183 *
2184 * @implemented
2185 */
2186 LONG
2187 STDCALL
2188 RegQueryValueExA(
2189 HKEY hKey,
2190 LPCSTR lpValueName,
2191 LPDWORD lpReserved,
2192 LPDWORD lpType,
2193 LPBYTE lpData,
2194 LPDWORD lpcbData)
2195 {
2196 UNICODE_STRING ValueName;
2197 UNICODE_STRING ValueData;
2198 ANSI_STRING AnsiString;
2199 LONG ErrorCode;
2200 DWORD Type;
2201
2202 if ((lpData) && (!lpcbData))
2203 {
2204 SetLastError(ERROR_INVALID_PARAMETER);
2205 return ERROR_INVALID_PARAMETER;
2206 }
2207
2208 if (lpData)
2209 {
2210 ValueData.Length = ValueData.MaximumLength = *lpcbData * sizeof(WCHAR);
2211 ValueData.Buffer = RtlAllocateHeap(
2212 ProcessHeap,
2213 0,
2214 ValueData.Length);
2215 if (!ValueData.Buffer)
2216 {
2217 SetLastError(ERROR_OUTOFMEMORY);
2218 return ERROR_OUTOFMEMORY;
2219 }
2220 }
2221 else
2222 {
2223 ValueData.Buffer = NULL;
2224 }
2225
2226 RtlCreateUnicodeStringFromAsciiz(&ValueName, (LPSTR)lpValueName);
2227
2228 ErrorCode = RegQueryValueExW(
2229 hKey,
2230 ValueName.Buffer,
2231 lpReserved,
2232 &Type,
2233 (LPBYTE)ValueData.Buffer,
2234 (LPDWORD)&ValueData.Length);
2235 if (lpType) *lpType = Type;
2236
2237 if ((ErrorCode == ERROR_SUCCESS) && (ValueData.Buffer != NULL))
2238 {
2239 if ((Type == REG_SZ) || (Type == REG_MULTI_SZ) || (Type == REG_EXPAND_SZ))
2240 {
2241 RtlInitAnsiString(&AnsiString, NULL);
2242 AnsiString.Buffer = lpData;
2243 AnsiString.MaximumLength = *lpcbData;
2244 RtlUnicodeStringToAnsiString(&AnsiString, &ValueData, FALSE);
2245 *lpcbData = ValueData.Length / sizeof(WCHAR);
2246 } else {
2247 RtlMoveMemory(lpData, ValueData.Buffer, *lpcbData);
2248 *lpcbData = ValueData.Length;
2249 }
2250 }
2251
2252 if (ValueData.Buffer)
2253 {
2254 RtlFreeHeap(ProcessHeap, 0, ValueData.Buffer);
2255 }
2256
2257 return ErrorCode;
2258 }
2259
2260
2261 /************************************************************************
2262 * RegQueryValueA
2263 *
2264 * @implemented
2265 */
2266 LONG STDCALL
2267 RegQueryValueA (HKEY hKey,
2268 LPCSTR lpSubKey,
2269 LPSTR lpValue,
2270 PLONG lpcbValue)
2271 {
2272 WCHAR SubKeyNameBuffer[MAX_PATH+1];
2273 UNICODE_STRING SubKeyName;
2274 UNICODE_STRING Value;
2275 ANSI_STRING AnsiString;
2276 LONG ValueSize;
2277 LONG ErrorCode;
2278
2279 if (lpValue != NULL &&
2280 lpcbValue == NULL)
2281 {
2282 SetLastError(ERROR_INVALID_PARAMETER);
2283 return ERROR_INVALID_PARAMETER;
2284 }
2285
2286 RtlInitUnicodeString (&SubKeyName,
2287 NULL);
2288 RtlInitUnicodeString (&Value,
2289 NULL);
2290 if (lpSubKey != NULL &&
2291 strlen(lpSubKey) != 0)
2292 {
2293 RtlInitAnsiString (&AnsiString,
2294 (LPSTR)lpSubKey);
2295 SubKeyName.Buffer = &SubKeyNameBuffer[0];
2296 SubKeyName.MaximumLength = sizeof(SubKeyNameBuffer);
2297 RtlAnsiStringToUnicodeString (&SubKeyName,
2298 &AnsiString,
2299 FALSE);
2300 }
2301
2302 if (lpValue != NULL)
2303 {
2304 ValueSize = *lpcbValue * sizeof(WCHAR);
2305 Value.MaximumLength = ValueSize;
2306 Value.Buffer = RtlAllocateHeap (ProcessHeap,
2307 0,
2308 ValueSize);
2309 if (Value.Buffer == NULL)
2310 {
2311 SetLastError(ERROR_OUTOFMEMORY);
2312 return ERROR_OUTOFMEMORY;
2313 }
2314 }
2315 else
2316 {
2317 ValueSize = 0;
2318 }
2319
2320 ErrorCode = RegQueryValueW (hKey,
2321 (LPCWSTR)SubKeyName.Buffer,
2322 Value.Buffer,
2323 &ValueSize);
2324 if (ErrorCode == ERROR_SUCCESS)
2325 {
2326 Value.Length = ValueSize;
2327 RtlInitAnsiString (&AnsiString,
2328 NULL);
2329 AnsiString.Buffer = lpValue;
2330 AnsiString.MaximumLength = *lpcbValue;
2331 RtlUnicodeStringToAnsiString (&AnsiString,
2332 &Value,
2333 FALSE);
2334 }
2335
2336 *lpcbValue = ValueSize;
2337 if (Value.Buffer != NULL)
2338 {
2339 RtlFreeHeap (ProcessHeap,
2340 0,
2341 Value.Buffer);
2342 }
2343
2344 return ErrorCode;
2345 }
2346
2347
2348 /************************************************************************
2349 * RegQueryValueW
2350 *
2351 * @implemented
2352 */
2353 LONG STDCALL
2354 RegQueryValueW (HKEY hKey,
2355 LPCWSTR lpSubKey,
2356 LPWSTR lpValue,
2357 PLONG lpcbValue)
2358 {
2359 OBJECT_ATTRIBUTES ObjectAttributes;
2360 UNICODE_STRING SubKeyString;
2361 HKEY KeyHandle;
2362 HANDLE RealKey;
2363 LONG ErrorCode;
2364 BOOL CloseRealKey;
2365 NTSTATUS Status;
2366
2367 Status = MapDefaultKey (&KeyHandle,
2368 hKey);
2369 if (!NT_SUCCESS(Status))
2370 {
2371 ErrorCode = RtlNtStatusToDosError (Status);
2372 SetLastError (ErrorCode);
2373 return ErrorCode;
2374 }
2375
2376 if (lpSubKey != NULL &&
2377 wcslen(lpSubKey) != 0)
2378 {
2379 RtlInitUnicodeString (&SubKeyString,
2380 (LPWSTR)lpSubKey);
2381 InitializeObjectAttributes (&ObjectAttributes,
2382 &SubKeyString,
2383 OBJ_CASE_INSENSITIVE,
2384 KeyHandle,
2385 NULL);
2386 Status = NtOpenKey (&RealKey,
2387 KEY_ALL_ACCESS,
2388 &ObjectAttributes);
2389 if (!NT_SUCCESS(Status))
2390 {
2391 ErrorCode = RtlNtStatusToDosError (Status);
2392 SetLastError (ErrorCode);
2393 return ErrorCode;
2394 }
2395 CloseRealKey = TRUE;
2396 }
2397 else
2398 {
2399 RealKey = hKey;
2400 CloseRealKey = FALSE;
2401 }
2402
2403 ErrorCode = RegQueryValueExW (RealKey,
2404 NULL,
2405 NULL,
2406 NULL,
2407 (LPBYTE)lpValue,
2408 (LPDWORD)lpcbValue);
2409 if (CloseRealKey)
2410 {
2411 NtClose (RealKey);
2412 }
2413
2414 return ErrorCode;
2415 }
2416
2417
2418 /************************************************************************
2419 * RegReplaceKeyA
2420 *
2421 * @implemented
2422 */
2423 LONG STDCALL
2424 RegReplaceKeyA (HKEY hKey,
2425 LPCSTR lpSubKey,
2426 LPCSTR lpNewFile,
2427 LPCSTR lpOldFile)
2428 {
2429 UNICODE_STRING lpSubKeyW;
2430 UNICODE_STRING lpNewFileW;
2431 UNICODE_STRING lpOldFileW;
2432 LONG ret;
2433
2434 RtlCreateUnicodeStringFromAsciiz( &lpSubKeyW, (PCSZ)lpSubKey );
2435 RtlCreateUnicodeStringFromAsciiz( &lpOldFileW, (PCSZ)lpOldFile );
2436 RtlCreateUnicodeStringFromAsciiz( &lpNewFileW, (PCSZ)lpNewFile );
2437 ret = RegReplaceKeyW( hKey, lpSubKeyW.Buffer, lpNewFileW.Buffer, lpOldFileW.Buffer );
2438 RtlFreeUnicodeString( &lpOldFileW );
2439 RtlFreeUnicodeString( &lpNewFileW );
2440 RtlFreeUnicodeString( &lpSubKeyW );
2441 return ret;
2442 }
2443
2444
2445 /************************************************************************
2446 * RegReplaceKeyW
2447 *
2448 * @unimplemented
2449 */
2450 LONG STDCALL
2451 RegReplaceKeyW (HKEY hKey,
2452 LPCWSTR lpSubKey,
2453 LPCWSTR lpNewFile,
2454 LPCWSTR lpOldFile)
2455 {
2456 UNIMPLEMENTED;
2457 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2458 return ERROR_CALL_NOT_IMPLEMENTED;
2459 }
2460
2461
2462 /************************************************************************
2463 * RegRestoreKeyA
2464 *
2465 * @implemented
2466 */
2467 LONG STDCALL
2468 RegRestoreKeyA (HKEY hKey,
2469 LPCSTR lpFile,
2470 DWORD dwFlags)
2471 {
2472 UNICODE_STRING lpFileW;
2473 LONG ret;
2474
2475 RtlCreateUnicodeStringFromAsciiz( &lpFileW, (PCSZ)lpFile );
2476 ret = RegRestoreKeyW( hKey, lpFileW.Buffer, dwFlags );
2477 RtlFreeUnicodeString( &lpFileW );
2478 return ret;
2479 }
2480
2481
2482 /************************************************************************
2483 * RegRestoreKeyW
2484 *
2485 * @unimplemented
2486 */
2487 LONG STDCALL
2488 RegRestoreKeyW (HKEY hKey,
2489 LPCWSTR lpFile,
2490 DWORD dwFlags)
2491 {
2492 UNIMPLEMENTED;
2493 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2494 return ERROR_CALL_NOT_IMPLEMENTED;
2495 }
2496
2497
2498 /************************************************************************
2499 * RegSaveKeyA
2500 *
2501 * @implemented
2502 */
2503 LONG STDCALL
2504 RegSaveKeyA(HKEY hKey,
2505 LPCSTR lpFile,
2506 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
2507 {
2508 UNICODE_STRING FileName;
2509 LONG ErrorCode;
2510
2511 RtlCreateUnicodeStringFromAsciiz (&FileName,
2512 (LPSTR)lpFile);
2513 ErrorCode = RegSaveKeyW (hKey,
2514 FileName.Buffer,
2515 lpSecurityAttributes);
2516 RtlFreeUnicodeString (&FileName);
2517
2518 return ErrorCode;
2519 }
2520
2521
2522 /************************************************************************
2523 * RegSaveKeyW
2524 *
2525 * @implemented
2526 */
2527 LONG STDCALL
2528 RegSaveKeyW (HKEY hKey,
2529 LPCWSTR lpFile,
2530 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
2531 {
2532 PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
2533 OBJECT_ATTRIBUTES ObjectAttributes;
2534 UNICODE_STRING NtName;
2535 IO_STATUS_BLOCK IoStatusBlock;
2536 HANDLE FileHandle;
2537 HKEY KeyHandle;
2538 NTSTATUS Status;
2539 LONG ErrorCode;
2540
2541 Status = MapDefaultKey (&KeyHandle,
2542 hKey);
2543 if (!NT_SUCCESS(Status))
2544 {
2545 ErrorCode = RtlNtStatusToDosError (Status);
2546 SetLastError (ErrorCode);
2547 return ErrorCode;
2548 }
2549
2550 if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFile,
2551 &NtName,
2552 NULL,
2553 NULL))
2554 {
2555 SetLastError (ERROR_INVALID_PARAMETER);
2556 return ERROR_INVALID_PARAMETER;
2557 }
2558
2559 if (lpSecurityAttributes != NULL)
2560 {
2561 SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
2562 }
2563
2564 InitializeObjectAttributes (&ObjectAttributes,
2565 &NtName,
2566 OBJ_CASE_INSENSITIVE,
2567 NULL,
2568 SecurityDescriptor);
2569 Status = NtCreateFile (&FileHandle,
2570 GENERIC_WRITE | SYNCHRONIZE,
2571 &ObjectAttributes,
2572 &IoStatusBlock,
2573 NULL,
2574 FILE_ATTRIBUTE_NORMAL,
2575 FILE_SHARE_READ,
2576 FILE_CREATE,
2577 FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
2578 NULL,
2579 0);
2580 RtlFreeUnicodeString (&NtName);
2581 if (!NT_SUCCESS(Status))
2582 {
2583 ErrorCode = RtlNtStatusToDosError (Status);
2584 SetLastError (ErrorCode);
2585 return ErrorCode;
2586 }
2587
2588 Status = NtSaveKey (KeyHandle,
2589 FileHandle);
2590 NtClose (FileHandle);
2591 if (!NT_SUCCESS(Status))
2592 {
2593 ErrorCode = RtlNtStatusToDosError (Status);
2594 SetLastError (ErrorCode);
2595 return ErrorCode;
2596 }
2597
2598 return ERROR_SUCCESS;
2599 }
2600
2601
2602 /************************************************************************
2603 * RegSetKeySecurity
2604 *
2605 * @implemented
2606 */
2607 LONG STDCALL
2608 RegSetKeySecurity (HKEY hKey,
2609 SECURITY_INFORMATION SecurityInformation,
2610 PSECURITY_DESCRIPTOR pSecurityDescriptor)
2611 {
2612 HKEY KeyHandle;
2613 NTSTATUS Status;
2614 LONG ErrorCode;
2615
2616 if (hKey == HKEY_PERFORMANCE_DATA)
2617 return ERROR_INVALID_HANDLE;
2618
2619 Status = MapDefaultKey (&KeyHandle,
2620 hKey);
2621 if (!NT_SUCCESS(Status))
2622 {
2623 ErrorCode = RtlNtStatusToDosError (Status);
2624 SetLastError (ErrorCode);
2625 return ErrorCode;
2626 }
2627
2628 Status = NtSetSecurityObject (KeyHandle,
2629 SecurityInformation,
2630 pSecurityDescriptor);
2631 if (!NT_SUCCESS(Status))
2632 {
2633 ErrorCode = RtlNtStatusToDosError (Status);
2634 SetLastError (ErrorCode);
2635 return ErrorCode;
2636 }
2637
2638 return ERROR_SUCCESS;
2639 }
2640
2641
2642 /************************************************************************
2643 * RegSetValueExA
2644 *
2645 * @implemented
2646 */
2647 LONG STDCALL
2648 RegSetValueExA (HKEY hKey,
2649 LPCSTR lpValueName,
2650 DWORD Reserved,
2651 DWORD dwType,
2652 CONST BYTE* lpData,
2653 DWORD cbData)
2654 {
2655 UNICODE_STRING ValueName;
2656 LPWSTR pValueName;
2657 ANSI_STRING AnsiString;
2658 UNICODE_STRING Data;
2659 LONG ErrorCode;
2660 LPBYTE pData;
2661 DWORD DataSize;
2662
2663 if (lpData == NULL)
2664 {
2665 SetLastError (ERROR_INVALID_PARAMETER);
2666 return ERROR_INVALID_PARAMETER;
2667 }
2668
2669 if (lpValueName != NULL &&
2670 strlen(lpValueName) != 0)
2671 {
2672 RtlCreateUnicodeStringFromAsciiz (&ValueName,
2673 (LPSTR)lpValueName);
2674 pValueName = (LPWSTR)ValueName.Buffer;
2675 }
2676 else
2677 {
2678 pValueName = NULL;
2679 }
2680
2681 if ((dwType == REG_SZ) ||
2682 (dwType == REG_MULTI_SZ) ||
2683 (dwType == REG_EXPAND_SZ))
2684 {
2685 RtlInitAnsiString (&AnsiString,
2686 NULL);
2687 AnsiString.Buffer = (LPSTR)lpData;
2688 AnsiString.Length = cbData;
2689 AnsiString.MaximumLength = cbData;
2690 RtlAnsiStringToUnicodeString (&Data,
2691 &AnsiString,
2692 TRUE);
2693 pData = (LPBYTE)Data.Buffer;
2694 DataSize = cbData * sizeof(WCHAR);
2695 }
2696 else
2697 {
2698 RtlInitUnicodeString (&Data,
2699 NULL);
2700 pData = (LPBYTE)lpData;
2701 DataSize = cbData;
2702 }
2703
2704 ErrorCode = RegSetValueExW (hKey,
2705 pValueName,
2706 Reserved,
2707 dwType,
2708 pData,
2709 DataSize);
2710 if (pValueName != NULL)
2711 {
2712 RtlFreeHeap (ProcessHeap,
2713 0,
2714 ValueName.Buffer);
2715 }
2716
2717 if (Data.Buffer != NULL)
2718 {
2719 RtlFreeHeap (ProcessHeap,
2720 0,
2721 Data.Buffer);
2722 }
2723
2724 return ErrorCode;
2725 }
2726
2727
2728 /************************************************************************
2729 * RegSetValueExW
2730 *
2731 * @implemented
2732 */
2733 LONG STDCALL
2734 RegSetValueExW (HKEY hKey,
2735 LPCWSTR lpValueName,
2736 DWORD Reserved,
2737 DWORD dwType,
2738 CONST BYTE* lpData,
2739 DWORD cbData)
2740 {
2741 UNICODE_STRING ValueName;
2742 PUNICODE_STRING pValueName;
2743 HKEY KeyHandle;
2744 NTSTATUS Status;
2745 LONG ErrorCode;
2746
2747 Status = MapDefaultKey (&KeyHandle,
2748 hKey);
2749 if (!NT_SUCCESS(Status))
2750 {
2751 ErrorCode = RtlNtStatusToDosError (Status);
2752 SetLastError (ErrorCode);
2753 return ErrorCode;
2754 }
2755
2756 if (lpValueName != NULL)
2757 {
2758 RtlInitUnicodeString (&ValueName,
2759 lpValueName);
2760 }
2761 else
2762 {
2763 RtlInitUnicodeString (&ValueName, L"");
2764 }
2765 pValueName = &ValueName;
2766
2767 Status = NtSetValueKey (KeyHandle,
2768 pValueName,
2769 0,
2770 dwType,
2771 (PVOID)lpData,
2772 (ULONG)cbData);
2773 if (!NT_SUCCESS(Status))
2774 {
2775 ErrorCode = RtlNtStatusToDosError (Status);
2776 SetLastError (ErrorCode);
2777 return ErrorCode;
2778 }
2779
2780 return ERROR_SUCCESS;
2781 }
2782
2783
2784 /************************************************************************
2785 * RegSetValueA
2786 *
2787 * @implemented
2788 */
2789 LONG STDCALL
2790 RegSetValueA (HKEY hKey,
2791 LPCSTR lpSubKey,
2792 DWORD dwType,
2793 LPCSTR lpData,
2794 DWORD cbData)
2795 {
2796 WCHAR SubKeyNameBuffer[MAX_PATH+1];
2797 UNICODE_STRING SubKeyName;
2798 UNICODE_STRING Data;
2799 ANSI_STRING AnsiString;
2800 LONG DataSize;
2801 LONG ErrorCode;
2802
2803 if (lpData == NULL)
2804 {
2805 SetLastError (ERROR_INVALID_PARAMETER);
2806 return ERROR_INVALID_PARAMETER;
2807 }
2808
2809 RtlInitUnicodeString (&SubKeyName, NULL);
2810 RtlInitUnicodeString (&Data, NULL);
2811 if (lpSubKey != NULL && (strlen(lpSubKey) != 0))
2812 {
2813 RtlInitAnsiString (&AnsiString, (LPSTR)lpSubKey);
2814 SubKeyName.Buffer = &SubKeyNameBuffer[0];
2815 SubKeyName.MaximumLength = sizeof(SubKeyNameBuffer);
2816 RtlAnsiStringToUnicodeString (&SubKeyName, &AnsiString, FALSE);
2817 }
2818
2819 DataSize = cbData * sizeof(WCHAR);
2820 Data.MaximumLength = DataSize;
2821 Data.Buffer = RtlAllocateHeap (ProcessHeap,
2822 0,
2823 DataSize);
2824 if (Data.Buffer == NULL)
2825 {
2826 SetLastError (ERROR_OUTOFMEMORY);
2827 return ERROR_OUTOFMEMORY;
2828 }
2829
2830 ErrorCode = RegSetValueW (hKey,
2831 (LPCWSTR)SubKeyName.Buffer,
2832 dwType,
2833 Data.Buffer,
2834 DataSize);
2835 RtlFreeHeap (ProcessHeap,
2836 0,
2837 Data.Buffer);
2838
2839 return ErrorCode;
2840 }
2841
2842
2843 /************************************************************************
2844 * RegSetValueW
2845 *
2846 * @implemented
2847 */
2848 LONG STDCALL
2849 RegSetValueW (HKEY hKey,
2850 LPCWSTR lpSubKey,
2851 DWORD dwType,
2852 LPCWSTR lpData,
2853 DWORD cbData)
2854 {
2855 OBJECT_ATTRIBUTES ObjectAttributes;
2856 UNICODE_STRING SubKeyString;
2857 HKEY KeyHandle;
2858 HANDLE RealKey;
2859 LONG ErrorCode;
2860 BOOL CloseRealKey;
2861 NTSTATUS Status;
2862
2863 Status = MapDefaultKey (&KeyHandle,
2864 hKey);
2865 if (!NT_SUCCESS(Status))
2866 {
2867 ErrorCode = RtlNtStatusToDosError (Status);
2868 SetLastError (ErrorCode);
2869 return ErrorCode;
2870 }
2871
2872 if ((lpSubKey) && (wcslen(lpSubKey) != 0))
2873 {
2874 RtlInitUnicodeString (&SubKeyString,
2875 (LPWSTR)lpSubKey);
2876 InitializeObjectAttributes (&ObjectAttributes,
2877 &SubKeyString,
2878 OBJ_CASE_INSENSITIVE,
2879 KeyHandle,
2880 NULL);
2881 Status = NtOpenKey (&RealKey,
2882 KEY_ALL_ACCESS,
2883 &ObjectAttributes);
2884 if (!NT_SUCCESS(Status))
2885 {
2886 ErrorCode = RtlNtStatusToDosError (Status);
2887 SetLastError (ErrorCode);
2888 return ErrorCode;
2889 }
2890 CloseRealKey = TRUE;
2891 }
2892 else
2893 {
2894 RealKey = hKey;
2895 CloseRealKey = FALSE;
2896 }
2897
2898 ErrorCode = RegSetValueExW (RealKey,
2899 NULL,
2900 0,
2901 dwType,
2902 (LPBYTE)lpData,
2903 cbData);
2904 if (CloseRealKey == TRUE)
2905 {
2906 NtClose (RealKey);
2907 }
2908
2909 return ErrorCode;
2910 }
2911
2912
2913 /************************************************************************
2914 * RegUnLoadKeyA
2915 *
2916 * @implemented
2917 */
2918 LONG STDCALL
2919 RegUnLoadKeyA (HKEY hKey,
2920 LPCSTR lpSubKey)
2921 {
2922 UNICODE_STRING KeyName;
2923 DWORD ErrorCode;
2924
2925 RtlCreateUnicodeStringFromAsciiz (&KeyName,
2926 (LPSTR)lpSubKey);
2927
2928 ErrorCode = RegUnLoadKeyW (hKey,
2929 KeyName.Buffer);
2930
2931 RtlFreeUnicodeString (&KeyName);
2932
2933 return ErrorCode;
2934 }
2935
2936
2937 /************************************************************************
2938 * RegUnLoadKeyW
2939 *
2940 * @implemented
2941 */
2942 LONG STDCALL
2943 RegUnLoadKeyW (HKEY hKey,
2944 LPCWSTR lpSubKey)
2945 {
2946 OBJECT_ATTRIBUTES ObjectAttributes;
2947 UNICODE_STRING KeyName;
2948 HANDLE KeyHandle;
2949 DWORD ErrorCode;
2950 NTSTATUS Status;
2951
2952 if (hKey == HKEY_PERFORMANCE_DATA)
2953 return ERROR_INVALID_HANDLE;
2954
2955 Status = MapDefaultKey (&KeyHandle, hKey);
2956 if (!NT_SUCCESS(Status))
2957 {
2958 ErrorCode = RtlNtStatusToDosError (Status);
2959 SetLastError (ErrorCode);
2960 return ErrorCode;
2961 }
2962
2963 RtlInitUnicodeString (&KeyName,
2964 (LPWSTR)lpSubKey);
2965
2966 InitializeObjectAttributes (&ObjectAttributes,
2967 &KeyName,
2968 OBJ_CASE_INSENSITIVE,
2969 KeyHandle,
2970 NULL);
2971
2972 Status = NtUnloadKey (&ObjectAttributes);
2973
2974 if (!NT_SUCCESS(Status))
2975 {
2976 ErrorCode = RtlNtStatusToDosError (Status);
2977 SetLastError (ErrorCode);
2978 return ErrorCode;
2979 }
2980
2981 return ERROR_SUCCESS;
2982 }
2983
2984 /* EOF */