Module: wine Branch: master Commit: 1372d8fc2cac3466d759500063a50d86f03dc94a URL: https://source.winehq.org/git/wine.git/?a=commit;h=1372d8fc2cac3466d75950006...
Author: Alexandre Julliard julliard@winehq.org Date: Wed Jul 22 14:15:55 2020 +0200
ntdll: Implement NtSetInformationProcess(ProcessThreadStackAllocation).
Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/ntdll/tests/info.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++ dlls/ntdll/unix/process.c | 22 ++++++++++++++++ include/winternl.h | 16 ++++++++++++ 3 files changed, 102 insertions(+)
diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c index e5137ef5a4..6fdd2b6e59 100644 --- a/dlls/ntdll/tests/info.c +++ b/dlls/ntdll/tests/info.c @@ -2081,6 +2081,69 @@ static void test_mapprotection(void) pNtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &oldflags, sizeof(oldflags) ); }
+static void test_threadstack(void) +{ + PROCESS_STACK_ALLOCATION_INFORMATION info = { 0x100000, 0, (void *)0xdeadbeef }; + PROCESS_STACK_ALLOCATION_INFORMATION_EX info_ex = { 0 }; + MEMORY_BASIC_INFORMATION meminfo; + SIZE_T retlen; + NTSTATUS status; + + info.ReserveSize = 0x100000; + info.StackBase = (void *)0xdeadbeef; + status = pNtSetInformationProcess( GetCurrentProcess(), ProcessThreadStackAllocation, &info, sizeof(info) ); + ok( !status, "NtSetInformationProcess failed %08x\n", status ); + ok( info.StackBase != (void *)0xdeadbeef, "stackbase not set\n" ); + + status = pNtQueryVirtualMemory( GetCurrentProcess(), info.StackBase, MemoryBasicInformation, + &meminfo, sizeof(meminfo), &retlen ); + ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status); + ok( retlen == sizeof(meminfo), "Expected STATUS_SUCCESS, got %08x\n", status); + ok( meminfo.AllocationBase == info.StackBase, "wrong base %p/%p\n", + meminfo.AllocationBase, info.StackBase ); + ok( meminfo.RegionSize == info.ReserveSize, "wrong size %lx/%lx\n", + meminfo.RegionSize, info.ReserveSize ); + ok( meminfo.State == MEM_RESERVE, "wrong state %x\n", meminfo.State ); + ok( meminfo.Protect == 0, "wrong protect %x\n", meminfo.Protect ); + ok( meminfo.Type == MEM_PRIVATE, "wrong type %x\n", meminfo.Type ); + + info_ex.AllocInfo = info; + status = pNtSetInformationProcess( GetCurrentProcess(), ProcessThreadStackAllocation, + &info_ex, sizeof(info_ex) ); + if (status != STATUS_INVALID_PARAMETER) + { + ok( !status, "NtSetInformationProcess failed %08x\n", status ); + ok( info_ex.AllocInfo.StackBase != info.StackBase, "stackbase not set\n" ); + status = pNtQueryVirtualMemory( GetCurrentProcess(), info_ex.AllocInfo.StackBase, + MemoryBasicInformation, &meminfo, sizeof(meminfo), &retlen ); + ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status); + ok( retlen == sizeof(meminfo), "Expected STATUS_SUCCESS, got %08x\n", status); + ok( meminfo.AllocationBase == info_ex.AllocInfo.StackBase, "wrong base %p/%p\n", + meminfo.AllocationBase, info_ex.AllocInfo.StackBase ); + ok( meminfo.RegionSize == info_ex.AllocInfo.ReserveSize, "wrong size %lx/%lx\n", + meminfo.RegionSize, info_ex.AllocInfo.ReserveSize ); + ok( meminfo.State == MEM_RESERVE, "wrong state %x\n", meminfo.State ); + ok( meminfo.Protect == 0, "wrong protect %x\n", meminfo.Protect ); + ok( meminfo.Type == MEM_PRIVATE, "wrong type %x\n", meminfo.Type ); + VirtualFree( info_ex.AllocInfo.StackBase, 0, MEM_FREE ); + status = pNtSetInformationProcess( GetCurrentProcess(), ProcessThreadStackAllocation, + &info, sizeof(info) - 1 ); + ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtSetInformationProcess failed %08x\n", status ); + status = pNtSetInformationProcess( GetCurrentProcess(), ProcessThreadStackAllocation, + &info, sizeof(info) + 1 ); + ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtSetInformationProcess failed %08x\n", status ); + status = pNtSetInformationProcess( GetCurrentProcess(), ProcessThreadStackAllocation, + &info_ex, sizeof(info_ex) - 1 ); + ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtSetInformationProcess failed %08x\n", status ); + status = pNtSetInformationProcess( GetCurrentProcess(), ProcessThreadStackAllocation, + &info_ex, sizeof(info_ex) + 1 ); + ok( status == STATUS_INFO_LENGTH_MISMATCH, "NtSetInformationProcess failed %08x\n", status ); + } + else win_skip( "ProcessThreadStackAllocation ex not supported\n" ); + + VirtualFree( info.StackBase, 0, MEM_FREE ); +} + static void test_queryvirtualmemory(void) { NTSTATUS status; @@ -2621,6 +2684,7 @@ START_TEST(info) test_query_process_debug_flags(argc, argv); test_query_process_image_info(); test_mapprotection(); + test_threadstack();
/* NtQueryInformationThread */ test_thread_info(); diff --git a/dlls/ntdll/unix/process.c b/dlls/ntdll/unix/process.c index 9854f13aba..bde46264d0 100644 --- a/dlls/ntdll/unix/process.c +++ b/dlls/ntdll/unix/process.c @@ -1580,6 +1580,28 @@ NTSTATUS WINAPI NtSetInformationProcess( HANDLE handle, PROCESSINFOCLASS class, } break;
+ case ProcessThreadStackAllocation: + { + void *addr = NULL; + SIZE_T reserve; + PROCESS_STACK_ALLOCATION_INFORMATION *stack = info; + if (size == sizeof(PROCESS_STACK_ALLOCATION_INFORMATION_EX)) + stack = &((PROCESS_STACK_ALLOCATION_INFORMATION_EX *)info)->AllocInfo; + else if (size != sizeof(*stack)) return STATUS_INFO_LENGTH_MISMATCH; + + reserve = stack->ReserveSize; + ret = NtAllocateVirtualMemory( GetCurrentProcess(), &addr, stack->ZeroBits, &reserve, + MEM_RESERVE, PAGE_READWRITE ); + if (!ret) + { +#ifdef VALGRIND_STACK_REGISTER + VALGRIND_STACK_REGISTER( addr, (char *)addr + reserve ); +#endif + stack->StackBase = addr; + } + break; + } + default: FIXME( "(%p,0x%08x,%p,0x%08x) stub\n", handle, class, info, size ); ret = STATUS_NOT_IMPLEMENTED; diff --git a/include/winternl.h b/include/winternl.h index b3fbb90fef..81eb417bb5 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -1313,6 +1313,22 @@ typedef struct _PROCESS_PRIORITY_CLASS { UCHAR PriorityClass; } PROCESS_PRIORITY_CLASS, *PPROCESS_PRIORITY_CLASS;
+typedef struct _PROCESS_STACK_ALLOCATION_INFORMATION +{ + SIZE_T ReserveSize; + SIZE_T ZeroBits; + PVOID StackBase; +} PROCESS_STACK_ALLOCATION_INFORMATION, *PPROCESS_STACK_ALLOCATION_INFORMATION; + +typedef struct _PROCESS_STACK_ALLOCATION_INFORMATION_EX +{ + ULONG PreferredNode; + ULONG Reserved0; + ULONG Reserved1; + ULONG Reserved2; + PROCESS_STACK_ALLOCATION_INFORMATION AllocInfo; +} PROCESS_STACK_ALLOCATION_INFORMATION_EX, *PPROCESS_STACK_ALLOCATION_INFORMATION_EX; + typedef struct _RTL_HEAP_DEFINITION { ULONG Length; /* = sizeof(RTL_HEAP_DEFINITION) */