Module: wine Branch: master Commit: fb6a6374dda0532b031fbd958a2770ef950f0f66 URL: https://gitlab.winehq.org/wine/wine/-/commit/fb6a6374dda0532b031fbd958a2770e...
Author: Paul Gofman pgofman@codeweavers.com Date: Fri Nov 11 18:41:50 2022 -0600
ntdll: Support partial view release in NtFreeVirtualMemory().
---
dlls/ntdll/tests/virtual.c | 14 +++++++------- dlls/ntdll/unix/virtual.c | 42 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 9 deletions(-)
diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c index 555dbb5b4ff..ffa462f579f 100644 --- a/dlls/ntdll/tests/virtual.c +++ b/dlls/ntdll/tests/virtual.c @@ -1869,7 +1869,7 @@ static void test_NtFreeVirtualMemory(void) size = 0xfff; addr = (char *)addr1 + 0x1001; status = NtFreeVirtualMemory(NtCurrentProcess(), &addr, &size, MEM_RELEASE); - todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); *(volatile char *)addr1 = 1; *((volatile char *)addr1 + 0x2000) = 1; ok(size == 0x1000, "Unexpected size %p.\n", (void *)size); @@ -1878,7 +1878,7 @@ static void test_NtFreeVirtualMemory(void) size = 0xfff; addr = (char *)addr1 + 1; status = NtFreeVirtualMemory(NtCurrentProcess(), &addr, &size, MEM_RELEASE); - todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); *((volatile char *)addr1 + 0x2000) = 1; ok(size == 0x1000, "Unexpected size %p.\n", (void *)size); ok(addr == addr1, "Got addr %p, addr1 %p.\n", addr, addr1); @@ -1886,17 +1886,17 @@ static void test_NtFreeVirtualMemory(void) size = 0x1000; addr = addr1; status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr, 0, &size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); - todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ok(addr == addr1, "Unexpected addr %p, addr1 %p.\n", addr, addr1); ok(size == 0x1000, "Unexpected size %p.\n", (void *)size);
size = 0x10000; status = NtFreeVirtualMemory(NtCurrentProcess(), &addr1, &size, MEM_DECOMMIT); - todo_wine ok(status == STATUS_UNABLE_TO_FREE_VM, "Unexpected status %08lx.\n", status); + ok(status == STATUS_UNABLE_TO_FREE_VM, "Unexpected status %08lx.\n", status);
size = 0x10000; status = NtFreeVirtualMemory(NtCurrentProcess(), &addr1, &size, MEM_RELEASE); - todo_wine ok(status == STATUS_UNABLE_TO_FREE_VM, "Unexpected status %08lx.\n", status); + ok(status == STATUS_UNABLE_TO_FREE_VM, "Unexpected status %08lx.\n", status);
size = 0; addr = (char *)addr1 + 0x1000; @@ -1911,11 +1911,11 @@ static void test_NtFreeVirtualMemory(void) size = 0; addr = (char *)addr1 + 0x2000; status = NtFreeVirtualMemory(NtCurrentProcess(), &addr, &size, MEM_RELEASE); - todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
size = 0x1000; status = NtFreeVirtualMemory(NtCurrentProcess(), &addr1, &size, MEM_RELEASE); - todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); }
static void test_prefetch(void) diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index 1f24cbd6914..ac3e4591ac4 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -4258,8 +4258,46 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si } else { - FIXME( "Parial view release is not supported.\n" ); - status = STATUS_INVALID_PARAMETER; + struct file_view *new_view = NULL; + + if (view->base != base && base + size != (char *)view->base + view->size + && !(new_view = alloc_view())) + { + ERR( "out of memory for %p-%p\n", base, (char *)base + size ); + return STATUS_NO_MEMORY; + } + unregister_view( view ); + + if (new_view) + { + new_view->base = base + size; + new_view->size = (char *)view->base + view->size - (char *)new_view->base; + new_view->protect = view->protect; + + view->size = base - (char *)view->base; + register_view( view ); + register_view( new_view ); + + VIRTUAL_DEBUG_DUMP_VIEW( view ); + VIRTUAL_DEBUG_DUMP_VIEW( new_view ); + } + else + { + if (view->base == base) + { + view->base = base + size; + view->size -= size; + } + else + { + view->size = base - (char *)view->base; + } + register_view( view ); + VIRTUAL_DEBUG_DUMP_VIEW( view ); + } + + set_page_vprot( base, size, 0 ); + unmap_area( base, size ); } *addr_ptr = base; *size_ptr = size;