ntdll/kernel32: #23

Eric Pouech pouech-eric at wanadoo.fr
Thu May 8 13:54:22 CDT 2003


this patch implements RtlExpandEnvironmentStrings_U and fixes a 
incorrect behavior in RtlQueryEnvironmentString

A+

-- 
Eric Pouech
-------------- next part --------------
diff -u -x '*~' -x '.#*' dlls/ntdll22/env.c dlls/ntdll/env.c
--- dlls/ntdll22/env.c	2003-05-08 05:47:00.000000000 +0200
+++ dlls/ntdll/env.c	2003-05-08 19:35:25.000000000 +0200
@@ -81,17 +81,37 @@
     return NtFreeVirtualMemory(NtCurrentProcess(), (void**)&env, &size, MEM_RELEASE);
 }
 
+static LPCWSTR ENV_FindVariable(PCWSTR var, PCWSTR name, unsigned namelen)
+{
+    for (; *var; var += strlenW(var) + 1)
+    {
+        /* match var names, but avoid setting a var with a name including a '='
+         * (a starting '=' is valid though)
+         */
+        if (strncmpiW(var, name, namelen) == 0 && var[namelen] == '=' &&
+            strchrW(var + 1, '=') == var + namelen) 
+        {
+            return var + namelen + 1;
+        }
+    }
+    return NULL;
+}
+
 /******************************************************************
  *		RtlQueryEnvironmentVariable_U   [NTDLL.@]
  *
+ * NOTES: when the buffer is too small, the string is not written, but if the
+ *      terminating null char is the only char that cannot be written, then
+ *      all chars (except the null) are written and success is returned
+ *      (behavior of Win2k at least)
  */
 NTSTATUS WINAPI RtlQueryEnvironmentVariable_U(PWSTR env,
                                               PUNICODE_STRING name,
                                               PUNICODE_STRING value)
 {
     NTSTATUS    nts = STATUS_VARIABLE_NOT_FOUND;
-    PWSTR       var;
-    unsigned    namelen, varlen;
+    PCWSTR      var;
+    unsigned    namelen;
 
     TRACE("%s %s %p\n", debugstr_w(env), debugstr_w(name->Buffer), value);
 
@@ -106,24 +126,16 @@
     }
     else var = env;
 
-    for (; *var; var += varlen + 1)
+    var = ENV_FindVariable(var, name->Buffer, namelen);
+    if (var != NULL)
     {
-        varlen = strlenW(var);
-        /* match var names, but avoid setting a var with a name including a '='
-         * (a starting '=' is valid though)
-         */
-        if (strncmpiW(var, name->Buffer, namelen) == 0 && var[namelen] == '=' &&
-            strchrW(var + 1, '=') == var + namelen) 
+        value->Length = strlenW(var) * sizeof(WCHAR);
+        if (value->Length <= value->MaximumLength)
         {
-            value->Length = (varlen - namelen - 1) * sizeof(WCHAR);
-            if (value->Length <= value->MaximumLength)
-            {
-                memmove(value->Buffer, var + namelen + 1, value->Length + sizeof(WCHAR));
-                nts = STATUS_SUCCESS;
-            }
-            else nts = STATUS_BUFFER_TOO_SMALL;
-            break;
+            memmove(value->Buffer, var, min(value->Length + sizeof(WCHAR), value->MaximumLength));
+            nts = STATUS_SUCCESS;
         }
+        else nts = STATUS_BUFFER_TOO_SMALL;
     }
 
     if (!env) RtlReleasePebLock();
@@ -240,6 +252,77 @@
     return nts;
 }
 
+/******************************************************************
+ *		RtlExpandEnvironmentStrings_U (NTDLL.@)
+ *
+ */
+NTSTATUS WINAPI RtlExpandEnvironmentStrings_U(PWSTR env, const UNICODE_STRING* us_src,
+                                              PUNICODE_STRING us_dst, PULONG plen)
+{
+    DWORD       len, count, total_size = 1;  /* 1 for terminating '\0' */
+    LPCWSTR     src, p, var;
+    LPWSTR      dst;
+
+    src = us_src->Buffer;
+    count = us_dst->MaximumLength / sizeof(WCHAR);
+    dst = count ? us_dst->Buffer : NULL;
+
+    RtlAcquirePebLock();
+
+    while (*src)
+    {
+        if (*src != '%')
+        {
+            if ((p = strchrW( src, '%' ))) len = p - src;
+            else len = strlenW(src);
+            var = src;
+            src += len;
+        }
+        else  /* we are at the start of a variable */
+        {
+            if ((p = strchrW( src + 1, '%' )))
+            {
+                len = p - src - 1;  /* Length of the variable name */
+                if ((var = ENV_FindVariable( env, src + 1, len )))
+                {
+                    src += len + 2;  /* Skip the variable name */
+                    len = strlenW(var);
+                }
+                else
+                {
+                    var = src;  /* Copy original name instead */
+                    len += 2;
+                    src += len;
+                }
+            }
+            else  /* unfinished variable name, ignore it */
+            {
+                var = src;
+                len = strlenW(src);  /* Copy whole string */
+                src += len;
+            }
+        }
+        total_size += len;
+        if (dst)
+        {
+            if (count < len) len = count;
+            memcpy(dst, var, len * sizeof(WCHAR));
+            count -= len;
+            dst += len;
+        }
+    }
+
+    RtlReleasePebLock();
+
+    /* Null-terminate the string */
+    if (dst && count) *dst = '\0';
+
+    us_dst->Length = (dst) ? (dst - us_dst->Buffer) * sizeof(WCHAR): 0;
+    if (plen) *plen = total_size * sizeof(WCHAR);
+
+    return (count) ? STATUS_SUCCESS : STATUS_BUFFER_TOO_SMALL;
+}
+
 /***********************************************************************
  *           build_environment
  *
diff -u -x '*~' -x '.#*' dlls/ntdll22/ntdll.spec dlls/ntdll/ntdll.spec
--- dlls/ntdll22/ntdll.spec	2003-05-08 13:58:53.000000000 +0200
+++ dlls/ntdll/ntdll.spec	2003-05-08 14:09:49.000000000 +0200
@@ -370,7 +370,7 @@
 @ stdcall RtlEqualString(ptr ptr long)
 @ stdcall RtlEqualUnicodeString(ptr ptr long)
 @ stdcall RtlEraseUnicodeString(ptr)
-@ stub RtlExpandEnvironmentStrings_U
+@ stdcall RtlExpandEnvironmentStrings_U(ptr ptr ptr ptr)
 @ stub RtlExtendHeap
 @ stdcall -ret64 RtlExtendedIntegerMultiply(long long long)
 @ stdcall -ret64 RtlExtendedLargeIntegerDivide(long long long ptr)
diff -u -x '*~' -x '.#*' include22/winternl.h include/winternl.h
--- include22/winternl.h	2003-05-08 13:59:36.000000000 +0200
+++ include/winternl.h	2003-05-08 16:16:08.000000000 +0200
@@ -989,6 +991,7 @@
 BOOL      WINAPI RtlEqualSid(PSID,PSID);
 BOOLEAN   WINAPI RtlEqualString(const STRING*,const STRING*,BOOLEAN);
 BOOLEAN   WINAPI RtlEqualUnicodeString(const UNICODE_STRING*,const UNICODE_STRING*,BOOLEAN);
+NTSTATUS  WINAPI RtlExpandEnvironmentStrings_U(PWSTR, const UNICODE_STRING*, UNICODE_STRING*, ULONG*);
 LONGLONG  WINAPI RtlExtendedMagicDivide(LONGLONG,LONGLONG,INT);
 LONGLONG  WINAPI RtlExtendedIntegerMultiply(LONGLONG,INT);
 LONGLONG  WINAPI RtlExtendedLargeIntegerDivide(LONGLONG,INT,INT *);


More information about the wine-patches mailing list