diff --git a/patches/ntdll-Placeholders/0008-ntdll-Handle-NULL-process-handle-in-MapViewOfFile3.patch b/patches/ntdll-Placeholders/0001-ntdll-Handle-NULL-process-handle-in-MapViewOfFile3.patch similarity index 60% rename from patches/ntdll-Placeholders/0008-ntdll-Handle-NULL-process-handle-in-MapViewOfFile3.patch rename to patches/ntdll-Placeholders/0001-ntdll-Handle-NULL-process-handle-in-MapViewOfFile3.patch index 8325a444..85bba7f5 100644 --- a/patches/ntdll-Placeholders/0008-ntdll-Handle-NULL-process-handle-in-MapViewOfFile3.patch +++ b/patches/ntdll-Placeholders/0001-ntdll-Handle-NULL-process-handle-in-MapViewOfFile3.patch @@ -1,13 +1,14 @@ -From ebca5e5a6d9e498ca1f7c0f823e40c25be547500 Mon Sep 17 00:00:00 2001 +From fdf68c567063a626f6e404da32eafe93a10c0c54 Mon Sep 17 00:00:00 2001 From: Paul Gofman Date: Thu, 10 Nov 2022 18:40:18 -0600 Subject: [PATCH] ntdll: Handle NULL process handle in MapViewOfFile3(). Based on a patch by Nikolay Sivov. --- - dlls/kernelbase/memory.c | 2 ++ - dlls/ntdll/tests/virtual.c | 13 +++++++++++++ - 2 files changed, 15 insertions(+) + dlls/kernelbase/memory.c | 2 ++ + dlls/kernelbase/tests/process.c | 2 +- + dlls/ntdll/tests/virtual.c | 12 ++++++++++++ + 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c index 4188eebf181..19381e00b31 100644 @@ -22,11 +23,24 @@ index 4188eebf181..19381e00b31 100644 addr = baseaddr; off.QuadPart = offset; if (!set_ntstatus( NtMapViewOfSectionEx( handle, process, &addr, &off, &size, alloc_type, protection, +diff --git a/dlls/kernelbase/tests/process.c b/dlls/kernelbase/tests/process.c +index 2979af39551..14eed7d8fe9 100644 +--- a/dlls/kernelbase/tests/process.c ++++ b/dlls/kernelbase/tests/process.c +@@ -123,7 +123,7 @@ static void test_MapViewOfFile3(void) + ok( mapping != 0, "CreateFileMapping error %lu\n", GetLastError() ); + + SetLastError(0xdeadbeef); +- ptr = pMapViewOfFile3( mapping, GetCurrentProcess(), NULL, 0, 4096, 0, PAGE_READONLY, NULL, 0); ++ ptr = pMapViewOfFile3( mapping, NULL, NULL, 0, 4096, 0, PAGE_READONLY, NULL, 0); + ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %lu\n", GetLastError() ); + UnmapViewOfFile( ptr ); + diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c -index ffa462f579f..559ba484d60 100644 +index c125fdff0d7..549a2b12d5a 100644 --- a/dlls/ntdll/tests/virtual.c +++ b/dlls/ntdll/tests/virtual.c -@@ -1131,6 +1131,13 @@ static void test_NtMapViewOfSection(void) +@@ -1131,6 +1131,12 @@ static void test_NtMapViewOfSection(void) process = create_target_process("sleep"); ok(process != NULL, "Can't start process\n"); @@ -35,17 +49,16 @@ index ffa462f579f..559ba484d60 100644 + offset.QuadPart = 0; + status = NtMapViewOfSection(mapping, NULL, &ptr, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE); + ok(status == STATUS_INVALID_HANDLE, "NtMapViewOfSection returned %08lx\n", status); -+ ok(!((ULONG_PTR)ptr & 0xffff), "returned memory %p is not aligned to 64k\n", ptr); + ptr = NULL; size = 0; offset.QuadPart = 0; -@@ -1404,6 +1411,12 @@ static void test_NtMapViewOfSectionEx(void) +@@ -1404,6 +1410,12 @@ static void test_NtMapViewOfSectionEx(void) process = create_target_process("sleep"); ok(process != NULL, "Can't start process\n"); + ptr = NULL; -+ size = 0; ++ size = 0x1000; + offset.QuadPart = 0; + status = pNtMapViewOfSectionEx(mapping, NULL, &ptr, &offset, &size, 0, PAGE_READWRITE, NULL, 0); + ok(status == STATUS_INVALID_HANDLE, "Unexpected status %08lx\n", status); diff --git a/patches/ntdll-Placeholders/0002-ntdll-Pass-allocation-type-to-map_view.patch b/patches/ntdll-Placeholders/0002-ntdll-Pass-allocation-type-to-map_view.patch new file mode 100644 index 00000000..cf530f20 --- /dev/null +++ b/patches/ntdll-Placeholders/0002-ntdll-Pass-allocation-type-to-map_view.patch @@ -0,0 +1,76 @@ +From 9262ac863f3c124e204a0fe96fbfc9ebefa2ee84 Mon Sep 17 00:00:00 2001 +From: Paul Gofman +Date: Thu, 10 Nov 2022 18:48:14 -0600 +Subject: [PATCH] ntdll: Pass allocation type to map_view(). + +Based on a patch by Nikolay Sivov. +--- + dlls/ntdll/unix/virtual.c | 15 ++++++++------- + 1 file changed, 8 insertions(+), 7 deletions(-) + +diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c +index a5c1c8214fa..e3df71a695c 100644 +--- a/dlls/ntdll/unix/virtual.c ++++ b/dlls/ntdll/unix/virtual.c +@@ -2011,8 +2011,9 @@ static NTSTATUS map_fixed_area( void *base, size_t size, unsigned int vprot ) + * virtual_mutex must be held by caller. + */ + static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size, +- int top_down, unsigned int vprot, ULONG_PTR limit, size_t align_mask ) ++ unsigned int alloc_type, unsigned int vprot, ULONG_PTR limit, size_t align_mask ) + { ++ int top_down = alloc_type & MEM_TOP_DOWN; + void *ptr; + NTSTATUS status; + +@@ -2285,7 +2286,7 @@ static NTSTATUS allocate_dos_memory( struct file_view **view, unsigned int vprot + if (mmap_is_in_reserved_area( low_64k, dosmem_size - 0x10000 ) != 1) + { + addr = anon_mmap_tryfixed( low_64k, dosmem_size - 0x10000, unix_prot, 0 ); +- if (addr == MAP_FAILED) return map_view( view, NULL, dosmem_size, FALSE, vprot, 0, 0 ); ++ if (addr == MAP_FAILED) return map_view( view, NULL, dosmem_size, 0, vprot, 0, 0 ); + } + + /* now try to allocate the low 64K too */ +@@ -2760,9 +2761,9 @@ static NTSTATUS virtual_map_image( HANDLE mapping, ACCESS_MASK access, void **ad + if ((ULONG_PTR)base != image_info->base) base = NULL; + + if ((char *)base >= (char *)address_space_start) /* make sure the DOS area remains free */ +- status = map_view( &view, base, size, alloc_type & MEM_TOP_DOWN, vprot, limit, 0 ); ++ status = map_view( &view, base, size, alloc_type, vprot, limit, 0 ); + +- if (status) status = map_view( &view, NULL, size, alloc_type & MEM_TOP_DOWN, vprot, limit, 0 ); ++ if (status) status = map_view( &view, NULL, size, alloc_type, vprot, limit, 0 ); + if (status) goto done; + + status = map_image_into_view( view, filename, unix_fd, base, image_info->header_size, +@@ -2885,7 +2886,7 @@ static unsigned int virtual_map_section( HANDLE handle, PVOID *addr_ptr, ULONG_P + + server_enter_uninterrupted_section( &virtual_mutex, &sigset ); + +- res = map_view( &view, base, size, alloc_type & MEM_TOP_DOWN, vprot, limit, 0 ); ++ res = map_view( &view, base, size, alloc_type, vprot, limit, 0 ); + if (res) goto done; + + TRACE( "handle=%p size=%lx offset=%s\n", handle, size, wine_dbgstr_longlong(offset.QuadPart) ); +@@ -3424,7 +3425,7 @@ NTSTATUS virtual_alloc_thread_stack( INITIAL_TEB *stack, ULONG_PTR limit, SIZE_T + + server_enter_uninterrupted_section( &virtual_mutex, &sigset ); + +- status = map_view( &view, NULL, size, FALSE, VPROT_READ | VPROT_WRITE | VPROT_COMMITTED, limit, 0 ); ++ status = map_view( &view, NULL, size, 0, VPROT_READ | VPROT_WRITE | VPROT_COMMITTED, limit, 0 ); + if (status != STATUS_SUCCESS) goto done; + + #ifdef VALGRIND_STACK_REGISTER +@@ -4120,7 +4121,7 @@ static NTSTATUS allocate_virtual_memory( void **ret, SIZE_T *size_ptr, ULONG typ + + if (vprot & VPROT_WRITECOPY) status = STATUS_INVALID_PAGE_PROTECTION; + else if (is_dos_memory) status = allocate_dos_memory( &view, vprot ); +- else status = map_view( &view, base, size, type & MEM_TOP_DOWN, vprot, limit, ++ else status = map_view( &view, base, size, type, vprot, limit, + align ? align - 1 : granularity_mask ); + + if (status == STATUS_SUCCESS) base = view->base; +-- +2.40.1 + diff --git a/patches/ntdll-Placeholders/0003-ntdll-Support-MEM_RESERVE_PLACEHOLDER-in-NtAllocateV.patch b/patches/ntdll-Placeholders/0003-ntdll-Support-MEM_RESERVE_PLACEHOLDER-in-NtAllocateV.patch new file mode 100644 index 00000000..2b7e6a51 --- /dev/null +++ b/patches/ntdll-Placeholders/0003-ntdll-Support-MEM_RESERVE_PLACEHOLDER-in-NtAllocateV.patch @@ -0,0 +1,367 @@ +From 73fa163482646dde03d10a2aaab1cb3df2d55225 Mon Sep 17 00:00:00 2001 +From: Paul Gofman +Date: Thu, 10 Nov 2022 18:53:10 -0600 +Subject: [PATCH] ntdll: Support MEM_RESERVE_PLACEHOLDER in + NtAllocateVirtualMemoryEx(). + +Based on a patch by Nikolay Sivov. +--- + dlls/kernelbase/tests/process.c | 37 +++++++------ + dlls/ntdll/tests/virtual.c | 95 +++++++++++++++------------------ + dlls/ntdll/unix/virtual.c | 30 ++++++++++- + 3 files changed, 90 insertions(+), 72 deletions(-) + +diff --git a/dlls/kernelbase/tests/process.c b/dlls/kernelbase/tests/process.c +index 14eed7d8fe9..f7b321cc09f 100644 +--- a/dlls/kernelbase/tests/process.c ++++ b/dlls/kernelbase/tests/process.c +@@ -168,9 +168,7 @@ static void test_VirtualAlloc2(void) + + /* Placeholder splitting functionality */ + placeholder1 = pVirtualAlloc2(NULL, NULL, 2 * size, MEM_RESERVE_PLACEHOLDER | MEM_RESERVE, PAGE_NOACCESS, NULL, 0); +- todo_wine + ok(!!placeholder1, "Failed to create a placeholder range.\n"); +- if (!placeholder1) return; + + memset(&info, 0, sizeof(info)); + VirtualQuery(placeholder1, &info, sizeof(info)); +@@ -180,14 +178,14 @@ static void test_VirtualAlloc2(void) + ok(info.RegionSize == 2 * size, "Unexpected size.\n"); + + ret = VirtualFree(placeholder1, size, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); +- ok(ret, "Failed to split placeholder.\n"); ++ todo_wine ok(ret, "Failed to split placeholder.\n"); + + memset(&info, 0, sizeof(info)); + VirtualQuery(placeholder1, &info, sizeof(info)); + ok(info.AllocationProtect == PAGE_NOACCESS, "Unexpected protection %#lx.\n", info.AllocationProtect); + ok(info.State == MEM_RESERVE, "Unexpected state %#lx.\n", info.State); + ok(info.Type == MEM_PRIVATE, "Unexpected type %#lx.\n", info.Type); +- ok(info.RegionSize == size, "Unexpected size.\n"); ++ todo_wine ok(info.RegionSize == size, "Unexpected size.\n"); + + placeholder2 = (void *)((BYTE *)placeholder1 + size); + memset(&info, 0, sizeof(info)); +@@ -201,10 +199,10 @@ static void test_VirtualAlloc2(void) + ok(!!section, "Failed to create a section.\n"); + + view1 = pMapViewOfFile3(section, NULL, placeholder1, 0, size, MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, NULL, 0); +- ok(!!view1, "Failed to map a section.\n"); ++ todo_wine ok(!!view1, "Failed to map a section.\n"); + + view2 = pMapViewOfFile3(section, NULL, placeholder2, 0, size, MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, NULL, 0); +- ok(!!view2, "Failed to map a section.\n"); ++ todo_wine ok(!!view2, "Failed to map a section.\n"); + + CloseHandle(section); + UnmapViewOfFile(view1); +@@ -220,16 +218,19 @@ static void test_VirtualAlloc2(void) + p1 = p + size / 2; + p2 = p1 + size / 4; + ret = VirtualFree(p1, size / 4, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); +- ok(ret, "Failed to split a placeholder.\n"); +- check_region_size(p, size / 2); +- check_region_size(p1, size / 4); ++ todo_wine ok(ret, "Failed to split a placeholder.\n"); ++ if (ret) ++ { ++ check_region_size(p, size / 2); ++ check_region_size(p1, size / 4); ++ } + check_region_size(p2, 2 * size - size / 2 - size / 4); + ret = VirtualFree(p, 0, MEM_RELEASE); + ok(ret, "Failed to release a region.\n"); + ret = VirtualFree(p1, 0, MEM_RELEASE); +- ok(ret, "Failed to release a region.\n"); ++ todo_wine ok(ret, "Failed to release a region.\n"); + ret = VirtualFree(p2, 0, MEM_RELEASE); +- ok(ret, "Failed to release a region.\n"); ++ todo_wine ok(ret, "Failed to release a region.\n"); + + /* Split in two regions, specifying lower part. */ + p = pVirtualAlloc2(NULL, NULL, 2 * size, MEM_RESERVE_PLACEHOLDER | MEM_RESERVE, PAGE_NOACCESS, NULL, 0); +@@ -238,13 +239,14 @@ static void test_VirtualAlloc2(void) + p1 = p; + p2 = p + size / 2; + ret = VirtualFree(p1, size / 2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); +- ok(ret, "Failed to split a placeholder.\n"); +- check_region_size(p1, size / 2); ++ todo_wine ok(ret, "Failed to split a placeholder.\n"); ++ if (ret) ++ check_region_size(p1, size / 2); + check_region_size(p2, 2 * size - size / 2); + ret = VirtualFree(p1, 0, MEM_RELEASE); + ok(ret, "Failed to release a region.\n"); + ret = VirtualFree(p2, 0, MEM_RELEASE); +- ok(ret, "Failed to release a region.\n"); ++ todo_wine ok(ret, "Failed to release a region.\n"); + + /* Split in two regions, specifying second half. */ + p = pVirtualAlloc2(NULL, NULL, 2 * size, MEM_RESERVE_PLACEHOLDER | MEM_RESERVE, PAGE_NOACCESS, NULL, 0); +@@ -253,13 +255,14 @@ static void test_VirtualAlloc2(void) + p1 = p; + p2 = p + size; + ret = VirtualFree(p2, size, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); +- ok(ret, "Failed to split a placeholder.\n"); +- check_region_size(p1, size); ++ todo_wine ok(ret, "Failed to split a placeholder.\n"); ++ if (ret) ++ check_region_size(p1, size); + check_region_size(p2, size); + ret = VirtualFree(p1, 0, MEM_RELEASE); + ok(ret, "Failed to release a region.\n"); + ret = VirtualFree(p2, 0, MEM_RELEASE); +- ok(ret, "Failed to release a region.\n"); ++ todo_wine ok(ret, "Failed to release a region.\n"); + } + + static void test_VirtualAllocFromApp(void) +diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c +index 549a2b12d5a..8b21e485736 100644 +--- a/dlls/ntdll/tests/virtual.c ++++ b/dlls/ntdll/tests/virtual.c +@@ -334,15 +334,11 @@ static void test_NtAllocateVirtualMemoryEx(void) + + status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, + PAGE_NOACCESS, NULL, 0); +- todo_wine + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + +- if (addr1) +- { +- size = 0; +- status = NtFreeVirtualMemory(NtCurrentProcess(), &addr1, &size, MEM_RELEASE); +- ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); +- } ++ size = 0; ++ status = NtFreeVirtualMemory(NtCurrentProcess(), &addr1, &size, MEM_RELEASE); ++ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + + /* Placeholder region splitting. */ + +@@ -351,79 +347,72 @@ static void test_NtAllocateVirtualMemoryEx(void) + size = 0x10000; + status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, + PAGE_NOACCESS, NULL, 0); +- todo_wine + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + ++ p = addr1; ++ p1 = p + size / 2; ++ p2 = p1 + size / 4; ++ size2 = size / 4; ++ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); ++ todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ++ + if (status == STATUS_SUCCESS) + { +- p = addr1; +- p1 = p + size / 2; +- p2 = p1 + size / 4; +- size2 = size / 4; +- status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); +- ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); +- + check_region_size(p, size / 2); + check_region_size(p1, size / 4); +- check_region_size(p2, size - size / 2 - size / 4); +- +- status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p, &size2, MEM_RELEASE); +- ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); +- status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE); +- ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); +- status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE); +- ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + } ++ check_region_size(p2, size - size / 2 - size / 4); ++ ++ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p, &size2, MEM_RELEASE); ++ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ++ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE); ++ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ++ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE); ++ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + + /* Split in two regions, specifying lower part. */ + addr1 = NULL; + size = 0x10000; + status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, + PAGE_NOACCESS, NULL, 0); +- todo_wine + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + +- if (status == STATUS_SUCCESS) +- { +- p1 = addr1; +- p2 = p1 + size / 4; +- size2 = size / 4; +- status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); +- ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); +- ok(p1 == addr1, "Unexpected address.\n"); ++ p1 = addr1; ++ p2 = p1 + size / 4; ++ size2 = size / 4; ++ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); ++ todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ++ ok(p1 == addr1, "Unexpected address.\n"); + ++ if (status == STATUS_SUCCESS) + check_region_size(p1, size / 4); +- check_region_size(p2, size - size / 4); +- status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE); +- ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); +- status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE); +- ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); +- } ++ check_region_size(p2, size - size / 4); ++ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE); ++ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ++ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE); ++ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + + /* Split in two regions, specifying second half. */ + addr1 = NULL; + size = 0x10000; + status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, + PAGE_NOACCESS, NULL, 0); +- todo_wine + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + +- if (status == STATUS_SUCCESS) +- { +- p1 = addr1; +- p2 = p1 + size / 2; ++ p1 = addr1; ++ p2 = p1 + size / 2; + +- size2 = size / 2; +- status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); +- ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); +- ok(p2 == p1 + size / 2, "Unexpected address.\n"); ++ size2 = size / 2; ++ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); ++ todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ++ ok(p2 == p1 + size / 2, "Unexpected address.\n"); ++ if (status == STATUS_SUCCESS) + check_region_size(p1, size / 2); +- check_region_size(p2, size / 2); +- status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE); +- ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); +- status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE); +- ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); +- } ++ check_region_size(p2, size / 2); ++ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE); ++ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ++ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE); ++ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + + memset( &ext, 0, sizeof(ext) ); + ext.Type = MemExtendedParameterAttributeFlags; +diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c +index e3df71a695c..77b0bc4c4c8 100644 +--- a/dlls/ntdll/unix/virtual.c ++++ b/dlls/ntdll/unix/virtual.c +@@ -125,6 +125,8 @@ struct file_view + #define VPROT_WRITTEN 0x80 + /* per-mapping protection flags */ + #define VPROT_SYSTEM 0x0200 /* system view (underlying mmap not under our control) */ ++#define VPROT_PLACEHOLDER 0x0400 ++#define VPROT_FREE_PLACEHOLDER 0x0800 + + /* Conversion from VPROT_* to Win32 flags */ + static const BYTE VIRTUAL_Win32Flags[16] = +@@ -1157,6 +1159,8 @@ static void dump_view( struct file_view *view ) + TRACE( "View: %p - %p", addr, addr + view->size - 1 ); + if (view->protect & VPROT_SYSTEM) + TRACE( " (builtin image)\n" ); ++ else if (view->protect & VPROT_FREE_PLACEHOLDER) ++ TRACE( " (placeholder)\n" ); + else if (view->protect & SEC_IMAGE) + TRACE( " (image)\n" ); + else if (view->protect & SEC_FILE) +@@ -4098,8 +4102,7 @@ static NTSTATUS allocate_virtual_memory( void **ret, SIZE_T *size_ptr, ULONG typ + + /* Compute the alloc type flags */ + +- if (!(type & (MEM_COMMIT | MEM_RESERVE | MEM_RESET)) || +- (type & ~(MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN | MEM_WRITE_WATCH | MEM_RESET))) ++ if (!(type & (MEM_COMMIT | MEM_RESERVE | MEM_RESET))) + { + WARN("called with wrong alloc type flags (%08x) !\n", (int)type); + return STATUS_INVALID_PARAMETER; +@@ -4107,6 +4110,12 @@ static NTSTATUS allocate_virtual_memory( void **ret, SIZE_T *size_ptr, ULONG typ + + if (!arm64ec_map && (attributes & MEM_EXTENDED_PARAMETER_EC_CODE)) return STATUS_INVALID_PARAMETER; + ++ if (type & MEM_RESERVE_PLACEHOLDER && (protect != PAGE_NOACCESS)) ++ { ++ WARN( "Wrong protect %#x for placeholder.\n", (unsigned int)protect ); ++ return STATUS_INVALID_PARAMETER; ++ } ++ + /* Reserve the memory */ + + server_enter_uninterrupted_section( &virtual_mutex, &sigset ); +@@ -4117,6 +4126,7 @@ static NTSTATUS allocate_virtual_memory( void **ret, SIZE_T *size_ptr, ULONG typ + { + if (type & MEM_COMMIT) vprot |= VPROT_COMMITTED; + if (type & MEM_WRITE_WATCH) vprot |= VPROT_WRITEWATCH; ++ if (type & MEM_RESERVE_PLACEHOLDER) vprot |= VPROT_PLACEHOLDER | VPROT_FREE_PLACEHOLDER; + if (protect & PAGE_NOCACHE) vprot |= SEC_NOCACHE; + + if (vprot & VPROT_WRITECOPY) status = STATUS_INVALID_PAGE_PROTECTION; +@@ -4136,6 +4146,7 @@ static NTSTATUS allocate_virtual_memory( void **ret, SIZE_T *size_ptr, ULONG typ + { + if (!(view = find_view( base, size ))) status = STATUS_NOT_MAPPED_VIEW; + else if (view->protect & SEC_FILE) status = STATUS_ALREADY_COMMITTED; ++ else if (view->protect & VPROT_FREE_PLACEHOLDER) status = STATUS_CONFLICTING_ADDRESSES; + else if (!(status = set_protection( view, base, size, protect )) && (view->protect & SEC_RESERVE)) + { + SERVER_START_REQ( add_mapping_committed_range ) +@@ -4171,6 +4182,7 @@ static NTSTATUS allocate_virtual_memory( void **ret, SIZE_T *size_ptr, ULONG typ + NTSTATUS WINAPI NtAllocateVirtualMemory( HANDLE process, PVOID *ret, ULONG_PTR zero_bits, + SIZE_T *size_ptr, ULONG type, ULONG protect ) + { ++ static const ULONG type_mask = MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN | MEM_WRITE_WATCH | MEM_RESET; + ULONG_PTR limit; + + TRACE("%p %p %08lx %x %08x\n", process, *ret, *size_ptr, (int)type, (int)protect ); +@@ -4182,6 +4194,12 @@ NTSTATUS WINAPI NtAllocateVirtualMemory( HANDLE process, PVOID *ret, ULONG_PTR z + if (!is_old_wow64() && zero_bits >= 32) return STATUS_INVALID_PARAMETER_3; + #endif + ++ if (type & ~type_mask) ++ { ++ WARN("Called with wrong alloc type flags %08x.\n", (int)type); ++ return STATUS_INVALID_PARAMETER; ++ } ++ + if (process != NtCurrentProcess()) + { + apc_call_t call; +@@ -4284,6 +4302,8 @@ NTSTATUS WINAPI NtAllocateVirtualMemoryEx( HANDLE process, PVOID *ret, SIZE_T *s + ULONG protect, MEM_EXTENDED_PARAMETER *parameters, + ULONG count ) + { ++ static const ULONG type_mask = MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN | MEM_WRITE_WATCH ++ | MEM_RESET | MEM_RESERVE_PLACEHOLDER; + ULONG_PTR limit = 0; + ULONG_PTR align = 0; + ULONG attributes = 0; +@@ -4295,6 +4315,12 @@ NTSTATUS WINAPI NtAllocateVirtualMemoryEx( HANDLE process, PVOID *ret, SIZE_T *s + status = get_extended_params( parameters, count, &limit, &align, &attributes ); + if (status) return status; + ++ if (type & ~type_mask) ++ { ++ WARN( "Called with wrong alloc type flags %08x.\n", (unsigned int)type ); ++ return STATUS_INVALID_PARAMETER; ++ } ++ + if (*ret && (align || limit)) return STATUS_INVALID_PARAMETER; + if (!*size_ptr) return STATUS_INVALID_PARAMETER; + +-- +2.40.1 + diff --git a/patches/ntdll-Placeholders/0004-ntdll-Support-MEM_REPLACE_PLACEHOLDER-in-map_view.patch b/patches/ntdll-Placeholders/0004-ntdll-Support-MEM_REPLACE_PLACEHOLDER-in-map_view.patch new file mode 100644 index 00000000..2e4e359f --- /dev/null +++ b/patches/ntdll-Placeholders/0004-ntdll-Support-MEM_REPLACE_PLACEHOLDER-in-map_view.patch @@ -0,0 +1,53 @@ +From 0a88728d7d5f32e64537ae01aba70376dba736fc Mon Sep 17 00:00:00 2001 +From: Paul Gofman +Date: Thu, 18 May 2023 20:42:05 -0600 +Subject: [PATCH] ntdll: Support MEM_REPLACE_PLACEHOLDER in map_view(). + +--- + dlls/ntdll/unix/virtual.c | 30 ++++++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c +index 77b0bc4c4c8..bd1a7c41543 100644 +--- a/dlls/ntdll/unix/virtual.c ++++ b/dlls/ntdll/unix/virtual.c +@@ -2021,6 +2021,36 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size, + void *ptr; + NTSTATUS status; + ++ if (alloc_type & MEM_REPLACE_PLACEHOLDER) ++ { ++ if (!(*view_ret = find_view( base, 0 ))) ++ { ++ TRACE( "MEM_REPLACE_PLACEHOLDER view not found.\n" ); ++ return STATUS_INVALID_PARAMETER; ++ } ++ TRACE( "found view %p, size %p, protect %#x.\n", ++ (*view_ret)->base, (void *)(*view_ret)->size, (*view_ret)->protect ); ++ ++ if ((*view_ret)->base != base || (*view_ret)->size != size) ++ { ++ WARN( "Wrond range.\n" ); ++ return STATUS_CONFLICTING_ADDRESSES; ++ } ++ ++ if (!((*view_ret)->protect & VPROT_FREE_PLACEHOLDER)) ++ { ++ TRACE( "Wrong protect %#x for MEM_REPLACE_PLACEHOLDER.\n", (*view_ret)->protect ); ++ return STATUS_INVALID_PARAMETER; ++ } ++ (*view_ret)->protect = vprot | VPROT_PLACEHOLDER; ++ ++ if (!set_vprot( *view_ret, base, size, vprot )) ++ ERR( "set_protection failed.\n" ); ++ if (vprot & VPROT_WRITEWATCH) ++ reset_write_watches( base, size ); ++ return STATUS_SUCCESS; ++ } ++ + if (base) + { + if (is_beyond_limit( base, size, address_space_limit )) +-- +2.40.1 + diff --git a/patches/ntdll-Placeholders/0005-ntdll-Support-MEM_REPLACE_PLACEHOLDER-in-NtAllocateV.patch b/patches/ntdll-Placeholders/0005-ntdll-Support-MEM_REPLACE_PLACEHOLDER-in-NtAllocateV.patch new file mode 100644 index 00000000..ced4aa4d --- /dev/null +++ b/patches/ntdll-Placeholders/0005-ntdll-Support-MEM_REPLACE_PLACEHOLDER-in-NtAllocateV.patch @@ -0,0 +1,45 @@ +From a72bcf44146603bcc500e1d3808c0a54f2d16da8 Mon Sep 17 00:00:00 2001 +From: Paul Gofman +Date: Thu, 10 Nov 2022 18:58:26 -0600 +Subject: [PATCH] ntdll: Support MEM_REPLACE_PLACEHOLDER in + NtAllocateVirtualMemoryEx(). + +--- + dlls/ntdll/unix/virtual.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c +index bd1a7c41543..a8af5946221 100644 +--- a/dlls/ntdll/unix/virtual.c ++++ b/dlls/ntdll/unix/virtual.c +@@ -4108,7 +4108,7 @@ static NTSTATUS allocate_virtual_memory( void **ret, SIZE_T *size_ptr, ULONG typ + + if (*ret) + { +- if (type & MEM_RESERVE) /* Round down to 64k boundary */ ++ if (type & MEM_RESERVE && !(type & MEM_REPLACE_PLACEHOLDER)) /* Round down to 64k boundary */ + base = ROUND_ADDR( *ret, granularity_mask ); + else + base = ROUND_ADDR( *ret, page_mask ); +@@ -4132,7 +4132,8 @@ static NTSTATUS allocate_virtual_memory( void **ret, SIZE_T *size_ptr, ULONG typ + + /* Compute the alloc type flags */ + +- if (!(type & (MEM_COMMIT | MEM_RESERVE | MEM_RESET))) ++ if (!(type & (MEM_COMMIT | MEM_RESERVE | MEM_RESET)) ++ || (type & MEM_REPLACE_PLACEHOLDER && !(type & MEM_RESERVE))) + { + WARN("called with wrong alloc type flags (%08x) !\n", (int)type); + return STATUS_INVALID_PARAMETER; +@@ -4333,7 +4334,7 @@ NTSTATUS WINAPI NtAllocateVirtualMemoryEx( HANDLE process, PVOID *ret, SIZE_T *s + ULONG count ) + { + static const ULONG type_mask = MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN | MEM_WRITE_WATCH +- | MEM_RESET | MEM_RESERVE_PLACEHOLDER; ++ | MEM_RESET | MEM_RESERVE_PLACEHOLDER | MEM_REPLACE_PLACEHOLDER; + ULONG_PTR limit = 0; + ULONG_PTR align = 0; + ULONG attributes = 0; +-- +2.40.1 + diff --git a/patches/ntdll-Placeholders/0006-ntdll-Support-MEM_PRESERVE_PLACEHOLDER-in-NtFreeVirt.patch b/patches/ntdll-Placeholders/0006-ntdll-Support-MEM_PRESERVE_PLACEHOLDER-in-NtFreeVirt.patch new file mode 100644 index 00000000..ad82abca --- /dev/null +++ b/patches/ntdll-Placeholders/0006-ntdll-Support-MEM_PRESERVE_PLACEHOLDER-in-NtFreeVirt.patch @@ -0,0 +1,242 @@ +From 4779aa6e891f32ff0b9bd37e95ed20e4522662e7 Mon Sep 17 00:00:00 2001 +From: Paul Gofman +Date: Thu, 10 Nov 2022 18:43:05 -0600 +Subject: [PATCH] ntdll: Support MEM_PRESERVE_PLACEHOLDER in + NtFreeVirtualMemory(). + +--- + dlls/kernelbase/tests/process.c | 35 +++++++++++------------- + dlls/ntdll/tests/virtual.c | 19 +++++-------- + dlls/ntdll/unix/virtual.c | 47 ++++++++++++++++++++++++++++++--- + 3 files changed, 65 insertions(+), 36 deletions(-) + +diff --git a/dlls/kernelbase/tests/process.c b/dlls/kernelbase/tests/process.c +index f7b321cc09f..b629b61ea5d 100644 +--- a/dlls/kernelbase/tests/process.c ++++ b/dlls/kernelbase/tests/process.c +@@ -178,14 +178,14 @@ static void test_VirtualAlloc2(void) + ok(info.RegionSize == 2 * size, "Unexpected size.\n"); + + ret = VirtualFree(placeholder1, size, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); +- todo_wine ok(ret, "Failed to split placeholder.\n"); ++ ok(ret, "Failed to split placeholder.\n"); + + memset(&info, 0, sizeof(info)); + VirtualQuery(placeholder1, &info, sizeof(info)); + ok(info.AllocationProtect == PAGE_NOACCESS, "Unexpected protection %#lx.\n", info.AllocationProtect); + ok(info.State == MEM_RESERVE, "Unexpected state %#lx.\n", info.State); + ok(info.Type == MEM_PRIVATE, "Unexpected type %#lx.\n", info.Type); +- todo_wine ok(info.RegionSize == size, "Unexpected size.\n"); ++ ok(info.RegionSize == size, "Unexpected size.\n"); + + placeholder2 = (void *)((BYTE *)placeholder1 + size); + memset(&info, 0, sizeof(info)); +@@ -199,10 +199,10 @@ static void test_VirtualAlloc2(void) + ok(!!section, "Failed to create a section.\n"); + + view1 = pMapViewOfFile3(section, NULL, placeholder1, 0, size, MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, NULL, 0); +- todo_wine ok(!!view1, "Failed to map a section.\n"); ++ ok(!!view1, "Failed to map a section.\n"); + + view2 = pMapViewOfFile3(section, NULL, placeholder2, 0, size, MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, NULL, 0); +- todo_wine ok(!!view2, "Failed to map a section.\n"); ++ ok(!!view2, "Failed to map a section.\n"); + + CloseHandle(section); + UnmapViewOfFile(view1); +@@ -218,19 +218,16 @@ static void test_VirtualAlloc2(void) + p1 = p + size / 2; + p2 = p1 + size / 4; + ret = VirtualFree(p1, size / 4, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); +- todo_wine ok(ret, "Failed to split a placeholder.\n"); +- if (ret) +- { +- check_region_size(p, size / 2); +- check_region_size(p1, size / 4); +- } ++ ok(ret, "Failed to split a placeholder.\n"); ++ check_region_size(p, size / 2); ++ check_region_size(p1, size / 4); + check_region_size(p2, 2 * size - size / 2 - size / 4); + ret = VirtualFree(p, 0, MEM_RELEASE); + ok(ret, "Failed to release a region.\n"); + ret = VirtualFree(p1, 0, MEM_RELEASE); +- todo_wine ok(ret, "Failed to release a region.\n"); ++ ok(ret, "Failed to release a region.\n"); + ret = VirtualFree(p2, 0, MEM_RELEASE); +- todo_wine ok(ret, "Failed to release a region.\n"); ++ ok(ret, "Failed to release a region.\n"); + + /* Split in two regions, specifying lower part. */ + p = pVirtualAlloc2(NULL, NULL, 2 * size, MEM_RESERVE_PLACEHOLDER | MEM_RESERVE, PAGE_NOACCESS, NULL, 0); +@@ -239,14 +236,13 @@ static void test_VirtualAlloc2(void) + p1 = p; + p2 = p + size / 2; + ret = VirtualFree(p1, size / 2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); +- todo_wine ok(ret, "Failed to split a placeholder.\n"); +- if (ret) +- check_region_size(p1, size / 2); ++ ok(ret, "Failed to split a placeholder.\n"); ++ check_region_size(p1, size / 2); + check_region_size(p2, 2 * size - size / 2); + ret = VirtualFree(p1, 0, MEM_RELEASE); + ok(ret, "Failed to release a region.\n"); + ret = VirtualFree(p2, 0, MEM_RELEASE); +- todo_wine ok(ret, "Failed to release a region.\n"); ++ ok(ret, "Failed to release a region.\n"); + + /* Split in two regions, specifying second half. */ + p = pVirtualAlloc2(NULL, NULL, 2 * size, MEM_RESERVE_PLACEHOLDER | MEM_RESERVE, PAGE_NOACCESS, NULL, 0); +@@ -255,14 +251,13 @@ static void test_VirtualAlloc2(void) + p1 = p; + p2 = p + size; + ret = VirtualFree(p2, size, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); +- todo_wine ok(ret, "Failed to split a placeholder.\n"); +- if (ret) +- check_region_size(p1, size); ++ ok(ret, "Failed to split a placeholder.\n"); ++ check_region_size(p1, size); + check_region_size(p2, size); + ret = VirtualFree(p1, 0, MEM_RELEASE); + ok(ret, "Failed to release a region.\n"); + ret = VirtualFree(p2, 0, MEM_RELEASE); +- todo_wine ok(ret, "Failed to release a region.\n"); ++ ok(ret, "Failed to release a region.\n"); + } + + static void test_VirtualAllocFromApp(void) +diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c +index 8b21e485736..03b9106bc6b 100644 +--- a/dlls/ntdll/tests/virtual.c ++++ b/dlls/ntdll/tests/virtual.c +@@ -354,13 +354,10 @@ static void test_NtAllocateVirtualMemoryEx(void) + p2 = p1 + size / 4; + size2 = size / 4; + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); +- todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ++ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + +- if (status == STATUS_SUCCESS) +- { +- check_region_size(p, size / 2); +- check_region_size(p1, size / 4); +- } ++ check_region_size(p, size / 2); ++ check_region_size(p1, size / 4); + check_region_size(p2, size - size / 2 - size / 4); + + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p, &size2, MEM_RELEASE); +@@ -381,11 +378,10 @@ static void test_NtAllocateVirtualMemoryEx(void) + p2 = p1 + size / 4; + size2 = size / 4; + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); +- todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ++ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + ok(p1 == addr1, "Unexpected address.\n"); + +- if (status == STATUS_SUCCESS) +- check_region_size(p1, size / 4); ++ check_region_size(p1, size / 4); + check_region_size(p2, size - size / 4); + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); +@@ -404,10 +400,9 @@ static void test_NtAllocateVirtualMemoryEx(void) + + size2 = size / 2; + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); +- todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ++ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + ok(p2 == p1 + size / 2, "Unexpected address.\n"); +- if (status == STATUS_SUCCESS) +- check_region_size(p1, size / 2); ++ check_region_size(p1, size / 2); + check_region_size(p2, size / 2); + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); +diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c +index a8af5946221..07c24a31592 100644 +--- a/dlls/ntdll/unix/virtual.c ++++ b/dlls/ntdll/unix/virtual.c +@@ -2242,18 +2242,43 @@ static NTSTATUS decommit_pages( struct file_view *view, size_t start, size_t siz + } + + ++/*********************************************************************** ++ * view_make_placeholder ++ * ++ * Setup placeholder view. ++ * virtual_mutex must be held by caller. ++ */ ++static void view_make_placeholder( struct file_view *view ) ++{ ++ view->protect = VPROT_PLACEHOLDER | VPROT_FREE_PLACEHOLDER; ++ set_page_vprot( view->base, view->size, 0 ); ++ if (arm64ec_map) clear_arm64ec_range( view->base, view->size ); ++ if (anon_mmap_fixed( view->base, view->size, PROT_NONE, 0 ) != view->base) ++ ERR( "anon_mmap_fixed failed, err %s.\n", strerror( errno )); ++} ++ ++ + /*********************************************************************** + * free_pages + * + * Free some pages of a given view. + * virtual_mutex must be held by caller. + */ +-static NTSTATUS free_pages( struct file_view *view, char *base, size_t size ) ++static NTSTATUS free_pages( struct file_view *view, char *base, size_t size, BOOL preserve_placeholder ) + { ++ if (preserve_placeholder) ++ { ++ if (!size) return STATUS_INVALID_PARAMETER_3; ++ if (!(view->protect & VPROT_PLACEHOLDER)) return STATUS_CONFLICTING_ADDRESSES; ++ if (view->protect & VPROT_FREE_PLACEHOLDER && size == view->size) return STATUS_CONFLICTING_ADDRESSES; ++ } ++ else if (!size) size = view->size; ++ + if (size == view->size) + { + assert( base == view->base ); +- delete_view( view ); ++ if (preserve_placeholder) view_make_placeholder( view ); ++ else delete_view( view ); + return STATUS_SUCCESS; + } + if (view->base != base && base + size != (char *)view->base + view->size) +@@ -2291,6 +2316,20 @@ static NTSTATUS free_pages( struct file_view *view, char *base, size_t size ) + VIRTUAL_DEBUG_DUMP_VIEW( view ); + } + ++ if (preserve_placeholder) ++ { ++ if (!(view = alloc_view())) ++ { ++ ERR( "Out of memory for %p-%p\n", base, base + size ); ++ return STATUS_NO_MEMORY; ++ } ++ view->base = base; ++ view->size = size; ++ view_make_placeholder( view ); ++ register_view( view ); ++ return STATUS_SUCCESS; ++ } ++ + set_page_vprot( base, size, 0 ); + if (arm64ec_map) clear_arm64ec_range( base, size ); + unmap_area( base, size ); +@@ -4441,10 +4480,10 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si + else if (!size && base != view->base) status = STATUS_FREE_VM_NOT_AT_BASE; + else if ((char *)view->base + view->size - base < size) status = STATUS_UNABLE_TO_FREE_VM; + else if (type == MEM_DECOMMIT) status = decommit_pages( view, base - (char *)view->base, size ); +- else if (type == MEM_RELEASE) ++ else if (type == MEM_RELEASE || (type == (MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER))) + { ++ status = free_pages( view, base, size, type & MEM_PRESERVE_PLACEHOLDER ); + if (!size) size = view->size; +- status = free_pages( view, base, size ); + } + else status = STATUS_INVALID_PARAMETER; + +-- +2.40.1 + diff --git a/patches/ntdll-Placeholders/0014-ntdll-tests-Add-more-tests-for-placeholders.patch b/patches/ntdll-Placeholders/0007-ntdll-tests-Add-more-tests-for-placeholders.patch similarity index 51% rename from patches/ntdll-Placeholders/0014-ntdll-tests-Add-more-tests-for-placeholders.patch rename to patches/ntdll-Placeholders/0007-ntdll-tests-Add-more-tests-for-placeholders.patch index a72c4616..29a48f8f 100644 --- a/patches/ntdll-Placeholders/0014-ntdll-tests-Add-more-tests-for-placeholders.patch +++ b/patches/ntdll-Placeholders/0007-ntdll-tests-Add-more-tests-for-placeholders.patch @@ -1,26 +1,18 @@ -From 2248dedbf01f0abeb4290d79c13c3b967010ba97 Mon Sep 17 00:00:00 2001 +From dc171d61ceb1aae3102063208de1b47ce58139d3 Mon Sep 17 00:00:00 2001 From: Paul Gofman Date: Wed, 9 Nov 2022 21:23:19 -0600 Subject: [PATCH] ntdll/tests: Add more tests for placeholders. --- - dlls/kernelbase/tests/process.c | 15 ++- - dlls/ntdll/tests/virtual.c | 217 +++++++++++++++++++++++--------- - 2 files changed, 171 insertions(+), 61 deletions(-) + dlls/kernelbase/tests/process.c | 14 +++ + dlls/ntdll/tests/virtual.c | 150 +++++++++++++++++++++++++++++++- + 2 files changed, 160 insertions(+), 4 deletions(-) diff --git a/dlls/kernelbase/tests/process.c b/dlls/kernelbase/tests/process.c -index b8c3bbb7276..03f76a1b73a 100644 +index b629b61ea5d..e5185a2587d 100644 --- a/dlls/kernelbase/tests/process.c +++ b/dlls/kernelbase/tests/process.c -@@ -168,7 +168,6 @@ static void test_VirtualAlloc2(void) - - /* Placeholder splitting functionality */ - placeholder1 = pVirtualAlloc2(NULL, NULL, 2 * size, MEM_RESERVE_PLACEHOLDER | MEM_RESERVE, PAGE_NOACCESS, NULL, 0); -- todo_wine - ok(!!placeholder1, "Failed to create a placeholder range.\n"); - if (!placeholder1) return; - -@@ -206,6 +205,20 @@ static void test_VirtualAlloc2(void) +@@ -204,6 +204,20 @@ static void test_VirtualAlloc2(void) view2 = pMapViewOfFile3(section, NULL, placeholder2, 0, size, MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, NULL, 0); ok(!!view2, "Failed to map a section.\n"); @@ -42,7 +34,7 @@ index b8c3bbb7276..03f76a1b73a 100644 UnmapViewOfFile(view1); UnmapViewOfFile(view2); diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c -index 335ba118fb9..3000ae68620 100644 +index 03b9106bc6b..3307c19bbea 100644 --- a/dlls/ntdll/tests/virtual.c +++ b/dlls/ntdll/tests/virtual.c @@ -293,10 +293,14 @@ static void check_region_size_(void *p, SIZE_T s, unsigned int line) @@ -50,8 +42,8 @@ index 335ba118fb9..3000ae68620 100644 static void test_NtAllocateVirtualMemoryEx(void) { + MEMORY_BASIC_INFORMATION mbi; -+ void *addresses[16]; MEM_EXTENDED_PARAMETER ext; ++ void *addresses[16]; SIZE_T size, size2; char *p, *p1, *p2; + ULONG granularity; @@ -60,7 +52,7 @@ index 335ba118fb9..3000ae68620 100644 void *addr1; if (!pNtAllocateVirtualMemoryEx) -@@ -332,48 +336,148 @@ static void test_NtAllocateVirtualMemoryEx(void) +@@ -332,15 +336,129 @@ static void test_NtAllocateVirtualMemoryEx(void) status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr1, 0, &size, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, PAGE_NOACCESS); ok(status == STATUS_INVALID_PARAMETER, "Unexpected status %08lx.\n", status); @@ -70,15 +62,11 @@ index 335ba118fb9..3000ae68620 100644 + status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, PAGE_NOACCESS, NULL, 0); - todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); -- if (addr1) -- { -- size = 0; -- status = NtFreeVirtualMemory(NtCurrentProcess(), &addr1, &size, MEM_RELEASE); -- ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); -- } +- size = 0; +- status = NtFreeVirtualMemory(NtCurrentProcess(), &addr1, &size, MEM_RELEASE); +- ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + size = 0x10000; + status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, MEM_RESERVE | MEM_COMMIT | MEM_REPLACE_PLACEHOLDER, + PAGE_READWRITE, NULL, 0); @@ -106,8 +94,7 @@ index 335ba118fb9..3000ae68620 100644 + size = 0x10000; + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&addr1, &size, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); + ok(!status, "Unexpected status %08lx.\n", status); - -- /* Placeholder region splitting. */ ++ + status = NtQueryVirtualMemory( NtCurrentProcess(), addr1, MemoryBasicInformation, &mbi, sizeof(mbi), &size ); + ok(!status, "Unexpected status %08lx.\n", status); + ok(mbi.AllocationProtect == PAGE_NOACCESS, "Unexpected protection %#lx.\n", mbi.AllocationProtect); @@ -145,39 +132,42 @@ index 335ba118fb9..3000ae68620 100644 + status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, + MEM_WRITE_WATCH | MEM_RESERVE | MEM_REPLACE_PLACEHOLDER, + PAGE_READONLY, NULL, 0); -+ ok(!status, "Unexpected status %08lx.\n", status); ++ ok(!status || broken(status == STATUS_INVALID_PARAMETER) /* Win10 1809, the version where ++ NtAllocateVirtualMemoryEx is introduced */, "Unexpected status %08lx.\n", status); + -+ size = 0x10000; -+ status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, MEM_COMMIT, PAGE_READWRITE, NULL, 0); -+ ok(!status, "Unexpected status %08lx.\n", status); ++ if (!status) ++ { ++ size = 0x10000; ++ status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, MEM_COMMIT, PAGE_READWRITE, NULL, 0); ++ ok(!status, "Unexpected status %08lx.\n", status); + -+ status = NtQueryVirtualMemory( NtCurrentProcess(), addr1, MemoryBasicInformation, &mbi, sizeof(mbi), &size ); -+ ok(!status, "Unexpected status %08lx.\n", status); -+ ok(mbi.AllocationProtect == PAGE_READONLY, "Unexpected protection %#lx.\n", mbi.AllocationProtect); -+ ok(mbi.State == MEM_COMMIT, "Unexpected state %#lx.\n", mbi.State); -+ ok(mbi.Type == MEM_PRIVATE, "Unexpected type %#lx.\n", mbi.Type); -+ ok(mbi.RegionSize == 0x10000, "Unexpected size.\n"); ++ status = NtQueryVirtualMemory( NtCurrentProcess(), addr1, MemoryBasicInformation, &mbi, sizeof(mbi), &size ); ++ ok(!status, "Unexpected status %08lx.\n", status); ++ ok(mbi.AllocationProtect == PAGE_READONLY, "Unexpected protection %#lx.\n", mbi.AllocationProtect); ++ ok(mbi.State == MEM_COMMIT, "Unexpected state %#lx.\n", mbi.State); ++ ok(mbi.Type == MEM_PRIVATE, "Unexpected type %#lx.\n", mbi.Type); ++ ok(mbi.RegionSize == 0x10000, "Unexpected size.\n"); + -+ size = 0x10000; -+ count = ARRAY_SIZE(addresses); -+ status = NtGetWriteWatch( NtCurrentProcess(), WRITE_WATCH_FLAG_RESET, addr1, size, -+ addresses, &count, &granularity ); -+ ok(!status, "Unexpected status %08lx.\n", status); -+ ok(!count, "Unexpected count %u.\n", (unsigned int)count); -+ trace("addr1 %p, addresses[0] %p.\n", addr1, addresses[0]); -+ *((char *)addr1 + 0x1000) = 1; -+ count = ARRAY_SIZE(addresses); -+ status = NtGetWriteWatch( NtCurrentProcess(), WRITE_WATCH_FLAG_RESET, addr1, size, -+ addresses, &count, &granularity ); -+ ok(!status, "Unexpected status %08lx.\n", status); -+ ok(count == 1, "Unexpected count %u.\n", (unsigned int)count); -+ ok(addresses[0] == (char *)addr1 + 0x1000, "Unexpected address %p.\n", addresses[0]); ++ size = 0x10000; ++ count = ARRAY_SIZE(addresses); ++ status = NtGetWriteWatch( NtCurrentProcess(), WRITE_WATCH_FLAG_RESET, addr1, size, ++ addresses, &count, &granularity ); ++ ok(!status, "Unexpected status %08lx.\n", status); ++ ok(!count, "Unexpected count %u.\n", (unsigned int)count); ++ *((char *)addr1 + 0x1000) = 1; ++ count = ARRAY_SIZE(addresses); ++ status = NtGetWriteWatch( NtCurrentProcess(), WRITE_WATCH_FLAG_RESET, addr1, size, ++ addresses, &count, &granularity ); ++ ok(!status, "Unexpected status %08lx.\n", status); ++ ok(count == 1, "Unexpected count %u.\n", (unsigned int)count); ++ ok(addresses[0] == (char *)addr1 + 0x1000, "Unexpected address %p.\n", addresses[0]); + -+ size = 0; -+ status = NtFreeVirtualMemory(NtCurrentProcess(), &addr1, &size, MEM_RELEASE); -+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); -+ -+ /* Placeholder region splitting. */ ++ size = 0; ++ status = NtFreeVirtualMemory(NtCurrentProcess(), &addr1, &size, MEM_RELEASE); ++ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ++ } + + /* Placeholder region splitting. */ + addr1 = NULL; + size = 0x10000; + status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, MEM_RESERVE, @@ -186,126 +176,95 @@ index 335ba118fb9..3000ae68620 100644 + p = addr1; + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p, &size, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); + ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status); ++ ok(size == 0x10000, "Unexpected size %#Ix.\n", size); + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p, &size, MEM_RELEASE); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ++ ok(size == 0x10000, "Unexpected size %#Ix.\n", size); ++ ok(p == addr1, "Unexpected addr %p, expected %p.\n", p, addr1); ++ /* Split in three regions. */ addr1 = NULL; - size = 0x10000; - status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, +@@ -349,12 +467,17 @@ static void test_NtAllocateVirtualMemoryEx(void) PAGE_NOACCESS, NULL, 0); -- todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); -- if (status == STATUS_SUCCESS) -- { -- p = addr1; -- p1 = p + size / 2; -- p2 = p1 + size / 4; -- size2 = size / 4; -- status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); -- ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); -- -- check_region_size(p, size / 2); -- check_region_size(p1, size / 4); -- check_region_size(p2, size - size / 2 - size / 4); -- -- status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p, &size2, MEM_RELEASE); -- ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); -- status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE); -- ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); -- status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE); -- ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); -- } -+ p = addr1; -+ p1 = p + size / 2; -+ p2 = p1 + size / 4; -+ size2 = size / 4; -+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); -+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ++ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&addr1, &size, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); ++ ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status); + -+ check_region_size(p, size / 2); -+ check_region_size(p1, size / 4); -+ check_region_size(p2, size - size / 2 - size / 4); -+ -+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p, &size2, MEM_RELEASE); -+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); -+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE); -+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); -+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE); -+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + p = addr1; + p1 = p + size / 2; + p2 = p1 + size / 4; + size2 = size / 4; + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ++ ok(size2 == 0x4000, "Unexpected size %#Ix.\n", size2); ++ ok(p1 == p + size / 2, "Unexpected addr %p, expected %p.\n", p, p + size / 2); + + check_region_size(p, size / 2); + check_region_size(p1, size / 4); +@@ -362,10 +485,16 @@ static void test_NtAllocateVirtualMemoryEx(void) + + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p, &size2, MEM_RELEASE); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ++ ok(size2 == 0x4000, "Unexpected size %#Ix.\n", size2); ++ ok(p == addr1, "Unexpected addr %p, expected %p.\n", p, addr1); + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ++ ok(size2 == 0x4000, "Unexpected size %#Ix.\n", size2); ++ ok(p1 == p + size / 2, "Unexpected addr %p, expected %p.\n", p1, p + size / 2); + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ++ ok(size2 == 0x4000, "Unexpected size %#Ix.\n", size2); ++ ok(p2 == p1 + size / 4, "Unexpected addr %p, expected %p.\n", p2, p1 + size / 4); /* Split in two regions, specifying lower part. */ addr1 = NULL; -@@ -383,22 +487,19 @@ static void test_NtAllocateVirtualMemoryEx(void) - todo_wine - ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); - -- if (status == STATUS_SUCCESS) -- { -- p1 = addr1; -- p2 = p1 + size / 4; -- size2 = size / 4; -- status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); -- ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); -- ok(p1 == addr1, "Unexpected address.\n"); -- -- check_region_size(p1, size / 4); -- check_region_size(p2, size - size / 4); -- status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE); -- ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); -- status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE); -- ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); -- } -+ p1 = addr1; -+ p2 = p1 + size / 4; -+ size2 = size / 4; -+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); -+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); -+ ok(p1 == addr1, "Unexpected address.\n"); -+ -+ check_region_size(p1, size / 4); -+ check_region_size(p2, size - size / 4); -+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE); -+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); -+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE); -+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); - - /* Split in two regions, specifying second half. */ - addr1 = NULL; -@@ -407,23 +508,19 @@ static void test_NtAllocateVirtualMemoryEx(void) +@@ -374,12 +503,19 @@ static void test_NtAllocateVirtualMemoryEx(void) PAGE_NOACCESS, NULL, 0); - todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); -+ p1 = addr1; -+ p2 = p1 + size / 2; -- if (status == STATUS_SUCCESS) -- { -- p1 = addr1; -- p2 = p1 + size / 2; -- -- size2 = size / 2; -- status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); -- ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); -- ok(p2 == p1 + size / 2, "Unexpected address.\n"); -- check_region_size(p1, size / 2); -- check_region_size(p2, size / 2); -- status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE); -- ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); -- status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE); -- ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); -- } -+ size2 = size / 2; -+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); -+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); -+ ok(p2 == p1 + size / 2, "Unexpected address.\n"); -+ check_region_size(p1, size / 2); -+ check_region_size(p2, size / 2); -+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE); -+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); -+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE); -+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ++ size2 = 0; ++ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&addr1, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); ++ ok(status == STATUS_INVALID_PARAMETER_3, "Unexpected status %08lx.\n", status); ++ ok(!size2, "Unexpected size %#Ix.\n", size2); ++ + p1 = addr1; + p2 = p1 + size / 4; + size2 = size / 4; + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + ok(p1 == addr1, "Unexpected address.\n"); ++ ok(size2 == 0x4000, "Unexpected size %#Ix.\n", size2); ++ ok(p1 == addr1, "Unexpected addr %p, expected %p.\n", p1, addr1); + + check_region_size(p1, size / 4); + check_region_size(p2, size - size / 4); +@@ -394,6 +530,7 @@ static void test_NtAllocateVirtualMemoryEx(void) + status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, + PAGE_NOACCESS, NULL, 0); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ++ ok(size == 0x10000, "Unexpected size %#Ix.\n", size); + + p1 = addr1; + p2 = p1 + size / 2; +@@ -401,13 +538,18 @@ static void test_NtAllocateVirtualMemoryEx(void) + size2 = size / 2; + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); +- ok(p2 == p1 + size / 2, "Unexpected address.\n"); ++ ok(size2 == 0x8000, "Unexpected size %#Ix.\n", size2); ++ ok(p2 == p1 + size / 2, "Unexpected addr %p, expected %p.\n", p2, p1 + size / 2); + check_region_size(p1, size / 2); + check_region_size(p2, size / 2); + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ++ ok(size2 == 0x8000, "Unexpected size %#Ix.\n", size2); ++ ok(p1 == addr1, "Unexpected addr %p, expected %p.\n", p1, addr1); + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ++ ok(size2 == 0x8000, "Unexpected size %#Ix.\n", size2); ++ ok(p2 == p1 + size / 2, "Unexpected addr %p, expected %p.\n", p2, p1 + size / 2); memset( &ext, 0, sizeof(ext) ); ext.Type = MemExtendedParameterAttributeFlags; diff --git a/patches/ntdll-Placeholders/0008-ntdll-Support-MEM_COALESCE_PLACEHOLDERS-in-NtFreeVir.patch b/patches/ntdll-Placeholders/0008-ntdll-Support-MEM_COALESCE_PLACEHOLDERS-in-NtFreeVir.patch new file mode 100644 index 00000000..ecbe199b --- /dev/null +++ b/patches/ntdll-Placeholders/0008-ntdll-Support-MEM_COALESCE_PLACEHOLDERS-in-NtFreeVir.patch @@ -0,0 +1,202 @@ +From e3fa80eae8154f4e621601d571306a96c71c285b Mon Sep 17 00:00:00 2001 +From: Paul Gofman +Date: Thu, 10 Nov 2022 19:02:50 -0600 +Subject: [PATCH] ntdll: Support MEM_COALESCE_PLACEHOLDERS in + NtFreeVirtualMemory(). + +--- + dlls/ntdll/tests/virtual.c | 72 ++++++++++++++++++++++++++++++++++++-- + dlls/ntdll/unix/virtual.c | 53 +++++++++++++++++++++++++++- + 2 files changed, 122 insertions(+), 3 deletions(-) + +diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c +index 3307c19bbea..c1e194f9e7d 100644 +--- a/dlls/ntdll/tests/virtual.c ++++ b/dlls/ntdll/tests/virtual.c +@@ -295,9 +295,9 @@ static void test_NtAllocateVirtualMemoryEx(void) + { + MEMORY_BASIC_INFORMATION mbi; + MEM_EXTENDED_PARAMETER ext; ++ char *p, *p1, *p2, *p3; + void *addresses[16]; + SIZE_T size, size2; +- char *p, *p1, *p2; + ULONG granularity; + NTSTATUS status; + ULONG_PTR count; +@@ -510,6 +510,7 @@ static void test_NtAllocateVirtualMemoryEx(void) + + p1 = addr1; + p2 = p1 + size / 4; ++ p3 = p2 + size / 4; + size2 = size / 4; + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); +@@ -517,12 +518,79 @@ static void test_NtAllocateVirtualMemoryEx(void) + ok(size2 == 0x4000, "Unexpected size %#Ix.\n", size2); + ok(p1 == addr1, "Unexpected addr %p, expected %p.\n", p1, addr1); + ++ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); ++ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ++ ++ check_region_size(p1, p2 - p1); ++ check_region_size(p2, p3 - p2); ++ check_region_size(p3, size - (p3 - p1)); ++ ++ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS); ++ ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status); ++ ++ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size, MEM_COALESCE_PLACEHOLDERS); ++ ok(status == STATUS_INVALID_PARAMETER_4, "Unexpected status %08lx.\n", status); ++ ++ size2 = size + 0x1000; ++ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS); ++ ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status); ++ ++ size2 = size - 0x1000; ++ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS); ++ ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status); ++ ++ p1 = (char *)addr1 + 0x1000; ++ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS); ++ ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status); ++ p1 = addr1; ++ ++ size2 = 0; ++ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS); ++ ok(status == STATUS_INVALID_PARAMETER_3, "Unexpected status %08lx.\n", status); ++ ++ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size, MEM_RELEASE); ++ ok(status == STATUS_UNABLE_TO_FREE_VM, "Unexpected status %08lx.\n", status); ++ ++ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS); ++ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ++ ok(size == 0x10000, "Unexpected size %#Ix.\n", size); ++ ok(p1 == addr1, "Unexpected addr %p, expected %p.\n", p1, addr1); ++ check_region_size(p1, size); ++ ++ size2 = size / 4; ++ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); ++ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ++ ok(size2 == 0x4000, "Unexpected size %#Ix.\n", size2); ++ ok(p1 == addr1, "Unexpected addr %p, expected %p.\n", p1, addr1); + check_region_size(p1, size / 4); + check_region_size(p2, size - size / 4); +- status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE); ++ ++ size2 = size - size / 4; ++ status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), (void **)&p2, &size2, MEM_RESERVE | MEM_REPLACE_PLACEHOLDER, ++ PAGE_READWRITE, NULL, 0); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ++ ++ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS); ++ ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status); ++ ++ size2 = size - size / 4; + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ++ ok(size2 == 0xc000, "Unexpected size %#Ix.\n", size2); ++ ok(p2 == p1 + size / 4, "Unexpected addr %p, expected %p.\n", p2, p1 + size / 4); ++ ++ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS); ++ ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status); ++ ++ size2 = size / 4; ++ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE); ++ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ++ ok(size2 == 0x4000, "Unexpected size %#Ix.\n", size2); ++ ok(p1 == addr1, "Unexpected addr %p, expected %p.\n", p1, addr1); ++ ++ size2 = 0; ++ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p3, &size2, MEM_RELEASE); ++ ok(status == STATUS_MEMORY_NOT_ALLOCATED, "Unexpected status %08lx.\n", status); + + /* Split in two regions, specifying second half. */ + addr1 = NULL; +diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c +index 07c24a31592..f7f5e44fb57 100644 +--- a/dlls/ntdll/unix/virtual.c ++++ b/dlls/ntdll/unix/virtual.c +@@ -114,6 +114,9 @@ struct file_view + unsigned int protect; /* protection for all pages at allocation time and SEC_* flags */ + }; + ++/* Assert this so RB_ENTRY_VALUE() result can be checked for NULL. */ ++C_ASSERT( offsetof( struct file_view, entry ) == 0 ); ++ + /* per-page protection flags */ + #define VPROT_READ 0x01 + #define VPROT_WRITE 0x02 +@@ -2337,6 +2340,52 @@ static NTSTATUS free_pages( struct file_view *view, char *base, size_t size, BOO + } + + ++/*********************************************************************** ++ * coalesce_placeholders ++ * ++ * Coalesce placeholder views. ++ * virtual_mutex must be held by caller. ++ */ ++static NTSTATUS coalesce_placeholders( struct file_view *view, char *base, size_t size, ULONG type ) ++{ ++ struct file_view *curr_view, *next_view; ++ unsigned int i, view_count = 0; ++ size_t views_size = 0; ++ ++ if (type != (MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS)) return STATUS_INVALID_PARAMETER_4; ++ if (!size) return STATUS_INVALID_PARAMETER_3; ++ if (base != view->base) return STATUS_CONFLICTING_ADDRESSES; ++ ++ curr_view = view; ++ while (curr_view->protect & VPROT_FREE_PLACEHOLDER) ++ { ++ ++view_count; ++ views_size += curr_view->size; ++ if (views_size >= size) break; ++ if (!(next_view = RB_ENTRY_VALUE( rb_next( &curr_view->entry ), struct file_view, entry ))) break; ++ if ((char *)curr_view->base + curr_view->size != next_view->base) break; ++ curr_view = next_view; ++ } ++ ++ if (view_count < 2 || size != views_size) return STATUS_CONFLICTING_ADDRESSES; ++ ++ for (i = 1; i < view_count; ++i) ++ { ++ curr_view = RB_ENTRY_VALUE( rb_next( &view->entry ), struct file_view, entry ); ++ unregister_view( curr_view ); ++ free_view( curr_view ); ++ } ++ ++ unregister_view( view ); ++ view->size = views_size; ++ register_view( view ); ++ ++ VIRTUAL_DEBUG_DUMP_VIEW( view ); ++ ++ return STATUS_SUCCESS; ++} ++ ++ + /*********************************************************************** + * allocate_dos_memory + * +@@ -4478,13 +4527,15 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si + else if (!(view = find_view( base, 0 ))) status = STATUS_MEMORY_NOT_ALLOCATED; + else if (!is_view_valloc( view )) status = STATUS_INVALID_PARAMETER; + else if (!size && base != view->base) status = STATUS_FREE_VM_NOT_AT_BASE; +- else if ((char *)view->base + view->size - base < size) status = STATUS_UNABLE_TO_FREE_VM; ++ else if ((char *)view->base + view->size - base < size && !(type & MEM_COALESCE_PLACEHOLDERS)) ++ status = STATUS_UNABLE_TO_FREE_VM; + else if (type == MEM_DECOMMIT) status = decommit_pages( view, base - (char *)view->base, size ); + else if (type == MEM_RELEASE || (type == (MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER))) + { + status = free_pages( view, base, size, type & MEM_PRESERVE_PLACEHOLDER ); + if (!size) size = view->size; + } ++ else if (type & MEM_COALESCE_PLACEHOLDERS) status = coalesce_placeholders( view, base, size, type ); + else status = STATUS_INVALID_PARAMETER; + + if (status == STATUS_SUCCESS) +-- +2.40.1 + diff --git a/patches/ntdll-Placeholders/0016-ntdll-Factor-out-unmap_view_of_section-function.patch b/patches/ntdll-Placeholders/0009-ntdll-Factor-out-unmap_view_of_section-function.patch similarity index 86% rename from patches/ntdll-Placeholders/0016-ntdll-Factor-out-unmap_view_of_section-function.patch rename to patches/ntdll-Placeholders/0009-ntdll-Factor-out-unmap_view_of_section-function.patch index 8594617b..5903bfa0 100644 --- a/patches/ntdll-Placeholders/0016-ntdll-Factor-out-unmap_view_of_section-function.patch +++ b/patches/ntdll-Placeholders/0009-ntdll-Factor-out-unmap_view_of_section-function.patch @@ -1,4 +1,4 @@ -From 41d2b081fcdf72704cfc9a7a0e0f53215074346c Mon Sep 17 00:00:00 2001 +From cf1caf109030ac7b89dae57666ee084b23637a65 Mon Sep 17 00:00:00 2001 From: Paul Gofman Date: Fri, 11 Nov 2022 12:41:31 -0600 Subject: [PATCH] ntdll: Factor out unmap_view_of_section() function. @@ -8,10 +8,10 @@ Subject: [PATCH] ntdll: Factor out unmap_view_of_section() function. 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c -index ed6d9be8b6f..320596c740e 100644 +index f7f5e44fb57..71a5b294940 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c -@@ -5208,11 +5208,7 @@ NTSTATUS WINAPI NtMapViewOfSectionEx( HANDLE handle, HANDLE process, PVOID *addr +@@ -5236,11 +5236,7 @@ NTSTATUS WINAPI NtMapViewOfSectionEx( HANDLE handle, HANDLE process, PVOID *addr return virtual_map_section( handle, addr_ptr, limit, 0, offset_ptr, size_ptr, alloc_type, protect ); } @@ -24,7 +24,7 @@ index ed6d9be8b6f..320596c740e 100644 { struct file_view *view; unsigned int status = STATUS_NOT_MAPPED_VIEW; -@@ -5269,6 +5265,15 @@ NTSTATUS WINAPI NtUnmapViewOfSection( HANDLE process, PVOID addr ) +@@ -5297,6 +5293,15 @@ NTSTATUS WINAPI NtUnmapViewOfSection( HANDLE process, PVOID addr ) return status; } @@ -40,7 +40,7 @@ index ed6d9be8b6f..320596c740e 100644 /*********************************************************************** * NtUnmapViewOfSectionEx (NTDLL.@) * ZwUnmapViewOfSectionEx (NTDLL.@) -@@ -5276,7 +5281,7 @@ NTSTATUS WINAPI NtUnmapViewOfSection( HANDLE process, PVOID addr ) +@@ -5304,7 +5309,7 @@ NTSTATUS WINAPI NtUnmapViewOfSection( HANDLE process, PVOID addr ) NTSTATUS WINAPI NtUnmapViewOfSectionEx( HANDLE process, PVOID addr, ULONG flags ) { if (flags) FIXME("Ignoring flags %#x.\n", (int)flags); diff --git a/patches/ntdll-Placeholders/0009-ntdll-Support-MEM_PRESERVE_PLACEHOLDER-in-NtFreeVirt.patch b/patches/ntdll-Placeholders/0009-ntdll-Support-MEM_PRESERVE_PLACEHOLDER-in-NtFreeVirt.patch deleted file mode 100644 index b5c1a09b..00000000 --- a/patches/ntdll-Placeholders/0009-ntdll-Support-MEM_PRESERVE_PLACEHOLDER-in-NtFreeVirt.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 5275b219783f0a85e3fad17ac0f999c98d4b7b1c Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Thu, 10 Nov 2022 18:43:05 -0600 -Subject: [PATCH] ntdll: Support MEM_PRESERVE_PLACEHOLDER in - NtFreeVirtualMemory(). - -Based on a patch by Nikolay Sivov. ---- - dlls/ntdll/unix/virtual.c | 46 +++++++++++++++++++++++++++++++++------ - 1 file changed, 39 insertions(+), 7 deletions(-) - -diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c -index 7142d2adf79..85c4ab878b3 100644 ---- a/dlls/ntdll/unix/virtual.c -+++ b/dlls/ntdll/unix/virtual.c -@@ -123,6 +123,7 @@ struct file_view - #define VPROT_WRITTEN 0x80 - /* per-mapping protection flags */ - #define VPROT_SYSTEM 0x0200 /* system view (underlying mmap not under our control) */ -+#define VPROT_PLACEHOLDER 0x0400 - - /* Conversion from VPROT_* to Win32 flags */ - static const BYTE VIRTUAL_Win32Flags[16] = -@@ -1115,6 +1116,8 @@ static void dump_view( struct file_view *view ) - TRACE( "View: %p - %p", addr, addr + view->size - 1 ); - if (view->protect & VPROT_SYSTEM) - TRACE( " (builtin image)\n" ); -+ else if (view->protect & VPROT_PLACEHOLDER) -+ TRACE( " (placeholder)\n" ); - else if (view->protect & SEC_IMAGE) - TRACE( " (image)\n" ); - else if (view->protect & SEC_FILE) -@@ -4180,7 +4183,7 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si - } - else if (!(view = find_view( base, 0 ))) status = STATUS_MEMORY_NOT_ALLOCATED; - else if (!is_view_valloc( view )) status = STATUS_INVALID_PARAMETER; -- else if (type == MEM_RELEASE) -+ else if (type == MEM_RELEASE || (type == (MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER))) - { - /* Free the pages */ - -@@ -4190,14 +4193,15 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si - { - if (!size) size = view->size; - -- if (size == view->size) -+ if (type == MEM_RELEASE && size == view->size) - { - assert( base == view->base ); - delete_view( view ); - } - else - { -- struct file_view *new_view = NULL; -+ struct file_view *new_view = NULL, *preserve_view = NULL; -+ int preserve_whole; - - if (view->base != base && base + size != (char *)view->base + view->size - && !(new_view = alloc_view())) -@@ -4205,7 +4209,8 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si - ERR( "out of memory for %p-%p\n", base, (char *)base + size ); - return STATUS_NO_MEMORY; - } -- unregister_view( view ); -+ preserve_whole = (size == view->size); -+ if (!preserve_whole) unregister_view( view ); - - if (new_view) - { -@@ -4220,7 +4225,7 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si - VIRTUAL_DEBUG_DUMP_VIEW( view ); - VIRTUAL_DEBUG_DUMP_VIEW( new_view ); - } -- else -+ else if (!preserve_whole) - { - if (view->base == base) - { -@@ -4235,8 +4240,35 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si - VIRTUAL_DEBUG_DUMP_VIEW( view ); - } - -- set_page_vprot( base, size, 0 ); -- unmap_area( base, size ); -+ if (type & MEM_PRESERVE_PLACEHOLDER) -+ { -+ if (preserve_whole) -+ { -+ view->protect = VPROT_PLACEHOLDER; -+ preserve_view = view; -+ } -+ else -+ { -+ if (!(preserve_view = alloc_view())) -+ { -+ ERR( "out of memory for %p-%p\n", base, (char *)base + size ); -+ return STATUS_NO_MEMORY; -+ } -+ preserve_view->base = base; -+ preserve_view->size = size; -+ preserve_view->protect = VPROT_PLACEHOLDER; -+ register_view( preserve_view ); -+ } -+ set_page_vprot( base, size, 0 ); -+ if (anon_mmap_fixed(base, size, 0, 0) != base) -+ ERR("anon_mmap_fixed failed, err %s.\n", strerror(errno)); -+ VIRTUAL_DEBUG_DUMP_VIEW( preserve_view ); -+ } -+ else -+ { -+ set_page_vprot( base, size, 0 ); -+ unmap_area( base, size ); -+ } - } - *addr_ptr = base; - *size_ptr = size; --- -2.38.1 - diff --git a/patches/ntdll-Placeholders/0010-ntdll-Pass-allocation-type-to-map_view.patch b/patches/ntdll-Placeholders/0010-ntdll-Pass-allocation-type-to-map_view.patch deleted file mode 100644 index 2744ce09..00000000 --- a/patches/ntdll-Placeholders/0010-ntdll-Pass-allocation-type-to-map_view.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 81be823356cc1752e878a0c26529d8a579d96a54 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Thu, 10 Nov 2022 18:48:14 -0600 -Subject: [PATCH] ntdll: Pass allocation type to map_view(). - -Based on a patch by Nikolay Sivov. ---- - dlls/ntdll/unix/virtual.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c -index 418ad19d990..71cf44bec39 100644 ---- a/dlls/ntdll/unix/virtual.c -+++ b/dlls/ntdll/unix/virtual.c -@@ -2012,8 +2012,9 @@ static NTSTATUS map_fixed_area( void *base, size_t size, unsigned int vprot ) - * virtual_mutex must be held by caller. - */ - static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size, -- int top_down, unsigned int vprot, ULONG_PTR limit, size_t align_mask ) -+ unsigned int alloc_type, unsigned int vprot, ULONG_PTR limit, size_t align_mask ) - { -+ int top_down = alloc_type & MEM_TOP_DOWN; - void *ptr; - NTSTATUS status; - -@@ -2230,7 +2231,7 @@ static NTSTATUS allocate_dos_memory( struct file_view **view, unsigned int vprot - if (mmap_is_in_reserved_area( low_64k, dosmem_size - 0x10000 ) != 1) - { - addr = anon_mmap_tryfixed( low_64k, dosmem_size - 0x10000, unix_prot, 0 ); -- if (addr == MAP_FAILED) return map_view( view, NULL, dosmem_size, FALSE, vprot, 0, 0 ); -+ if (addr == MAP_FAILED) return map_view( view, NULL, dosmem_size, 0, vprot, 0, 0 ); - } - - /* now try to allocate the low 64K too */ -@@ -3371,7 +3372,7 @@ NTSTATUS virtual_alloc_thread_stack( INITIAL_TEB *stack, ULONG_PTR limit, SIZE_T - - server_enter_uninterrupted_section( &virtual_mutex, &sigset ); - -- status = map_view( &view, NULL, size, FALSE, VPROT_READ | VPROT_WRITE | VPROT_COMMITTED, limit, 0 ); -+ status = map_view( &view, NULL, size, 0, VPROT_READ | VPROT_WRITE | VPROT_COMMITTED, limit, 0 ); - if (status != STATUS_SUCCESS) goto done; - - #ifdef VALGRIND_STACK_REGISTER --- -2.40.1 - diff --git a/patches/ntdll-Placeholders/0017-ntdll-Support-MEM_PRESERVE_PLACEHOLDER-in-NtUnmapVie.patch b/patches/ntdll-Placeholders/0010-ntdll-Support-MEM_PRESERVE_PLACEHOLDER-in-NtUnmapVie.patch similarity index 87% rename from patches/ntdll-Placeholders/0017-ntdll-Support-MEM_PRESERVE_PLACEHOLDER-in-NtUnmapVie.patch rename to patches/ntdll-Placeholders/0010-ntdll-Support-MEM_PRESERVE_PLACEHOLDER-in-NtUnmapVie.patch index ba235a7f..2907a726 100644 --- a/patches/ntdll-Placeholders/0017-ntdll-Support-MEM_PRESERVE_PLACEHOLDER-in-NtUnmapVie.patch +++ b/patches/ntdll-Placeholders/0010-ntdll-Support-MEM_PRESERVE_PLACEHOLDER-in-NtUnmapVie.patch @@ -1,4 +1,4 @@ -From af7dcbb2688ca53aa22421b30f02e2b7b08601ca Mon Sep 17 00:00:00 2001 +From 0242eb04e638bde912dec2c7ee189be12ad24b47 Mon Sep 17 00:00:00 2001 From: Paul Gofman Date: Fri, 11 Nov 2022 12:54:19 -0600 Subject: [PATCH] ntdll: Support MEM_PRESERVE_PLACEHOLDER in @@ -7,12 +7,12 @@ Subject: [PATCH] ntdll: Support MEM_PRESERVE_PLACEHOLDER in --- dlls/kernelbase/tests/process.c | 53 +++++++++++++++++++++++++++++++-- dlls/ntdll/unix/server.c | 2 +- - dlls/ntdll/unix/virtual.c | 25 +++++++++++++--- + dlls/ntdll/unix/virtual.c | 18 ++++++++--- server/protocol.def | 1 + - 4 files changed, 73 insertions(+), 8 deletions(-) + 4 files changed, 66 insertions(+), 8 deletions(-) diff --git a/dlls/kernelbase/tests/process.c b/dlls/kernelbase/tests/process.c -index 03f76a1b73a..448369a3743 100644 +index e5185a2587d..d70f947d6aa 100644 --- a/dlls/kernelbase/tests/process.c +++ b/dlls/kernelbase/tests/process.c @@ -41,6 +41,7 @@ static PVOID (WINAPI *pVirtualAllocFromApp)(PVOID, SIZE_T, DWORD, DWORD); @@ -37,7 +37,7 @@ index 03f76a1b73a..448369a3743 100644 /* Placeholder splitting functionality */ placeholder1 = pVirtualAlloc2(NULL, NULL, 2 * size, MEM_RESERVE_PLACEHOLDER | MEM_RESERVE, PAGE_NOACCESS, NULL, 0); ok(!!placeholder1, "Failed to create a placeholder range.\n"); -@@ -199,11 +207,20 @@ static void test_VirtualAlloc2(void) +@@ -198,11 +206,20 @@ static void test_VirtualAlloc2(void) section = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, NULL); ok(!!section, "Failed to create a section.\n"); @@ -60,7 +60,7 @@ index 03f76a1b73a..448369a3743 100644 memset(&info, 0, sizeof(info)); VirtualQuery(placeholder1, &info, sizeof(info)); -@@ -220,7 +237,34 @@ static void test_VirtualAlloc2(void) +@@ -219,7 +236,34 @@ static void test_VirtualAlloc2(void) ok(info.RegionSize == size, "Unexpected size.\n"); CloseHandle(section); @@ -96,7 +96,7 @@ index 03f76a1b73a..448369a3743 100644 UnmapViewOfFile(view2); VirtualFree(placeholder1, 0, MEM_RELEASE); -@@ -250,6 +294,8 @@ static void test_VirtualAlloc2(void) +@@ -249,6 +293,8 @@ static void test_VirtualAlloc2(void) p1 = p; p2 = p + size / 2; @@ -105,7 +105,7 @@ index 03f76a1b73a..448369a3743 100644 ret = VirtualFree(p1, size / 2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); ok(ret, "Failed to split a placeholder.\n"); check_region_size(p1, size / 2); -@@ -462,6 +508,7 @@ static void init_funcs(void) +@@ -461,6 +507,7 @@ static void init_funcs(void) X(VirtualAlloc2); X(VirtualAlloc2FromApp); X(VirtualAllocFromApp); @@ -114,10 +114,10 @@ index 03f76a1b73a..448369a3743 100644 hmod = GetModuleHandleA("ntdll.dll"); diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c -index c143560e360..40efda551e0 100644 +index 469c012190c..f481a1394b8 100644 --- a/dlls/ntdll/unix/server.c +++ b/dlls/ntdll/unix/server.c -@@ -618,7 +618,7 @@ static void invoke_system_apc( const apc_call_t *call, apc_result_t *result, BOO +@@ -638,7 +638,7 @@ static void invoke_system_apc( const apc_call_t *call, apc_result_t *result, BOO result->type = call->type; addr = wine_server_get_ptr( call->unmap_view.addr ); if ((ULONG_PTR)addr == call->unmap_view.addr) @@ -127,10 +127,10 @@ index c143560e360..40efda551e0 100644 result->unmap_view.status = STATUS_INVALID_PARAMETER; break; diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c -index 320596c740e..493f6b80419 100644 +index 71a5b294940..2e61e8ba22f 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c -@@ -5208,7 +5208,7 @@ NTSTATUS WINAPI NtMapViewOfSectionEx( HANDLE handle, HANDLE process, PVOID *addr +@@ -5236,7 +5236,7 @@ NTSTATUS WINAPI NtMapViewOfSectionEx( HANDLE handle, HANDLE process, PVOID *addr return virtual_map_section( handle, addr_ptr, limit, 0, offset_ptr, size_ptr, alloc_type, protect ); } @@ -139,7 +139,7 @@ index 320596c740e..493f6b80419 100644 { struct file_view *view; unsigned int status = STATUS_NOT_MAPPED_VIEW; -@@ -5223,6 +5223,7 @@ NTSTATUS unmap_view_of_section( HANDLE process, PVOID addr ) +@@ -5251,6 +5251,7 @@ NTSTATUS unmap_view_of_section( HANDLE process, PVOID addr ) call.unmap_view.type = APC_UNMAP_VIEW; call.unmap_view.addr = wine_server_client_ptr( addr ); @@ -147,11 +147,11 @@ index 320596c740e..493f6b80419 100644 status = server_queue_process_apc( process, &call, &result ); if (status == STATUS_SUCCESS) status = result.unmap_view.status; return status; -@@ -5231,6 +5232,11 @@ NTSTATUS unmap_view_of_section( HANDLE process, PVOID addr ) +@@ -5259,6 +5260,11 @@ NTSTATUS unmap_view_of_section( HANDLE process, PVOID addr ) server_enter_uninterrupted_section( &virtual_mutex, &sigset ); if ((view = find_view( addr, 0 )) && !is_view_valloc( view )) { -+ if (flags & MEM_PRESERVE_PLACEHOLDER && !(view->protect & VPROT_FROMPLACEHOLDER)) ++ if (flags & MEM_PRESERVE_PLACEHOLDER && !(view->protect & VPROT_PLACEHOLDER)) + { + status = STATUS_CONFLICTING_ADDRESSES; + goto done; @@ -159,22 +159,15 @@ index 320596c740e..493f6b80419 100644 if (view->protect & VPROT_SYSTEM) { struct builtin_module *builtin; -@@ -5257,10 +5263,21 @@ NTSTATUS unmap_view_of_section( HANDLE process, PVOID addr ) +@@ -5285,10 +5291,14 @@ NTSTATUS unmap_view_of_section( HANDLE process, PVOID addr ) if (!status) { if (view->protect & SEC_IMAGE) release_builtin_module( view->base ); - delete_view( view ); + if (flags & MEM_PRESERVE_PLACEHOLDER) -+ { -+ view->protect = VPROT_PLACEHOLDER; -+ set_page_vprot( view->base, view->size, 0 ); -+ if (anon_mmap_fixed(view->base, view->size, 0, 0) != view->base) -+ ERR("anon_mmap_fixed failed, err %s.\n", strerror(errno)); -+ } ++ view_make_placeholder( view ); + else -+ { + delete_view( view ); -+ } } else FIXME( "failed to unmap %p %x\n", view->base, status ); } @@ -182,7 +175,7 @@ index 320596c740e..493f6b80419 100644 server_leave_uninterrupted_section( &virtual_mutex, &sigset ); return status; } -@@ -5271,7 +5288,7 @@ NTSTATUS unmap_view_of_section( HANDLE process, PVOID addr ) +@@ -5299,7 +5309,7 @@ NTSTATUS unmap_view_of_section( HANDLE process, PVOID addr ) */ NTSTATUS WINAPI NtUnmapViewOfSection( HANDLE process, PVOID addr ) { @@ -191,7 +184,7 @@ index 320596c740e..493f6b80419 100644 } /*********************************************************************** -@@ -5281,7 +5298,7 @@ NTSTATUS WINAPI NtUnmapViewOfSection( HANDLE process, PVOID addr ) +@@ -5309,7 +5319,7 @@ NTSTATUS WINAPI NtUnmapViewOfSection( HANDLE process, PVOID addr ) NTSTATUS WINAPI NtUnmapViewOfSectionEx( HANDLE process, PVOID addr, ULONG flags ) { if (flags) FIXME("Ignoring flags %#x.\n", (int)flags); @@ -201,7 +194,7 @@ index 320596c740e..493f6b80419 100644 /****************************************************************************** diff --git a/server/protocol.def b/server/protocol.def -index 8f5202792b4..10729e3ff64 100644 +index 0515dcb2245..9c084fdfff7 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -615,6 +615,7 @@ typedef union diff --git a/patches/ntdll-Placeholders/0011-ntdll-Support-MEM_RESERVE_PLACEHOLDER-in-NtAllocateV.patch b/patches/ntdll-Placeholders/0011-ntdll-Support-MEM_RESERVE_PLACEHOLDER-in-NtAllocateV.patch deleted file mode 100644 index 6ab19d07..00000000 --- a/patches/ntdll-Placeholders/0011-ntdll-Support-MEM_RESERVE_PLACEHOLDER-in-NtAllocateV.patch +++ /dev/null @@ -1,100 +0,0 @@ -From ed0aa7cbd5dcaad27598466c273ed4fb96c71a60 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Thu, 10 Nov 2022 18:53:10 -0600 -Subject: [PATCH] ntdll: Support MEM_RESERVE_PLACEHOLDER in - NtAllocateVirtualMemoryEx(). - -Based on a patch by Nikolay Sivov. ---- - dlls/ntdll/unix/virtual.c | 26 ++++++++++++++++++++++++-- - 1 file changed, 24 insertions(+), 2 deletions(-) - -diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c -index 71cf44bec39..d0f1a1d37b1 100644 ---- a/dlls/ntdll/unix/virtual.c -+++ b/dlls/ntdll/unix/virtual.c -@@ -4045,8 +4045,7 @@ static NTSTATUS allocate_virtual_memory( void **ret, SIZE_T *size_ptr, ULONG typ - - /* Compute the alloc type flags */ - -- if (!(type & (MEM_COMMIT | MEM_RESERVE | MEM_RESET)) || -- (type & ~(MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN | MEM_WRITE_WATCH | MEM_RESET))) -+ if (!(type & (MEM_COMMIT | MEM_RESERVE | MEM_RESET))) - { - WARN("called with wrong alloc type flags (%08x) !\n", (int)type); - return STATUS_INVALID_PARAMETER; -@@ -4054,6 +4053,12 @@ static NTSTATUS allocate_virtual_memory( void **ret, SIZE_T *size_ptr, ULONG typ - - if (!arm64ec_map && (attributes & MEM_EXTENDED_PARAMETER_EC_CODE)) return STATUS_INVALID_PARAMETER; - -+ if (type & MEM_RESERVE_PLACEHOLDER && (protect != PAGE_NOACCESS)) -+ { -+ WARN("Wrong protect %#x for placeholder.\n", protect); -+ return STATUS_INVALID_PARAMETER; -+ } -+ - /* Reserve the memory */ - - server_enter_uninterrupted_section( &virtual_mutex, &sigset ); -@@ -4064,6 +4069,7 @@ static NTSTATUS allocate_virtual_memory( void **ret, SIZE_T *size_ptr, ULONG typ - { - if (type & MEM_COMMIT) vprot |= VPROT_COMMITTED; - if (type & MEM_WRITE_WATCH) vprot |= VPROT_WRITEWATCH; -+ if (type & MEM_RESERVE_PLACEHOLDER) vprot |= VPROT_PLACEHOLDER; - if (protect & PAGE_NOCACHE) vprot |= SEC_NOCACHE; - - if (vprot & VPROT_WRITECOPY) status = STATUS_INVALID_PAGE_PROTECTION; -@@ -4083,6 +4089,7 @@ static NTSTATUS allocate_virtual_memory( void **ret, SIZE_T *size_ptr, ULONG typ - { - if (!(view = find_view( base, size ))) status = STATUS_NOT_MAPPED_VIEW; - else if (view->protect & SEC_FILE) status = STATUS_ALREADY_COMMITTED; -+ else if (view->protect & VPROT_PLACEHOLDER) status = STATUS_CONFLICTING_ADDRESSES; - else if (!(status = set_protection( view, base, size, protect )) && (view->protect & SEC_RESERVE)) - { - SERVER_START_REQ( add_mapping_committed_range ) -@@ -4118,6 +4125,7 @@ static NTSTATUS allocate_virtual_memory( void **ret, SIZE_T *size_ptr, ULONG typ - NTSTATUS WINAPI NtAllocateVirtualMemory( HANDLE process, PVOID *ret, ULONG_PTR zero_bits, - SIZE_T *size_ptr, ULONG type, ULONG protect ) - { -+ static const ULONG type_mask = MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN | MEM_WRITE_WATCH | MEM_RESET; - ULONG_PTR limit; - - TRACE("%p %p %08lx %x %08x\n", process, *ret, *size_ptr, (int)type, (int)protect ); -@@ -4129,6 +4137,12 @@ NTSTATUS WINAPI NtAllocateVirtualMemory( HANDLE process, PVOID *ret, ULONG_PTR z - if (!is_old_wow64() && zero_bits >= 32) return STATUS_INVALID_PARAMETER_3; - #endif - -+ if (type & ~type_mask) -+ { -+ WARN("Called with wrong alloc type flags %08x.\n", type); -+ return STATUS_INVALID_PARAMETER; -+ } -+ - if (process != NtCurrentProcess()) - { - apc_call_t call; -@@ -4231,6 +4245,8 @@ NTSTATUS WINAPI NtAllocateVirtualMemoryEx( HANDLE process, PVOID *ret, SIZE_T *s - ULONG protect, MEM_EXTENDED_PARAMETER *parameters, - ULONG count ) - { -+ static const ULONG type_mask = MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN | MEM_WRITE_WATCH -+ | MEM_RESET | MEM_RESERVE_PLACEHOLDER; - ULONG_PTR limit = 0; - ULONG_PTR align = 0; - ULONG attributes = 0; -@@ -4239,6 +4255,12 @@ NTSTATUS WINAPI NtAllocateVirtualMemoryEx( HANDLE process, PVOID *ret, SIZE_T *s - TRACE( "%p %p %08lx %x %08x %p %u\n", - process, *ret, *size_ptr, (int)type, (int)protect, parameters, (int)count ); - -+ if (type & ~type_mask) -+ { -+ WARN("Called with wrong alloc type flags %08x.\n", type); -+ return STATUS_INVALID_PARAMETER; -+ } -+ - status = get_extended_params( parameters, count, &limit, &align, &attributes ); - if (status) return status; - --- -2.40.1 - diff --git a/patches/ntdll-Placeholders/0012-ntdll-Support-MEM_REPLACE_PLACEHOLDER-in-NtAllocateV.patch b/patches/ntdll-Placeholders/0012-ntdll-Support-MEM_REPLACE_PLACEHOLDER-in-NtAllocateV.patch deleted file mode 100644 index 160e1eeb..00000000 --- a/patches/ntdll-Placeholders/0012-ntdll-Support-MEM_REPLACE_PLACEHOLDER-in-NtAllocateV.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 34562a9ed59356de31669c76bdf87886ee9febe4 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Thu, 10 Nov 2022 18:58:26 -0600 -Subject: [PATCH] ntdll: Support MEM_REPLACE_PLACEHOLDER in - NtAllocateVirtualMemoryEx(). - ---- - dlls/ntdll/unix/virtual.c | 41 +++++++++++++++++++++++++++++++++++---- - 1 file changed, 37 insertions(+), 4 deletions(-) - -diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c -index dd146126361..0f2818f563d 100644 ---- a/dlls/ntdll/unix/virtual.c -+++ b/dlls/ntdll/unix/virtual.c -@@ -126,6 +126,7 @@ struct file_view - /* per-mapping protection flags */ - #define VPROT_SYSTEM 0x0200 /* system view (underlying mmap not under our control) */ - #define VPROT_PLACEHOLDER 0x0400 -+#define VPROT_FROMPLACEHOLDER 0x0800 - - /* Conversion from VPROT_* to Win32 flags */ - static const BYTE VIRTUAL_Win32Flags[16] = -@@ -2044,6 +2045,31 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size, - void *ptr; - NTSTATUS status; - -+ if (alloc_type & MEM_REPLACE_PLACEHOLDER) -+ { -+ if ((*view_ret = find_view( base, 0 ))) -+ { -+ TRACE( "found view %p, size %p, protect %#x.\n", -+ (*view_ret)->base, (void *)(*view_ret)->size, (*view_ret)->protect ); -+ if ((*view_ret)->base != base || (*view_ret)->size != size) -+ return STATUS_CONFLICTING_ADDRESSES; -+ if (!((*view_ret)->protect & VPROT_PLACEHOLDER)) -+ { -+ TRACE("Wrong protect %#x for MEM_REPLACE_PLACEHOLDER.\n", (*view_ret)->protect); -+ return STATUS_INVALID_PARAMETER; -+ } -+ (*view_ret)->protect = vprot | VPROT_FROMPLACEHOLDER; -+ -+ if (!set_vprot( *view_ret, base, size, vprot | VPROT_COMMITTED )) -+ ERR("set_protection failed.\n"); -+ if (vprot & VPROT_WRITEWATCH) -+ reset_write_watches( base, size ); -+ return STATUS_SUCCESS; -+ } -+ TRACE("MEM_REPLACE_PLACEHOLDER view not found.\n"); -+ return STATUS_INVALID_PARAMETER; -+ } -+ - if (base) - { - if (is_beyond_limit( base, size, address_space_limit )) -@@ -4048,7 +4074,7 @@ static NTSTATUS allocate_virtual_memory( void **ret, SIZE_T *size_ptr, ULONG typ - - if (*ret) - { -- if (type & MEM_RESERVE) /* Round down to 64k boundary */ -+ if (type & MEM_RESERVE && !(type & MEM_REPLACE_PLACEHOLDER)) /* Round down to 64k boundary */ - base = ROUND_ADDR( *ret, granularity_mask ); - else - base = ROUND_ADDR( *ret, page_mask ); -@@ -4072,7 +4098,8 @@ static NTSTATUS allocate_virtual_memory( void **ret, SIZE_T *size_ptr, ULONG typ - - /* Compute the alloc type flags */ - -- if (!(type & (MEM_COMMIT | MEM_RESERVE | MEM_RESET))) -+ if (!(type & (MEM_COMMIT | MEM_RESERVE | MEM_RESET)) -+ || (type & MEM_REPLACE_PLACEHOLDER && !(type & MEM_RESERVE))) - { - WARN("called with wrong alloc type flags (%08x) !\n", (int)type); - return STATUS_INVALID_PARAMETER; -@@ -4101,7 +4128,7 @@ static NTSTATUS allocate_virtual_memory( void **ret, SIZE_T *size_ptr, ULONG typ - - if (vprot & VPROT_WRITECOPY) status = STATUS_INVALID_PAGE_PROTECTION; - else if (is_dos_memory) status = allocate_dos_memory( &view, vprot ); -- else status = map_view( &view, base, size, type & MEM_TOP_DOWN, vprot, limit, -+ else status = map_view( &view, base, size, type & (MEM_TOP_DOWN | MEM_REPLACE_PLACEHOLDER), vprot, limit, - align ? align - 1 : granularity_mask ); - - if (status == STATUS_SUCCESS) base = view->base; -@@ -4213,7 +4240,7 @@ NTSTATUS WINAPI NtAllocateVirtualMemoryEx( HANDLE process, PVOID *ret, SIZE_T *s - ULONG count ) - { - static const ULONG type_mask = MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN | MEM_WRITE_WATCH -- | MEM_RESET | MEM_RESERVE_PLACEHOLDER; -+ | MEM_RESET | MEM_RESERVE_PLACEHOLDER | MEM_REPLACE_PLACEHOLDER; - ULONG_PTR limit = 0; - ULONG_PTR align = 0; - ULONG attributes = 0; -@@ -4371,6 +4398,12 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si - - if (size && (char *)view->base + view->size - base < size) status = STATUS_UNABLE_TO_FREE_VM; - else if (!size && base != view->base) status = STATUS_FREE_VM_NOT_AT_BASE; -+ else if (type == (MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER) && !size) status = STATUS_INVALID_PARAMETER_3; -+ else if (type == (MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER) && !((view->protect & VPROT_FROMPLACEHOLDER) -+ || (view->protect & VPROT_PLACEHOLDER && size != view->size))) -+ { -+ status = STATUS_CONFLICTING_ADDRESSES; -+ } - else - { - if (!size) size = view->size; --- -2.40.1 - diff --git a/patches/ntdll-Placeholders/0013-ntdll-Support-MEM_REPLACE_PLACEHOLDER-in-virtual_map.patch b/patches/ntdll-Placeholders/0013-ntdll-Support-MEM_REPLACE_PLACEHOLDER-in-virtual_map.patch deleted file mode 100644 index d2fe875c..00000000 --- a/patches/ntdll-Placeholders/0013-ntdll-Support-MEM_REPLACE_PLACEHOLDER-in-virtual_map.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 96519657b5925777d613f6a6c0e93bc4d85897b9 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Thu, 10 Nov 2022 19:01:50 -0600 -Subject: [PATCH] ntdll: Support MEM_REPLACE_PLACEHOLDER in - virtual_map_section(). - -Based on a patch by Nikolay Sivov. ---- - dlls/ntdll/unix/virtual.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c -index a36d2c47269..7f57b436b55 100644 ---- a/dlls/ntdll/unix/virtual.c -+++ b/dlls/ntdll/unix/virtual.c -@@ -2857,7 +2857,7 @@ static unsigned int virtual_map_section( HANDLE handle, PVOID *addr_ptr, ULONG_P - - server_enter_uninterrupted_section( &virtual_mutex, &sigset ); - -- res = map_view( &view, base, size, alloc_type & MEM_TOP_DOWN, vprot, limit, 0 ); -+ res = map_view( &view, base, size, alloc_type & (MEM_TOP_DOWN | MEM_REPLACE_PLACEHOLDER), vprot, limit, 0 ); - if (res) goto done; - - TRACE( "handle=%p size=%lx offset=%s\n", handle, size, wine_dbgstr_longlong(offset.QuadPart) ); --- -2.40.1 - diff --git a/patches/ntdll-Placeholders/0015-ntdll-Support-MEM_COALESCE_PLACEHOLDERS-in-NtFreeVir.patch b/patches/ntdll-Placeholders/0015-ntdll-Support-MEM_COALESCE_PLACEHOLDERS-in-NtFreeVir.patch deleted file mode 100644 index 3c62e0a3..00000000 --- a/patches/ntdll-Placeholders/0015-ntdll-Support-MEM_COALESCE_PLACEHOLDERS-in-NtFreeVir.patch +++ /dev/null @@ -1,117 +0,0 @@ -From b7bd1f2c2c63573e47b07f178711586a1f37d765 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Thu, 10 Nov 2022 19:02:50 -0600 -Subject: [PATCH] ntdll: Support MEM_COALESCE_PLACEHOLDERS in - NtFreeVirtualMemory(). - ---- - dlls/ntdll/tests/virtual.c | 53 +++++++++++++++++++++++++++++++++++++- - dlls/ntdll/unix/virtual.c | 24 +++++++++++++++++ - 2 files changed, 76 insertions(+), 1 deletion(-) - -diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c -index b41f42ac9d1..11ccca2ffb4 100644 ---- a/dlls/ntdll/tests/virtual.c -+++ b/dlls/ntdll/tests/virtual.c -@@ -499,11 +499,62 @@ static void test_NtAllocateVirtualMemoryEx(void) - - check_region_size(p1, size / 4); - check_region_size(p2, size - size / 4); -- status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE); -+ -+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS); -+ ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status); -+ -+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size, MEM_COALESCE_PLACEHOLDERS); -+ ok(status == STATUS_INVALID_PARAMETER_4, "Unexpected status %08lx.\n", status); -+ -+ size2 = size + 0x1000; -+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS); -+ ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status); -+ -+ size2 = size - 0x1000; -+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS); -+ ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status); -+ -+ p1 = (char *)addr1 + 0x1000; -+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS); -+ ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status); -+ p1 = addr1; -+ -+ size2 = 0; -+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS); -+ ok(status == STATUS_INVALID_PARAMETER_3, "Unexpected status %08lx.\n", status); -+ -+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size, MEM_RELEASE); -+ ok(status == STATUS_UNABLE_TO_FREE_VM, "Unexpected status %08lx.\n", status); -+ -+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS); - ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); -+ check_region_size(p1, size); -+ -+ size2 = size / 4; -+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); -+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); -+ check_region_size(p1, size / 4); -+ check_region_size(p2, size - size / 4); -+ -+ size2 = size - size / 4; -+ status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), (void **)&p2, &size2, MEM_RESERVE | MEM_REPLACE_PLACEHOLDER, -+ PAGE_READWRITE, NULL, 0); -+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); -+ -+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS); -+ ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status); -+ -+ size2 = size - size / 4; - status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE); - ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); - -+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS); -+ ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status); -+ -+ size2 = size / 4; -+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE); -+ ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); -+ - /* Split in two regions, specifying second half. */ - addr1 = NULL; - size = 0x10000; -diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c -index 60203bd4380..226c99c5512 100644 ---- a/dlls/ntdll/unix/virtual.c -+++ b/dlls/ntdll/unix/virtual.c -@@ -4339,6 +4339,30 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si - *size_ptr = size; - } - } -+ else if (type & MEM_COALESCE_PLACEHOLDERS) -+ { -+ struct file_view *next_view = RB_ENTRY_VALUE( rb_next( &view->entry ), struct file_view, entry ); -+ -+ if (type != (MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS)) status = STATUS_INVALID_PARAMETER_4; -+ else if (!size) status = STATUS_INVALID_PARAMETER_3; -+ else if (!next_view || (char *)view->base + view->size != next_view->base -+ || base != view->base || size != view->size + next_view->size -+ || !(view->protect & VPROT_PLACEHOLDER) || !(next_view->protect & VPROT_PLACEHOLDER)) -+ { -+ status = STATUS_CONFLICTING_ADDRESSES; -+ } -+ else -+ { -+ unregister_view( view ); -+ unregister_view( next_view ); -+ -+ view->size += next_view->size; -+ free_view( next_view ); -+ -+ register_view( view ); -+ VIRTUAL_DEBUG_DUMP_VIEW( view ); -+ } -+ } - else - { - WARN("called with wrong free type flags (%08x) !\n", (int)type); --- -2.38.1 - diff --git a/patches/ntdll-Placeholders/definition b/patches/ntdll-Placeholders/definition index 7603fe36..b8bfd7e6 100644 --- a/patches/ntdll-Placeholders/definition +++ b/patches/ntdll-Placeholders/definition @@ -2,4 +2,3 @@ # and "Halo Infinite". Neither have been tested with upstream Wine. Added to # wine-staging primarly because ntdll-ForceBottomUpAlloc touches the same area. Depends: ntdll-WRITECOPY -Disabled: True