From: Paul Gofman pgofman@codeweavers.com
--- dlls/kernelbase/tests/process.c | 16 ++++++++-------- dlls/ntdll/unix/server.c | 2 +- dlls/ntdll/unix/virtual.c | 17 ++++++++++++----- server/protocol.def | 1 + 4 files changed, 22 insertions(+), 14 deletions(-)
diff --git a/dlls/kernelbase/tests/process.c b/dlls/kernelbase/tests/process.c index 2e5bb7ca458..88a527c45d5 100644 --- a/dlls/kernelbase/tests/process.c +++ b/dlls/kernelbase/tests/process.c @@ -211,9 +211,9 @@ static void test_VirtualAlloc2(void) ret = VirtualFree( view1, size, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER ); ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "Got ret %d, error %lu.\n", ret, GetLastError()); ret = pUnmapViewOfFile2(GetCurrentProcess(), view1, MEM_PRESERVE_PLACEHOLDER); - todo_wine ok(!ret && GetLastError() == ERROR_INVALID_ADDRESS, "Got ret %d, error %lu.\n", ret, GetLastError()); + ok(!ret && GetLastError() == ERROR_INVALID_ADDRESS, "Got ret %d, error %lu.\n", ret, GetLastError()); ret = pUnmapViewOfFile2(GetCurrentProcess(), view1, 0); - todo_wine ok(ret, "Got error %lu.\n", GetLastError()); + ok(ret, "Got error %lu.\n", GetLastError());
view1 = pMapViewOfFile3(section, NULL, placeholder1, 0, size, MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, NULL, 0); ok(view1 == placeholder1, "Address does not match.\n"); @@ -248,9 +248,9 @@ static void test_VirtualAlloc2(void)
memset(&info, 0, sizeof(info)); VirtualQuery(placeholder1, &info, sizeof(info)); - todo_wine ok(info.AllocationProtect == PAGE_NOACCESS, "Unexpected protection %#lx.\n", info.AllocationProtect); - todo_wine ok(info.State == MEM_RESERVE, "Unexpected state %#lx.\n", info.State); - todo_wine ok(info.Type == MEM_PRIVATE, "Unexpected type %#lx.\n", info.Type); + 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");
ret = pUnmapViewOfFile2(GetCurrentProcess(), view1, MEM_PRESERVE_PLACEHOLDER); @@ -260,21 +260,21 @@ static void test_VirtualAlloc2(void) ok(!ret && GetLastError() == ERROR_INVALID_ADDRESS, "Got error %lu.\n", GetLastError());
view1 = pMapViewOfFile3(section, NULL, placeholder1, 0, size, MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, NULL, 0); - todo_wine ok(view1 == placeholder1, "Address does not match.\n"); + ok(view1 == placeholder1, "Address does not match.\n"); CloseHandle(section);
ret = VirtualFree( view1, size, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER ); ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "Got ret %d, error %lu.\n", ret, GetLastError());
ret = pUnmapViewOfFile2(GetCurrentProcess(), view1, MEM_UNMAP_WITH_TRANSIENT_BOOST | MEM_PRESERVE_PLACEHOLDER); - todo_wine ok(ret, "Got error %lu.\n", GetLastError()); + ok(ret, "Got error %lu.\n", GetLastError());
ret = VirtualFree( placeholder1, size, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER ); ok(!ret && GetLastError() == ERROR_INVALID_ADDRESS, "Got ret %d, error %lu.\n", ret, GetLastError()); ret = VirtualFreeEx(GetCurrentProcess(), placeholder1, size, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER ); ok(!ret && GetLastError() == ERROR_INVALID_ADDRESS, "Got ret %d, error %lu.\n", ret, GetLastError()); ret = VirtualFree(placeholder1, 0, MEM_RELEASE); - todo_wine ok(ret, "Got error %lu.\n", GetLastError()); + ok(ret, "Got error %lu.\n", GetLastError());
UnmapViewOfFile(view2);
diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c index 53deff744ba..227784448d3 100644 --- a/dlls/ntdll/unix/server.c +++ b/dlls/ntdll/unix/server.c @@ -615,7 +615,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) - result->unmap_view.status = NtUnmapViewOfSection( NtCurrentProcess(), addr ); + result->unmap_view.status = NtUnmapViewOfSectionEx( NtCurrentProcess(), addr, call->unmap_view.flags ); else result->unmap_view.status = STATUS_INVALID_PARAMETER; break; diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index 0396b49b60f..b4d8a2bf269 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -5221,7 +5221,7 @@ NTSTATUS WINAPI NtMapViewOfSectionEx( HANDLE handle, HANDLE process, PVOID *addr * * NtUnmapViewOfSection[Ex] implementation. */ -static NTSTATUS unmap_view_of_section( HANDLE process, PVOID addr ) +static NTSTATUS unmap_view_of_section( HANDLE process, PVOID addr, ULONG flags ) { struct file_view *view; unsigned int status = STATUS_NOT_MAPPED_VIEW; @@ -5236,6 +5236,7 @@ static 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 ); + call.unmap_view.flags = flags; status = server_queue_process_apc( process, &call, &result ); if (status == STATUS_SUCCESS) status = result.unmap_view.status; return status; @@ -5244,6 +5245,11 @@ static 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 )) goto done;
+ if (flags & MEM_PRESERVE_PLACEHOLDER && !(view->protect & VPROT_PLACEHOLDER)) + { + status = STATUS_CONFLICTING_ADDRESSES; + goto done; + } if (view->protect & VPROT_SYSTEM) { struct builtin_module *builtin; @@ -5270,7 +5276,8 @@ static 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) free_pages_preserve_placeholder( view, view->base, view->size ); + else delete_view( view ); } else FIXME( "failed to unmap %p %x\n", view->base, status ); done: @@ -5285,7 +5292,7 @@ done: */ NTSTATUS WINAPI NtUnmapViewOfSection( HANDLE process, PVOID addr ) { - return unmap_view_of_section( process, addr ); + return unmap_view_of_section( process, addr, 0 ); }
/*********************************************************************** @@ -5301,8 +5308,8 @@ NTSTATUS WINAPI NtUnmapViewOfSectionEx( HANDLE process, PVOID addr, ULONG flags WARN( "Unsupported flags %#x.\n", (int)flags ); return STATUS_INVALID_PARAMETER; } - if (flags) FIXME( "Ignoring flags %#x.\n", (int)flags ); - return unmap_view_of_section( process, addr ); + if (flags & MEM_UNMAP_WITH_TRANSIENT_BOOST) FIXME( "Ignoring MEM_UNMAP_WITH_TRANSIENT_BOOST.\n" ); + return unmap_view_of_section( process, addr, flags ); }
/****************************************************************************** diff --git a/server/protocol.def b/server/protocol.def index 95ddb1d5011..70948c32f30 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -616,6 +616,7 @@ typedef union enum apc_type type; /* APC_UNMAP_VIEW */ int __pad; client_ptr_t addr; /* view address */ + unsigned int flags; /* unmap flags */ } unmap_view; struct {