Dmitry Timoshkov : ntdll: Setting WRITECOPY protection on a memory-mapped file is allowed.

Alexandre Julliard julliard at winehq.org
Fri Dec 16 11:22:53 CST 2011


Module: wine
Branch: master
Commit: eed406e028102e40a8d33cfd319884015c4496f1
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=eed406e028102e40a8d33cfd319884015c4496f1

Author: Dmitry Timoshkov <dmitry at 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)




More information about the wine-cvs mailing list