From: Kareem Aladli karimri@protonmail.com
--- dlls/ntdll/tests/virtual.c | 72 ++++++++++++++++++++++++++++++++++++++ dlls/ntdll/unix/virtual.c | 19 +++++++--- 2 files changed, 87 insertions(+), 4 deletions(-)
diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c index c48652f0f65..0628a636264 100644 --- a/dlls/ntdll/tests/virtual.c +++ b/dlls/ntdll/tests/virtual.c @@ -2503,6 +2503,77 @@ static void test_NtFreeVirtualMemory(void) ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); }
+static void test_NtProtectVirtualMemory(void) +{ + void *addr, *addr2; + NTSTATUS status; + SIZE_T size; + DWORD old_prot; + + size = page_size * 16; + addr = NULL; + status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr, 0, &size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + + old_prot = 0; + status = NtProtectVirtualMemory(NtCurrentProcess(), &addr, &size, PAGE_READONLY, &old_prot); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + ok(old_prot == PAGE_READWRITE, "Unexpected old_prot %lx.\n", old_prot); + + status = NtProtectVirtualMemory(NULL, &addr, &size, PAGE_READONLY, &old_prot); + ok(status == STATUS_INVALID_HANDLE, "Unexpected status %08lx.\n", status); + + status = NtProtectVirtualMemory(NtCurrentProcess(), &addr, &size, PAGE_READONLY, NULL); + ok(status == STATUS_ACCESS_VIOLATION, "Unexpected status %08lx.\n", status); + + status = NtProtectVirtualMemory(NtCurrentProcess(), &addr, &size, 0, &old_prot); + ok(status == STATUS_INVALID_PAGE_PROTECTION, "Unexpected status %08lx.\n", status); + + size = page_size * 8; + status = NtProtectVirtualMemory(NtCurrentProcess(), &addr, &size, PAGE_READWRITE, &old_prot); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + ok(old_prot == PAGE_READONLY, "Unexpected old_prot %lx.\n", old_prot); + addr = (char *)addr + page_size * 8; + status = NtProtectVirtualMemory(NtCurrentProcess(), &addr, &size, PAGE_EXECUTE_READWRITE, &old_prot); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + ok(old_prot == PAGE_READONLY, "Unexpected old_prot %lx.\n", old_prot); + addr = (char *)addr - page_size * 8; + size = page_size * 16; + status = NtProtectVirtualMemory(NtCurrentProcess(), &addr, &size, PAGE_EXECUTE_READ, &old_prot); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + ok(old_prot == PAGE_READWRITE, "Unexpected old_prot %lx.\n", old_prot); + + status = NtFreeVirtualMemory(NtCurrentProcess(), &addr, &size, MEM_RELEASE); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + + addr = NULL; + size = page_size; + status = NtProtectVirtualMemory(NtCurrentProcess(), &addr, &size, PAGE_READONLY, &old_prot); + /* todo: STATUS_INVALID_PARAMETER in wine, STATUS_CONFLICTING_ADDRESSES in win64 */ + ok(status, "Unexpected status %08lx.\n", status); + ok(old_prot == PAGE_NOACCESS, "Unexpected old_prot %lx.\n", old_prot); + + status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr, 0, &size, MEM_RESERVE, PAGE_READWRITE); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + status = NtProtectVirtualMemory(NtCurrentProcess(), &addr, &size, PAGE_READONLY, &old_prot); + ok(status == STATUS_NOT_COMMITTED, "Unexpected status %08lx.\n", status); + ok(old_prot == PAGE_NOACCESS, "Unexpected old_prot %lx.\n", old_prot); + status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr, 0, &size, MEM_COMMIT, PAGE_READWRITE); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + + addr2 = addr; + addr = (char *)addr + 1; + size = 1; + status = NtProtectVirtualMemory(NtCurrentProcess(), &addr, &size, PAGE_READONLY, &old_prot); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + ok(old_prot == PAGE_READWRITE, "Unexpected old_prot %lx.\n", old_prot); + ok(size == page_size, "Unexpected size %p.\n", (void *)size); + ok(addr == addr2, "Got addr %p, addr2 %p.\n", addr, addr2); + + status = NtFreeVirtualMemory(NtCurrentProcess(), &addr, &size, MEM_RELEASE); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); +} + static void test_prefetch(void) { NTSTATUS status; @@ -3251,6 +3322,7 @@ START_TEST(virtual) test_NtAllocateVirtualMemoryEx(); test_NtAllocateVirtualMemoryEx_address_requirements(); test_NtFreeVirtualMemory(); + test_NtProtectVirtualMemory(); test_RtlCreateUserStack(); test_NtMapViewOfSection(); test_NtMapViewOfSectionEx(); diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index c5408cbb5da..eb22cfa40df 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -5350,7 +5350,6 @@ NTSTATUS WINAPI NtProtectVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T
if (!old_prot) return STATUS_ACCESS_VIOLATION; - *old_prot = PAGE_NOACCESS;
if (process != NtCurrentProcess()) { @@ -5366,11 +5365,15 @@ NTSTATUS WINAPI NtProtectVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T status = server_queue_process_apc( process, &call, &result ); if (status != STATUS_SUCCESS) return status;
- if (result.virtual_protect.status == STATUS_SUCCESS) + switch (result.virtual_protect.status) { + case STATUS_SUCCESS: *addr_ptr = wine_server_get_ptr( result.virtual_protect.addr ); *size_ptr = result.virtual_protect.size; + case STATUS_NOT_COMMITTED: + case STATUS_INVALID_PARAMETER: *old_prot = result.virtual_protect.prot; + break; } return result.virtual_protect.status; } @@ -5390,9 +5393,17 @@ NTSTATUS WINAPI NtProtectVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T old = get_win32_prot( vprot, view->protect ); status = set_protection( view, base, size, new_prot ); } - else status = STATUS_NOT_COMMITTED; + else + { + status = STATUS_NOT_COMMITTED; + *old_prot = PAGE_NOACCESS; + } + } + else + { + status = STATUS_INVALID_PARAMETER; + *old_prot = PAGE_NOACCESS; } - else status = STATUS_INVALID_PARAMETER;
if (!status) VIRTUAL_DEBUG_DUMP_VIEW( view );