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