Commit dc90fe9a authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Set the environment size in the process parameters.

parent ea5e89a5
...@@ -715,6 +715,7 @@ void WINAPI RtlSetCurrentEnvironment(PWSTR new_env, PWSTR* old_env) ...@@ -715,6 +715,7 @@ void WINAPI RtlSetCurrentEnvironment(PWSTR new_env, PWSTR* old_env)
prev = NtCurrentTeb()->Peb->ProcessParameters->Environment; prev = NtCurrentTeb()->Peb->ProcessParameters->Environment;
NtCurrentTeb()->Peb->ProcessParameters->Environment = new_env; NtCurrentTeb()->Peb->ProcessParameters->Environment = new_env;
NtCurrentTeb()->Peb->ProcessParameters->EnvironmentSize = RtlSizeHeap( GetProcessHeap(), 0, new_env );
RtlReleasePebLock(); RtlReleasePebLock();
...@@ -775,7 +776,7 @@ NTSTATUS WINAPI RtlSetEnvironmentVariable(PWSTR* penv, PUNICODE_STRING name, ...@@ -775,7 +776,7 @@ NTSTATUS WINAPI RtlSetEnvironmentVariable(PWSTR* penv, PUNICODE_STRING name,
if ((old_size + len) * sizeof(WCHAR) > RtlSizeHeap( GetProcessHeap(), 0, env )) if ((old_size + len) * sizeof(WCHAR) > RtlSizeHeap( GetProcessHeap(), 0, env ))
{ {
SIZE_T new_size = max( old_size * 2, old_size + len ) * sizeof(WCHAR); SIZE_T new_size = (old_size + len) * sizeof(WCHAR);
LPWSTR new_env = RtlAllocateHeap( GetProcessHeap(), 0, new_size ); LPWSTR new_env = RtlAllocateHeap( GetProcessHeap(), 0, new_size );
if (!new_env) if (!new_env)
...@@ -783,13 +784,16 @@ NTSTATUS WINAPI RtlSetEnvironmentVariable(PWSTR* penv, PUNICODE_STRING name, ...@@ -783,13 +784,16 @@ NTSTATUS WINAPI RtlSetEnvironmentVariable(PWSTR* penv, PUNICODE_STRING name,
nts = STATUS_NO_MEMORY; nts = STATUS_NO_MEMORY;
goto done; goto done;
} }
memmove(new_env, env, (p - env) * sizeof(WCHAR)); memcpy(new_env, env, (p - env) * sizeof(WCHAR));
assert(len > 0); memcpy(new_env + (p - env) + len, p, (old_size - (p - env)) * sizeof(WCHAR));
memmove(new_env + (p - env) + len, p, (old_size - (p - env)) * sizeof(WCHAR));
p = new_env + (p - env); p = new_env + (p - env);
RtlDestroyEnvironment(env); RtlDestroyEnvironment(env);
if (!penv) NtCurrentTeb()->Peb->ProcessParameters->Environment = new_env; if (!penv)
{
NtCurrentTeb()->Peb->ProcessParameters->Environment = new_env;
NtCurrentTeb()->Peb->ProcessParameters->EnvironmentSize = new_size;
}
else *penv = new_env; else *penv = new_env;
} }
else else
...@@ -1023,12 +1027,14 @@ NTSTATUS WINAPI RtlCreateProcessParametersEx( RTL_USER_PROCESS_PARAMETERS **resu ...@@ -1023,12 +1027,14 @@ NTSTATUS WINAPI RtlCreateProcessParametersEx( RTL_USER_PROCESS_PARAMETERS **resu
+ ROUND_SIZE( ShellInfo->MaximumLength ) + ROUND_SIZE( ShellInfo->MaximumLength )
+ ROUND_SIZE( RuntimeInfo->MaximumLength )); + ROUND_SIZE( RuntimeInfo->MaximumLength ));
if ((ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, size + ROUND_SIZE(env_size) ))) env_size = ROUND_SIZE( env_size );
if ((ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, size + env_size )))
{ {
RTL_USER_PROCESS_PARAMETERS *params = ptr; RTL_USER_PROCESS_PARAMETERS *params = ptr;
params->AllocationSize = size; params->AllocationSize = size;
params->Size = size; params->Size = size;
params->Flags = PROCESS_PARAMS_FLAG_NORMALIZED; params->Flags = PROCESS_PARAMS_FLAG_NORMALIZED;
params->EnvironmentSize = env_size;
if (cur_params) params->ConsoleFlags = cur_params->ConsoleFlags; if (cur_params) params->ConsoleFlags = cur_params->ConsoleFlags;
/* all other fields are zero */ /* all other fields are zero */
...@@ -1263,4 +1269,5 @@ done: ...@@ -1263,4 +1269,5 @@ done:
RtlSetCurrentDirectory_U( &curdir ); RtlSetCurrentDirectory_U( &curdir );
} }
set_wow64_environment( &params->Environment ); set_wow64_environment( &params->Environment );
params->EnvironmentSize = RtlSizeHeap( GetProcessHeap(), 0, params->Environment );
} }
...@@ -325,6 +325,13 @@ static WCHAR *get_params_string( RTL_USER_PROCESS_PARAMETERS *params, UNICODE_ST ...@@ -325,6 +325,13 @@ static WCHAR *get_params_string( RTL_USER_PROCESS_PARAMETERS *params, UNICODE_ST
return (WCHAR *)((char *)params + (UINT_PTR)str->Buffer); return (WCHAR *)((char *)params + (UINT_PTR)str->Buffer);
} }
static SIZE_T get_env_length( const WCHAR *env )
{
const WCHAR *end = env;
while (*end) end += wcslen(end) + 1;
return end + 1 - env;
}
static UINT_PTR align(UINT_PTR size, unsigned int alignment) static UINT_PTR align(UINT_PTR size, unsigned int alignment)
{ {
return (size + (alignment - 1)) & ~(alignment - 1); return (size + (alignment - 1)) & ~(alignment - 1);
...@@ -438,12 +445,12 @@ static void test_process_params(void) ...@@ -438,12 +445,12 @@ static void test_process_params(void)
{ {
ok( (char *)params->Environment - (char *)params == (UINT_PTR)pos, ok( (char *)params->Environment - (char *)params == (UINT_PTR)pos,
"wrong env %lx/%lx\n", (UINT_PTR)((char *)params->Environment - (char *)params), pos); "wrong env %lx/%lx\n", (UINT_PTR)((char *)params->Environment - (char *)params), pos);
str = params->Environment; pos += get_env_length(params->Environment) * sizeof(WCHAR);
while (*str) str += lstrlenW(str) + 1;
str++;
pos += (str - params->Environment) * sizeof(WCHAR);
ok( align(pos, sizeof(void *)) == size || ok( align(pos, sizeof(void *)) == size ||
broken( align(pos, 4) == size ), "wrong size %lx/%lx\n", pos, size ); broken( align(pos, 4) == size ), "wrong size %lx/%lx\n", pos, size );
ok( params->EnvironmentSize == size - ((char *)params->Environment - (char *)params),
"wrong len %x/%lx\n", params->EnvironmentSize,
size - ((char *)params->Environment - (char *)params) );
} }
else ok( broken(TRUE), "environment not inside block\n" ); /* <= win2k3 */ else ok( broken(TRUE), "environment not inside block\n" ); /* <= win2k3 */
pRtlDestroyProcessParameters( params ); pRtlDestroyProcessParameters( params );
...@@ -492,12 +499,12 @@ static void test_process_params(void) ...@@ -492,12 +499,12 @@ static void test_process_params(void)
{ {
ok( (char *)params->Environment - (char *)params == pos, ok( (char *)params->Environment - (char *)params == pos,
"wrong env %lx/%lx\n", (UINT_PTR)((char *)params->Environment - (char *)params), pos); "wrong env %lx/%lx\n", (UINT_PTR)((char *)params->Environment - (char *)params), pos);
str = params->Environment; pos += get_env_length(params->Environment) * sizeof(WCHAR);
while (*str) str += lstrlenW(str) + 1;
str++;
pos += (str - params->Environment) * sizeof(WCHAR);
ok( align(pos, sizeof(void *)) == size || ok( align(pos, sizeof(void *)) == size ||
broken( align(pos, 4) == size ), "wrong size %lx/%lx\n", pos, size ); broken( align(pos, 4) == size ), "wrong size %lx/%lx\n", pos, size );
ok( params->EnvironmentSize == size - ((char *)params->Environment - (char *)params),
"wrong len %x/%lx\n", params->EnvironmentSize,
size - ((char *)params->Environment - (char *)params) );
} }
else ok( broken(TRUE), "environment not inside block\n" ); /* <= win2k3 */ else ok( broken(TRUE), "environment not inside block\n" ); /* <= win2k3 */
pRtlDestroyProcessParameters( params ); pRtlDestroyProcessParameters( params );
...@@ -532,11 +539,7 @@ static void test_process_params(void) ...@@ -532,11 +539,7 @@ static void test_process_params(void)
pos = check_string( cur_params, &cur_params->RuntimeInfo, NULL, pos ); pos = check_string( cur_params, &cur_params->RuntimeInfo, NULL, pos );
/* environment may follow */ /* environment may follow */
str = (WCHAR *)pos; str = (WCHAR *)pos;
if (pos - (UINT_PTR)cur_params < cur_params->Size) if (pos - (UINT_PTR)cur_params < cur_params->Size) str += get_env_length(str);
{
while (*str) str += lstrlenW(str) + 1;
str++;
}
ok( (char *)str == (char *)cur_params + cur_params->Size, ok( (char *)str == (char *)cur_params + cur_params->Size,
"wrong end ptr %p/%p\n", str, (char *)cur_params + cur_params->Size ); "wrong end ptr %p/%p\n", str, (char *)cur_params + cur_params->Size );
...@@ -547,13 +550,14 @@ static void test_process_params(void) ...@@ -547,13 +550,14 @@ static void test_process_params(void)
if (VirtualQuery( initial_env, &info, sizeof(info) ) && info.AllocationBase == initial_env) if (VirtualQuery( initial_env, &info, sizeof(info) ) && info.AllocationBase == initial_env)
{ {
todo_wine
ok( broken(TRUE), "env not a heap block %p / %p\n", cur_params, initial_env ); /* winxp */ ok( broken(TRUE), "env not a heap block %p / %p\n", cur_params, initial_env ); /* winxp */
} }
else else
{ {
size = HeapSize( GetProcessHeap(), 0, initial_env ); size = HeapSize( GetProcessHeap(), 0, initial_env );
ok( size != ~(SIZE_T)0, "env is not a heap block %p / %p\n", cur_params, initial_env ); ok( size != ~(SIZE_T)0, "env is not a heap block %p / %p\n", cur_params, initial_env );
ok( cur_params->EnvironmentSize == size,
"wrong len %x/%lx\n", cur_params->EnvironmentSize, size );
} }
} }
...@@ -587,6 +591,7 @@ static void test_RtlSetCurrentEnvironment(void) ...@@ -587,6 +591,7 @@ static void test_RtlSetCurrentEnvironment(void)
NTSTATUS status; NTSTATUS status;
WCHAR *old_env, *env, *prev; WCHAR *old_env, *env, *prev;
BOOL ret; BOOL ret;
SIZE_T size;
status = RtlCreateEnvironment(FALSE, &env); status = RtlCreateEnvironment(FALSE, &env);
ok(!status, "got %#x\n", status); ok(!status, "got %#x\n", status);
...@@ -602,25 +607,56 @@ static void test_RtlSetCurrentEnvironment(void) ...@@ -602,25 +607,56 @@ static void test_RtlSetCurrentEnvironment(void)
ok(!status, "got %#x\n", status); ok(!status, "got %#x\n", status);
old_env = NtCurrentTeb()->Peb->ProcessParameters->Environment; old_env = NtCurrentTeb()->Peb->ProcessParameters->Environment;
ok(NtCurrentTeb()->Peb->ProcessParameters->EnvironmentSize == get_env_length(old_env) * sizeof(WCHAR),
"got wrong size %u\n", NtCurrentTeb()->Peb->ProcessParameters->EnvironmentSize);
ok(NtCurrentTeb()->Peb->ProcessParameters->EnvironmentSize == HeapSize( GetProcessHeap(), 0, old_env ),
"got wrong size %u\n", NtCurrentTeb()->Peb->ProcessParameters->EnvironmentSize);
RtlSetCurrentEnvironment(env, &prev); RtlSetCurrentEnvironment(env, &prev);
ok(prev == old_env, "got wrong previous env %p\n", prev); ok(prev == old_env, "got wrong previous env %p\n", prev);
ok(NtCurrentTeb()->Peb->ProcessParameters->Environment == env, "got wrong current env\n"); ok(NtCurrentTeb()->Peb->ProcessParameters->Environment == env, "got wrong current env\n");
ok(NtCurrentTeb()->Peb->ProcessParameters->EnvironmentSize == get_env_length(env) * sizeof(WCHAR),
"got wrong size %u\n", NtCurrentTeb()->Peb->ProcessParameters->EnvironmentSize);
ok(NtCurrentTeb()->Peb->ProcessParameters->EnvironmentSize == HeapSize( GetProcessHeap(), 0, env ),
"got wrong size %u\n", NtCurrentTeb()->Peb->ProcessParameters->EnvironmentSize);
check_env_var("testenv1", "unus"); check_env_var("testenv1", "unus");
check_env_var("testenv2", NULL); check_env_var("testenv2", NULL);
check_env_var("testenv3", "tres"); check_env_var("testenv3", "tres");
check_env_var("PATH", NULL); check_env_var("PATH", NULL);
env = HeapReAlloc( GetProcessHeap(), 0, env, HeapSize( GetProcessHeap(), 0, env) + 120 );
RtlSetCurrentEnvironment(env, &prev);
ok(NtCurrentTeb()->Peb->ProcessParameters->EnvironmentSize == HeapSize( GetProcessHeap(), 0, env ),
"got wrong size %u\n", NtCurrentTeb()->Peb->ProcessParameters->EnvironmentSize);
RtlSetCurrentEnvironment(old_env, NULL); RtlSetCurrentEnvironment(old_env, NULL);
ok(NtCurrentTeb()->Peb->ProcessParameters->Environment == old_env, "got wrong current env\n"); ok(NtCurrentTeb()->Peb->ProcessParameters->Environment == old_env, "got wrong current env\n");
ok(NtCurrentTeb()->Peb->ProcessParameters->EnvironmentSize == get_env_length(old_env) * sizeof(WCHAR),
"got wrong size %u\n", NtCurrentTeb()->Peb->ProcessParameters->EnvironmentSize);
ok(NtCurrentTeb()->Peb->ProcessParameters->EnvironmentSize == HeapSize( GetProcessHeap(), 0, old_env ),
"got wrong size %u\n", NtCurrentTeb()->Peb->ProcessParameters->EnvironmentSize);
check_env_var("testenv1", "heis"); check_env_var("testenv1", "heis");
check_env_var("testenv2", "dyo"); check_env_var("testenv2", "dyo");
check_env_var("testenv3", NULL); check_env_var("testenv3", NULL);
env = NtCurrentTeb()->Peb->ProcessParameters->Environment;
size = get_env_length(env) * sizeof(WCHAR);
ok( NtCurrentTeb()->Peb->ProcessParameters->EnvironmentSize == size,
"got wrong size %u\n", NtCurrentTeb()->Peb->ProcessParameters->EnvironmentSize );
ok( size == HeapSize( GetProcessHeap(), 0, env ),
"got wrong size %lu / %lu\n", size, HeapSize( GetProcessHeap(), 0, env ));
SetEnvironmentVariableA("testenv1", NULL); SetEnvironmentVariableA("testenv1", NULL);
SetEnvironmentVariableA("testenv2", NULL); SetEnvironmentVariableA("testenv2", NULL);
env = NtCurrentTeb()->Peb->ProcessParameters->Environment;
ok( NtCurrentTeb()->Peb->ProcessParameters->EnvironmentSize == size,
"got wrong size %u\n", NtCurrentTeb()->Peb->ProcessParameters->EnvironmentSize );
ok( size == HeapSize( GetProcessHeap(), 0, env ),
"got wrong size %lu / %lu\n", size, HeapSize( GetProcessHeap(), 0, env ));
ok( size > get_env_length(env) * sizeof(WCHAR), "got wrong size %lu\n", size );
} }
START_TEST(env) START_TEST(env)
......
...@@ -199,6 +199,11 @@ typedef struct _RTL_USER_PROCESS_PARAMETERS ...@@ -199,6 +199,11 @@ typedef struct _RTL_USER_PROCESS_PARAMETERS
UNICODE_STRING ShellInfo; UNICODE_STRING ShellInfo;
UNICODE_STRING RuntimeInfo; UNICODE_STRING RuntimeInfo;
RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20]; RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20];
ULONG EnvironmentSize;
ULONG EnvironmentVersion;
PVOID PackageDependencyData;
ULONG ProcessGroupId;
ULONG LoaderThreads;
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS; } RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
/* value for Flags field (FIXME: not the correct name) */ /* value for Flags field (FIXME: not the correct name) */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment