Module: wine Branch: master Commit: eed406e028102e40a8d33cfd319884015c4496f1 URL: http://source.winehq.org/git/wine.git/?a=commit;h=eed406e028102e40a8d33cfd31...
Author: Dmitry Timoshkov dmitry@baikal.ru Date: Fri Dec 16 14:44:35 2011 +0800
ntdll: Setting WRITECOPY protection on a memory-mapped file is allowed.
---
dlls/kernel32/tests/virtual.c | 21 +++++---------------- dlls/ntdll/virtual.c | 24 ++++++++++++++---------- 2 files changed, 19 insertions(+), 26 deletions(-)
diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c index 3812cb2..336fd87 100644 --- a/dlls/kernel32/tests/virtual.c +++ b/dlls/kernel32/tests/virtual.c @@ -1787,13 +1787,6 @@ static void test_CreateFileMapping_protection(void) { if (!ret) { - /* FIXME: completely remove the condition below once Wine is fixed */ - if (td[i].prot == PAGE_WRITECOPY) - { - todo_wine - ok(ret, "%d: VirtualProtect error %d\n", i, GetLastError()); - continue; - } /* win2k and XP don't support EXEC on file mappings */ if (td[i].prot == PAGE_EXECUTE) { @@ -1809,7 +1802,6 @@ static void test_CreateFileMapping_protection(void) /* Vista+ supports PAGE_EXECUTE_WRITECOPY, earlier versions don't */ if (td[i].prot == PAGE_EXECUTE_WRITECOPY) { - todo_wine ok(broken(!ret), "%d: VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY\n", i); continue; } @@ -1827,7 +1819,11 @@ static void test_CreateFileMapping_protection(void) ok(ret, "VirtualQuery failed %d\n", GetLastError()); ok(info.BaseAddress == base, "%d: got %p != expected %p\n", i, info.BaseAddress, base); ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize); - ok(info.Protect == prot, "%d: got %#x != expected %#x\n", i, info.Protect, prot); + /* FIXME: remove the condition below once Wine is fixed */ + if (td[i].prot == PAGE_EXECUTE_WRITECOPY) + todo_wine ok(info.Protect == prot, "%d: got %#x != expected %#x\n", i, info.Protect, prot); + else + ok(info.Protect == prot, "%d: got %#x != expected %#x\n", i, info.Protect, prot); ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base); ok(info.AllocationProtect == alloc_prot, "%d: %#x != %#x\n", i, info.AllocationProtect, alloc_prot); ok(info.State == MEM_COMMIT, "%d: %#x != MEM_COMMIT\n", i, info.State); @@ -2122,13 +2118,6 @@ static void test_mapping(void) ok(broken(!ret), "VirtualProtect doesn't support PAGE_EXECUTE_WRITECOPY view properly\n"); continue; } - /* FIXME: completely remove the condition below once Wine is fixed */ - if (!ret && page_prot[k] == PAGE_WRITECOPY) - { - todo_wine - ok(ret, "VirtualProtect error %d\n", GetLastError()); - continue; - }
ok(ret, "VirtualProtect error %d, map %#x, view %#x, requested prot %#x\n", GetLastError(), page_prot[i], view[j].prot, page_prot[k]); ok(old_prot == prev_prot, "got %#x, expected %#x\n", old_prot, prev_prot); diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c index e6ca21a..ee56e71 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -2079,26 +2079,30 @@ NTSTATUS WINAPI NtProtectVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T
size = ROUND_SIZE( addr, size ); base = ROUND_ADDR( addr, page_mask ); - if ((status = get_vprot_flags( new_prot, &new_vprot ))) return status; - if (new_vprot & VPROT_WRITECOPY) return STATUS_INVALID_PAGE_PROTECTION; - new_vprot |= VPROT_COMMITTED;
server_enter_uninterrupted_section( &csVirtual, &sigset );
- if (!(view = VIRTUAL_FindView( base, size ))) - { - status = STATUS_INVALID_PARAMETER; - } - else + if ((view = VIRTUAL_FindView( base, size ))) { /* Make sure all the pages are committed */ if (get_committed_size( view, base, &vprot ) >= size && (vprot & VPROT_COMMITTED)) { - if (old_prot) *old_prot = VIRTUAL_GetWin32Prot( vprot ); - if (!VIRTUAL_SetProt( view, base, size, new_vprot )) status = STATUS_ACCESS_DENIED; + if (!(status = get_vprot_flags( new_prot, &new_vprot ))) + { + if ((new_vprot & VPROT_WRITECOPY) && (view->protect & VPROT_VALLOC)) + status = STATUS_INVALID_PAGE_PROTECTION; + else + { + new_vprot |= VPROT_COMMITTED; + if (old_prot) *old_prot = VIRTUAL_GetWin32Prot( vprot ); + if (!VIRTUAL_SetProt( view, base, size, new_vprot )) status = STATUS_ACCESS_DENIED; + } + } } else status = STATUS_NOT_COMMITTED; } + else status = STATUS_INVALID_PARAMETER; + server_leave_uninterrupted_section( &csVirtual, &sigset );
if (status == STATUS_SUCCESS)