Commit 40165dfa authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: RtlCreateUserThread() also takes a zero_bits parameter.

parent 6de7fa1b
...@@ -84,7 +84,7 @@ HANDLE WINAPI DECLSPEC_HOTPATCH CreateRemoteThreadEx( HANDLE process, SECURITY_A ...@@ -84,7 +84,7 @@ HANDLE WINAPI DECLSPEC_HOTPATCH CreateRemoteThreadEx( HANDLE process, SECURITY_A
else stack_commit = stack; else stack_commit = stack;
if (!set_ntstatus( RtlCreateUserThread( process, sa ? sa->lpSecurityDescriptor : NULL, TRUE, 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 ))) (PRTL_THREAD_START_ROUTINE)start, param, &handle, &client_id )))
return 0; return 0;
......
...@@ -562,7 +562,7 @@ ...@@ -562,7 +562,7 @@
@ stdcall RtlCreateUserProcess(ptr long ptr ptr ptr long long long long ptr) @ stdcall RtlCreateUserProcess(ptr long ptr ptr ptr long long long long ptr)
@ stub RtlCreateUserSecurityObject @ stub RtlCreateUserSecurityObject
@ stdcall RtlCreateUserStack(long long long long long ptr) @ 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) @ stdcall RtlCustomCPToUnicodeN(ptr ptr long ptr str long)
@ stub RtlCutoverTimeToSystemTime @ stub RtlCutoverTimeToSystemTime
@ stdcall RtlDeNormalizeProcessParams(ptr) @ stdcall RtlDeNormalizeProcessParams(ptr)
......
...@@ -31,6 +31,8 @@ static unsigned int page_size; ...@@ -31,6 +31,8 @@ static unsigned int page_size;
static DWORD64 (WINAPI *pGetEnabledXStateFeatures)(void); static DWORD64 (WINAPI *pGetEnabledXStateFeatures)(void);
static NTSTATUS (WINAPI *pRtlCreateUserStack)(SIZE_T, SIZE_T, ULONG, SIZE_T, SIZE_T, INITIAL_TEB *); 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 ULONG64 (WINAPI *pRtlGetEnabledExtendedFeatures)(ULONG64);
static NTSTATUS (WINAPI *pRtlFreeUserStack)(void *); static NTSTATUS (WINAPI *pRtlFreeUserStack)(void *);
static void * (WINAPI *pRtlFindExportedRoutineByName)(HMODULE,const char*); static void * (WINAPI *pRtlFindExportedRoutineByName)(HMODULE,const char*);
...@@ -38,6 +40,7 @@ static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL); ...@@ -38,6 +40,7 @@ static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
static NTSTATUS (WINAPI *pNtAllocateVirtualMemoryEx)(HANDLE, PVOID *, SIZE_T *, ULONG, ULONG, static NTSTATUS (WINAPI *pNtAllocateVirtualMemoryEx)(HANDLE, PVOID *, SIZE_T *, ULONG, ULONG,
MEM_EXTENDED_PARAMETER *, ULONG); MEM_EXTENDED_PARAMETER *, ULONG);
static const BOOL is_win64 = sizeof(void*) != sizeof(int); static const BOOL is_win64 = sizeof(void*) != sizeof(int);
static BOOL is_wow64;
static SYSTEM_BASIC_INFORMATION sbi; static SYSTEM_BASIC_INFORMATION sbi;
...@@ -91,9 +94,6 @@ static void test_NtAllocateVirtualMemory(void) ...@@ -91,9 +94,6 @@ static void test_NtAllocateVirtualMemory(void)
NTSTATUS status; NTSTATUS status;
SIZE_T size; SIZE_T size;
ULONG_PTR zero_bits; ULONG_PTR zero_bits;
BOOL is_wow64;
if (!pIsWow64Process || !pIsWow64Process(NtCurrentProcess(), &is_wow64)) is_wow64 = FALSE;
/* simple allocation should success */ /* simple allocation should success */
size = 0x1000; size = 0x1000;
...@@ -485,7 +485,7 @@ static DWORD WINAPI test_stack_size_thread(void *ptr) ...@@ -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 ); todo_wine ok( committed == 0x6000, "unexpected stack committed size %x, expected 6000\n", committed );
#endif #endif
return 0; ExitThread(0);
} }
static void test_RtlCreateUserStack(void) static void test_RtlCreateUserStack(void)
...@@ -498,6 +498,7 @@ static void test_RtlCreateUserStack(void) ...@@ -498,6 +498,7 @@ static void test_RtlCreateUserStack(void)
unsigned int i; unsigned int i;
NTSTATUS ret; NTSTATUS ret;
HANDLE thread; HANDLE thread;
CLIENT_ID id;
struct struct
{ {
...@@ -563,6 +564,54 @@ static void test_RtlCreateUserStack(void) ...@@ -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); thread = CreateThread(NULL, 0x3ff000, test_stack_size_thread, &args, STACK_SIZE_PARAM_IS_A_RESERVATION, NULL);
WaitForSingleObject(thread, INFINITE); WaitForSingleObject(thread, INFINITE);
CloseHandle(thread); 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) static void test_NtMapViewOfSection(void)
...@@ -572,7 +621,7 @@ static void test_NtMapViewOfSection(void) ...@@ -572,7 +621,7 @@ static void test_NtMapViewOfSection(void)
char buffer[sizeof(data)]; char buffer[sizeof(data)];
HANDLE file, mapping, process; HANDLE file, mapping, process;
void *ptr, *ptr2; void *ptr, *ptr2;
BOOL is_wow64, ret; BOOL ret;
DWORD status, written; DWORD status, written;
SIZE_T size, result; SIZE_T size, result;
LARGE_INTEGER offset; LARGE_INTEGER offset;
...@@ -1051,6 +1100,7 @@ START_TEST(virtual) ...@@ -1051,6 +1100,7 @@ START_TEST(virtual)
pGetEnabledXStateFeatures = (void *)GetProcAddress(mod, "GetEnabledXStateFeatures"); pGetEnabledXStateFeatures = (void *)GetProcAddress(mod, "GetEnabledXStateFeatures");
mod = GetModuleHandleA("ntdll.dll"); mod = GetModuleHandleA("ntdll.dll");
pRtlCreateUserStack = (void *)GetProcAddress(mod, "RtlCreateUserStack"); pRtlCreateUserStack = (void *)GetProcAddress(mod, "RtlCreateUserStack");
pRtlCreateUserThread = (void *)GetProcAddress(mod, "RtlCreateUserThread");
pRtlFreeUserStack = (void *)GetProcAddress(mod, "RtlFreeUserStack"); pRtlFreeUserStack = (void *)GetProcAddress(mod, "RtlFreeUserStack");
pRtlFindExportedRoutineByName = (void *)GetProcAddress(mod, "RtlFindExportedRoutineByName"); pRtlFindExportedRoutineByName = (void *)GetProcAddress(mod, "RtlFindExportedRoutineByName");
pRtlGetEnabledExtendedFeatures = (void *)GetProcAddress(mod, "RtlGetEnabledExtendedFeatures"); pRtlGetEnabledExtendedFeatures = (void *)GetProcAddress(mod, "RtlGetEnabledExtendedFeatures");
...@@ -1059,6 +1109,7 @@ START_TEST(virtual) ...@@ -1059,6 +1109,7 @@ START_TEST(virtual)
NtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), NULL); NtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), NULL);
trace("system page size %#x\n", sbi.PageSize); trace("system page size %#x\n", sbi.PageSize);
page_size = sbi.PageSize; page_size = sbi.PageSize;
if (!pIsWow64Process || !pIsWow64Process(NtCurrentProcess(), &is_wow64)) is_wow64 = FALSE;
test_NtAllocateVirtualMemory(); test_NtAllocateVirtualMemory();
test_RtlCreateUserStack(); test_RtlCreateUserStack();
......
...@@ -150,7 +150,7 @@ void WINAPI RtlUserThreadStart( PRTL_THREAD_START_ROUTINE entry, void *arg ) ...@@ -150,7 +150,7 @@ void WINAPI RtlUserThreadStart( PRTL_THREAD_START_ROUTINE entry, void *arg )
* RtlCreateUserThread (NTDLL.@) * RtlCreateUserThread (NTDLL.@)
*/ */
NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, SECURITY_DESCRIPTOR *descr, 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, SIZE_T stack_reserve, SIZE_T stack_commit,
PRTL_THREAD_START_ROUTINE start, void *param, PRTL_THREAD_START_ROUTINE start, void *param,
HANDLE *handle_ptr, CLIENT_ID *id ) HANDLE *handle_ptr, CLIENT_ID *id )
...@@ -181,7 +181,7 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, SECURITY_DESCRIPTOR *descr, ...@@ -181,7 +181,7 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, SECURITY_DESCRIPTOR *descr,
if (actctx) flags |= THREAD_CREATE_FLAGS_CREATE_SUSPENDED; if (actctx) flags |= THREAD_CREATE_FLAGS_CREATE_SUSPENDED;
status = NtCreateThreadEx( &handle, THREAD_ALL_ACCESS, &attr, process, start, param, 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 (!status)
{ {
if (actctx) if (actctx)
......
...@@ -783,7 +783,7 @@ NTSTATUS WINAPI RtlCreateTimerQueue(PHANDLE NewTimerQueue) ...@@ -783,7 +783,7 @@ NTSTATUS WINAPI RtlCreateTimerQueue(PHANDLE NewTimerQueue)
RtlFreeHeap(GetProcessHeap(), 0, q); RtlFreeHeap(GetProcessHeap(), 0, q);
return status; 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); timer_queue_thread_proc, q, &q->thread, NULL);
if (status != STATUS_SUCCESS) if (status != STATUS_SUCCESS)
{ {
...@@ -1141,7 +1141,7 @@ static NTSTATUS tp_new_worker_thread( struct threadpool *pool ) ...@@ -1141,7 +1141,7 @@ static NTSTATUS tp_new_worker_thread( struct threadpool *pool )
HANDLE thread; HANDLE thread;
NTSTATUS status; NTSTATUS status;
status = RtlCreateUserThread( GetCurrentProcess(), NULL, FALSE, NULL, 0, 0, status = RtlCreateUserThread( GetCurrentProcess(), NULL, FALSE, 0, 0, 0,
threadpool_worker_proc, pool, &thread, NULL ); threadpool_worker_proc, pool, &thread, NULL );
if (status == STATUS_SUCCESS) if (status == STATUS_SUCCESS)
{ {
...@@ -1176,7 +1176,7 @@ static NTSTATUS tp_timerqueue_lock( struct threadpool_object *timer ) ...@@ -1176,7 +1176,7 @@ static NTSTATUS tp_timerqueue_lock( struct threadpool_object *timer )
if (!timerqueue.thread_running) if (!timerqueue.thread_running)
{ {
HANDLE thread; HANDLE thread;
status = RtlCreateUserThread( GetCurrentProcess(), NULL, FALSE, NULL, 0, 0, status = RtlCreateUserThread( GetCurrentProcess(), NULL, FALSE, 0, 0, 0,
timerqueue_thread_proc, NULL, &thread, NULL ); timerqueue_thread_proc, NULL, &thread, NULL );
if (status == STATUS_SUCCESS) if (status == STATUS_SUCCESS)
{ {
...@@ -1454,7 +1454,7 @@ static NTSTATUS tp_waitqueue_lock( struct threadpool_object *wait ) ...@@ -1454,7 +1454,7 @@ static NTSTATUS tp_waitqueue_lock( struct threadpool_object *wait )
goto out; goto out;
} }
status = RtlCreateUserThread( GetCurrentProcess(), NULL, FALSE, NULL, 0, 0, status = RtlCreateUserThread( GetCurrentProcess(), NULL, FALSE, 0, 0, 0,
waitqueue_thread_proc, bucket, &thread, NULL ); waitqueue_thread_proc, bucket, &thread, NULL );
if (status == STATUS_SUCCESS) if (status == STATUS_SUCCESS)
{ {
...@@ -1592,7 +1592,7 @@ static NTSTATUS tp_ioqueue_lock( struct threadpool_object *io, HANDLE file ) ...@@ -1592,7 +1592,7 @@ static NTSTATUS tp_ioqueue_lock( struct threadpool_object *io, HANDLE file )
HANDLE thread; HANDLE thread;
if (!(status = RtlCreateUserThread( GetCurrentProcess(), NULL, FALSE, 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; ioqueue.thread_running = TRUE;
NtClose( thread ); NtClose( thread );
......
...@@ -3958,7 +3958,7 @@ NTSYSAPI NTSTATUS WINAPI RtlCreateTimer(PHANDLE, HANDLE, RTL_WAITORTIMERCALLBAC ...@@ -3958,7 +3958,7 @@ NTSYSAPI NTSTATUS WINAPI RtlCreateTimer(PHANDLE, HANDLE, RTL_WAITORTIMERCALLBAC
NTSYSAPI BOOLEAN WINAPI RtlCreateUnicodeString(PUNICODE_STRING,LPCWSTR); NTSYSAPI BOOLEAN WINAPI RtlCreateUnicodeString(PUNICODE_STRING,LPCWSTR);
NTSYSAPI BOOLEAN WINAPI RtlCreateUnicodeStringFromAsciiz(PUNICODE_STRING,LPCSTR); 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 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 RtlCreateUserStack(SIZE_T,SIZE_T,ULONG,SIZE_T,SIZE_T,INITIAL_TEB*);
NTSYSAPI NTSTATUS WINAPI RtlCustomCPToUnicodeN(CPTABLEINFO*,WCHAR*,DWORD,DWORD*,const char*,DWORD); NTSYSAPI NTSTATUS WINAPI RtlCustomCPToUnicodeN(CPTABLEINFO*,WCHAR*,DWORD,DWORD*,const char*,DWORD);
NTSYSAPI void WINAPI RtlDeactivateActivationContext(DWORD,ULONG_PTR); NTSYSAPI void WINAPI RtlDeactivateActivationContext(DWORD,ULONG_PTR);
......
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