Alexandre Julliard : ntdll: Implement NtSetInformationProcess(ProcessThreadStackAllocation).

Alexandre Julliard julliard at winehq.org
Wed Jul 22 16:34:29 CDT 2020


Module: wine
Branch: master
Commit: 1372d8fc2cac3466d759500063a50d86f03dc94a
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=1372d8fc2cac3466d759500063a50d86f03dc94a

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Wed Jul 22 14:15:55 2020 +0200

ntdll: Implement NtSetInformationProcess(ProcessThreadStackAllocation).

Signed-off-by: Alexandre Julliard <julliard at 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) */
 




More information about the wine-cvs mailing list