From 40165dfa5843a4b5ce5d93da8f6a1b771f810cdb Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 7 May 2021 16:03:27 +0200 Subject: [PATCH] ntdll: RtlCreateUserThread() also takes a zero_bits parameter. Signed-off-by: Alexandre Julliard --- dlls/kernelbase/thread.c | 2 +- dlls/ntdll/ntdll.spec | 2 +- dlls/ntdll/tests/virtual.c | 61 ++++++++++++++++++++++++++++++++++---- dlls/ntdll/thread.c | 4 +-- dlls/ntdll/threadpool.c | 10 +++---- include/winternl.h | 2 +- 6 files changed, 66 insertions(+), 15 deletions(-) diff --git a/dlls/kernelbase/thread.c b/dlls/kernelbase/thread.c index ffa05f8fe81..61cb74c6222 100644 --- a/dlls/kernelbase/thread.c +++ b/dlls/kernelbase/thread.c @@ -84,7 +84,7 @@ HANDLE WINAPI DECLSPEC_HOTPATCH CreateRemoteThreadEx( HANDLE process, SECURITY_A else stack_commit = stack; if (!set_ntstatus( RtlCreateUserThread( process, sa ? sa->lpSecurityDescriptor : NULL, TRUE, - NULL, stack_reserve, stack_commit, + 0, stack_reserve, stack_commit, (PRTL_THREAD_START_ROUTINE)start, param, &handle, &client_id ))) return 0; diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 0ccd06d351f..05712d842c4 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -562,7 +562,7 @@ @ stdcall RtlCreateUserProcess(ptr long ptr ptr ptr long long long long ptr) @ stub RtlCreateUserSecurityObject @ stdcall RtlCreateUserStack(long long long long long ptr) -@ stdcall RtlCreateUserThread(long ptr long ptr long long ptr ptr ptr ptr) +@ stdcall RtlCreateUserThread(long ptr long long long long ptr ptr ptr ptr) @ stdcall RtlCustomCPToUnicodeN(ptr ptr long ptr str long) @ stub RtlCutoverTimeToSystemTime @ stdcall RtlDeNormalizeProcessParams(ptr) diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c index 8f5b0092bea..6980f10c85b 100644 --- a/dlls/ntdll/tests/virtual.c +++ b/dlls/ntdll/tests/virtual.c @@ -31,6 +31,8 @@ static unsigned int page_size; static DWORD64 (WINAPI *pGetEnabledXStateFeatures)(void); static NTSTATUS (WINAPI *pRtlCreateUserStack)(SIZE_T, SIZE_T, ULONG, SIZE_T, SIZE_T, INITIAL_TEB *); +static NTSTATUS (WINAPI *pRtlCreateUserThread)(HANDLE, SECURITY_DESCRIPTOR*, BOOLEAN, ULONG, SIZE_T, + SIZE_T, PRTL_THREAD_START_ROUTINE, void*, HANDLE*, CLIENT_ID* ); static ULONG64 (WINAPI *pRtlGetEnabledExtendedFeatures)(ULONG64); static NTSTATUS (WINAPI *pRtlFreeUserStack)(void *); static void * (WINAPI *pRtlFindExportedRoutineByName)(HMODULE,const char*); @@ -38,6 +40,7 @@ static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL); static NTSTATUS (WINAPI *pNtAllocateVirtualMemoryEx)(HANDLE, PVOID *, SIZE_T *, ULONG, ULONG, MEM_EXTENDED_PARAMETER *, ULONG); static const BOOL is_win64 = sizeof(void*) != sizeof(int); +static BOOL is_wow64; static SYSTEM_BASIC_INFORMATION sbi; @@ -91,9 +94,6 @@ static void test_NtAllocateVirtualMemory(void) NTSTATUS status; SIZE_T size; ULONG_PTR zero_bits; - BOOL is_wow64; - - if (!pIsWow64Process || !pIsWow64Process(NtCurrentProcess(), &is_wow64)) is_wow64 = FALSE; /* simple allocation should success */ size = 0x1000; @@ -485,7 +485,7 @@ static DWORD WINAPI test_stack_size_thread(void *ptr) todo_wine ok( committed == 0x6000, "unexpected stack committed size %x, expected 6000\n", committed ); #endif - return 0; + ExitThread(0); } static void test_RtlCreateUserStack(void) @@ -498,6 +498,7 @@ static void test_RtlCreateUserStack(void) unsigned int i; NTSTATUS ret; HANDLE thread; + CLIENT_ID id; struct { @@ -563,6 +564,54 @@ static void test_RtlCreateUserStack(void) thread = CreateThread(NULL, 0x3ff000, test_stack_size_thread, &args, STACK_SIZE_PARAM_IS_A_RESERVATION, NULL); WaitForSingleObject(thread, INFINITE); CloseHandle(thread); + + args.expect_committed = default_commit < 0x2000 ? 0x2000 : default_commit; + args.expect_reserved = 0x100000; + for (i = 0; i < 32; i++) + { + ULONG mask = ~0u >> i; + NTSTATUS expect_ret = STATUS_SUCCESS; + + if (i == 12) expect_ret = STATUS_CONFLICTING_ADDRESSES; + else if (i >= 13) expect_ret = STATUS_INVALID_PARAMETER; + ret = pRtlCreateUserStack( args.expect_committed, args.expect_reserved, i, 0x1000, 0x1000, &stack ); + ok( ret == expect_ret || ret == STATUS_NO_MEMORY || + (ret == STATUS_INVALID_PARAMETER_3 && expect_ret == STATUS_INVALID_PARAMETER) || + broken( i == 1 && ret == STATUS_INVALID_PARAMETER_3 ), /* win7 */ + "%u: got %x / %x\n", i, ret, expect_ret ); + if (!ret) pRtlFreeUserStack( stack.DeallocationStack ); + ret = pRtlCreateUserThread( GetCurrentProcess(), NULL, FALSE, i, + args.expect_reserved, args.expect_committed, + (void *)test_stack_size_thread, &args, &thread, &id ); + ok( ret == expect_ret || ret == STATUS_NO_MEMORY || + (ret == STATUS_INVALID_PARAMETER_3 && expect_ret == STATUS_INVALID_PARAMETER) || + broken( i == 1 && ret == STATUS_INVALID_PARAMETER_3 ), /* win7 */ + "%u: got %x / %x\n", i, ret, expect_ret ); + if (!ret) + { + WaitForSingleObject( thread, INFINITE ); + CloseHandle( thread ); + } + + if (mask <= 31) continue; + if (!is_win64 && !is_wow64) expect_ret = STATUS_INVALID_PARAMETER_3; + ret = pRtlCreateUserStack( args.expect_committed, args.expect_reserved, mask, 0x1000, 0x1000, &stack ); + ok( ret == expect_ret || ret == STATUS_NO_MEMORY || + (ret == STATUS_INVALID_PARAMETER_3 && expect_ret == STATUS_INVALID_PARAMETER), + "%08x: got %x / %x\n", mask, ret, expect_ret ); + if (!ret) pRtlFreeUserStack( stack.DeallocationStack ); + ret = pRtlCreateUserThread( GetCurrentProcess(), NULL, FALSE, mask, + args.expect_reserved, args.expect_committed, + (void *)test_stack_size_thread, &args, &thread, &id ); + ok( ret == expect_ret || ret == STATUS_NO_MEMORY || + (ret == STATUS_INVALID_PARAMETER_3 && expect_ret == STATUS_INVALID_PARAMETER), + "%08x: got %x / %x\n", mask, ret, expect_ret ); + if (!ret) + { + WaitForSingleObject( thread, INFINITE ); + CloseHandle( thread ); + } + } } static void test_NtMapViewOfSection(void) @@ -572,7 +621,7 @@ static void test_NtMapViewOfSection(void) char buffer[sizeof(data)]; HANDLE file, mapping, process; void *ptr, *ptr2; - BOOL is_wow64, ret; + BOOL ret; DWORD status, written; SIZE_T size, result; LARGE_INTEGER offset; @@ -1051,6 +1100,7 @@ START_TEST(virtual) pGetEnabledXStateFeatures = (void *)GetProcAddress(mod, "GetEnabledXStateFeatures"); mod = GetModuleHandleA("ntdll.dll"); pRtlCreateUserStack = (void *)GetProcAddress(mod, "RtlCreateUserStack"); + pRtlCreateUserThread = (void *)GetProcAddress(mod, "RtlCreateUserThread"); pRtlFreeUserStack = (void *)GetProcAddress(mod, "RtlFreeUserStack"); pRtlFindExportedRoutineByName = (void *)GetProcAddress(mod, "RtlFindExportedRoutineByName"); pRtlGetEnabledExtendedFeatures = (void *)GetProcAddress(mod, "RtlGetEnabledExtendedFeatures"); @@ -1059,6 +1109,7 @@ START_TEST(virtual) NtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), NULL); trace("system page size %#x\n", sbi.PageSize); page_size = sbi.PageSize; + if (!pIsWow64Process || !pIsWow64Process(NtCurrentProcess(), &is_wow64)) is_wow64 = FALSE; test_NtAllocateVirtualMemory(); test_RtlCreateUserStack(); diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index 3cb3bd469ba..a95880ca4bd 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -150,7 +150,7 @@ void WINAPI RtlUserThreadStart( PRTL_THREAD_START_ROUTINE entry, void *arg ) * RtlCreateUserThread (NTDLL.@) */ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, SECURITY_DESCRIPTOR *descr, - BOOLEAN suspended, PVOID stack_addr, + BOOLEAN suspended, ULONG zero_bits, SIZE_T stack_reserve, SIZE_T stack_commit, PRTL_THREAD_START_ROUTINE start, void *param, HANDLE *handle_ptr, CLIENT_ID *id ) @@ -181,7 +181,7 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, SECURITY_DESCRIPTOR *descr, if (actctx) flags |= THREAD_CREATE_FLAGS_CREATE_SUSPENDED; status = NtCreateThreadEx( &handle, THREAD_ALL_ACCESS, &attr, process, start, param, - flags, 0, stack_commit, stack_reserve, attr_list ); + flags, zero_bits, stack_commit, stack_reserve, attr_list ); if (!status) { if (actctx) diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c index 6f03e96780c..9e99398bdee 100644 --- a/dlls/ntdll/threadpool.c +++ b/dlls/ntdll/threadpool.c @@ -783,7 +783,7 @@ NTSTATUS WINAPI RtlCreateTimerQueue(PHANDLE NewTimerQueue) RtlFreeHeap(GetProcessHeap(), 0, q); return status; } - status = RtlCreateUserThread(GetCurrentProcess(), NULL, FALSE, NULL, 0, 0, + status = RtlCreateUserThread(GetCurrentProcess(), NULL, FALSE, 0, 0, 0, timer_queue_thread_proc, q, &q->thread, NULL); if (status != STATUS_SUCCESS) { @@ -1141,7 +1141,7 @@ static NTSTATUS tp_new_worker_thread( struct threadpool *pool ) HANDLE thread; NTSTATUS status; - status = RtlCreateUserThread( GetCurrentProcess(), NULL, FALSE, NULL, 0, 0, + status = RtlCreateUserThread( GetCurrentProcess(), NULL, FALSE, 0, 0, 0, threadpool_worker_proc, pool, &thread, NULL ); if (status == STATUS_SUCCESS) { @@ -1176,7 +1176,7 @@ static NTSTATUS tp_timerqueue_lock( struct threadpool_object *timer ) if (!timerqueue.thread_running) { HANDLE thread; - status = RtlCreateUserThread( GetCurrentProcess(), NULL, FALSE, NULL, 0, 0, + status = RtlCreateUserThread( GetCurrentProcess(), NULL, FALSE, 0, 0, 0, timerqueue_thread_proc, NULL, &thread, NULL ); if (status == STATUS_SUCCESS) { @@ -1454,7 +1454,7 @@ static NTSTATUS tp_waitqueue_lock( struct threadpool_object *wait ) goto out; } - status = RtlCreateUserThread( GetCurrentProcess(), NULL, FALSE, NULL, 0, 0, + status = RtlCreateUserThread( GetCurrentProcess(), NULL, FALSE, 0, 0, 0, waitqueue_thread_proc, bucket, &thread, NULL ); if (status == STATUS_SUCCESS) { @@ -1592,7 +1592,7 @@ static NTSTATUS tp_ioqueue_lock( struct threadpool_object *io, HANDLE file ) HANDLE thread; if (!(status = RtlCreateUserThread( GetCurrentProcess(), NULL, FALSE, - NULL, 0, 0, ioqueue_thread_proc, NULL, &thread, NULL ))) + 0, 0, 0, ioqueue_thread_proc, NULL, &thread, NULL ))) { ioqueue.thread_running = TRUE; NtClose( thread ); diff --git a/include/winternl.h b/include/winternl.h index 48ad80c6037..8bfc7de67d0 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -3958,7 +3958,7 @@ NTSYSAPI NTSTATUS WINAPI RtlCreateTimer(PHANDLE, HANDLE, RTL_WAITORTIMERCALLBAC NTSYSAPI BOOLEAN WINAPI RtlCreateUnicodeString(PUNICODE_STRING,LPCWSTR); NTSYSAPI BOOLEAN WINAPI RtlCreateUnicodeStringFromAsciiz(PUNICODE_STRING,LPCSTR); NTSYSAPI NTSTATUS WINAPI RtlCreateUserProcess(UNICODE_STRING*,ULONG,RTL_USER_PROCESS_PARAMETERS*,SECURITY_DESCRIPTOR*,SECURITY_DESCRIPTOR*,HANDLE,BOOLEAN,HANDLE,HANDLE,RTL_USER_PROCESS_INFORMATION*); -NTSYSAPI NTSTATUS WINAPI RtlCreateUserThread(HANDLE,SECURITY_DESCRIPTOR*,BOOLEAN,PVOID,SIZE_T,SIZE_T,PRTL_THREAD_START_ROUTINE,void*,HANDLE*,CLIENT_ID*); +NTSYSAPI NTSTATUS WINAPI RtlCreateUserThread(HANDLE,SECURITY_DESCRIPTOR*,BOOLEAN,ULONG,SIZE_T,SIZE_T,PRTL_THREAD_START_ROUTINE,void*,HANDLE*,CLIENT_ID*); NTSYSAPI NTSTATUS WINAPI RtlCreateUserStack(SIZE_T,SIZE_T,ULONG,SIZE_T,SIZE_T,INITIAL_TEB*); NTSYSAPI NTSTATUS WINAPI RtlCustomCPToUnicodeN(CPTABLEINFO*,WCHAR*,DWORD,DWORD*,const char*,DWORD); NTSYSAPI void WINAPI RtlDeactivateActivationContext(DWORD,ULONG_PTR);