Module: wine Branch: master Commit: fce615a2c3da4d408d61ddca6e6b34c606fc2171 URL: https://gitlab.winehq.org/wine/wine/-/commit/fce615a2c3da4d408d61ddca6e6b34c...
Author: Paul Gofman pgofman@codeweavers.com Date: Fri Nov 11 12:54:19 2022 -0600
ntdll: Support MEM_PRESERVE_PLACEHOLDER in NtUnmapViewOfSectionEx().
---
dlls/kernelbase/tests/process.c | 16 ++++++++-------- dlls/ntdll/unix/server.c | 2 +- dlls/ntdll/unix/virtual.c | 17 ++++++++++++----- include/wine/server_protocol.h | 4 ++-- server/protocol.def | 2 +- 5 files changed, 24 insertions(+), 17 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 40fe2c9b282..b208d7d8e9b 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -5225,7 +5225,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; @@ -5240,6 +5240,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; @@ -5248,6 +5249,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; @@ -5274,7 +5280,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: @@ -5289,7 +5296,7 @@ done: */ NTSTATUS WINAPI NtUnmapViewOfSection( HANDLE process, PVOID addr ) { - return unmap_view_of_section( process, addr ); + return unmap_view_of_section( process, addr, 0 ); }
/*********************************************************************** @@ -5305,8 +5312,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/include/wine/server_protocol.h b/include/wine/server_protocol.h index 87626aaf051..de56b8420d5 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -598,7 +598,7 @@ typedef union struct { enum apc_type type; - int __pad; + unsigned int flags; client_ptr_t addr; } unmap_view; struct @@ -6415,7 +6415,7 @@ union generic_reply
/* ### protocol_version begin ### */
-#define SERVER_PROTOCOL_VERSION 770 +#define SERVER_PROTOCOL_VERSION 771
/* ### protocol_version end ### */
diff --git a/server/protocol.def b/server/protocol.def index 1c492ea5cc2..a1d066b0918 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -614,7 +614,7 @@ typedef union struct { enum apc_type type; /* APC_UNMAP_VIEW */ - int __pad; + unsigned int flags; /* unmap flags */ client_ptr_t addr; /* view address */ } unmap_view; struct