From 76cbf12894b9ee83ea8dd6fb5b9443720a90fe19 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 16 Oct 2018 20:25:02 +0200 Subject: [PATCH] ntdll/tests: Add tests for RtlCreateProcessParameters(). Signed-off-by: Alexandre Julliard --- dlls/ntdll/tests/env.c | 198 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 187 insertions(+), 11 deletions(-) diff --git a/dlls/ntdll/tests/env.c b/dlls/ntdll/tests/env.c index 8989760f43c..0c864fb2bca 100644 --- a/dlls/ntdll/tests/env.c +++ b/dlls/ntdll/tests/env.c @@ -30,6 +30,12 @@ static NTSTATUS (WINAPI *pRtlQueryEnvironmentVariable_U)(PWSTR, PUNICODE_STRING, static void (WINAPI *pRtlSetCurrentEnvironment)(PWSTR, PWSTR*); static NTSTATUS (WINAPI *pRtlSetEnvironmentVariable)(PWSTR*, PUNICODE_STRING, PUNICODE_STRING); static NTSTATUS (WINAPI *pRtlExpandEnvironmentStrings_U)(LPWSTR, PUNICODE_STRING, PUNICODE_STRING, PULONG); +static NTSTATUS (WINAPI *pRtlCreateProcessParameters)(RTL_USER_PROCESS_PARAMETERS**, + const UNICODE_STRING*, const UNICODE_STRING*, + const UNICODE_STRING*, const UNICODE_STRING*, + PWSTR, const UNICODE_STRING*, const UNICODE_STRING*, + const UNICODE_STRING*, const UNICODE_STRING*); +static void (WINAPI *pRtlDestroyProcessParameters)(RTL_USER_PROCESS_PARAMETERS *); static WCHAR small_env[] = {'f','o','o','=','t','o','t','o',0, 'f','o','=','t','i','t','i',0, @@ -274,14 +280,184 @@ static void testExpand(void) } +static WCHAR *get_params_string( RTL_USER_PROCESS_PARAMETERS *params, UNICODE_STRING *str ) +{ + if (params->Flags & PROCESS_PARAMS_FLAG_NORMALIZED) return str->Buffer; + return (WCHAR *)((char *)params + (UINT_PTR)str->Buffer); +} + +static UINT_PTR check_string_( int line, RTL_USER_PROCESS_PARAMETERS *params, UNICODE_STRING *str, + const UNICODE_STRING *expect, UINT_PTR pos ) +{ + ok_(__FILE__,line)( str->Length == expect->Length, "wrong length %u/%u\n", + str->Length, expect->Length ); + ok_(__FILE__,line)( str->MaximumLength == expect->MaximumLength || + broken( str->MaximumLength == 1 && expect->MaximumLength == 2 ), /* winxp */ + "wrong maxlength %u/%u\n", str->MaximumLength, expect->MaximumLength ); + if (!str->MaximumLength) + { + ok_(__FILE__,line)( str->Buffer == NULL, "buffer not null %p\n", str->Buffer ); + return pos; + } + ok_(__FILE__,line)( (UINT_PTR)str->Buffer == ((pos + sizeof(void*) - 1) & ~(sizeof(void *) - 1)) || + broken( (UINT_PTR)str->Buffer == ((pos + 3) & ~3) ), "wrong buffer %lx/%lx\n", + (UINT_PTR)str->Buffer, pos ); + if (str->Length < str->MaximumLength) + { + WCHAR *ptr = get_params_string( params, str ); + ok_(__FILE__,line)( !ptr[str->Length / sizeof(WCHAR)], "string not null-terminated %s\n", + wine_dbgstr_wn( ptr, str->MaximumLength / sizeof(WCHAR) )); + } + return (UINT_PTR)str->Buffer + str->MaximumLength; +} +#define check_string(params,str,expect,pos) check_string_(__LINE__,params,str,expect,pos) + +static void test_process_params(void) +{ + static WCHAR empty[] = {0}; + static const UNICODE_STRING empty_str = { 0, sizeof(empty), empty }; + static const UNICODE_STRING null_str = { 0, 0, NULL }; + static WCHAR exeW[] = {'c',':','\\','f','o','o','.','e','x','e',0}; + static WCHAR dummyW[] = {'d','u','m','m','y','1',0}; + static WCHAR dummy_dirW[MAX_PATH] = {'d','u','m','m','y','2',0}; + static WCHAR dummy_env[] = {'a','=','b',0,'c','=','d',0,0}; + UNICODE_STRING image = { sizeof(exeW) - sizeof(WCHAR), sizeof(exeW), exeW }; + UNICODE_STRING dummy = { sizeof(dummyW) - sizeof(WCHAR), sizeof(dummyW), dummyW }; + UNICODE_STRING dummy_dir = { 6*sizeof(WCHAR), sizeof(dummy_dirW), dummy_dirW }; + RTL_USER_PROCESS_PARAMETERS *params = NULL; + RTL_USER_PROCESS_PARAMETERS *cur_params = NtCurrentTeb()->Peb->ProcessParameters; + SIZE_T size; + WCHAR *str; + UINT_PTR pos; + MEMORY_BASIC_INFORMATION info; + NTSTATUS status = pRtlCreateProcessParameters( ¶ms, &image, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL ); + ok( !status, "failed %x\n", status ); + if (VirtualQuery( params, &info, sizeof(info) ) && info.AllocationBase == params) + { + size = info.RegionSize; + ok( broken(TRUE), "not a heap block %p\n", params ); /* winxp */ + ok( params->AllocationSize == info.RegionSize, + "wrong AllocationSize %x/%lx\n", params->AllocationSize, info.RegionSize ); + } + else + { + size = HeapSize( GetProcessHeap(), 0, params ); + ok( size != ~0UL, "not a heap block %p\n", params ); + ok( params->AllocationSize == params->Size, + "wrong AllocationSize %x/%x\n", params->AllocationSize, params->Size ); + } + ok( params->Size < size || broken(params->Size == size), /* <= win2k3 */ + "wrong Size %x/%lx\n", params->Size, size ); + ok( params->Flags == 0, "wrong Flags %u\n", params->Flags ); + ok( params->DebugFlags == 0, "wrong Flags %u\n", params->DebugFlags ); + ok( params->ConsoleHandle == 0, "wrong ConsoleHandle %p\n", params->ConsoleHandle ); + ok( params->ConsoleFlags == 0, "wrong ConsoleFlags %u\n", params->ConsoleFlags ); + ok( params->hStdInput == 0, "wrong hStdInput %p\n", params->hStdInput ); + ok( params->hStdOutput == 0, "wrong hStdOutput %p\n", params->hStdOutput ); + ok( params->hStdError == 0, "wrong hStdError %p\n", params->hStdError ); + ok( params->dwX == 0, "wrong dwX %u\n", params->dwX ); + ok( params->dwY == 0, "wrong dwY %u\n", params->dwY ); + ok( params->dwXSize == 0, "wrong dwXSize %u\n", params->dwXSize ); + ok( params->dwYSize == 0, "wrong dwYSize %u\n", params->dwYSize ); + ok( params->dwXCountChars == 0, "wrong dwXCountChars %u\n", params->dwXCountChars ); + ok( params->dwYCountChars == 0, "wrong dwYCountChars %u\n", params->dwYCountChars ); + ok( params->dwFillAttribute == 0, "wrong dwFillAttribute %u\n", params->dwFillAttribute ); + ok( params->dwFlags == 0, "wrong dwFlags %u\n", params->dwFlags ); + ok( params->wShowWindow == 0, "wrong wShowWindow %u\n", params->wShowWindow ); + pos = (UINT_PTR)params->CurrentDirectory.DosPath.Buffer; + + ok( params->CurrentDirectory.DosPath.MaximumLength == MAX_PATH * sizeof(WCHAR), + "wrong length %x\n", params->CurrentDirectory.DosPath.MaximumLength ); + pos = check_string( params, ¶ms->CurrentDirectory.DosPath, + &cur_params->CurrentDirectory.DosPath, pos ); + if (params->DllPath.MaximumLength) + pos = check_string( params, ¶ms->DllPath, &cur_params->DllPath, pos ); + else + pos = check_string( params, ¶ms->DllPath, &null_str, pos ); + pos = check_string( params, ¶ms->ImagePathName, &image, pos ); + pos = check_string( params, ¶ms->CommandLine, &image, pos ); + pos = check_string( params, ¶ms->WindowTitle, &empty_str, pos ); + pos = check_string( params, ¶ms->Desktop, &empty_str, pos ); + pos = check_string( params, ¶ms->ShellInfo, &empty_str, pos ); + pos = check_string( params, ¶ms->RuntimeInfo, &null_str, pos ); + pos = (pos + 3) & ~3; + ok( pos == params->Size || pos + 4 == params->Size, + "wrong pos %lx/%x\n", pos, params->Size ); + pos = params->Size; + if ((char *)params->Environment > (char *)params && + (char *)params->Environment < (char *)params + size) + { + 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); + ok( ((pos + sizeof(void *) - 1) & ~(sizeof(void *) - 1)) == size || + broken( ((pos + 3) & ~3) == size ), "wrong size %lx/%lx\n", pos, size ); + } + else ok( broken(TRUE), "environment not inside block\n" ); /* <= win2k3 */ + pRtlDestroyProcessParameters( params ); + + status = pRtlCreateProcessParameters( ¶ms, &image, &dummy, &dummy, &dummy, dummy_env, + &dummy, &dummy, &dummy, &dummy ); + ok( !status, "failed %x\n", status ); + if (VirtualQuery( params, &info, sizeof(info) ) && info.AllocationBase == params) + { + size = info.RegionSize; + ok( broken(TRUE), "not a heap block %p\n", params ); /* winxp */ + ok( params->AllocationSize == info.RegionSize, + "wrong AllocationSize %x/%lx\n", params->AllocationSize, info.RegionSize ); + } + else + { + size = HeapSize( GetProcessHeap(), 0, params ); + ok( size != ~0UL, "not a heap block %p\n", params ); + ok( params->AllocationSize == params->Size, + "wrong AllocationSize %x/%x\n", params->AllocationSize, params->Size ); + } + ok( params->Size < size || broken(params->Size == size), /* <= win2k3 */ + "wrong Size %x/%lx\n", params->Size, size ); + pos = (UINT_PTR)params->CurrentDirectory.DosPath.Buffer; + + if (params->CurrentDirectory.DosPath.Length == dummy_dir.Length + sizeof(WCHAR)) + { + /* win10 appends a backslash */ + dummy_dirW[dummy_dir.Length / sizeof(WCHAR)] = '\\'; + dummy_dir.Length += sizeof(WCHAR); + } + pos = check_string( params, ¶ms->CurrentDirectory.DosPath, &dummy_dir, pos ); + pos = check_string( params, ¶ms->DllPath, &dummy, pos ); + pos = check_string( params, ¶ms->ImagePathName, &image, pos ); + pos = check_string( params, ¶ms->CommandLine, &dummy, pos ); + pos = check_string( params, ¶ms->WindowTitle, &dummy, pos ); + pos = check_string( params, ¶ms->Desktop, &dummy, pos ); + pos = check_string( params, ¶ms->ShellInfo, &dummy, pos ); + pos = check_string( params, ¶ms->RuntimeInfo, &dummy, pos ); + pos = (pos + 3) & ~3; + ok( pos == params->Size || pos + 4 == params->Size, + "wrong pos %lx/%x\n", pos, params->Size ); + pos = params->Size; + if ((char *)params->Environment > (char *)params && + (char *)params->Environment < (char *)params + size) + { + 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); + ok( ((pos + sizeof(void *) - 1) & ~(sizeof(void *) - 1)) == size || + broken( ((pos + 3) & ~3) == size ), "wrong size %lx/%lx\n", pos, size ); + } + else ok( broken(TRUE), "environment not inside block\n" ); /* <= win2k3 */ + pRtlDestroyProcessParameters( params ); +} + START_TEST(env) { HMODULE mod = GetModuleHandleA("ntdll.dll"); - if (!mod) - { - win_skip("Not running on NT, skipping tests\n"); - return; - } pRtlMultiByteToUnicodeN = (void *)GetProcAddress(mod,"RtlMultiByteToUnicodeN"); pRtlCreateEnvironment = (void*)GetProcAddress(mod, "RtlCreateEnvironment"); @@ -290,11 +466,11 @@ START_TEST(env) pRtlSetCurrentEnvironment = (void*)GetProcAddress(mod, "RtlSetCurrentEnvironment"); pRtlSetEnvironmentVariable = (void*)GetProcAddress(mod, "RtlSetEnvironmentVariable"); pRtlExpandEnvironmentStrings_U = (void*)GetProcAddress(mod, "RtlExpandEnvironmentStrings_U"); + pRtlCreateProcessParameters = (void*)GetProcAddress(mod, "RtlCreateProcessParameters"); + pRtlDestroyProcessParameters = (void*)GetProcAddress(mod, "RtlDestroyProcessParameters"); - if (pRtlQueryEnvironmentVariable_U) - testQuery(); - if (pRtlSetEnvironmentVariable) - testSet(); - if (pRtlExpandEnvironmentStrings_U) - testExpand(); + testQuery(); + testSet(); + testExpand(); + test_process_params(); }