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