From ef70bdf99074b74f80adfc796997d3c422b0710c Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Sat, 2 May 2026 13:02:47 +0300 Subject: [PATCH] [RTL][NTDLL] Implement RtlQueryEnvironmentVariable Make RtlQueryEnvironmentVariable_U a wrapper around RtlQueryEnvironmentVariable. --- dll/ntdll/def/ntdll.spec | 2 +- sdk/lib/rtl/env.c | 73 +++++++++++++++++++++++++++++++--------- 2 files changed, 58 insertions(+), 17 deletions(-) diff --git a/dll/ntdll/def/ntdll.spec b/dll/ntdll/def/ntdll.spec index 033b8b434ae..eea5027baa0 100644 --- a/dll/ntdll/def/ntdll.spec +++ b/dll/ntdll/def/ntdll.spec @@ -1077,7 +1077,7 @@ @ stdcall RtlQueryDepthSList(ptr) @ stdcall -stub -version=0x600+ RtlQueryDynamicTimeZoneInformation(ptr) @ stdcall -stub -version=0x600+ RtlQueryElevationFlags(ptr) -@ stdcall -stub -version=0x600+ RtlQueryEnvironmentVariable(ptr ptr long ptr long ptr) +@ stdcall -version=0x600+ RtlQueryEnvironmentVariable(ptr ptr long ptr long ptr) @ stdcall RtlQueryEnvironmentVariable_U(ptr ptr ptr) @ stdcall RtlQueryHeapInformation(long long ptr long ptr) @ stdcall RtlQueryInformationAcl(ptr ptr long long) diff --git a/sdk/lib/rtl/env.c b/sdk/lib/rtl/env.c index ddf6177f365..4e4f32bc07f 100644 --- a/sdk/lib/rtl/env.c +++ b/sdk/lib/rtl/env.c @@ -512,14 +512,20 @@ found: /* * @implemented */ -NTSTATUS NTAPI -RtlQueryEnvironmentVariable_U(PWSTR Environment, - PCUNICODE_STRING Name, - PUNICODE_STRING Value) +NTSTATUS +NTAPI +RtlQueryEnvironmentVariable( + _In_opt_ PVOID Environment, + _In_reads_(NameLength) PWSTR Name, + _In_ SIZE_T NameLength, + _Out_writes_(ValueLength) PWSTR Value, + _In_ SIZE_T ValueLength, + _Out_ PSIZE_T ReturnLength) { NTSTATUS Status; PWSTR wcs; - UNICODE_STRING var; + PWSTR varName; + SIZE_T varNameLen; PWSTR val; BOOLEAN SysEnvUsed = FALSE; @@ -544,42 +550,42 @@ RtlQueryEnvironmentVariable_U(PWSTR Environment, return STATUS_VARIABLE_NOT_FOUND; } - Value->Length = 0; + *ReturnLength = 0; wcs = Environment; DPRINT("Starting search at :%p\n", wcs); while (*wcs) { - var.Buffer = wcs++; + varName = wcs++; wcs = wcschr(wcs, L'='); if (wcs == NULL) { - wcs = var.Buffer + wcslen(var.Buffer); + wcs = varName + wcslen(varName); DPRINT("Search at :%S\n", wcs); } - if (*wcs) { - var.Length = var.MaximumLength = (USHORT)(wcs - var.Buffer) * sizeof(WCHAR); + varNameLen = (wcs - varName); val = ++wcs; wcs += wcslen(wcs); DPRINT("Search at :%S\n", wcs); - if (RtlEqualUnicodeString(&var, Name, TRUE)) + if ((varNameLen == NameLength) && _wcsnicmp(varName, Name, NameLength) == 0) { - Value->Length = (USHORT)(wcs - val) * sizeof(WCHAR); - if (Value->Length <= Value->MaximumLength) + *ReturnLength = (wcs - val); + if (*ReturnLength < ValueLength) { - memcpy(Value->Buffer, - val, - min(Value->Length + sizeof(WCHAR), Value->MaximumLength)); + memcpy(Value, val, (*ReturnLength + 1) * sizeof(WCHAR)); DPRINT("Value %S\n", val); DPRINT("Return STATUS_SUCCESS\n"); Status = STATUS_SUCCESS; } else { + if (ValueLength > 0) + Value[0] = UNICODE_NULL; DPRINT("Return STATUS_BUFFER_TOO_SMALL\n"); + *ReturnLength += 1; Status = STATUS_BUFFER_TOO_SMALL; } @@ -600,4 +606,39 @@ RtlQueryEnvironmentVariable_U(PWSTR Environment, return STATUS_VARIABLE_NOT_FOUND; } +/* + * @implemented + */ +NTSTATUS +NTAPI +RtlQueryEnvironmentVariable_U( + _In_opt_ PWSTR Environment, + _In_ PCUNICODE_STRING Name, + _Out_ PUNICODE_STRING Value) +{ + NTSTATUS Status; + SIZE_T ReturnLength; + + Status = RtlQueryEnvironmentVariable(Environment, + Name->Buffer, + Name->Length / sizeof(WCHAR), + Value->Buffer, + Value->MaximumLength / sizeof(WCHAR), + &ReturnLength); + + if (ReturnLength > UNICODE_STRING_MAX_CHARS) + { + return STATUS_UNSUCCESSFUL; + } + + /* Correct for extra length returned by RtlQueryEnvironmentVariable */ + if (Status == STATUS_BUFFER_TOO_SMALL) + { + ReturnLength -= 1; + } + + Value->Length = (USHORT)ReturnLength * sizeof(WCHAR); + return Status; +} + /* EOF */