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