Alon Barzilai : ntdll: Add missing RtlQueryEnvironmentVariable function.

Alexandre Julliard julliard at winehq.org
Mon May 18 15:00:15 CDT 2020


Module: wine
Branch: master
Commit: 058f86958cae87bd3e2f1dd55b0605ff50306b4f
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=058f86958cae87bd3e2f1dd55b0605ff50306b4f

Author: Alon Barzilai <alon.barzilai at 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 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at 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);




More information about the wine-cvs mailing list