ntdll: Set the environment size in the process parameters.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50405
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2021-01-13 15:23:28 +01:00
parent ea5e89a545
commit dc90fe9a94
3 changed files with 71 additions and 23 deletions

View File

@ -715,6 +715,7 @@ void WINAPI RtlSetCurrentEnvironment(PWSTR new_env, PWSTR* old_env)
prev = NtCurrentTeb()->Peb->ProcessParameters->Environment;
NtCurrentTeb()->Peb->ProcessParameters->Environment = new_env;
NtCurrentTeb()->Peb->ProcessParameters->EnvironmentSize = RtlSizeHeap( GetProcessHeap(), 0, new_env );
RtlReleasePebLock();
@ -775,7 +776,7 @@ NTSTATUS WINAPI RtlSetEnvironmentVariable(PWSTR* penv, PUNICODE_STRING name,
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 );
if (!new_env)
@ -783,13 +784,16 @@ NTSTATUS WINAPI RtlSetEnvironmentVariable(PWSTR* penv, PUNICODE_STRING name,
nts = STATUS_NO_MEMORY;
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));
memcpy(new_env, env, (p - env) * sizeof(WCHAR));
memcpy(new_env + (p - env) + len, p, (old_size - (p - env)) * sizeof(WCHAR));
p = new_env + (p - 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
@ -1023,12 +1027,14 @@ NTSTATUS WINAPI RtlCreateProcessParametersEx( RTL_USER_PROCESS_PARAMETERS **resu
+ ROUND_SIZE( ShellInfo->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;
params->AllocationSize = size;
params->Size = size;
params->Flags = PROCESS_PARAMS_FLAG_NORMALIZED;
params->AllocationSize = size;
params->Size = size;
params->Flags = PROCESS_PARAMS_FLAG_NORMALIZED;
params->EnvironmentSize = env_size;
if (cur_params) params->ConsoleFlags = cur_params->ConsoleFlags;
/* all other fields are zero */
@ -1263,4 +1269,5 @@ done:
RtlSetCurrentDirectory_U( &curdir );
}
set_wow64_environment( &params->Environment );
params->EnvironmentSize = RtlSizeHeap( GetProcessHeap(), 0, params->Environment );
}

View File

@ -325,6 +325,13 @@ static WCHAR *get_params_string( RTL_USER_PROCESS_PARAMETERS *params, UNICODE_ST
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)
{
return (size + (alignment - 1)) & ~(alignment - 1);
@ -438,12 +445,12 @@ static void test_process_params(void)
{
ok( (char *)params->Environment - (char *)params == (UINT_PTR)pos,
"wrong env %lx/%lx\n", (UINT_PTR)((char *)params->Environment - (char *)params), pos);
str = params->Environment;
while (*str) str += lstrlenW(str) + 1;
str++;
pos += (str - params->Environment) * sizeof(WCHAR);
pos += get_env_length(params->Environment) * sizeof(WCHAR);
ok( align(pos, sizeof(void *)) == 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 */
pRtlDestroyProcessParameters( params );
@ -492,12 +499,12 @@ static void test_process_params(void)
{
ok( (char *)params->Environment - (char *)params == pos,
"wrong env %lx/%lx\n", (UINT_PTR)((char *)params->Environment - (char *)params), pos);
str = params->Environment;
while (*str) str += lstrlenW(str) + 1;
str++;
pos += (str - params->Environment) * sizeof(WCHAR);
pos += get_env_length(params->Environment) * sizeof(WCHAR);
ok( align(pos, sizeof(void *)) == 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 */
pRtlDestroyProcessParameters( params );
@ -532,11 +539,7 @@ static void test_process_params(void)
pos = check_string( cur_params, &cur_params->RuntimeInfo, NULL, pos );
/* environment may follow */
str = (WCHAR *)pos;
if (pos - (UINT_PTR)cur_params < cur_params->Size)
{
while (*str) str += lstrlenW(str) + 1;
str++;
}
if (pos - (UINT_PTR)cur_params < cur_params->Size) str += get_env_length(str);
ok( (char *)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)
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 */
}
else
{
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( cur_params->EnvironmentSize == size,
"wrong len %x/%lx\n", cur_params->EnvironmentSize, size );
}
}
@ -587,6 +591,7 @@ static void test_RtlSetCurrentEnvironment(void)
NTSTATUS status;
WCHAR *old_env, *env, *prev;
BOOL ret;
SIZE_T size;
status = RtlCreateEnvironment(FALSE, &env);
ok(!status, "got %#x\n", status);
@ -602,25 +607,56 @@ static void test_RtlSetCurrentEnvironment(void)
ok(!status, "got %#x\n", status);
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);
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->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("testenv2", NULL);
check_env_var("testenv3", "tres");
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);
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("testenv2", "dyo");
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("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)

View File

@ -199,6 +199,11 @@ typedef struct _RTL_USER_PROCESS_PARAMETERS
UNICODE_STRING ShellInfo;
UNICODE_STRING RuntimeInfo;
RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20];
ULONG EnvironmentSize;
ULONG EnvironmentVersion;
PVOID PackageDependencyData;
ULONG ProcessGroupId;
ULONG LoaderThreads;
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
/* value for Flags field (FIXME: not the correct name) */