From: Paul Gofman pgofman@codeweavers.com
--- 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 823c947a550..79b067ae640 100644 --- a/dlls/ntdll/tests/virtual.c +++ b/dlls/ntdll/tests/virtual.c @@ -1697,7 +1697,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); @@ -1706,7 +1706,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); @@ -1714,17 +1714,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; @@ -1739,11 +1739,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 506b8f0d72b..566e2dcfb90 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -4069,8 +4069,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;