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