Eric Pouech wrote:
This patch implements a bunch of environment related APIs (note that
kernel32 doesn't make use of it yet)
Please use this version instead, I forgot to add a modified file
A+
--
Eric Pouech
Name: ntkrnl_20
ChangeLog: Implement a bunch of environment related NTDLL's API
License: X11
GenDate: 2003/05/03 07:37:41 UTC
ModifiedFiles: dlls/ntdll/Makefile.in dlls/ntdll/ntdll.spec dlls/ntdll/ntdll_misc.h include/winternl.h
AddedFiles: dlls/ntdll/env.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/dlls/ntdll/Makefile.in,v
retrieving revision 1.59
diff -u -u -r1.59 Makefile.in
--- dlls/ntdll/Makefile.in 30 Apr 2003 00:53:23 -0000 1.59
+++ dlls/ntdll/Makefile.in 2 May 2003 16:48:38 -0000
@@ -70,6 +70,7 @@
cdrom.c \
critsection.c \
debugtools.c \
+ env.c \
error.c \
exception.c \
file.c \
Index: dlls/ntdll/ntdll.spec
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/dlls/ntdll/ntdll.spec,v
retrieving revision 1.109
diff -u -u -r1.109 ntdll.spec
--- dlls/ntdll/ntdll.spec 1 May 2003 00:29:26 -0000 1.109
+++ dlls/ntdll/ntdll.spec 3 May 2003 07:30:27 -0000
@@ -319,7 +319,7 @@
@ stdcall RtlCopyUnicodeString(ptr ptr)
@ stdcall RtlCreateAcl(ptr long long)
@ stub RtlCreateAndSetSD
-@ stdcall RtlCreateEnvironment(long long)
+@ stdcall RtlCreateEnvironment(long ptr)
@ stdcall RtlCreateHeap(long ptr long long ptr ptr)
@ stub RtlCreateProcessParameters
@ stub RtlCreateQueryDebugBuffer
@@ -343,7 +343,7 @@
@ stub RtlDeleteRegistryValue
@ stdcall RtlDeleteResource(ptr)
@ stdcall RtlDeleteSecurityObject(long)
-@ stdcall RtlDestroyEnvironment(long)
+@ stdcall RtlDestroyEnvironment(ptr)
@ stdcall RtlDestroyHeap(long)
@ stub RtlDestroyProcessParameters
@ stub RtlDestroyQueryDebugBuffer
@@ -481,7 +481,7 @@
@ stdcall RtlPrefixString(ptr ptr long)
@ stdcall RtlPrefixUnicodeString(ptr ptr long)
@ stub RtlProtectHeap
-@ stdcall RtlQueryEnvironmentVariable_U(long long long)
+@ stdcall RtlQueryEnvironmentVariable_U(ptr ptr ptr)
@ stub RtlQueryInformationAcl
@ stub RtlQueryProcessBackTraceInformation
@ stub RtlQueryProcessDebugInformation
@@ -508,10 +508,10 @@
@ stub RtlSelfRelativeToAbsoluteSD
@ stdcall RtlSetAllBits(ptr)
@ stdcall RtlSetBits(ptr long long)
@ stub RtlSetCurrentDirectory_U
-@ stub RtlSetCurrentEnvironment
+@ stdcall RtlSetCurrentEnvironment(wstr ptr)
@ stdcall RtlSetDaclSecurityDescriptor(ptr long ptr long)
-@ stdcall RtlSetEnvironmentVariable(long long long)
+@ stdcall RtlSetEnvironmentVariable(ptr ptr ptr)
@ stdcall RtlSetGroupSecurityDescriptor(ptr ptr long)
@ stub RtlSetInformationAcl
@ stdcall RtlSetOwnerSecurityDescriptor(ptr ptr long)
Index: dlls/ntdll/ntdll_misc.h
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/dlls/ntdll/ntdll_misc.h,v
retrieving revision 1.15
diff -u -u -r1.15 ntdll_misc.h
--- dlls/ntdll/ntdll_misc.h 7 Apr 2003 23:27:55 -0000 1.15
+++ dlls/ntdll/ntdll_misc.h 2 May 2003 19:30:30 -0000
@@ -40,9 +40,49 @@
FARPROC origfun, DWORD ordinal );
extern void RELAY_SetupDLL( const char *module );
+typedef struct _RTL_USER_PROCESS_PARAMETERS
+{
+ ULONG AllocationSize;
+ ULONG Size;
+ ULONG Flags;
+ ULONG DebugFlags;
+ HANDLE hConsole;
+ ULONG ProcessGroup;
+ HANDLE hStdInput;
+ HANDLE hStdOutput;
+ HANDLE hStdError;
+ UNICODE_STRING CurrentDirectoryName;
+ HANDLE CurrentDirectoryHandle;
+ UNICODE_STRING DllPath;
+ UNICODE_STRING ImagePathName;
+ UNICODE_STRING CommandLine;
+ PWSTR Environment;
+ ULONG dwX;
+ ULONG dwY;
+ ULONG dwXSize;
+ ULONG dwYSize;
+ ULONG dwXCountChars;
+ ULONG dwYCountChars;
+ ULONG dwFillAttribute;
+ ULONG dwFlags;
+ ULONG wShowWindow;
+ UNICODE_STRING WindowTitle;
+ UNICODE_STRING DesktopInfo;
+ UNICODE_STRING ShellInfo;
+ UNICODE_STRING RuntimeInfo;
+} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
+
static inline HANDLE ntdll_get_process_heap(void)
{
HANDLE *pdb = (HANDLE *)NtCurrentTeb()->process;
return pdb[0x18 / sizeof(HANDLE)]; /* get dword at offset 0x18 in pdb */
+}
+
+/* FIXME: this should be part of PEB, once it's defined */
+extern RTL_USER_PROCESS_PARAMETERS* process_pmts;
+
+static inline RTL_USER_PROCESS_PARAMETERS* ntdll_get_process_pmts(void)
+{
+ return process_pmts;
}
#endif
Index: include/winternl.h
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/include/winternl.h,v
retrieving revision 1.29
diff -u -u -r1.29 winternl.h
--- include/winternl.h 1 May 2003 00:29:26 -0000 1.29
+++ include/winternl.h 2 May 2003 19:25:33 -0000
@@ -951,7 +951,7 @@
void WINAPI RtlCopyString(STRING*,const STRING*);
void WINAPI RtlCopyUnicodeString(UNICODE_STRING*,const UNICODE_STRING*);
NTSTATUS WINAPI RtlCreateAcl(PACL,DWORD,DWORD);
-DWORD WINAPI RtlCreateEnvironment(DWORD,DWORD);
+NTSTATUS WINAPI RtlCreateEnvironment(BOOLEAN, PWSTR*);
HANDLE WINAPI RtlCreateHeap(ULONG,PVOID,ULONG,ULONG,PVOID,PRTL_HEAP_DEFINITION);
NTSTATUS WINAPI RtlCreateSecurityDescriptor(PSECURITY_DESCRIPTOR,DWORD);
BOOLEAN WINAPI RtlCreateUnicodeString(PUNICODE_STRING,LPCWSTR);
@@ -960,10 +960,10 @@
NTSTATUS WINAPI RtlDeleteCriticalSection(RTL_CRITICAL_SECTION *);
void WINAPI RtlDeleteResource(LPRTL_RWLOCK);
DWORD WINAPI RtlDeleteSecurityObject(DWORD);
-DWORD WINAPI RtlDestroyEnvironment(DWORD);
+NTSTATUS WINAPI RtlDestroyEnvironment(PWSTR);
HANDLE WINAPI RtlDestroyHeap(HANDLE);
DOS_PATHNAME_TYPE WINAPI RtlDetermineDosPathNameType_U(PCWSTR);
BOOLEAN WINAPI RtlDosPathNameToNtPathName_U(LPWSTR,PUNICODE_STRING,DWORD,DWORD);
WCHAR WINAPI RtlDowncaseUnicodeChar(WCHAR);
NTSTATUS WINAPI RtlDowncaseUnicodeString(UNICODE_STRING*,const UNICODE_STRING*,BOOLEAN);
void WINAPI RtlDumpResource(LPRTL_RWLOCK);
@@ -1073,7 +1074,7 @@
BOOLEAN WINAPI RtlPrefixString(const STRING*,const STRING*,BOOLEAN);
BOOLEAN WINAPI RtlPrefixUnicodeString(const UNICODE_STRING*,const UNICODE_STRING*,BOOLEAN);
-DWORD WINAPI RtlQueryEnvironmentVariable_U(DWORD,PUNICODE_STRING,PUNICODE_STRING) ;
+NTSTATUS WINAPI RtlQueryEnvironmentVariable_U(PWSTR,PUNICODE_STRING,PUNICODE_STRING);
NTSTATUS WINAPI RtlQueryTimeZoneInformation(LPTIME_ZONE_INFORMATION);
void WINAPI RtlRaiseException(PEXCEPTION_RECORD);
@@ -1087,8 +1088,9 @@
void WINAPI RtlSecondsSince1980ToTime(DWORD,LARGE_INTEGER *);
void WINAPI RtlSetAllBits(PRTL_BITMAP);
void WINAPI RtlSetBits(PRTL_BITMAP,ULONG,ULONG);
+void WINAPI RtlSetCurrentEnvironment(PWSTR, PWSTR*);
NTSTATUS WINAPI RtlSetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR,BOOLEAN,PACL,BOOLEAN);
-DWORD WINAPI RtlSetEnvironmentVariable(DWORD,PUNICODE_STRING,PUNICODE_STRING);
+NTSTATUS WINAPI RtlSetEnvironmentVariable(PWSTR*,PUNICODE_STRING,PUNICODE_STRING);
NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(PSECURITY_DESCRIPTOR,PSID,BOOLEAN);
NTSTATUS WINAPI RtlSetGroupSecurityDescriptor(PSECURITY_DESCRIPTOR,PSID,BOOLEAN);
NTSTATUS WINAPI RtlSetSaclSecurityDescriptor(PSECURITY_DESCRIPTOR,BOOLEAN,PACL,BOOLEAN);
--- /dev/null 1970-01-01 01:00:00.000000000 +0100
+++ dlls/ntdll/env.c 2003-05-02 21:06:20.000000000 +0200
@@ -0,0 +1,287 @@
+/*
+ * Ntdll environment functions
+ *
+ * Copyright 1996, 1998 Alexandre Julliard
+ * Copyright 2003 Eric Pouech
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include "config.h"
+
+#include <assert.h>
+
+#include "winternl.h"
+#include "wine/unicode.h"
+#include "wine/debug.h"
+#include "ntdll_misc.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(environ);
+
+/******************************************************************************
+ * RtlCreateEnvironment [NTDLL.@]
+ */
+NTSTATUS WINAPI RtlCreateEnvironment(BOOLEAN inherit, PWSTR* env)
+{
+ NTSTATUS nts;
+
+ TRACE("(%u,%p)!\n", inherit, env);
+
+ if (inherit)
+ {
+ MEMORY_BASIC_INFORMATION mbi;
+
+ RtlAcquirePebLock();
+
+ nts = NtQueryVirtualMemory(NtCurrentProcess(), ntdll_get_process_pmts()->Environment,
+ 0, &mbi, sizeof(mbi), NULL);
+ if (nts == STATUS_SUCCESS)
+ {
+ *env = NULL;
+ nts = NtAllocateVirtualMemory(NtCurrentProcess(), (void**)env, 0, &mbi.RegionSize,
+ MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+ if (nts == STATUS_SUCCESS)
+ memcpy(*env, ntdll_get_process_pmts()->Environment, mbi.RegionSize);
+ else *env = NULL;
+ }
+ RtlReleasePebLock();
+ }
+ else
+ {
+ ULONG size = 1;
+ nts = NtAllocateVirtualMemory(NtCurrentProcess(), (void**)env, 0, &size,
+ MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+ if (nts == STATUS_SUCCESS)
+ memset(*env, 0, size);
+ }
+
+ return nts;
+}
+
+/******************************************************************************
+ * RtlDestroyEnvironment [NTDLL.@]
+ */
+NTSTATUS WINAPI RtlDestroyEnvironment(PWSTR env)
+{
+ ULONG size = 0;
+
+ TRACE("(%p)!\n", env);
+
+ return NtFreeVirtualMemory(NtCurrentProcess(), (void**)&env, &size, MEM_RELEASE);
+}
+
+/******************************************************************
+ * RtlQueryEnvironmentVariable_U [NTDLL.@]
+ *
+ */
+NTSTATUS WINAPI RtlQueryEnvironmentVariable_U(PWSTR env,
+ PUNICODE_STRING name,
+ PUNICODE_STRING value)
+{
+ NTSTATUS nts = STATUS_VARIABLE_NOT_FOUND;
+ PWSTR var;
+ unsigned namelen, varlen;
+
+ TRACE("%s %s %p\n", debugstr_w(env), debugstr_w(name->Buffer), value);
+
+ value->Length = 0;
+ namelen = name->Length / sizeof(WCHAR);
+ if (!namelen) return nts;
+
+ if (!env)
+ {
+ RtlAcquirePebLock();
+ var = ntdll_get_process_pmts()->Environment;
+ }
+ else var = env;
+
+ for (; *var; var += varlen + 1)
+ {
+ 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 = (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;
+ }
+ }
+
+ if (!env) RtlReleasePebLock();
+
+ return nts;
+}
+
+/******************************************************************
+ * RtlSetCurrentEnvironment [NTDLL.@]
+ *
+ */
+void WINAPI RtlSetCurrentEnvironment(PWSTR new_env, PWSTR* old_env)
+{
+ TRACE("(%p %p)\n", new_env, old_env);
+
+ RtlAcquirePebLock();
+
+ if (old_env) *old_env = ntdll_get_process_pmts()->Environment;
+ ntdll_get_process_pmts()->Environment = new_env;
+
+ RtlReleasePebLock();
+}
+
+
+/******************************************************************************
+ * RtlSetEnvironmentVariable [NTDLL.@]
+ */
+NTSTATUS WINAPI RtlSetEnvironmentVariable(PWSTR* penv, PUNICODE_STRING name,
+ PUNICODE_STRING value)
+{
+ INT len, old_size;
+ LPWSTR p, env;
+ NTSTATUS nts = STATUS_VARIABLE_NOT_FOUND;
+ MEMORY_BASIC_INFORMATION mbi;
+
+ TRACE("(%p,%s,%s): stub!\n", penv, debugstr_w(name->Buffer), debugstr_w(value->Buffer));
+
+ if (!name || !name->Buffer || !name->Buffer[0])
+ return STATUS_INVALID_PARAMETER_1;
+ /* variable names can't contain a '=' except as a first character */
+ if (strchrW(name->Buffer + 1, '=')) return STATUS_INVALID_PARAMETER;
+
+ if (!penv)
+ {
+ RtlAcquirePebLock();
+ env = ntdll_get_process_pmts()->Environment;
+ } else env = *penv;
+
+ len = name->Length / sizeof(WCHAR);
+
+ /* compute current size of environment */
+ for (p = env; *p; p += strlenW(p) + 1);
+ old_size = p + 1 - env;
+
+ /* Find a place to insert the string */
+ for (p = env; *p; p += strlenW(p) + 1)
+ {
+ if (!strncmpiW(name->Buffer, p, len) && (p[len] == '=')) break;
+ }
+ if (!value && !*p) goto done; /* Value to remove doesn't exist */
+
+ /* Realloc the buffer */
+ len = value ? len + value->Length / sizeof(WCHAR) + 2 : 0;
+ if (*p) len -= strlenW(p) + 1; /* The name already exists */
+
+ if (len < 0)
+ {
+ LPWSTR next = p + strlenW(p) + 1; /* We know there is a next one */
+ memmove(next + len, next, (old_size - (next - env)) * sizeof(WCHAR));
+ }
+
+ nts = NtQueryVirtualMemory(NtCurrentProcess(), env, 0,
+ &mbi, sizeof(mbi), NULL);
+ if (nts != STATUS_SUCCESS) goto done;
+
+ if ((old_size + len) * sizeof(WCHAR) > mbi.RegionSize)
+ {
+ LPWSTR new_env;
+ ULONG new_size = (old_size + len) * sizeof(WCHAR);
+
+ new_env = NULL;
+ nts = NtAllocateVirtualMemory(NtCurrentProcess(), (void**)&new_env, 0,
+ &new_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+ if (nts != STATUS_SUCCESS) goto done;
+
+ memmove(new_env, env, (p - env) * sizeof(WCHAR));
+ assert(len > 0);
+ memmove(new_env + (p - env) + len, p, (old_size - (p - env)) * sizeof(WCHAR));
+ p = new_env + (p - env);
+
+ RtlDestroyEnvironment(env);
+ if (!penv) ntdll_get_process_pmts()->Environment = new_env;
+ else *penv = new_env;
+ env = new_env;
+ }
+ else
+ {
+ if (len > 0) memmove(p + len, p, (old_size - (p - env)) * sizeof(WCHAR));
+ }
+
+ /* Set the new string */
+ if (value)
+ {
+ static const WCHAR equalW[] = {'=',0};
+
+ strcpyW(p, name->Buffer);
+ strcatW(p, equalW);
+ strcatW(p, value->Buffer);
+ }
+
+done:
+ if (!penv) RtlReleasePebLock();
+
+ return nts;
+}
+
+/***********************************************************************
+ * build_environment
+ *
+ * Build the Win32 environment from the Unix environment
+ */
+BOOL build_initial_environment(void)
+{
+ extern char **environ;
+ LPSTR* e, te;
+ LPWSTR p;
+ ULONG size;
+ NTSTATUS nts;
+ int len;
+
+ /* Compute the total size of the Unix environment */
+ size = sizeof(BYTE);
+ for (e = environ; *e; e++)
+ {
+ if (!memcmp(*e, "PATH=", 5)) continue;
+ size += strlen(*e) + 1;
+ }
+ size *= sizeof(WCHAR);
+
+ /* Now allocate the environment */
+ nts = NtAllocateVirtualMemory(NtCurrentProcess(), (void**)&p, 0, &size,
+ MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+ if (nts != STATUS_SUCCESS) return FALSE;
+
+ ntdll_get_process_pmts()->Environment = p;
+ /* And fill it with the Unix environment */
+ for (e = environ; *e; e++)
+ {
+ /* skip Unix PATH and store WINEPATH as PATH */
+ if (!memcmp(*e, "PATH=", 5)) continue;
+ if (!memcmp(*e, "WINEPATH=", 9 )) te = *e + 4; else te = *e;
+ len = strlen(te);
+ RtlMultiByteToUnicodeN(p, len * sizeof(WCHAR), NULL, te, len);
+ p[len] = 0;
+ p += len + 1;
+ }
+ *p = 0;
+
+ return TRUE;
+}
+