Module: wine Branch: master Commit: 058f86958cae87bd3e2f1dd55b0605ff50306b4f URL: https://source.winehq.org/git/wine.git/?a=commit;h=058f86958cae87bd3e2f1dd55...
Author: Alon Barzilai alon.barzilai@gmail.com Date: Mon May 4 08:59:53 2020 +0300
ntdll: Add missing RtlQueryEnvironmentVariable function.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48773 Signed-off-by: Alon Barzilai alon.barzilai@gmail.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/ntdll/env.c | 42 ++++++++++++++++++++++++++++++++++++++++++ dlls/ntdll/ntdll.spec | 1 + dlls/ntdll/tests/env.c | 38 ++++++++++++++++++++++++++++++++++++++ include/winternl.h | 1 + 4 files changed, 82 insertions(+)
diff --git a/dlls/ntdll/env.c b/dlls/ntdll/env.c index 5ba3c7c7b3..e48c516211 100644 --- a/dlls/ntdll/env.c +++ b/dlls/ntdll/env.c @@ -981,6 +981,48 @@ NTSTATUS WINAPI RtlQueryEnvironmentVariable_U(PWSTR env, return nts; }
+ +/****************************************************************** + * RtlQueryEnvironmentVariable [NTDLL.@] + */ +NTSTATUS WINAPI RtlQueryEnvironmentVariable( WCHAR *env, const WCHAR *name, SIZE_T namelen, + WCHAR *value, SIZE_T value_length, SIZE_T *return_length ) +{ + NTSTATUS nts = STATUS_VARIABLE_NOT_FOUND; + SIZE_T len = 0; + const WCHAR *var; + + if (!namelen) return nts; + + if (!env) + { + RtlAcquirePebLock(); + var = NtCurrentTeb()->Peb->ProcessParameters->Environment; + } + else var = env; + + var = ENV_FindVariable(var, name, namelen); + if (var != NULL) + { + len = wcslen(var); + if (len <= value_length) + { + memcpy(value, var, min(len + 1, value_length) * sizeof(WCHAR)); + nts = STATUS_SUCCESS; + } + else + { + len++; + nts = STATUS_BUFFER_TOO_SMALL; + } + } + *return_length = len; + + if (!env) RtlReleasePebLock(); + + return nts; +} + /****************************************************************** * RtlSetCurrentEnvironment [NTDLL.@] * diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 1326c62fcf..e82fb6a2aa 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -863,6 +863,7 @@ @ stdcall RtlQueryDepthSList(ptr) @ stdcall RtlQueryDynamicTimeZoneInformation(ptr) @ stdcall RtlQueryEnvironmentVariable_U(ptr ptr ptr) +@ stdcall RtlQueryEnvironmentVariable(ptr ptr long ptr long ptr) @ stdcall RtlQueryHeapInformation(long long ptr long ptr) @ stdcall RtlQueryInformationAcl(ptr ptr long long) @ stdcall RtlQueryInformationActivationContext(long long ptr long ptr long ptr) diff --git a/dlls/ntdll/tests/env.c b/dlls/ntdll/tests/env.c index 98a9f7bb56..9883739eba 100644 --- a/dlls/ntdll/tests/env.c +++ b/dlls/ntdll/tests/env.c @@ -27,6 +27,7 @@ static NTSTATUS (WINAPI *pRtlMultiByteToUnicodeN)( LPWSTR dst, DWORD dstlen, LPD static NTSTATUS (WINAPI *pRtlCreateEnvironment)(BOOLEAN, PWSTR*); static NTSTATUS (WINAPI *pRtlDestroyEnvironment)(PWSTR); static NTSTATUS (WINAPI *pRtlQueryEnvironmentVariable_U)(PWSTR, PUNICODE_STRING, PUNICODE_STRING); +static NTSTATUS (WINAPI* pRtlQueryEnvironmentVariable)(WCHAR*, WCHAR*, SIZE_T, WCHAR*, SIZE_T, SIZE_T*); static void (WINAPI *pRtlSetCurrentEnvironment)(PWSTR, PWSTR*); static NTSTATUS (WINAPI *pRtlSetEnvironmentVariable)(PWSTR*, PUNICODE_STRING, PUNICODE_STRING); static NTSTATUS (WINAPI *pRtlExpandEnvironmentStrings_U)(LPWSTR, PUNICODE_STRING, PUNICODE_STRING, PULONG); @@ -95,6 +96,9 @@ static void testQuery(void) UNICODE_STRING name; UNICODE_STRING value; NTSTATUS nts; + SIZE_T name_length; + SIZE_T value_length; + SIZE_T return_length; unsigned int i;
for (i = 0; tests[i].var; i++) @@ -130,6 +134,39 @@ static void testQuery(void) break; } } + + if (pRtlQueryEnvironmentVariable) + { + for (i = 0; tests[i].var; i++) + { + const struct test* test = &tests[i]; + name_length = strlen(test->var); + value_length = test->len; + value.Buffer = bv; + bv[test->len] = '@'; + + pRtlMultiByteToUnicodeN(bn, sizeof(bn), NULL, test->var, strlen(test->var) + 1); + nts = pRtlQueryEnvironmentVariable(small_env, bn, name_length, bv, value_length, &return_length); + ok(nts == test->status || (test->alt && nts == test->alt), + "[%d]: Wrong status for '%s', expecting %x got %x\n", + i, test->var, test->status, nts); + if (nts == test->status) switch (nts) + { + case STATUS_SUCCESS: + pRtlMultiByteToUnicodeN(bn, sizeof(bn), NULL, test->val, strlen(test->val) + 1); + ok(return_length == strlen(test->val), "Wrong length %ld for %s\n", + return_length, test->var); + ok(!memcmp(bv, bn, return_length), "Wrong result for %s/%d\n", test->var, test->len); + ok(bv[test->len] == '@', "Writing too far away in the buffer for %s/%d\n", test->var, test->len); + break; + case STATUS_BUFFER_TOO_SMALL: + ok(return_length == (strlen(test->val) + 1), + "Wrong returned length %ld (too small buffer) for %s\n", return_length, test->var); + break; + } + } + } + else win_skip("RtlQueryEnvironmentVariable not available, skipping tests\n"); }
static void testSetHelper(LPWSTR* env, const char* var, const char* val, NTSTATUS ret, NTSTATUS alt) @@ -591,6 +628,7 @@ START_TEST(env) pRtlCreateEnvironment = (void*)GetProcAddress(mod, "RtlCreateEnvironment"); pRtlDestroyEnvironment = (void*)GetProcAddress(mod, "RtlDestroyEnvironment"); pRtlQueryEnvironmentVariable_U = (void*)GetProcAddress(mod, "RtlQueryEnvironmentVariable_U"); + pRtlQueryEnvironmentVariable = (void*)GetProcAddress(mod, "RtlQueryEnvironmentVariable"); pRtlSetCurrentEnvironment = (void*)GetProcAddress(mod, "RtlSetCurrentEnvironment"); pRtlSetEnvironmentVariable = (void*)GetProcAddress(mod, "RtlSetEnvironmentVariable"); pRtlExpandEnvironmentStrings_U = (void*)GetProcAddress(mod, "RtlExpandEnvironmentStrings_U"); diff --git a/include/winternl.h b/include/winternl.h index 9df1f0bb80..ed8b28ea1f 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -2945,6 +2945,7 @@ NTSYSAPI void WINAPI RtlPushFrame(TEB_ACTIVE_FRAME*); NTSYSAPI NTSTATUS WINAPI RtlQueryActivationContextApplicationSettings(DWORD,HANDLE,const WCHAR*,const WCHAR*,WCHAR*,SIZE_T,SIZE_T*); NTSYSAPI NTSTATUS WINAPI RtlQueryAtomInAtomTable(RTL_ATOM_TABLE,RTL_ATOM,ULONG*,ULONG*,WCHAR*,ULONG*); NTSYSAPI NTSTATUS WINAPI RtlQueryDynamicTimeZoneInformation(RTL_DYNAMIC_TIME_ZONE_INFORMATION*); +NTSYSAPI NTSTATUS WINAPI RtlQueryEnvironmentVariable(WCHAR*,const WCHAR*,SIZE_T,WCHAR*,SIZE_T,SIZE_T*); NTSYSAPI NTSTATUS WINAPI RtlQueryEnvironmentVariable_U(PWSTR,PUNICODE_STRING,PUNICODE_STRING); NTSYSAPI NTSTATUS WINAPI RtlQueryHeapInformation(HANDLE,HEAP_INFORMATION_CLASS,PVOID,SIZE_T,PSIZE_T); NTSYSAPI NTSTATUS WINAPI RtlQueryInformationAcl(PACL,LPVOID,DWORD,ACL_INFORMATION_CLASS);