2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * PURPOSE: Rtl registry functions
5 * FILE: lib/rtl/registry.c
11 * - finish RtlQueryRegistryValues()
14 /* INCLUDES *****************************************************************/
21 #define TAG_RTLREGISTRY TAG('R', 't', 'l', 'R')
23 /* DATA **********************************************************************/
25 PCWSTR RtlpRegPaths
[RTL_REGISTRY_MAXIMUM
] =
28 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services",
29 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control",
30 L
"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion",
31 L
"\\Registry\\Machine\\Hardware\\DeviceMap",
32 L
"\\Registry\\User\\.Default",
35 /* PRIVATE FUNCTIONS *********************************************************/
39 RtlpGetRegistryHandle(IN ULONG RelativeTo
,
44 UNICODE_STRING KeyPath
, KeyName
;
45 WCHAR KeyBuffer
[MAX_PATH
];
46 OBJECT_ATTRIBUTES ObjectAttributes
;
49 /* Check if we just want the handle */
50 if (RelativeTo
& RTL_REGISTRY_HANDLE
)
52 *KeyHandle
= (HANDLE
)Path
;
53 return STATUS_SUCCESS
;
56 /* Check for optional flag */
57 if (RelativeTo
& RTL_REGISTRY_OPTIONAL
)
60 RelativeTo
&= ~RTL_REGISTRY_OPTIONAL
;
63 /* Fail on invalid parameter */
64 if (RelativeTo
>= RTL_REGISTRY_MAXIMUM
) return STATUS_INVALID_PARAMETER
;
66 /* Initialize the key name */
67 RtlInitEmptyUnicodeString(&KeyName
, KeyBuffer
, sizeof(KeyBuffer
));
69 /* Check if we have to lookup a path to prefix */
70 if (RelativeTo
!= RTL_REGISTRY_ABSOLUTE
)
72 /* Check if we need the current user key */
73 if (RelativeTo
== RTL_REGISTRY_USER
)
76 Status
= RtlFormatCurrentUserKeyPath(&KeyPath
);
77 if (!NT_SUCCESS(Status
)) return(Status
);
80 Status
= RtlAppendUnicodeStringToString(&KeyName
, &KeyPath
);
81 RtlFreeUnicodeString (&KeyPath
);
85 /* Get one of the prefixes */
86 Status
= RtlAppendUnicodeToString(&KeyName
,
87 RtlpRegPaths
[RelativeTo
]);
90 /* Check for failure, otherwise, append the path separator */
91 if (!NT_SUCCESS(Status
)) return Status
;
92 Status
= RtlAppendUnicodeToString(&KeyName
, L
"\\");
93 if (!NT_SUCCESS(Status
)) return Status
;
96 /* And now append the path */
97 if (Path
[0] == L
'\\' && RelativeTo
!= RTL_REGISTRY_ABSOLUTE
) Path
++; // HACK!
98 Status
= RtlAppendUnicodeToString(&KeyName
, Path
);
99 if (!NT_SUCCESS(Status
)) return Status
;
101 /* Initialize the object attributes */
102 InitializeObjectAttributes(&ObjectAttributes
,
104 OBJ_CASE_INSENSITIVE
,
108 /* Check if we want to create it */
111 /* Create the key with write privileges */
112 Status
= ZwCreateKey(KeyHandle
,
122 /* Otherwise, just open it with read access */
123 Status
= ZwOpenKey(KeyHandle
,
124 MAXIMUM_ALLOWED
| GENERIC_READ
,
132 /* PUBLIC FUNCTIONS **********************************************************/
139 RtlCheckRegistryKey(IN ULONG RelativeTo
,
146 /* Call the helper */
147 Status
= RtlpGetRegistryHandle(RelativeTo
,
151 if (!NT_SUCCESS(Status
)) return Status
;
153 /* All went well, close the handle and return success */
155 return STATUS_SUCCESS
;
163 RtlCreateRegistryKey(IN ULONG RelativeTo
,
170 /* Call the helper */
171 Status
= RtlpGetRegistryHandle(RelativeTo
,
175 if (!NT_SUCCESS(Status
)) return Status
;
177 /* All went well, close the handle and return success */
179 return STATUS_SUCCESS
;
187 RtlDeleteRegistryValue(IN ULONG RelativeTo
,
196 /* Call the helper */
197 Status
= RtlpGetRegistryHandle(RelativeTo
,
201 if (!NT_SUCCESS(Status
)) return Status
;
203 /* Initialize the key name and delete it */
204 RtlInitUnicodeString(&Name
, ValueName
);
205 Status
= ZwDeleteValueKey(KeyHandle
, &Name
);
207 /* All went well, close the handle and return status */
217 RtlWriteRegistryValue(IN ULONG RelativeTo
,
222 IN ULONG ValueLength
)
229 /* Call the helper */
230 Status
= RtlpGetRegistryHandle(RelativeTo
,
234 if (!NT_SUCCESS(Status
)) return Status
;
236 /* Initialize the key name and set it */
237 RtlInitUnicodeString(&Name
, ValueName
);
238 Status
= ZwSetValueKey(KeyHandle
,
245 /* All went well, close the handle and return status */
255 RtlOpenCurrentUser(IN ACCESS_MASK DesiredAccess
,
256 OUT PHANDLE KeyHandle
)
258 OBJECT_ATTRIBUTES ObjectAttributes
;
259 UNICODE_STRING KeyPath
;
263 /* Get the user key */
264 Status
= RtlFormatCurrentUserKeyPath(&KeyPath
);
265 if (NT_SUCCESS(Status
))
267 /* Initialize the attributes and open it */
268 InitializeObjectAttributes(&ObjectAttributes
,
270 OBJ_CASE_INSENSITIVE
,
273 Status
= ZwOpenKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
);
275 /* Free the path and return success if it worked */
276 RtlFreeUnicodeString(&KeyPath
);
277 if (NT_SUCCESS(Status
)) return STATUS_SUCCESS
;
280 /* It didn't work, so use the default key */
281 RtlInitUnicodeString(&KeyPath
, RtlpRegPaths
[RTL_REGISTRY_USER
]);
282 InitializeObjectAttributes(&ObjectAttributes
,
284 OBJ_CASE_INSENSITIVE
,
287 Status
= ZwOpenKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
);
298 RtlFormatCurrentUserKeyPath(OUT PUNICODE_STRING KeyPath
)
302 PSID_AND_ATTRIBUTES SidBuffer
;
304 UNICODE_STRING SidString
;
308 /* Open the thread token */
309 Status
= ZwOpenThreadToken(NtCurrentThread(),
313 if (!NT_SUCCESS(Status
))
315 /* We failed, is it because we don't have a thread token? */
316 if (Status
!= STATUS_NO_TOKEN
) return Status
;
318 /* It is, so use the process token */
319 Status
= ZwOpenProcessToken(NtCurrentProcess(),
322 if (!NT_SUCCESS(Status
)) return Status
;
325 /* Now query the token information */
326 SidBuffer
= (PSID_AND_ATTRIBUTES
)Buffer
;
327 Status
= ZwQueryInformationToken(TokenHandle
,
333 /* Close the handle and handle failure */
334 ZwClose(TokenHandle
);
335 if (!NT_SUCCESS(Status
)) return Status
;
337 /* Convert the SID */
338 Status
= RtlConvertSidToUnicodeString(&SidString
, SidBuffer
[0].Sid
, TRUE
);
339 if (!NT_SUCCESS(Status
)) return Status
;
341 /* Add the length of the prefix */
342 Length
= SidString
.Length
+ sizeof(L
"\\REGISTRY\\USER\\");
344 /* Initialize a string */
345 RtlInitEmptyUnicodeString(KeyPath
,
346 RtlpAllocateStringMemory(Length
, TAG_USTR
),
348 if (!KeyPath
->Buffer
)
350 /* Free the string and fail */
351 RtlFreeUnicodeString(&SidString
);
352 return STATUS_NO_MEMORY
;
355 /* Append the prefix and SID */
356 RtlAppendUnicodeToString(KeyPath
, L
"\\REGISTRY\\USER\\");
357 RtlAppendUnicodeStringToString(KeyPath
, &SidString
);
359 /* Free the temporary string and return success */
360 RtlFreeUnicodeString(&SidString
);
361 return STATUS_SUCCESS
;
369 RtlpNtCreateKey(OUT HANDLE KeyHandle
,
370 IN ACCESS_MASK DesiredAccess
,
371 IN POBJECT_ATTRIBUTES ObjectAttributes
,
373 IN PUNICODE_STRING Class
,
374 OUT PULONG Disposition
)
376 /* Check if we have object attributes */
377 if (ObjectAttributes
)
379 /* Mask out the unsupported flags */
380 ObjectAttributes
->Attributes
&= ~(OBJ_PERMANENT
| OBJ_EXCLUSIVE
);
384 return ZwCreateKey(KeyHandle
,
398 RtlpNtEnumerateSubKey(IN HANDLE KeyHandle
,
399 OUT PUNICODE_STRING SubKeyName
,
403 PKEY_BASIC_INFORMATION KeyInfo
= NULL
;
404 ULONG BufferLength
= 0;
405 ULONG ReturnedLength
;
408 /* Check if we have a name */
409 if (SubKeyName
->MaximumLength
)
411 /* Allocate a buffer for it */
412 BufferLength
= SubKeyName
->MaximumLength
+
413 sizeof(KEY_BASIC_INFORMATION
);
414 KeyInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength
);
415 if (!KeyInfo
) return STATUS_NO_MEMORY
;
418 /* Enumerate the key */
419 Status
= ZwEnumerateKey(KeyHandle
,
425 if (NT_SUCCESS(Status
))
427 /* Check if the name fits */
428 if (KeyInfo
->NameLength
<= SubKeyName
->MaximumLength
)
431 SubKeyName
->Length
= KeyInfo
->NameLength
;
434 RtlMoveMemory(SubKeyName
->Buffer
,
440 /* Otherwise, we ran out of buffer space */
441 Status
= STATUS_BUFFER_OVERFLOW
;
445 /* Free the buffer and return status */
446 if (KeyInfo
) RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo
);
455 RtlpNtMakeTemporaryKey(IN HANDLE KeyHandle
)
457 /* This just deletes the key */
458 return ZwDeleteKey(KeyHandle
);
466 RtlpNtOpenKey(OUT HANDLE KeyHandle
,
467 IN ACCESS_MASK DesiredAccess
,
468 IN POBJECT_ATTRIBUTES ObjectAttributes
,
471 /* Check if we have object attributes */
472 if (ObjectAttributes
)
474 /* Mask out the unsupported flags */
475 ObjectAttributes
->Attributes
&= ~(OBJ_PERMANENT
| OBJ_EXCLUSIVE
);
479 return ZwOpenKey(KeyHandle
, DesiredAccess
, ObjectAttributes
);
487 RtlpNtQueryValueKey(IN HANDLE KeyHandle
,
488 OUT PULONG Type OPTIONAL
,
489 OUT PVOID Data OPTIONAL
,
490 IN OUT PULONG DataLength OPTIONAL
,
493 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
494 UNICODE_STRING ValueName
;
495 ULONG BufferLength
= 0;
498 /* Clear the value name */
499 RtlInitEmptyUnicodeString(&ValueName
, NULL
, 0);
501 /* Check if we were already given a length */
502 if (DataLength
) BufferLength
= *DataLength
;
504 /* Add the size of the structure */
505 BufferLength
+= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
);
507 /* Allocate memory for the value */
508 ValueInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength
);
509 if (!ValueInfo
) return STATUS_NO_MEMORY
;
511 /* Query the value */
512 Status
= ZwQueryValueKey(KeyHandle
,
514 KeyValuePartialInformation
,
518 if ((NT_SUCCESS(Status
)) || (Status
== STATUS_BUFFER_OVERFLOW
))
520 /* Return the length and type */
521 if (DataLength
) *DataLength
= ValueInfo
->DataLength
;
522 if (Type
) *Type
= ValueInfo
->Type
;
525 /* Check if the caller wanted data back, and we got it */
526 if ((NT_SUCCESS(Status
)) && (Data
))
529 RtlMoveMemory(Data
, ValueInfo
->Data
, ValueInfo
->DataLength
);
532 /* Free the memory and return status */
533 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo
);
542 RtlpNtSetValueKey(IN HANDLE KeyHandle
,
547 UNICODE_STRING ValueName
;
550 RtlInitEmptyUnicodeString(&ValueName
, NULL
, 0);
551 return ZwSetValueKey(KeyHandle
,
563 RtlQueryRegistryValues(IN ULONG RelativeTo
,
565 IN PRTL_QUERY_REGISTRY_TABLE QueryTable
,
567 IN PVOID Environment OPTIONAL
)
570 HANDLE BaseKeyHandle
;
571 HANDLE CurrentKeyHandle
;
572 PRTL_QUERY_REGISTRY_TABLE QueryEntry
;
573 OBJECT_ATTRIBUTES ObjectAttributes
;
574 UNICODE_STRING KeyName
;
575 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
576 PKEY_VALUE_FULL_INFORMATION FullValueInfo
;
585 UNICODE_STRING EnvValue
;
586 UNICODE_STRING EnvExpandedValue
;
593 DPRINT("RtlQueryRegistryValues() called\n");
595 Status
= RtlpGetRegistryHandle(RelativeTo
,
599 if (!NT_SUCCESS(Status
))
601 DPRINT("RtlpGetRegistryHandle() failed (Status %lx)\n", Status
);
605 CurrentKeyHandle
= BaseKeyHandle
;
606 QueryEntry
= QueryTable
;
607 while ((QueryEntry
->QueryRoutine
!= NULL
) ||
608 (QueryEntry
->Name
!= NULL
))
610 if (((QueryEntry
->Flags
& (RTL_QUERY_REGISTRY_SUBKEY
| RTL_QUERY_REGISTRY_TOPKEY
)) != 0) &&
611 (BaseKeyHandle
!= CurrentKeyHandle
))
613 ZwClose(CurrentKeyHandle
);
614 CurrentKeyHandle
= BaseKeyHandle
;
617 if (QueryEntry
->Flags
& RTL_QUERY_REGISTRY_SUBKEY
)
619 DPRINT("Open new subkey: %S\n", QueryEntry
->Name
);
621 RtlInitUnicodeString(&KeyName
,
623 InitializeObjectAttributes(&ObjectAttributes
,
625 OBJ_CASE_INSENSITIVE
,
628 Status
= ZwOpenKey(&CurrentKeyHandle
,
631 if (!NT_SUCCESS(Status
))
634 else if (QueryEntry
->Flags
& RTL_QUERY_REGISTRY_DIRECT
)
636 DPRINT("Query value directly: %S\n", QueryEntry
->Name
);
638 RtlInitUnicodeString(&KeyName
,
641 BufferSize
= sizeof (KEY_VALUE_PARTIAL_INFORMATION
) + 4096;
642 ValueInfo
= RtlpAllocateMemory(BufferSize
, TAG_RTLREGISTRY
);
643 if (ValueInfo
== NULL
)
645 Status
= STATUS_NO_MEMORY
;
649 Status
= ZwQueryValueKey(CurrentKeyHandle
,
651 KeyValuePartialInformation
,
655 if (!NT_SUCCESS(Status
))
657 if (QueryEntry
->Flags
& RTL_QUERY_REGISTRY_REQUIRED
)
659 RtlpFreeMemory(ValueInfo
, TAG_RTLREGISTRY
);
660 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
664 if (QueryEntry
->DefaultType
== REG_SZ
)
666 PUNICODE_STRING ValueString
;
667 PUNICODE_STRING SourceString
;
669 SourceString
= (PUNICODE_STRING
)QueryEntry
->DefaultData
;
670 ValueString
= (PUNICODE_STRING
)QueryEntry
->EntryContext
;
671 if (ValueString
->Buffer
== NULL
)
673 ValueString
->Length
= SourceString
->Length
;
674 ValueString
->MaximumLength
= SourceString
->MaximumLength
;
675 ValueString
->Buffer
= RtlpAllocateMemory(BufferSize
, TAG_RTLREGISTRY
);
676 if (!ValueString
->Buffer
)
678 ValueString
->Buffer
[0] = 0;
679 memcpy(ValueString
->Buffer
,
680 SourceString
->Buffer
,
681 SourceString
->MaximumLength
);
685 ValueString
->Length
= min(SourceString
->Length
,
686 ValueString
->MaximumLength
- sizeof(WCHAR
));
687 memcpy(ValueString
->Buffer
,
688 SourceString
->Buffer
,
689 ValueString
->Length
);
690 ((PWSTR
)ValueString
->Buffer
)[ValueString
->Length
/ sizeof(WCHAR
)] = 0;
695 memcpy(QueryEntry
->EntryContext
,
696 QueryEntry
->DefaultData
,
697 QueryEntry
->DefaultLength
);
699 Status
= STATUS_SUCCESS
;
703 if ((ValueInfo
->Type
== REG_SZ
) ||
704 (ValueInfo
->Type
== REG_MULTI_SZ
) ||
705 (ValueInfo
->Type
== REG_EXPAND_SZ
&& (QueryEntry
->Flags
& RTL_QUERY_REGISTRY_NOEXPAND
)))
707 PUNICODE_STRING ValueString
;
709 ValueString
= (PUNICODE_STRING
)QueryEntry
->EntryContext
;
710 if (ValueString
->Buffer
== NULL
)
712 ValueString
->MaximumLength
= ValueInfo
->DataLength
;
713 ValueString
->Buffer
= RtlpAllocateMemory(ValueString
->MaximumLength
, TAG_RTLREGISTRY
);
714 if (ValueString
->Buffer
== NULL
)
716 Status
= STATUS_INSUFFICIENT_RESOURCES
;
719 ValueString
->Buffer
[0] = 0;
721 ValueString
->Length
= min(ValueInfo
->DataLength
,
722 ValueString
->MaximumLength
) - sizeof(WCHAR
);
723 memcpy(ValueString
->Buffer
,
725 ValueString
->Length
);
726 ((PWSTR
)ValueString
->Buffer
)[ValueString
->Length
/ sizeof(WCHAR
)] = 0;
728 else if (ValueInfo
->Type
== REG_EXPAND_SZ
)
730 PUNICODE_STRING ValueString
;
732 DPRINT("Expand REG_EXPAND_SZ type\n");
734 ValueString
= (PUNICODE_STRING
)QueryEntry
->EntryContext
;
736 ExpandBuffer
= RtlpAllocateMemory(ValueInfo
->DataLength
* 2, TAG_RTLREGISTRY
);
737 if (ExpandBuffer
== NULL
)
739 Status
= STATUS_NO_MEMORY
;
743 RtlInitUnicodeString(&EnvValue
,
744 (PWSTR
)ValueInfo
->Data
);
745 EnvExpandedValue
.Length
= 0;
746 EnvExpandedValue
.MaximumLength
= ValueInfo
->DataLength
* 2;
747 EnvExpandedValue
.Buffer
= ExpandBuffer
;
750 RtlExpandEnvironmentStrings_U(Environment
,
755 if (ValueString
->Buffer
== NULL
)
757 ValueString
->MaximumLength
= EnvExpandedValue
.Length
+ sizeof(WCHAR
);
758 ValueString
->Length
= EnvExpandedValue
.Length
;
759 ValueString
->Buffer
= RtlpAllocateMemory(ValueString
->MaximumLength
, TAG_RTLREGISTRY
);
760 if (ValueString
->Buffer
== NULL
)
762 Status
= STATUS_INSUFFICIENT_RESOURCES
;
768 ValueString
->Length
= min(EnvExpandedValue
.Length
,
769 ValueString
->MaximumLength
- sizeof(WCHAR
));
772 memcpy(ValueString
->Buffer
,
773 EnvExpandedValue
.Buffer
,
774 ValueString
->Length
);
775 ((PWSTR
)ValueString
->Buffer
)[ValueString
->Length
/ sizeof(WCHAR
)] = 0;
777 RtlpFreeMemory(ExpandBuffer
, TAG_RTLREGISTRY
);
781 memcpy(QueryEntry
->EntryContext
,
783 ValueInfo
->DataLength
);
787 if (QueryEntry
->Flags
& RTL_QUERY_REGISTRY_DELETE
)
789 Status
= ZwDeleteValueKey(CurrentKeyHandle
, &KeyName
);
793 RtlpFreeMemory(ValueInfo
, TAG_RTLREGISTRY
);
797 DPRINT("Query value via query routine: %S\n", QueryEntry
->Name
);
798 if (QueryEntry
->Name
!= NULL
)
800 RtlInitUnicodeString(&KeyName
,
803 BufferSize
= sizeof (KEY_VALUE_PARTIAL_INFORMATION
) + 4096;
804 ValueInfo
= RtlpAllocateMemory(BufferSize
, TAG_RTLREGISTRY
);
805 if (ValueInfo
== NULL
)
807 Status
= STATUS_NO_MEMORY
;
811 Status
= ZwQueryValueKey(CurrentKeyHandle
,
813 KeyValuePartialInformation
,
817 if (!NT_SUCCESS(Status
))
819 if (!(QueryEntry
->Flags
& RTL_QUERY_REGISTRY_REQUIRED
))
821 Status
= QueryEntry
->QueryRoutine(QueryEntry
->Name
,
822 QueryEntry
->DefaultType
,
823 QueryEntry
->DefaultData
,
824 QueryEntry
->DefaultLength
,
826 QueryEntry
->EntryContext
);
829 else if ((ValueInfo
->Type
== REG_MULTI_SZ
) &&
830 !(QueryEntry
->Flags
& RTL_QUERY_REGISTRY_NOEXPAND
))
832 DPRINT("Expand REG_MULTI_SZ type\n");
834 StringPtr
= (PWSTR
)ValueInfo
->Data
;
835 while (DataSize
< (ValueInfo
->DataLength
-2))
837 StringLen
= (wcslen(StringPtr
) + 1) * sizeof(WCHAR
);
838 Status
= QueryEntry
->QueryRoutine(QueryEntry
->Name
,
843 QueryEntry
->EntryContext
);
844 if(!NT_SUCCESS(Status
))
846 StringPtr
= (PWSTR
)((PUCHAR
)StringPtr
+ StringLen
);
847 DataSize
+= StringLen
;
850 else if ((ValueInfo
->Type
== REG_EXPAND_SZ
) &&
851 !(QueryEntry
->Flags
& RTL_QUERY_REGISTRY_NOEXPAND
))
853 DPRINT("Expand REG_EXPAND_SZ type\n");
855 ExpandBuffer
= RtlpAllocateMemory(ValueInfo
->DataLength
* 2, TAG_RTLREGISTRY
);
856 if (ExpandBuffer
== NULL
)
858 Status
= STATUS_NO_MEMORY
;
862 RtlInitUnicodeString(&EnvValue
,
863 (PWSTR
)ValueInfo
->Data
);
864 EnvExpandedValue
.Length
= 0;
865 EnvExpandedValue
.MaximumLength
= ValueInfo
->DataLength
* 2 * sizeof(WCHAR
);
866 EnvExpandedValue
.Buffer
= ExpandBuffer
;
869 RtlExpandEnvironmentStrings_U(Environment
,
874 StringLen
= (wcslen(ExpandBuffer
) + 1) * sizeof(WCHAR
);
875 Status
= QueryEntry
->QueryRoutine(QueryEntry
->Name
,
880 QueryEntry
->EntryContext
);
882 RtlpFreeMemory(ExpandBuffer
, TAG_RTLREGISTRY
);
886 Status
= QueryEntry
->QueryRoutine(QueryEntry
->Name
,
889 ValueInfo
->DataLength
,
891 QueryEntry
->EntryContext
);
894 if (QueryEntry
->Flags
& RTL_QUERY_REGISTRY_DELETE
)
896 Status
= ZwDeleteValueKey(CurrentKeyHandle
, &KeyName
);
899 RtlpFreeMemory(ValueInfo
, TAG_RTLREGISTRY
);
900 if (!NT_SUCCESS(Status
))
903 else if (QueryEntry
->Flags
& RTL_QUERY_REGISTRY_NOVALUE
)
905 DPRINT("Simple callback\n");
906 Status
= QueryEntry
->QueryRoutine(NULL
,
911 QueryEntry
->EntryContext
);
912 if (!NT_SUCCESS(Status
))
917 DPRINT("Enumerate values\n");
919 BufferSize
= sizeof(KEY_VALUE_FULL_INFORMATION
) + 4096;
920 FullValueInfo
= RtlpAllocateMemory(BufferSize
, TAG_RTLREGISTRY
);
921 if (FullValueInfo
== NULL
)
923 Status
= STATUS_NO_MEMORY
;
926 ValueNameSize
= 256 * sizeof(WCHAR
);
927 ValueName
= RtlpAllocateMemory(ValueNameSize
, TAG_RTLREGISTRY
);
928 if (ValueName
== NULL
)
930 Status
= STATUS_NO_MEMORY
;
936 Status
= ZwEnumerateValueKey(CurrentKeyHandle
,
938 KeyValueFullInformation
,
942 if (!NT_SUCCESS(Status
))
944 if ((Status
== STATUS_NO_MORE_ENTRIES
) &&
946 (QueryEntry
->Flags
& RTL_QUERY_REGISTRY_REQUIRED
))
948 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
950 else if (Status
== STATUS_NO_MORE_ENTRIES
)
952 Status
= STATUS_SUCCESS
;
957 if (FullValueInfo
->NameLength
> ValueNameSize
- sizeof(WCHAR
))
959 /* Should not happen, because the name length is limited to 255 characters */
960 RtlpFreeMemory(ValueName
, TAG_RTLREGISTRY
);
961 ValueNameSize
= FullValueInfo
->NameLength
+ sizeof(WCHAR
);
962 ValueName
= RtlpAllocateMemory(ValueNameSize
, TAG_RTLREGISTRY
);
963 if (ValueName
== NULL
)
965 Status
= STATUS_NO_MEMORY
;
972 FullValueInfo
->NameLength
);
973 ValueName
[FullValueInfo
->NameLength
/ sizeof(WCHAR
)] = 0;
975 DPRINT("FullValueInfo->Type: %lu\n", FullValueInfo
->Type
);
976 if ((FullValueInfo
->Type
== REG_MULTI_SZ
) &&
977 !(QueryEntry
->Flags
& RTL_QUERY_REGISTRY_NOEXPAND
))
979 DPRINT("Expand REG_MULTI_SZ type\n");
980 StringPtr
= (PWSTR
)((ULONG_PTR
)FullValueInfo
+ FullValueInfo
->DataOffset
);
981 while (*StringPtr
!= 0)
983 StringLen
= (wcslen(StringPtr
) + 1) * sizeof(WCHAR
);
984 Status
= QueryEntry
->QueryRoutine(ValueName
,
989 QueryEntry
->EntryContext
);
990 if(!NT_SUCCESS(Status
))
992 StringPtr
= (PWSTR
)((PUCHAR
)StringPtr
+ StringLen
);
995 else if ((FullValueInfo
->Type
== REG_EXPAND_SZ
) &&
996 !(QueryEntry
->Flags
& RTL_QUERY_REGISTRY_NOEXPAND
))
998 DPRINT("Expand REG_EXPAND_SZ type\n");
1000 StringPtr
= (PWSTR
)((ULONG_PTR
)FullValueInfo
+ FullValueInfo
->DataOffset
);
1001 ExpandBuffer
= RtlpAllocateMemory(FullValueInfo
->DataLength
* 2, TAG_RTLREGISTRY
);
1002 if (ExpandBuffer
== NULL
)
1004 Status
= STATUS_NO_MEMORY
;
1008 RtlInitUnicodeString(&EnvValue
,
1010 EnvExpandedValue
.Length
= 0;
1011 EnvExpandedValue
.MaximumLength
= FullValueInfo
->DataLength
* 2;
1012 EnvExpandedValue
.Buffer
= ExpandBuffer
;
1015 RtlExpandEnvironmentStrings_U(Environment
,
1020 StringLen
= (wcslen(ExpandBuffer
) + 1) * sizeof(WCHAR
);
1021 Status
= QueryEntry
->QueryRoutine(ValueName
,
1023 (PVOID
)ExpandBuffer
,
1026 QueryEntry
->EntryContext
);
1028 RtlpFreeMemory(ExpandBuffer
, TAG_RTLREGISTRY
);
1032 Status
= QueryEntry
->QueryRoutine(ValueName
,
1033 FullValueInfo
->Type
,
1034 (PVOID
)((ULONG_PTR
)FullValueInfo
+ FullValueInfo
->DataOffset
),
1035 FullValueInfo
->DataLength
,
1037 QueryEntry
->EntryContext
);
1040 if (!NT_SUCCESS(Status
))
1043 /* FIXME: How will these be deleted? */
1048 RtlpFreeMemory(FullValueInfo
, TAG_RTLREGISTRY
);
1049 RtlpFreeMemory(ValueName
, TAG_RTLREGISTRY
);
1050 if (!NT_SUCCESS(Status
))
1058 if (CurrentKeyHandle
!= BaseKeyHandle
)
1059 ZwClose(CurrentKeyHandle
);
1061 ZwClose(BaseKeyHandle
);