Fix for wide character streams.
[reactos.git] / reactos / lib / advapi32 / reg / reg.c
1 /* $Id: reg.c,v 1.21 2002/12/08 16:14:28 robd 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 #ifndef WIN32_REGDBG
13
14 #define NTOS_MODE_USER
15 #include <ntos.h>
16 #include <ddk/ntddk.h>
17 #include <ntdll/rtl.h>
18 #include <windows.h>
19 #include <wchar.h>
20
21 #define NDEBUG
22 #include <debug.h>
23
24 #else /*WIN32_REGDBG*/
25 #include "cm_win32.h"
26 #ifdef __GNUC__
27 #define WINAPI __stdcall
28 #define WINAPIV __cdecl
29 #define APIENTRY __stdcall
30 #define DECLSPEC_IMPORT __declspec(dllimport)
31 #define DECLSPEC_EXPORT __declspec(dllexport)
32 #define DECLARE_HANDLE(n) typedef HANDLE n
33 #define HKEY_PERFORMANCE_DATA ((HKEY)0x80000004)
34 #define ERROR_SUCCESS 0L
35 #define ERROR_INVALID_HANDLE 6L
36 #define ERROR_OUTOFMEMORY 14L
37 #define ERROR_INVALID_PARAMETER 87L
38 #define ERROR_CALL_NOT_IMPLEMENTED 120L
39 #define ERROR_MORE_DATA 234L
40
41 void WINAPI SetLastError(DWORD);
42 BOOLEAN STDCALL RtlDosPathNameToNtPathName_U(PWSTR dosname, PUNICODE_STRING ntname, PWSTR* shortname, PCURDIR nah);
43 NTSTATUS STDCALL RtlInitializeCriticalSection(LPCRITICAL_SECTION lpcs);
44 NTSTATUS STDCALL RtlDeleteCriticalSection(LPCRITICAL_SECTION lpcs);
45 NTSTATUS STDCALL RtlLeaveCriticalSection(LPCRITICAL_SECTION lpcs);
46 NTSTATUS STDCALL RtlEnterCriticalSection(LPCRITICAL_SECTION lpcs);
47
48 DECLARE_HANDLE(HKEY);
49 typedef HKEY *PHKEY;
50 typedef ACCESS_MASK REGSAM;
51
52 typedef struct value_entA {
53 LPSTR ve_valuename;
54 DWORD ve_valuelen;
55 DWORD ve_valueptr;
56 DWORD ve_type;
57 } VALENTA,*PVALENTA;
58 typedef struct value_entW {
59 LPWSTR ve_valuename;
60 DWORD ve_valuelen;
61 DWORD ve_valueptr;
62 DWORD ve_type;
63 } VALENTW,*PVALENTW;
64 #endif
65 #undef STDCALL
66 #define STDCALL _stdcall
67 #undef RegSetValueEx
68 #undef RegCreateKeyEx
69 #undef RegQueryInfoKey
70 #undef RegDeleteKey
71 #undef RegOpenKey
72 #undef RegOpenKeyEx
73 #undef RegEnumKeyEx
74 #undef RegEnumValue
75 #endif /*WIN32_REGDBG*/
76
77 #define CHECK_STATUS \
78 { \
79 if (!NT_SUCCESS(Status)) \
80 { \
81 LONG _ErrorCode = RtlNtStatusToDosError(Status); \
82 SetLastError(_ErrorCode); \
83 return _ErrorCode; \
84 } \
85 }
86
87 /* GLOBALS *******************************************************************/
88
89 #define MAX_DEFAULT_HANDLES 6
90
91 static CRITICAL_SECTION HandleTableCS;
92 static HANDLE DefaultHandleTable[MAX_DEFAULT_HANDLES];
93
94
95 /* PROTOTYPES ****************************************************************/
96
97 static NTSTATUS MapDefaultKey (PHKEY ParentKey, HKEY Key);
98 static VOID CloseDefaultKeys(VOID);
99
100 static NTSTATUS OpenClassesRootKey(PHANDLE KeyHandle);
101 static NTSTATUS OpenLocalMachineKey (PHANDLE KeyHandle);
102 static NTSTATUS OpenUsersKey (PHANDLE KeyHandle);
103 static NTSTATUS OpenCurrentConfigKey(PHANDLE KeyHandle);
104
105
106 /* FUNCTIONS *****************************************************************/
107
108 inline RegiTerminateWideString(LPWSTR String, DWORD Length)
109 {
110 LPWSTR AfterString = String + Length;
111 *AfterString = 0;
112 }
113
114 /************************************************************************
115 * RegInitDefaultHandles
116 */
117
118 BOOL
119 RegInitialize(VOID)
120 {
121 DPRINT("RegInitialize()\n");
122
123 RtlZeroMemory (DefaultHandleTable,
124 MAX_DEFAULT_HANDLES * sizeof(HANDLE));
125 RtlInitializeCriticalSection(&HandleTableCS);
126 return TRUE;
127 }
128
129
130 /************************************************************************
131 * RegInit
132 */
133 BOOL
134 RegCleanup(VOID)
135 {
136 DPRINT("RegCleanup()\n");
137
138 CloseDefaultKeys();
139 RtlDeleteCriticalSection(&HandleTableCS);
140 return TRUE;
141 }
142
143
144 static NTSTATUS
145 MapDefaultKey(PHKEY RealKey,
146 HKEY Key)
147 {
148 PHANDLE Handle;
149 ULONG Index;
150 NTSTATUS Status = STATUS_SUCCESS;
151
152 DPRINT("MapDefaultKey (Key %x)\n", Key);
153
154 if (((ULONG)Key & 0xF0000000) != 0x80000000) {
155 *RealKey = Key;
156 return STATUS_SUCCESS;
157 }
158 /* Handle special cases here */
159 Index = (ULONG)Key & 0x0FFFFFFF;
160 if (Index >= MAX_DEFAULT_HANDLES)
161 return STATUS_INVALID_PARAMETER;
162 RtlEnterCriticalSection(&HandleTableCS);
163 Handle = &DefaultHandleTable[Index];
164 if (*Handle == NULL) {
165 /* create/open the default handle */
166 switch (Index) {
167 case 0: /* HKEY_CLASSES_ROOT */
168 Status = OpenClassesRootKey(Handle);
169 break;
170 case 1: /* HKEY_CURRENT_USER */
171 Status = RtlOpenCurrentUser(KEY_ALL_ACCESS, Handle);
172 break;
173 case 2: /* HKEY_LOCAL_MACHINE */
174 Status = OpenLocalMachineKey(Handle);
175 break;
176 case 3: /* HKEY_USERS */
177 Status = OpenUsersKey(Handle);
178 break;
179 #if 0
180 case 4: /* HKEY_PERFORMANCE_DATA */
181 Status = OpenPerformanceDataKey(Handle);
182 break;
183 #endif
184 case 5: /* HKEY_CURRENT_CONFIG */
185 Status = OpenCurrentConfigKey(Handle);
186 break;
187 default:
188 DPRINT("MapDefaultHandle() no handle creator\n");
189 Status = STATUS_INVALID_PARAMETER;
190 }
191 }
192 RtlLeaveCriticalSection(&HandleTableCS);
193 if (NT_SUCCESS(Status)) {
194 *RealKey = (HKEY)*Handle;
195 }
196 return Status;
197 }
198
199
200 static VOID
201 CloseDefaultKeys(VOID)
202 {
203 ULONG i;
204
205 RtlEnterCriticalSection(&HandleTableCS);
206 for (i = 0; i < MAX_DEFAULT_HANDLES; i++) {
207 if (DefaultHandleTable[i] != NULL) {
208 NtClose (DefaultHandleTable[i]);
209 DefaultHandleTable[i] = NULL;
210 }
211 }
212 RtlLeaveCriticalSection(&HandleTableCS);
213 }
214
215
216 static NTSTATUS
217 OpenClassesRootKey(PHANDLE KeyHandle)
218 {
219 OBJECT_ATTRIBUTES Attributes;
220 UNICODE_STRING KeyName = UNICODE_STRING_INITIALIZER(L"\\Registry\\Machine\\Software\\CLASSES");
221
222 DPRINT("OpenClassesRootKey()\n");
223
224 InitializeObjectAttributes(&Attributes,
225 &KeyName,
226 OBJ_CASE_INSENSITIVE,
227 NULL,
228 NULL);
229 return(NtOpenKey(KeyHandle,
230 KEY_ALL_ACCESS,
231 &Attributes));
232 }
233
234
235 static NTSTATUS
236 OpenLocalMachineKey(PHANDLE KeyHandle)
237 {
238 OBJECT_ATTRIBUTES Attributes;
239 UNICODE_STRING KeyName = UNICODE_STRING_INITIALIZER(L"\\Registry\\Machine");
240
241 DPRINT("OpenLocalMachineKey()\n");
242
243 InitializeObjectAttributes(&Attributes,
244 &KeyName,
245 OBJ_CASE_INSENSITIVE,
246 NULL,
247 NULL);
248 return(NtOpenKey(KeyHandle,
249 KEY_ALL_ACCESS,
250 &Attributes));
251 }
252
253
254 static NTSTATUS
255 OpenUsersKey(PHANDLE KeyHandle)
256 {
257 OBJECT_ATTRIBUTES Attributes;
258 UNICODE_STRING KeyName = UNICODE_STRING_INITIALIZER(L"\\Registry\\User");
259
260 DPRINT("OpenUsersKey()\n");
261
262 InitializeObjectAttributes(&Attributes,
263 &KeyName,
264 OBJ_CASE_INSENSITIVE,
265 NULL,
266 NULL);
267 return(NtOpenKey(KeyHandle,
268 KEY_ALL_ACCESS,
269 &Attributes));
270 }
271
272
273 static NTSTATUS
274 OpenCurrentConfigKey(PHANDLE KeyHandle)
275 {
276 OBJECT_ATTRIBUTES Attributes;
277 UNICODE_STRING KeyName =
278 UNICODE_STRING_INITIALIZER(L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current");
279
280 DPRINT("OpenCurrentConfigKey()\n");
281
282 InitializeObjectAttributes(&Attributes,
283 &KeyName,
284 OBJ_CASE_INSENSITIVE,
285 NULL,
286 NULL);
287 return(NtOpenKey(KeyHandle,
288 KEY_ALL_ACCESS,
289 &Attributes));
290 }
291
292 /************************************************************************
293 * RegCloseKey
294 */
295 LONG STDCALL
296 RegCloseKey(HKEY hKey)
297 {
298 NTSTATUS Status;
299
300 /* don't close null handle or a pseudo handle */
301 if ((!hKey) || (((ULONG)hKey & 0xF0000000) == 0x80000000))
302 return ERROR_INVALID_HANDLE;
303 Status = NtClose (hKey);
304 if (!NT_SUCCESS(Status)) {
305 LONG ErrorCode = RtlNtStatusToDosError(Status);
306 SetLastError (ErrorCode);
307 return ErrorCode;
308 }
309 return ERROR_SUCCESS;
310 }
311
312
313 /************************************************************************
314 * RegConnectRegistryA
315 */
316 LONG STDCALL
317 RegConnectRegistryA(LPCSTR lpMachineName,
318 HKEY hKey,
319 PHKEY phkResult)
320 {
321 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
322 return ERROR_CALL_NOT_IMPLEMENTED;
323 }
324
325
326 /************************************************************************
327 * RegConnectRegistryW
328 */
329 LONG STDCALL
330 RegConnectRegistryW(LPCWSTR lpMachineName,
331 HKEY hKey,
332 PHKEY phkResult)
333 {
334 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
335 return ERROR_CALL_NOT_IMPLEMENTED;
336 }
337
338
339 /************************************************************************
340 * RegCreateKeyExA
341 */
342 LONG STDCALL
343 RegCreateKeyExA(HKEY hKey,
344 LPCSTR lpSubKey,
345 DWORD Reserved,
346 LPSTR lpClass,
347 DWORD dwOptions,
348 REGSAM samDesired,
349 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
350 PHKEY phkResult,
351 LPDWORD lpdwDisposition)
352 {
353 UNICODE_STRING SubKeyString;
354 UNICODE_STRING ClassString;
355 OBJECT_ATTRIBUTES Attributes;
356 NTSTATUS Status;
357 HKEY ParentKey;
358
359 DPRINT("RegCreateKeyExW() called\n");
360
361 /* get the real parent key */
362 Status = MapDefaultKey(&ParentKey, hKey);
363 if (!NT_SUCCESS(Status)) {
364 LONG ErrorCode = RtlNtStatusToDosError(Status);
365 SetLastError(ErrorCode);
366 return(ErrorCode);
367 }
368 DPRINT("ParentKey %x\n", (ULONG)ParentKey);
369
370 if (lpClass != NULL)
371 RtlCreateUnicodeStringFromAsciiz(&ClassString, lpClass);
372 RtlCreateUnicodeStringFromAsciiz(&SubKeyString, (LPSTR)lpSubKey);
373 InitializeObjectAttributes(&Attributes,
374 &SubKeyString,
375 OBJ_CASE_INSENSITIVE,
376 (HANDLE)ParentKey,
377 (PSECURITY_DESCRIPTOR)lpSecurityAttributes);
378 Status = NtCreateKey(phkResult,
379 samDesired,
380 &Attributes,
381 0,
382 (lpClass == NULL)? NULL : &ClassString,
383 dwOptions,
384 (PULONG)lpdwDisposition);
385 RtlFreeUnicodeString(&SubKeyString);
386 if (lpClass != NULL)
387 RtlFreeUnicodeString(&ClassString);
388 DPRINT("Status %x\n", Status);
389 if (!NT_SUCCESS(Status)) {
390 LONG ErrorCode = RtlNtStatusToDosError(Status);
391 SetLastError (ErrorCode);
392 return ErrorCode;
393 }
394 return(ERROR_SUCCESS);
395 }
396
397
398 /************************************************************************
399 * RegCreateKeyExW
400 */
401 LONG STDCALL
402 RegCreateKeyExW(HKEY hKey,
403 LPCWSTR lpSubKey,
404 DWORD Reserved,
405 LPWSTR lpClass,
406 DWORD dwOptions,
407 REGSAM samDesired,
408 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
409 PHKEY phkResult,
410 LPDWORD lpdwDisposition)
411 {
412 UNICODE_STRING SubKeyString;
413 UNICODE_STRING ClassString;
414 OBJECT_ATTRIBUTES Attributes;
415 NTSTATUS Status;
416 HKEY ParentKey;
417
418 DPRINT("RegCreateKeyExW() called\n");
419
420 /* get the real parent key */
421 Status = MapDefaultKey (&ParentKey, hKey);
422 if (!NT_SUCCESS(Status)) {
423 LONG ErrorCode = RtlNtStatusToDosError(Status);
424 SetLastError (ErrorCode);
425 return ErrorCode;
426 }
427 DPRINT("ParentKey %x\n", (ULONG)ParentKey);
428 RtlInitUnicodeString (&ClassString, lpClass);
429 RtlInitUnicodeString (&SubKeyString, lpSubKey);
430 InitializeObjectAttributes (&Attributes,
431 &SubKeyString,
432 OBJ_CASE_INSENSITIVE,
433 (HANDLE)ParentKey,
434 (PSECURITY_DESCRIPTOR)lpSecurityAttributes);
435 Status = NtCreateKey (phkResult,
436 samDesired,
437 &Attributes,
438 0,
439 (lpClass == NULL)? NULL : &ClassString,
440 dwOptions,
441 (PULONG)lpdwDisposition);
442 DPRINT("Status %x\n", Status);
443 if (!NT_SUCCESS(Status)) {
444 LONG ErrorCode = RtlNtStatusToDosError(Status);
445 SetLastError (ErrorCode);
446 return ErrorCode;
447 }
448 return ERROR_SUCCESS;
449 }
450
451
452 /************************************************************************
453 * RegCreateKeyA
454 */
455 LONG STDCALL
456 RegCreateKeyA(HKEY hKey,
457 LPCSTR lpSubKey,
458 PHKEY phkResult)
459 {
460 return(RegCreateKeyExA(hKey,
461 lpSubKey,
462 0,
463 NULL,
464 0,
465 KEY_ALL_ACCESS,
466 NULL,
467 phkResult,
468 NULL));
469 }
470
471
472 /************************************************************************
473 * RegCreateKeyW
474 */
475 LONG STDCALL
476 RegCreateKeyW(HKEY hKey,
477 LPCWSTR lpSubKey,
478 PHKEY phkResult)
479 {
480 return(RegCreateKeyExW(hKey,
481 lpSubKey,
482 0,
483 NULL,
484 0,
485 KEY_ALL_ACCESS,
486 NULL,
487 phkResult,
488 NULL));
489 }
490
491
492 /************************************************************************
493 * RegDeleteKeyA
494 */
495 LONG
496 STDCALL
497 RegDeleteKeyA(
498 HKEY hKey,
499 LPCSTR lpSubKey)
500 {
501 OBJECT_ATTRIBUTES ObjectAttributes;
502 UNICODE_STRING SubKeyStringW;
503 ANSI_STRING SubKeyStringA;
504 // HANDLE ParentKey;
505 HKEY ParentKey;
506 HANDLE TargetKey;
507 NTSTATUS Status;
508 LONG ErrorCode;
509
510 Status = MapDefaultKey(&ParentKey, hKey);
511 if (!NT_SUCCESS(Status)) {
512 ErrorCode = RtlNtStatusToDosError(Status);
513 SetLastError (ErrorCode);
514 return ErrorCode;
515 }
516 RtlInitAnsiString(&SubKeyStringA, (LPSTR)lpSubKey);
517 RtlAnsiStringToUnicodeString(&SubKeyStringW, &SubKeyStringA, TRUE);
518 InitializeObjectAttributes (&ObjectAttributes,
519 &SubKeyStringW,
520 OBJ_CASE_INSENSITIVE,
521 (HANDLE)ParentKey,
522 NULL);
523 Status = NtOpenKey(&TargetKey, DELETE, &ObjectAttributes);
524 RtlFreeUnicodeString(&SubKeyStringW);
525 if (!NT_SUCCESS(Status)) {
526 ErrorCode = RtlNtStatusToDosError(Status);
527 SetLastError(ErrorCode);
528 return ErrorCode;
529 }
530 Status = NtDeleteKey(TargetKey);
531 NtClose(TargetKey);
532 if (!NT_SUCCESS(Status)) {
533 ErrorCode = RtlNtStatusToDosError(Status);
534 SetLastError(ErrorCode);
535 return ErrorCode;
536 }
537 return ERROR_SUCCESS;
538 }
539
540
541 /************************************************************************
542 * RegDeleteKeyW
543 */
544 LONG
545 STDCALL
546 RegDeleteKeyW(
547 HKEY hKey,
548 LPCWSTR lpSubKey)
549 {
550 OBJECT_ATTRIBUTES ObjectAttributes;
551 UNICODE_STRING SubKeyString;
552 HKEY ParentKey;
553 HANDLE TargetKey;
554 NTSTATUS Status;
555 LONG ErrorCode;
556
557 Status = MapDefaultKey(&ParentKey, hKey);
558 if (!NT_SUCCESS(Status)) {
559 ErrorCode = RtlNtStatusToDosError(Status);
560 SetLastError (ErrorCode);
561 return ErrorCode;
562 }
563 RtlInitUnicodeString(&SubKeyString, (LPWSTR)lpSubKey);
564
565 InitializeObjectAttributes (&ObjectAttributes,
566 &SubKeyString,
567 OBJ_CASE_INSENSITIVE,
568 (HANDLE)ParentKey,
569 NULL);
570 Status = NtOpenKey(&TargetKey, DELETE, &ObjectAttributes);
571 if (!NT_SUCCESS(Status)) {
572 ErrorCode = RtlNtStatusToDosError(Status);
573 SetLastError (ErrorCode);
574 return ErrorCode;
575 }
576 Status = NtDeleteKey(TargetKey);
577 NtClose(TargetKey);
578 if (!NT_SUCCESS(Status)) {
579 ErrorCode = RtlNtStatusToDosError(Status);
580 SetLastError (ErrorCode);
581 return ErrorCode;
582 }
583 return ERROR_SUCCESS;
584 }
585
586
587 /************************************************************************
588 * RegDeleteValueA
589 */
590 LONG
591 STDCALL
592 RegDeleteValueA(
593 HKEY hKey,
594 LPCSTR lpValueName)
595 {
596 UNICODE_STRING ValueNameW;
597 ANSI_STRING ValueNameA;
598 NTSTATUS Status;
599 LONG ErrorCode;
600 HKEY KeyHandle;
601
602 Status = MapDefaultKey(&KeyHandle, hKey);
603 if (!NT_SUCCESS(Status)) {
604 ErrorCode = RtlNtStatusToDosError(Status);
605 SetLastError (ErrorCode);
606 return ErrorCode;
607 }
608 RtlInitAnsiString(&ValueNameA, (LPSTR)lpValueName);
609 RtlAnsiStringToUnicodeString(&ValueNameW, &ValueNameA, TRUE);
610 Status = NtDeleteValueKey(KeyHandle, &ValueNameW);
611 RtlFreeUnicodeString (&ValueNameW);
612 if (!NT_SUCCESS(Status)) {
613 ErrorCode = RtlNtStatusToDosError(Status);
614 SetLastError (ErrorCode);
615 return ErrorCode;
616 }
617 return ERROR_SUCCESS;
618 }
619
620
621 /************************************************************************
622 * RegDeleteValueW
623 */
624 LONG
625 STDCALL
626 RegDeleteValueW(
627 HKEY hKey,
628 LPCWSTR lpValueName)
629 {
630 UNICODE_STRING ValueName;
631 NTSTATUS Status;
632 LONG ErrorCode;
633 HKEY KeyHandle;
634
635 Status = MapDefaultKey(&KeyHandle, hKey);
636 if (!NT_SUCCESS(Status))
637 {
638 ErrorCode = RtlNtStatusToDosError(Status);
639 SetLastError (ErrorCode);
640 return ErrorCode;
641 }
642 RtlInitUnicodeString(&ValueName, (LPWSTR)lpValueName);
643 Status = NtDeleteValueKey(KeyHandle, &ValueName);
644 if (!NT_SUCCESS(Status)) {
645 ErrorCode = RtlNtStatusToDosError(Status);
646 SetLastError (ErrorCode);
647 return ErrorCode;
648 }
649 return ERROR_SUCCESS;
650 }
651
652
653 /************************************************************************
654 * RegEnumKeyExW
655 */
656 LONG
657 STDCALL
658 RegEnumKeyExW(
659 HKEY hKey,
660 DWORD dwIndex,
661 LPWSTR lpName,
662 LPDWORD lpcbName,
663 LPDWORD lpReserved,
664 LPWSTR lpClass,
665 LPDWORD lpcbClass,
666 PFILETIME lpftLastWriteTime)
667 {
668 PKEY_NODE_INFORMATION KeyInfo;
669 NTSTATUS Status;
670 DWORD dwError = ERROR_SUCCESS;
671 ULONG BufferSize;
672 ULONG ResultSize;
673 HKEY KeyHandle;
674
675 Status = MapDefaultKey(&KeyHandle, hKey);
676 if (!NT_SUCCESS(Status)) {
677 dwError = RtlNtStatusToDosError(Status);
678 SetLastError (dwError);
679 return dwError;
680 }
681
682 BufferSize = sizeof (KEY_NODE_INFORMATION) + *lpcbName * sizeof(WCHAR);
683 if (lpClass)
684 BufferSize += *lpcbClass;
685
686 //
687 // I think this is a memory leak, always allocated again below ???
688 //
689 // KeyInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
690 //
691
692 /* We don't know the exact size of the data returned, so call
693 NtEnumerateKey() with a buffer size determined from parameters
694 to this function. If that call fails with a status code of
695 STATUS_BUFFER_OVERFLOW, allocate a new buffer and try again */
696 while (TRUE) {
697 KeyInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
698 if (KeyInfo == NULL) {
699 SetLastError(ERROR_OUTOFMEMORY);
700 return ERROR_OUTOFMEMORY;
701 }
702 Status = NtEnumerateKey(
703 KeyHandle,
704 (ULONG)dwIndex,
705 KeyNodeInformation,
706 KeyInfo,
707 BufferSize,
708 &ResultSize);
709
710 DPRINT("NtEnumerateKey() returned status 0x%X\n", Status);
711
712 if (Status == STATUS_BUFFER_OVERFLOW) {
713 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
714 BufferSize = ResultSize;
715 continue;
716 }
717 if (!NT_SUCCESS(Status)) {
718 dwError = RtlNtStatusToDosError(Status);
719 SetLastError(dwError);
720 break;
721 } else {
722 if ((lpClass) && (*lpcbClass != 0) && (KeyInfo->ClassLength > *lpcbClass)) {
723 dwError = ERROR_MORE_DATA;
724 SetLastError(dwError);
725 break;
726 }
727 RtlMoveMemory(lpName, KeyInfo->Name, KeyInfo->NameLength);
728 *lpcbName = (DWORD)(KeyInfo->NameLength / sizeof(WCHAR));
729 RegiTerminateWideString(lpName, *lpcbName);
730 if (lpClass) {
731 RtlMoveMemory(lpClass,
732 (PVOID)((ULONG_PTR)KeyInfo->Name + KeyInfo->ClassOffset),
733 KeyInfo->ClassLength);
734 *lpcbClass = (DWORD)(KeyInfo->ClassLength / sizeof(WCHAR));
735 }
736 if (lpftLastWriteTime) {
737 /* FIXME: Fill lpftLastWriteTime */
738 }
739 break;
740 }
741 }
742 RtlFreeHeap (RtlGetProcessHeap(), 0, KeyInfo);
743 return dwError;
744 }
745
746
747 /************************************************************************
748 * RegEnumKeyW
749 */
750 LONG
751 STDCALL
752 RegEnumKeyW(
753 HKEY hKey,
754 DWORD dwIndex,
755 LPWSTR lpName,
756 DWORD cbName)
757 {
758 DWORD dwLength = cbName;
759
760 return RegEnumKeyExW(hKey,
761 dwIndex,
762 lpName,
763 &dwLength,
764 NULL,
765 NULL,
766 NULL,
767 NULL);
768 }
769
770
771 /************************************************************************
772 * RegEnumKeyExA
773 */
774 LONG
775 STDCALL
776 RegEnumKeyExA(
777 HKEY hKey,
778 DWORD dwIndex,
779 LPSTR lpName,
780 LPDWORD lpcbName,
781 LPDWORD lpReserved,
782 LPSTR lpClass,
783 LPDWORD lpcbClass,
784 PFILETIME lpftLastWriteTime)
785 {
786 WCHAR Name[MAX_PATH+1];
787 UNICODE_STRING UnicodeStringName;
788 WCHAR Class[MAX_PATH+1];
789 UNICODE_STRING UnicodeStringClass;
790 ANSI_STRING AnsiString;
791 LONG ErrorCode;
792 DWORD NameLength;
793 DWORD ClassLength;
794
795 DPRINT("hKey 0x%x dwIndex %d lpName 0x%x *lpcbName %d lpClass 0x%x lpcbClass %d\n",
796 hKey, dwIndex, lpName, *lpcbName, lpClass, lpcbClass);
797
798 if ((lpClass) && (!lpcbClass)) {
799 SetLastError(ERROR_INVALID_PARAMETER);
800 return ERROR_INVALID_PARAMETER;
801 }
802 RtlInitUnicodeString(&UnicodeStringName, NULL);
803 UnicodeStringName.Buffer = &Name[0];
804 UnicodeStringName.MaximumLength = sizeof(Name);
805 RtlInitUnicodeString(&UnicodeStringClass, NULL);
806 if (lpClass) {
807 UnicodeStringClass.Buffer = &Class[0];
808 UnicodeStringClass.MaximumLength = sizeof(Class);
809 ClassLength = *lpcbClass;
810 } else {
811 ClassLength = 0;
812 }
813 NameLength = *lpcbName;
814 ErrorCode = RegEnumKeyExW(
815 hKey,
816 dwIndex,
817 UnicodeStringName.Buffer,
818 &NameLength,
819 lpReserved,
820 UnicodeStringClass.Buffer,
821 &ClassLength,
822 lpftLastWriteTime);
823
824 if (ErrorCode != ERROR_SUCCESS)
825 return ErrorCode;
826
827 UnicodeStringName.Length = NameLength * sizeof(WCHAR);
828 UnicodeStringClass.Length = ClassLength * sizeof(WCHAR);
829 RtlInitAnsiString(&AnsiString, NULL);
830 AnsiString.Buffer = lpName;
831 AnsiString.MaximumLength = *lpcbName;
832 RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeStringName, FALSE);
833 *lpcbName = AnsiString.Length;
834
835 DPRINT("Key Namea0 Length %d\n", UnicodeStringName.Length);
836 DPRINT("Key Namea1 Length %d\n", NameLength);
837 DPRINT("Key Namea Length %d\n", *lpcbName);
838 DPRINT("Key Namea %s\n", lpName);
839
840 if (lpClass) {
841 RtlInitAnsiString(&AnsiString, NULL);
842 AnsiString.Buffer = lpClass;
843 AnsiString.MaximumLength = *lpcbClass;
844 RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeStringClass, FALSE);
845 *lpcbClass = AnsiString.Length;
846 }
847 return ERROR_SUCCESS;
848 }
849
850
851 /************************************************************************
852 * RegEnumKeyA
853 */
854 LONG
855 STDCALL
856 RegEnumKeyA(
857 HKEY hKey,
858 DWORD dwIndex,
859 LPSTR lpName,
860 DWORD cbName)
861 {
862 DWORD dwLength = cbName;
863
864 return RegEnumKeyExA(hKey,
865 dwIndex,
866 lpName,
867 &dwLength,
868 NULL,
869 NULL,
870 NULL,
871 NULL);
872 }
873
874
875 /************************************************************************
876 * RegEnumValueW
877 */
878 LONG
879 STDCALL
880 RegEnumValueW(
881 HKEY hKey,
882 DWORD dwIndex,
883 LPWSTR lpValueName,
884 LPDWORD lpcbValueName,
885 LPDWORD lpReserved,
886 LPDWORD lpType,
887 LPBYTE lpData,
888 LPDWORD lpcbData)
889 {
890 PKEY_VALUE_FULL_INFORMATION ValueInfo;
891 NTSTATUS Status;
892 DWORD dwError = ERROR_SUCCESS;
893 ULONG BufferSize;
894 ULONG ResultSize;
895 HKEY KeyHandle;
896
897 Status = MapDefaultKey(&KeyHandle, hKey);
898 if (!NT_SUCCESS(Status)) {
899 dwError = RtlNtStatusToDosError(Status);
900 SetLastError(dwError);
901 return(dwError);
902 }
903 BufferSize = sizeof (KEY_VALUE_FULL_INFORMATION) + *lpcbValueName * sizeof(WCHAR);
904 if (lpcbData)
905 BufferSize += *lpcbData;
906
907 /* We don't know the exact size of the data returned, so call
908 NtEnumerateValueKey() with a buffer size determined from parameters
909 to this function. If that call fails with a status code of
910 STATUS_BUFFER_OVERFLOW, allocate a new buffer and try again */
911 while (TRUE) {
912 ValueInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
913 if (ValueInfo == NULL) {
914 SetLastError(ERROR_OUTOFMEMORY);
915 return ERROR_OUTOFMEMORY;
916 }
917 Status = NtEnumerateValueKey(
918 KeyHandle,
919 (ULONG)dwIndex,
920 KeyValueFullInformation,
921 ValueInfo,
922 BufferSize,
923 &ResultSize);
924
925 DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status);
926
927 if (Status == STATUS_BUFFER_OVERFLOW) {
928 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo);
929 BufferSize = ResultSize;
930 continue;
931 }
932 if (!NT_SUCCESS(Status)) {
933 dwError = RtlNtStatusToDosError(Status);
934 SetLastError(dwError);
935 break;
936 } else {
937 if ((lpData) && (*lpcbData != 0) && (ValueInfo->DataLength > *lpcbData)) {
938 dwError = ERROR_MORE_DATA;
939 SetLastError(dwError);
940 break;
941 }
942 memcpy(lpValueName, ValueInfo->Name, ValueInfo->NameLength);
943 *lpcbValueName = (DWORD)(ValueInfo->NameLength / sizeof(WCHAR));
944 RegiTerminateWideString(lpValueName, *lpcbValueName);
945 if (lpType)
946 *lpType = ValueInfo->Type;
947 if (lpData) {
948 memcpy(lpData,
949 //(PVOID)((ULONG_PTR)ValueInfo->Name + ValueInfo->DataOffset),
950 (PVOID)((ULONG_PTR)ValueInfo + ValueInfo->DataOffset),
951 ValueInfo->DataLength);
952 *lpcbData = (DWORD)ValueInfo->DataLength;
953 /*
954 RtlCopyMemory((PCHAR) ValueFullInformation + ValueFullInformation->DataOffset,
955 DataCell->Data,
956 ValueCell->DataSize & LONG_MAX);
957 */
958 }
959 break;
960 }
961 }
962 RtlFreeHeap (RtlGetProcessHeap(), 0, ValueInfo);
963 return dwError;
964 }
965
966
967 /************************************************************************
968 * RegEnumValueA
969 */
970 LONG
971 STDCALL
972 RegEnumValueA(
973 HKEY hKey,
974 DWORD dwIndex,
975 LPSTR lpValueName,
976 LPDWORD lpcbValueName,
977 LPDWORD lpReserved,
978 LPDWORD lpType,
979 LPBYTE lpData,
980 LPDWORD lpcbData)
981 {
982 WCHAR ValueName[MAX_PATH+1];
983 UNICODE_STRING UnicodeString;
984 ANSI_STRING AnsiString;
985 LONG ErrorCode;
986 DWORD ValueNameLength;
987 BYTE* lpDataBuffer = NULL;
988 DWORD cbData = 0;
989 DWORD Type;
990 ANSI_STRING AnsiDataString;
991 UNICODE_STRING UnicodeDataString;
992
993 if (lpData != NULL /*&& lpcbData != NULL*/) {
994 cbData = *lpcbData; // this should always be valid if lpData is valid
995 lpDataBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, (*lpcbData) * sizeof(WCHAR));
996 if (lpDataBuffer == NULL) {
997 SetLastError(ERROR_OUTOFMEMORY);
998 return ERROR_OUTOFMEMORY;
999 }
1000 }
1001 RtlInitUnicodeString(&UnicodeString, NULL);
1002 UnicodeString.Buffer = &ValueName[0];
1003 UnicodeString.MaximumLength = sizeof(ValueName);
1004 ValueNameLength = *lpcbValueName;
1005 ErrorCode = RegEnumValueW(
1006 hKey,
1007 dwIndex,
1008 UnicodeString.Buffer,
1009 &ValueNameLength,
1010 lpReserved,
1011 &Type,
1012 lpDataBuffer,
1013 &cbData);
1014 if (ErrorCode != ERROR_SUCCESS)
1015 return ErrorCode;
1016 UnicodeString.Length = ValueNameLength * sizeof(WCHAR);
1017 RtlInitAnsiString(&AnsiString, NULL);
1018 AnsiString.Buffer = lpValueName;
1019 AnsiString.MaximumLength = *lpcbValueName;
1020 RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE);
1021 *lpcbValueName = AnsiString.Length;
1022 // if (lpData != lpDataBuffer) { // did we use a temp buffer
1023 if (lpDataBuffer) { // did we use a temp buffer
1024 if ((Type == REG_SZ) || (Type == REG_MULTI_SZ) || (Type == REG_EXPAND_SZ)) {
1025 RtlInitUnicodeString(&UnicodeDataString, NULL);
1026 UnicodeDataString.Buffer = (WCHAR*)lpDataBuffer;
1027 UnicodeDataString.MaximumLength = (*lpcbData) * sizeof(WCHAR);
1028 UnicodeDataString.Length = cbData /* * sizeof(WCHAR)*/;
1029 RtlInitAnsiString(&AnsiDataString, NULL);
1030 AnsiDataString.Buffer = lpData;
1031 AnsiDataString.MaximumLength = *lpcbData;
1032 RtlUnicodeStringToAnsiString(&AnsiDataString, &UnicodeDataString, FALSE);
1033 *lpcbData = AnsiDataString.Length;
1034 // else if (Type == REG_EXPAND_SZ) {
1035 } else {
1036 memcpy(lpData, lpDataBuffer, min(*lpcbData, cbData));
1037 *lpcbData = cbData;
1038 }
1039 RtlFreeHeap(RtlGetProcessHeap(), 0, lpDataBuffer);
1040 }
1041 if (lpType != NULL) {
1042 *lpType = Type;
1043 }
1044 return ERROR_SUCCESS;
1045 }
1046
1047
1048 /************************************************************************
1049 * RegFlushKey
1050 */
1051 LONG STDCALL
1052 RegFlushKey(HKEY hKey)
1053 {
1054 HKEY KeyHandle;
1055 NTSTATUS Status;
1056 LONG ErrorCode;
1057
1058 if (hKey == HKEY_PERFORMANCE_DATA)
1059 return(ERROR_SUCCESS);
1060 Status = MapDefaultKey(&KeyHandle, hKey);
1061 if (!NT_SUCCESS(Status)) {
1062 ErrorCode = RtlNtStatusToDosError(Status);
1063 SetLastError(ErrorCode);
1064 return(ErrorCode);
1065 }
1066 Status = NtFlushKey(KeyHandle);
1067 if (!NT_SUCCESS(Status)) {
1068 ErrorCode = RtlNtStatusToDosError(Status);
1069 SetLastError(ErrorCode);
1070 return(ErrorCode);
1071 }
1072 return(ERROR_SUCCESS);
1073 }
1074
1075
1076 /************************************************************************
1077 * RegGetKeySecurity
1078 */
1079 LONG
1080 STDCALL
1081 RegGetKeySecurity(
1082 HKEY hKey,
1083 SECURITY_INFORMATION SecurityInformation,
1084 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1085 LPDWORD lpcbSecurityDescriptor)
1086 {
1087 UNIMPLEMENTED;
1088 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1089 return ERROR_CALL_NOT_IMPLEMENTED;
1090 }
1091
1092
1093 /************************************************************************
1094 * RegLoadKeyA
1095 */
1096 LONG
1097 STDCALL
1098 RegLoadKeyA(
1099 HKEY hKey,
1100 LPCSTR lpSubKey,
1101 LPCSTR lpFile)
1102 {
1103 UNIMPLEMENTED;
1104 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1105 return ERROR_CALL_NOT_IMPLEMENTED;
1106 }
1107
1108
1109 /************************************************************************
1110 * RegLoadKeyW
1111 */
1112 LONG
1113 STDCALL
1114 RegLoadKeyW(
1115 HKEY hKey,
1116 LPCWSTR lpSubKey,
1117 LPCWSTR lpFile)
1118 {
1119 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1120 return ERROR_CALL_NOT_IMPLEMENTED;
1121 }
1122
1123
1124 /************************************************************************
1125 * RegNotifyChangeKeyValue
1126 */
1127 LONG
1128 STDCALL
1129 RegNotifyChangeKeyValue(
1130 HKEY hKey,
1131 BOOL bWatchSubtree,
1132 DWORD dwNotifyFilter,
1133 HANDLE hEvent,
1134 BOOL fAsynchronous)
1135 {
1136 UNIMPLEMENTED;
1137 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1138 return ERROR_CALL_NOT_IMPLEMENTED;
1139 }
1140
1141
1142
1143 /************************************************************************
1144 * RegOpenKeyA
1145 */
1146 LONG STDCALL
1147 RegOpenKeyA(HKEY hKey,
1148 LPCSTR lpSubKey,
1149 PHKEY phkResult)
1150 {
1151 OBJECT_ATTRIBUTES ObjectAttributes;
1152 UNICODE_STRING SubKeyString;
1153 HKEY KeyHandle;
1154 LONG ErrorCode;
1155 NTSTATUS Status;
1156
1157 Status = MapDefaultKey(&KeyHandle, hKey);
1158 if (!NT_SUCCESS(Status)) {
1159 ErrorCode = RtlNtStatusToDosError(Status);
1160 SetLastError(ErrorCode);
1161 return(ErrorCode);
1162 }
1163 RtlCreateUnicodeStringFromAsciiz(&SubKeyString, (LPSTR)lpSubKey);
1164 InitializeObjectAttributes(&ObjectAttributes,
1165 &SubKeyString,
1166 OBJ_CASE_INSENSITIVE,
1167 KeyHandle,
1168 NULL);
1169 Status = NtOpenKey(phkResult, KEY_ALL_ACCESS, &ObjectAttributes);
1170 RtlFreeUnicodeString(&SubKeyString);
1171 if (!NT_SUCCESS(Status)) {
1172 ErrorCode = RtlNtStatusToDosError(Status);
1173 SetLastError(ErrorCode);
1174 return(ErrorCode);
1175 }
1176 return(ERROR_SUCCESS);
1177 }
1178
1179
1180 /************************************************************************
1181 * RegOpenKeyW
1182 *
1183 * 19981101 Ariadne
1184 * 19990525 EA
1185 */
1186 LONG
1187 STDCALL
1188 RegOpenKeyW(
1189 HKEY hKey,
1190 LPCWSTR lpSubKey,
1191 PHKEY phkResult)
1192 {
1193 NTSTATUS errCode;
1194 UNICODE_STRING SubKeyString;
1195 OBJECT_ATTRIBUTES ObjectAttributes;
1196 HKEY KeyHandle;
1197 LONG ErrorCode;
1198
1199 errCode = MapDefaultKey(&KeyHandle, hKey);
1200 if (!NT_SUCCESS(errCode)) {
1201 ErrorCode = RtlNtStatusToDosError(errCode);
1202 SetLastError (ErrorCode);
1203 return ErrorCode;
1204 }
1205 RtlInitUnicodeString(&SubKeyString, (LPWSTR)lpSubKey);
1206 InitializeObjectAttributes(&ObjectAttributes,
1207 &SubKeyString,
1208 OBJ_CASE_INSENSITIVE,
1209 KeyHandle,
1210 NULL);
1211 errCode = NtOpenKey(phkResult, KEY_ALL_ACCESS, &ObjectAttributes);
1212 if (!NT_SUCCESS(errCode)) {
1213 ErrorCode = RtlNtStatusToDosError(errCode);
1214 SetLastError(ErrorCode);
1215 return ErrorCode;
1216 }
1217 return ERROR_SUCCESS;
1218 }
1219
1220
1221 /************************************************************************
1222 * RegOpenKeyExA
1223 */
1224 LONG STDCALL
1225 RegOpenKeyExA(HKEY hKey,
1226 LPCSTR lpSubKey,
1227 DWORD ulOptions,
1228 REGSAM samDesired,
1229 PHKEY phkResult)
1230 {
1231 OBJECT_ATTRIBUTES ObjectAttributes;
1232 UNICODE_STRING SubKeyString;
1233 HKEY KeyHandle;
1234 LONG ErrorCode;
1235 NTSTATUS Status;
1236
1237 Status = MapDefaultKey(&KeyHandle, hKey);
1238 if (!NT_SUCCESS(Status)) {
1239 ErrorCode = RtlNtStatusToDosError(Status);
1240 SetLastError(ErrorCode);
1241 return(ErrorCode);
1242 }
1243 RtlCreateUnicodeStringFromAsciiz(&SubKeyString, (LPSTR)lpSubKey);
1244 InitializeObjectAttributes(&ObjectAttributes,
1245 &SubKeyString,
1246 OBJ_CASE_INSENSITIVE,
1247 KeyHandle,
1248 NULL);
1249 Status = NtOpenKey(phkResult, samDesired, &ObjectAttributes);
1250 RtlFreeUnicodeString(&SubKeyString);
1251 if (!NT_SUCCESS(Status)) {
1252 ErrorCode = RtlNtStatusToDosError(Status);
1253 SetLastError(ErrorCode);
1254 return(ErrorCode);
1255 }
1256 return(ERROR_SUCCESS);
1257 }
1258
1259
1260 /************************************************************************
1261 * RegOpenKeyExW
1262 */
1263 LONG STDCALL
1264 RegOpenKeyExW(HKEY hKey,
1265 LPCWSTR lpSubKey,
1266 DWORD ulOptions,
1267 REGSAM samDesired,
1268 PHKEY phkResult)
1269 {
1270 OBJECT_ATTRIBUTES ObjectAttributes;
1271 UNICODE_STRING SubKeyString;
1272 HKEY KeyHandle;
1273 LONG ErrorCode;
1274 NTSTATUS Status;
1275
1276 Status = MapDefaultKey(&KeyHandle, hKey);
1277 if (!NT_SUCCESS(Status)) {
1278 ErrorCode = RtlNtStatusToDosError(Status);
1279 SetLastError (ErrorCode);
1280 return(ErrorCode);
1281 }
1282 if (lpSubKey != NULL) {
1283 RtlInitUnicodeString(&SubKeyString, (LPWSTR)lpSubKey);
1284 } else {
1285 RtlInitUnicodeString(&SubKeyString, (LPWSTR)L"");
1286 }
1287 InitializeObjectAttributes(&ObjectAttributes,
1288 &SubKeyString,
1289 OBJ_CASE_INSENSITIVE,
1290 KeyHandle,
1291 NULL);
1292 Status = NtOpenKey(phkResult, samDesired, &ObjectAttributes);
1293 if (!NT_SUCCESS(Status)) {
1294 ErrorCode = RtlNtStatusToDosError(Status);
1295 SetLastError(ErrorCode);
1296 return(ErrorCode);
1297 }
1298 return(ERROR_SUCCESS);
1299 }
1300
1301
1302 /************************************************************************
1303 * RegQueryInfoKeyW
1304 */
1305 LONG
1306 STDCALL
1307 RegQueryInfoKeyW(
1308 HKEY hKey,
1309 LPWSTR lpClass,
1310 LPDWORD lpcbClass,
1311 LPDWORD lpReserved,
1312 LPDWORD lpcSubKeys,
1313 LPDWORD lpcbMaxSubKeyLen,
1314 LPDWORD lpcbMaxClassLen,
1315 LPDWORD lpcValues,
1316 LPDWORD lpcbMaxValueNameLen,
1317 LPDWORD lpcbMaxValueLen,
1318 LPDWORD lpcbSecurityDescriptor,
1319 PFILETIME lpftLastWriteTime)
1320 {
1321 KEY_FULL_INFORMATION FullInfoBuffer;
1322 PKEY_FULL_INFORMATION FullInfo;
1323 ULONG FullInfoSize;
1324 HKEY KeyHandle;
1325 NTSTATUS Status;
1326 LONG ErrorCode;
1327 ULONG Length;
1328
1329 if ((lpClass) && (!lpcbClass)) {
1330 SetLastError(ERROR_INVALID_PARAMETER);
1331 return ERROR_INVALID_PARAMETER;
1332 }
1333
1334 Status = MapDefaultKey(&KeyHandle, hKey);
1335 CHECK_STATUS;
1336
1337 if (lpClass) {
1338 FullInfoSize = sizeof(KEY_FULL_INFORMATION) + *lpcbClass;
1339 FullInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, FullInfoSize);
1340 if (!FullInfo) {
1341 SetLastError(ERROR_OUTOFMEMORY);
1342 return ERROR_OUTOFMEMORY;
1343 }
1344 FullInfo->ClassLength = *lpcbClass;
1345 } else {
1346 FullInfoSize = sizeof(KEY_FULL_INFORMATION);
1347 FullInfo = &FullInfoBuffer;
1348 FullInfo->ClassLength = 1;
1349 }
1350 FullInfo->ClassOffset = FIELD_OFFSET(KEY_FULL_INFORMATION, Class);
1351 Status = NtQueryKey(
1352 KeyHandle,
1353 KeyFullInformation,
1354 FullInfo,
1355 FullInfoSize,
1356 &Length);
1357 if (!NT_SUCCESS(Status)) {
1358 if (lpClass) {
1359 RtlFreeHeap(RtlGetProcessHeap(), 0, FullInfo);
1360 }
1361 ErrorCode = RtlNtStatusToDosError(Status);
1362 SetLastError(ErrorCode);
1363 return ErrorCode;
1364 }
1365 if (lpcSubKeys) {
1366 *lpcSubKeys = FullInfo->SubKeys;
1367 }
1368 if (lpcbMaxSubKeyLen) {
1369 *lpcbMaxSubKeyLen = FullInfo->MaxNameLen;
1370 }
1371 if (lpcbMaxClassLen) {
1372 *lpcbMaxClassLen = FullInfo->MaxClassLen;
1373 }
1374 if (lpcValues) {
1375 *lpcValues = FullInfo->Values;
1376 }
1377 if (lpcbMaxValueNameLen) {
1378 *lpcbMaxValueNameLen = FullInfo->MaxValueNameLen;
1379 }
1380 if (lpcbMaxValueLen) {
1381 *lpcbMaxValueLen = FullInfo->MaxValueDataLen;
1382 }
1383 if (lpcbSecurityDescriptor) {
1384 *lpcbSecurityDescriptor = 0;
1385 /* FIXME */
1386 }
1387 if (lpftLastWriteTime != NULL) {
1388 lpftLastWriteTime->dwLowDateTime = FullInfo->LastWriteTime.u.LowPart;
1389 lpftLastWriteTime->dwHighDateTime = FullInfo->LastWriteTime.u.HighPart;
1390 }
1391 if (lpClass) {
1392 wcsncpy(lpClass, FullInfo->Class, *lpcbClass);
1393 RtlFreeHeap(RtlGetProcessHeap(), 0, FullInfo);
1394 }
1395 SetLastError(ERROR_SUCCESS);
1396 return ERROR_SUCCESS;
1397 }
1398
1399
1400 /************************************************************************
1401 * RegQueryInfoKeyA
1402 */
1403 LONG
1404 STDCALL
1405 RegQueryInfoKeyA(
1406 HKEY hKey,
1407 LPSTR lpClass,
1408 LPDWORD lpcbClass,
1409 LPDWORD lpReserved,
1410 LPDWORD lpcSubKeys,
1411 LPDWORD lpcbMaxSubKeyLen,
1412 LPDWORD lpcbMaxClassLen,
1413 LPDWORD lpcValues,
1414 LPDWORD lpcbMaxValueNameLen,
1415 LPDWORD lpcbMaxValueLen,
1416 LPDWORD lpcbSecurityDescriptor,
1417 PFILETIME lpftLastWriteTime)
1418 {
1419 WCHAR ClassName[MAX_PATH];
1420 UNICODE_STRING UnicodeString;
1421 ANSI_STRING AnsiString;
1422 LONG ErrorCode;
1423
1424 RtlInitUnicodeString(&UnicodeString, NULL);
1425 if (lpClass) {
1426 UnicodeString.Buffer = &ClassName[0];
1427 UnicodeString.MaximumLength = sizeof(ClassName);
1428 }
1429 ErrorCode = RegQueryInfoKeyW(
1430 hKey,
1431 UnicodeString.Buffer,
1432 lpcbClass,
1433 lpReserved,
1434 lpcSubKeys,
1435 lpcbMaxSubKeyLen,
1436 lpcbMaxClassLen,
1437 lpcValues,
1438 lpcbMaxValueNameLen,
1439 lpcbMaxValueLen,
1440 lpcbSecurityDescriptor,
1441 lpftLastWriteTime);
1442
1443 if ((ErrorCode == ERROR_SUCCESS) && (lpClass)) {
1444 RtlInitAnsiString(&AnsiString, NULL);
1445 AnsiString.Buffer = lpClass;
1446 AnsiString.MaximumLength = *lpcbClass;
1447 RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE);
1448 *lpcbClass = AnsiString.Length;
1449 }
1450 return ErrorCode;
1451 }
1452
1453
1454 /************************************************************************
1455 * RegQueryMultipleValuesA
1456 */
1457 LONG
1458 STDCALL
1459 RegQueryMultipleValuesA(
1460 HKEY hKey,
1461 PVALENTA val_list,
1462 DWORD num_vals,
1463 LPSTR lpValueBuf,
1464 LPDWORD ldwTotsize)
1465 {
1466 UNIMPLEMENTED;
1467 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1468 return ERROR_CALL_NOT_IMPLEMENTED;
1469 }
1470
1471
1472 /************************************************************************
1473 * RegQueryMultipleValuesW
1474 */
1475 LONG
1476 STDCALL
1477 RegQueryMultipleValuesW(
1478 HKEY hKey,
1479 PVALENTW val_list,
1480 DWORD num_vals,
1481 LPWSTR lpValueBuf,
1482 LPDWORD ldwTotsize)
1483 {
1484 UNIMPLEMENTED;
1485 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1486 return ERROR_CALL_NOT_IMPLEMENTED;
1487 }
1488
1489
1490 /************************************************************************
1491 * RegQueryValueExW
1492 */
1493 LONG
1494 STDCALL
1495 RegQueryValueExW(
1496 HKEY hKey,
1497 LPCWSTR lpValueName,
1498 LPDWORD lpReserved,
1499 LPDWORD lpType,
1500 LPBYTE lpData,
1501 LPDWORD lpcbData)
1502 {
1503 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
1504 UNICODE_STRING ValueName;
1505 NTSTATUS Status;
1506 DWORD dwError = ERROR_SUCCESS;
1507 ULONG BufferSize;
1508 ULONG ResultSize;
1509 HKEY KeyHandle;
1510
1511 DPRINT("hKey 0x%X lpValueName %S lpData 0x%X lpcbData %d\n",
1512 hKey, lpValueName, lpData, lpcbData ? *lpcbData : 0);
1513 Status = MapDefaultKey(&KeyHandle, hKey);
1514 if (!NT_SUCCESS(Status)) {
1515 dwError = RtlNtStatusToDosError(Status);
1516 SetLastError(dwError);
1517 return(dwError);
1518 }
1519 if ((lpData) && (!lpcbData)) {
1520 SetLastError(ERROR_INVALID_PARAMETER);
1521 return ERROR_INVALID_PARAMETER;
1522 }
1523 RtlInitUnicodeString (&ValueName, lpValueName);
1524 BufferSize = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + *lpcbData;
1525 ValueInfo = RtlAllocateHeap (RtlGetProcessHeap(),
1526 0,
1527 BufferSize);
1528 if (ValueInfo == NULL) {
1529 SetLastError(ERROR_OUTOFMEMORY);
1530 return ERROR_OUTOFMEMORY;
1531 }
1532 Status = NtQueryValueKey (hKey,
1533 &ValueName,
1534 KeyValuePartialInformation,
1535 ValueInfo,
1536 BufferSize,
1537 &ResultSize);
1538 DPRINT("Status 0x%X\n", Status);
1539 if (Status == STATUS_BUFFER_TOO_SMALL) {
1540 /* Return ERROR_SUCCESS and the buffer space needed for a successful call */
1541 dwError = ERROR_SUCCESS;
1542 }
1543 else if (!NT_SUCCESS(Status)) {
1544 dwError = RtlNtStatusToDosError(Status);
1545 SetLastError(dwError);
1546 }
1547 else {
1548 if (lpType) {
1549 *lpType = ValueInfo->Type;
1550 }
1551 RtlMoveMemory(lpData, ValueInfo->Data, ValueInfo->DataLength);
1552 if ((ValueInfo->Type == REG_SZ) ||
1553 (ValueInfo->Type == REG_MULTI_SZ) ||
1554 (ValueInfo->Type == REG_EXPAND_SZ)) {
1555 ((PWSTR)lpData)[ValueInfo->DataLength / sizeof(WCHAR)] = 0;
1556 }
1557 }
1558 DPRINT("Type %d ResultSize %d\n", ValueInfo->Type, ResultSize);
1559 *lpcbData = (DWORD)ResultSize;
1560 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo);
1561 return dwError;
1562 }
1563
1564
1565 /************************************************************************
1566 * RegQueryValueExA
1567 */
1568 LONG
1569 STDCALL
1570 RegQueryValueExA(
1571 HKEY hKey,
1572 LPCSTR lpValueName,
1573 LPDWORD lpReserved,
1574 LPDWORD lpType,
1575 LPBYTE lpData,
1576 LPDWORD lpcbData)
1577 {
1578 WCHAR ValueNameBuffer[MAX_PATH+1];
1579 UNICODE_STRING ValueName;
1580 UNICODE_STRING ValueData;
1581 ANSI_STRING AnsiString;
1582 LONG ErrorCode;
1583 DWORD ResultSize;
1584 DWORD Type;
1585
1586 /* FIXME: HKEY_PERFORMANCE_DATA is special, see MS SDK */
1587
1588 if ((lpData) && (!lpcbData)) {
1589 SetLastError(ERROR_INVALID_PARAMETER);
1590 return ERROR_INVALID_PARAMETER;
1591 }
1592 RtlInitUnicodeString(&ValueData, NULL);
1593 if (lpData) {
1594 ValueData.MaximumLength = *lpcbData * sizeof(WCHAR);
1595 ValueData.Buffer = RtlAllocateHeap(
1596 RtlGetProcessHeap(),
1597 0,
1598 ValueData.MaximumLength);
1599 if (!ValueData.Buffer) {
1600 SetLastError(ERROR_OUTOFMEMORY);
1601 return ERROR_OUTOFMEMORY;
1602 }
1603 }
1604 RtlInitAnsiString(&AnsiString, (LPSTR)lpValueName);
1605 RtlInitUnicodeString(&ValueName, NULL);
1606 ValueName.Buffer = &ValueNameBuffer[0];
1607 ValueName.MaximumLength = sizeof(ValueNameBuffer);
1608 RtlAnsiStringToUnicodeString(&ValueName, &AnsiString, FALSE);
1609 if (lpcbData) {
1610 ResultSize = *lpcbData;
1611 } else {
1612 ResultSize = 0;
1613 }
1614 ErrorCode = RegQueryValueExW(
1615 hKey,
1616 ValueName.Buffer,
1617 lpReserved,
1618 &Type,
1619 (LPBYTE)ValueData.Buffer,
1620 &ResultSize);
1621 if ((ErrorCode == ERROR_SUCCESS) && (ValueData.Buffer != NULL)) {
1622 if (lpType) {
1623 *lpType = Type;
1624 }
1625 if ((Type == REG_SZ) || (Type == REG_MULTI_SZ) || (Type == REG_EXPAND_SZ)) {
1626 ValueData.Length = ResultSize;
1627 RtlInitAnsiString(&AnsiString, NULL);
1628 AnsiString.Buffer = lpData;
1629 AnsiString.MaximumLength = *lpcbData;
1630 RtlUnicodeStringToAnsiString(&AnsiString, &ValueData, FALSE);
1631 } else {
1632 RtlMoveMemory(lpData, ValueData.Buffer, ResultSize);
1633 }
1634 }
1635 if (lpcbData) {
1636 *lpcbData = ResultSize;
1637 }
1638 if (ValueData.Buffer) {
1639 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueData.Buffer);
1640 }
1641 return ErrorCode;
1642 }
1643
1644
1645 /************************************************************************
1646 * RegQueryValueW
1647 */
1648 LONG
1649 STDCALL
1650 RegQueryValueW(
1651 HKEY hKey,
1652 LPCWSTR lpSubKey,
1653 LPWSTR lpValue,
1654 PLONG lpcbValue)
1655 {
1656 NTSTATUS errCode;
1657 UNICODE_STRING SubKeyString;
1658 OBJECT_ATTRIBUTES ObjectAttributes;
1659 HKEY KeyHandle;
1660 HANDLE RealKey;
1661 LONG ErrorCode;
1662 BOOL CloseRealKey;
1663
1664 errCode = MapDefaultKey(&KeyHandle, hKey);
1665 if (!NT_SUCCESS(errCode)) {
1666 ErrorCode = RtlNtStatusToDosError(errCode);
1667 SetLastError (ErrorCode);
1668 return ErrorCode;
1669 }
1670 if ((lpSubKey) && (wcslen(lpSubKey) != 0)) {
1671 RtlInitUnicodeString(&SubKeyString, (LPWSTR)lpSubKey);
1672 InitializeObjectAttributes(&ObjectAttributes,
1673 &SubKeyString,
1674 OBJ_CASE_INSENSITIVE,
1675 KeyHandle,
1676 NULL);
1677 errCode = NtOpenKey(
1678 &RealKey,
1679 KEY_ALL_ACCESS,
1680 & ObjectAttributes);
1681 if (!NT_SUCCESS(errCode)) {
1682 ErrorCode = RtlNtStatusToDosError(errCode);
1683 SetLastError(ErrorCode);
1684 return ErrorCode;
1685 }
1686 CloseRealKey = TRUE;
1687 } else {
1688 RealKey = hKey;
1689 CloseRealKey = FALSE;
1690 }
1691 ErrorCode = RegQueryValueExW(
1692 RealKey,
1693 NULL,
1694 NULL,
1695 NULL,
1696 (LPBYTE)lpValue,
1697 (LPDWORD)lpcbValue);
1698 if (CloseRealKey) {
1699 NtClose(RealKey);
1700 }
1701 return ErrorCode;
1702 }
1703
1704
1705 /************************************************************************
1706 * RegQueryValueA
1707 */
1708 LONG
1709 STDCALL
1710 RegQueryValueA(
1711 HKEY hKey,
1712 LPCSTR lpSubKey,
1713 LPSTR lpValue,
1714 PLONG lpcbValue)
1715 {
1716 WCHAR SubKeyNameBuffer[MAX_PATH+1];
1717 UNICODE_STRING SubKeyName;
1718 UNICODE_STRING Value;
1719 ANSI_STRING AnsiString;
1720 LONG ValueSize;
1721 LONG ErrorCode;
1722
1723 if ((lpValue) && (!lpcbValue)) {
1724 SetLastError(ERROR_INVALID_PARAMETER);
1725 return ERROR_INVALID_PARAMETER;
1726 }
1727 RtlInitUnicodeString(&SubKeyName, NULL);
1728 RtlInitUnicodeString(&Value, NULL);
1729 if ((lpSubKey) && (strlen(lpSubKey) != 0)) {
1730 RtlInitAnsiString(&AnsiString, (LPSTR)lpSubKey);
1731 SubKeyName.Buffer = &SubKeyNameBuffer[0];
1732 SubKeyName.MaximumLength = sizeof(SubKeyNameBuffer);
1733 RtlAnsiStringToUnicodeString(&SubKeyName, &AnsiString, FALSE);
1734 }
1735 if (lpValue) {
1736 ValueSize = *lpcbValue * sizeof(WCHAR);
1737 Value.MaximumLength = ValueSize;
1738 Value.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, ValueSize);
1739 if (!Value.Buffer) {
1740 SetLastError(ERROR_OUTOFMEMORY);
1741 return ERROR_OUTOFMEMORY;
1742 }
1743 } else {
1744 ValueSize = 0;
1745 }
1746 ErrorCode = RegQueryValueW(
1747 hKey,
1748 (LPCWSTR)SubKeyName.Buffer,
1749 Value.Buffer,
1750 &ValueSize);
1751 if (ErrorCode == ERROR_SUCCESS) {
1752 Value.Length = ValueSize;
1753 RtlInitAnsiString(&AnsiString, NULL);
1754 AnsiString.Buffer = lpValue;
1755 AnsiString.MaximumLength = *lpcbValue;
1756 RtlUnicodeStringToAnsiString(&AnsiString, &Value, FALSE);
1757 }
1758 *lpcbValue = ValueSize;
1759 if (Value.Buffer) {
1760 RtlFreeHeap(RtlGetProcessHeap(), 0, Value.Buffer);
1761 }
1762 return ErrorCode;
1763 }
1764
1765
1766 /************************************************************************
1767 * RegReplaceKeyA
1768 */
1769 LONG
1770 STDCALL
1771 RegReplaceKeyA(
1772 HKEY hKey,
1773 LPCSTR lpSubKey,
1774 LPCSTR lpNewFile,
1775 LPCSTR lpOldFile)
1776 {
1777 UNIMPLEMENTED;
1778 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1779 return ERROR_CALL_NOT_IMPLEMENTED;
1780 }
1781
1782
1783 /************************************************************************
1784 * RegReplaceKeyW
1785 */
1786 LONG
1787 STDCALL
1788 RegReplaceKeyW(
1789 HKEY hKey,
1790 LPCWSTR lpSubKey,
1791 LPCWSTR lpNewFile,
1792 LPCWSTR lpOldFile)
1793 {
1794 UNIMPLEMENTED;
1795 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1796 return ERROR_CALL_NOT_IMPLEMENTED;
1797 }
1798
1799
1800 /************************************************************************
1801 * RegRestoreKeyA
1802 */
1803 LONG
1804 STDCALL
1805 RegRestoreKeyA(
1806 HKEY hKey,
1807 LPCSTR lpFile,
1808 DWORD dwFlags)
1809 {
1810 UNIMPLEMENTED;
1811 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1812 return ERROR_CALL_NOT_IMPLEMENTED;
1813 }
1814
1815
1816 /************************************************************************
1817 * RegRestoreKeyW
1818 */
1819 LONG
1820 STDCALL
1821 RegRestoreKeyW(
1822 HKEY hKey,
1823 LPCWSTR lpFile,
1824 DWORD dwFlags)
1825 {
1826 UNIMPLEMENTED;
1827 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1828 return ERROR_CALL_NOT_IMPLEMENTED;
1829 }
1830
1831
1832 /************************************************************************
1833 * RegSaveKeyW
1834 */
1835 LONG STDCALL
1836 RegSaveKeyW(HKEY hKey,
1837 LPCWSTR lpFile,
1838 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
1839 {
1840 PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
1841 OBJECT_ATTRIBUTES ObjectAttributes;
1842 UNICODE_STRING NtName;
1843 IO_STATUS_BLOCK IoStatusBlock;
1844 HANDLE FileHandle;
1845 HKEY KeyHandle;
1846 NTSTATUS Status;
1847 LONG ErrorCode;
1848
1849 Status = MapDefaultKey(&KeyHandle, hKey);
1850 if (!NT_SUCCESS(Status)) {
1851 ErrorCode = RtlNtStatusToDosError(Status);
1852 SetLastError(ErrorCode);
1853 return(ErrorCode);
1854 }
1855 if (!RtlDosPathNameToNtPathName_U((LPWSTR)lpFile,
1856 &NtName, NULL, NULL)) {
1857 SetLastError(ERROR_INVALID_PARAMETER);
1858 return(ERROR_INVALID_PARAMETER);
1859 }
1860 if (lpSecurityAttributes != NULL)
1861 SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
1862 InitializeObjectAttributes(&ObjectAttributes,
1863 &NtName,
1864 OBJ_CASE_INSENSITIVE,
1865 NULL,
1866 SecurityDescriptor);
1867 Status = NtCreateFile(&FileHandle,
1868 GENERIC_WRITE | SYNCHRONIZE,
1869 &ObjectAttributes,
1870 &IoStatusBlock,
1871 NULL,
1872 FILE_ATTRIBUTE_NORMAL,
1873 FILE_SHARE_READ,
1874 FILE_CREATE,
1875 FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
1876 NULL,
1877 0);
1878 RtlFreeUnicodeString(&NtName);
1879 if (!NT_SUCCESS(Status)) {
1880 ErrorCode = RtlNtStatusToDosError(Status);
1881 SetLastError(ErrorCode);
1882 return(ErrorCode);
1883 }
1884 Status = NtSaveKey(KeyHandle, FileHandle);
1885 NtClose(FileHandle);
1886 if (!NT_SUCCESS(Status)) {
1887 ErrorCode = RtlNtStatusToDosError(Status);
1888 SetLastError(ErrorCode);
1889 return(ErrorCode);
1890 }
1891 return(ERROR_SUCCESS);
1892 }
1893
1894
1895 /************************************************************************
1896 * RegSaveKeyA
1897 */
1898 LONG STDCALL
1899 RegSaveKeyA(HKEY hKey,
1900 LPCSTR lpFile,
1901 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
1902 {
1903 UNICODE_STRING FileName;
1904 LONG ErrorCode;
1905
1906 RtlCreateUnicodeStringFromAsciiz(&FileName, (LPSTR)lpFile);
1907 ErrorCode = RegSaveKeyW(hKey, FileName.Buffer, lpSecurityAttributes);
1908 RtlFreeUnicodeString(&FileName);
1909 return(ErrorCode);
1910 }
1911
1912
1913 /************************************************************************
1914 * RegSetKeySecurity
1915 */
1916 LONG
1917 STDCALL
1918 RegSetKeySecurity(
1919 HKEY hKey,
1920 SECURITY_INFORMATION SecurityInformation, /* FIXME: ULONG? */
1921 PSECURITY_DESCRIPTOR pSecurityDescriptor
1922 )
1923 {
1924 UNIMPLEMENTED;
1925 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1926 return ERROR_CALL_NOT_IMPLEMENTED;
1927 }
1928
1929
1930 /************************************************************************
1931 * RegSetValueExW
1932 */
1933 LONG
1934 STDCALL
1935 RegSetValueExW(
1936 HKEY hKey,
1937 LPCWSTR lpValueName,
1938 DWORD Reserved,
1939 DWORD dwType,
1940 CONST BYTE* lpData,
1941 DWORD cbData)
1942 {
1943 UNICODE_STRING ValueName;
1944 PUNICODE_STRING pValueName;
1945 HKEY KeyHandle;
1946 NTSTATUS Status;
1947 LONG ErrorCode;
1948
1949 Status = MapDefaultKey(&KeyHandle, hKey);
1950 if (!NT_SUCCESS(Status)) {
1951 ErrorCode = RtlNtStatusToDosError(Status);
1952 SetLastError(ErrorCode);
1953 return ErrorCode;
1954 }
1955 if (lpValueName) {
1956 RtlInitUnicodeString(&ValueName, lpValueName);
1957 pValueName = &ValueName;
1958 } else {
1959 pValueName = NULL;
1960 }
1961 Status = NtSetValueKey(
1962 KeyHandle,
1963 pValueName,
1964 0,
1965 dwType,
1966 (PVOID)lpData,
1967 (ULONG)cbData);
1968 if (!NT_SUCCESS(Status)) {
1969 LONG ErrorCode = RtlNtStatusToDosError(Status);
1970 SetLastError (ErrorCode);
1971 return ErrorCode;
1972 }
1973 return ERROR_SUCCESS;
1974 }
1975
1976
1977 /************************************************************************
1978 * RegSetValueExA
1979 */
1980 LONG
1981 STDCALL
1982 RegSetValueExA(
1983 HKEY hKey,
1984 LPCSTR lpValueName,
1985 DWORD Reserved,
1986 DWORD dwType,
1987 CONST BYTE* lpData,
1988 DWORD cbData)
1989 {
1990 UNICODE_STRING ValueName;
1991 LPWSTR pValueName;
1992 ANSI_STRING AnsiString;
1993 UNICODE_STRING Data;
1994 LONG ErrorCode;
1995 LPBYTE pData;
1996 DWORD DataSize;
1997
1998 if (!lpData) {
1999 SetLastError(ERROR_INVALID_PARAMETER);
2000 return ERROR_INVALID_PARAMETER;
2001 }
2002 if ((lpValueName) && (strlen(lpValueName) != 0)) {
2003 RtlCreateUnicodeStringFromAsciiz(&ValueName, (LPSTR)lpValueName);
2004 pValueName = (LPWSTR)ValueName.Buffer;
2005 } else {
2006 pValueName = NULL;
2007 }
2008 if ((dwType == REG_SZ) || (dwType == REG_MULTI_SZ) || (dwType == REG_EXPAND_SZ)) {
2009 RtlInitAnsiString(&AnsiString, NULL);
2010 AnsiString.Buffer = (LPSTR)lpData;
2011 AnsiString.Length = cbData;
2012 AnsiString.MaximumLength = cbData;
2013 RtlAnsiStringToUnicodeString(&Data, &AnsiString, TRUE);
2014 pData = (LPBYTE)Data.Buffer;
2015 DataSize = cbData * sizeof(WCHAR);
2016 } else {
2017 RtlInitUnicodeString(&Data, NULL);
2018 pData = (LPBYTE)lpData;
2019 DataSize = cbData;
2020 }
2021 ErrorCode = RegSetValueExW(
2022 hKey,
2023 pValueName,
2024 Reserved,
2025 dwType,
2026 pData,
2027 DataSize);
2028 if (pValueName) {
2029 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueName.Buffer);
2030 }
2031 if (Data.Buffer) {
2032 RtlFreeHeap(RtlGetProcessHeap(), 0, Data.Buffer);
2033 }
2034 return ErrorCode;
2035 }
2036
2037
2038 /************************************************************************
2039 * RegSetValueW
2040 */
2041 LONG
2042 STDCALL
2043 RegSetValueW(
2044 HKEY hKey,
2045 LPCWSTR lpSubKey,
2046 DWORD dwType,
2047 LPCWSTR lpData,
2048 DWORD cbData)
2049 {
2050 NTSTATUS errCode;
2051 UNICODE_STRING SubKeyString;
2052 OBJECT_ATTRIBUTES ObjectAttributes;
2053 HKEY KeyHandle;
2054 HANDLE RealKey;
2055 LONG ErrorCode;
2056 BOOL CloseRealKey;
2057
2058 errCode = MapDefaultKey(&KeyHandle, hKey);
2059 if (!NT_SUCCESS(errCode)) {
2060 ErrorCode = RtlNtStatusToDosError(errCode);
2061 SetLastError (ErrorCode);
2062 return ErrorCode;
2063 }
2064 if ((lpSubKey) && (wcslen(lpSubKey) != 0)) {
2065 RtlInitUnicodeString(&SubKeyString, (LPWSTR)lpSubKey);
2066 InitializeObjectAttributes(&ObjectAttributes,
2067 &SubKeyString,
2068 OBJ_CASE_INSENSITIVE,
2069 KeyHandle,
2070 NULL);
2071 errCode = NtOpenKey(&RealKey, KEY_ALL_ACCESS, &ObjectAttributes);
2072 if (!NT_SUCCESS(errCode)) {
2073 ErrorCode = RtlNtStatusToDosError(errCode);
2074 SetLastError(ErrorCode);
2075 return ErrorCode;
2076 }
2077 CloseRealKey = TRUE;
2078 } else {
2079 RealKey = hKey;
2080 CloseRealKey = FALSE;
2081 }
2082 ErrorCode = RegSetValueExW(
2083 RealKey,
2084 NULL,
2085 0,
2086 dwType,
2087 (LPBYTE)lpData,
2088 cbData);
2089 if (CloseRealKey) {
2090 NtClose(RealKey);
2091 }
2092 return ErrorCode;
2093 }
2094
2095
2096 /************************************************************************
2097 * RegSetValueA
2098 */
2099 LONG
2100 STDCALL
2101 RegSetValueA(
2102 HKEY hKey,
2103 LPCSTR lpSubKey,
2104 DWORD dwType,
2105 LPCSTR lpData,
2106 DWORD cbData)
2107 {
2108 WCHAR SubKeyNameBuffer[MAX_PATH+1];
2109 UNICODE_STRING SubKeyName;
2110 UNICODE_STRING Data;
2111 ANSI_STRING AnsiString;
2112 LONG DataSize;
2113 LONG ErrorCode;
2114
2115 if (!lpData) {
2116 SetLastError(ERROR_INVALID_PARAMETER);
2117 return ERROR_INVALID_PARAMETER;
2118 }
2119 RtlInitUnicodeString(&SubKeyName, NULL);
2120 RtlInitUnicodeString(&Data, NULL);
2121 if ((lpSubKey) && (strlen(lpSubKey) != 0)) {
2122 RtlInitAnsiString(&AnsiString, (LPSTR)lpSubKey);
2123 SubKeyName.Buffer = &SubKeyNameBuffer[0];
2124 SubKeyName.MaximumLength = sizeof(SubKeyNameBuffer);
2125 RtlAnsiStringToUnicodeString(&SubKeyName, &AnsiString, FALSE);
2126 }
2127 DataSize = cbData * sizeof(WCHAR);
2128 Data.MaximumLength = DataSize;
2129 Data.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, DataSize);
2130 if (!Data.Buffer) {
2131 SetLastError(ERROR_OUTOFMEMORY);
2132 return ERROR_OUTOFMEMORY;
2133 }
2134 ErrorCode = RegSetValueW(
2135 hKey,
2136 (LPCWSTR)SubKeyName.Buffer,
2137 dwType,
2138 Data.Buffer,
2139 DataSize);
2140 RtlFreeHeap(RtlGetProcessHeap(), 0, Data.Buffer);
2141 return ErrorCode;
2142 }
2143
2144
2145 /************************************************************************
2146 * RegUnLoadKeyA
2147 */
2148 LONG
2149 STDCALL
2150 RegUnLoadKeyA(
2151 HKEY hKey,
2152 LPCSTR lpSubKey)
2153 {
2154 UNIMPLEMENTED;
2155 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2156 return ERROR_CALL_NOT_IMPLEMENTED;
2157 }
2158
2159
2160 /************************************************************************
2161 * RegUnLoadKeyW
2162 */
2163 LONG
2164 STDCALL
2165 RegUnLoadKeyW(
2166 HKEY hKey,
2167 LPCWSTR lpSubKey)
2168 {
2169 UNIMPLEMENTED;
2170 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2171 return ERROR_CALL_NOT_IMPLEMENTED;
2172 }
2173
2174 /* EOF */