Alexandre Julliard : ntdll: Disallow changing PAGE_NOCACHE flag for individual pages.

Alexandre Julliard julliard at winehq.org
Fri Sep 8 15:03:21 CDT 2017


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Fri Sep  8 12:41:01 2017 +0200

ntdll: Disallow changing PAGE_NOCACHE flag for individual pages.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/kernel32/tests/virtual.c | 69 +++++++++++++++++++++++++++++++++++++++++++
 dlls/ntdll/virtual.c          |  2 ++
 2 files changed, 71 insertions(+)

diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c
index 538de70..76953d5 100644
--- a/dlls/kernel32/tests/virtual.c
+++ b/dlls/kernel32/tests/virtual.c
@@ -362,6 +362,75 @@ static void test_VirtualAlloc(void)
 
     ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
 
+    /* PAGE_NOCACHE cannot be set per page in recent Windows */
+    addr1 = VirtualAlloc( NULL, 0x2000, MEM_COMMIT, PAGE_READWRITE | PAGE_NOCACHE );
+    ok( addr1 != NULL, "VirtualAlloc failed\n");
+    ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info), "VirtualQuery failed\n");
+    ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
+    ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
+    ok(info.AllocationProtect == (PAGE_READWRITE | PAGE_NOCACHE),
+       "wrong protect %x\n", info.AllocationProtect);
+    ok(info.RegionSize == 0x2000, "wrong size %lx\n", info.RegionSize);
+    ok(info.State == MEM_COMMIT, "wrong state %x\n", info.State);
+    ok(info.Protect == (PAGE_READWRITE | PAGE_NOCACHE), "wrong protect %x\n", info.Protect);
+    ok(info.Type == MEM_PRIVATE, "wrong type %x\n", info.Type);
+
+    ok(VirtualProtect(addr1, 0x1000, PAGE_READWRITE, &old_prot), "VirtualProtect failed\n");
+    ok( old_prot == (PAGE_READWRITE | PAGE_NOCACHE), "wrong protect %x\n", old_prot );
+    ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info), "VirtualQuery failed\n");
+    ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
+    ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
+    ok(info.AllocationProtect == (PAGE_READWRITE | PAGE_NOCACHE),
+       "wrong protect %x\n", info.AllocationProtect);
+    ok(info.RegionSize == 0x2000 || broken(info.RegionSize == 0x1000),
+       "wrong size %lx\n", info.RegionSize);
+    ok(info.State == MEM_COMMIT, "wrong state %x\n", info.State);
+    ok(info.Protect == (PAGE_READWRITE | PAGE_NOCACHE) || broken(info.Protect == PAGE_READWRITE),
+       "wrong protect %x\n", info.Protect);
+    ok(info.Type == MEM_PRIVATE, "wrong type %x\n", info.Type);
+
+    ok(VirtualProtect(addr1, 0x1000, PAGE_READONLY, &old_prot), "VirtualProtect failed\n");
+    ok( old_prot == (PAGE_READWRITE | PAGE_NOCACHE) || broken(old_prot == PAGE_READWRITE),
+        "wrong protect %x\n", old_prot );
+    ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info), "VirtualQuery failed\n");
+    ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
+    ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
+    ok(info.AllocationProtect == (PAGE_READWRITE | PAGE_NOCACHE),
+       "wrong protect %x\n", info.AllocationProtect);
+    ok(info.RegionSize == 0x1000, "wrong size %lx\n", info.RegionSize);
+    ok(info.State == MEM_COMMIT, "wrong state %x\n", info.State);
+    ok(info.Protect == (PAGE_READONLY | PAGE_NOCACHE) || broken(info.Protect == PAGE_READONLY),
+       "wrong protect %x\n", info.Protect);
+    ok(info.Type == MEM_PRIVATE, "wrong type %x\n", info.Type);
+
+    ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
+
+    addr1 = VirtualAlloc( NULL, 0x2000, MEM_COMMIT, PAGE_READWRITE );
+    ok( addr1 != NULL, "VirtualAlloc failed\n");
+    ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info), "VirtualQuery failed\n");
+    ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
+    ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
+    ok(info.AllocationProtect == PAGE_READWRITE,
+       "wrong protect %x\n", info.AllocationProtect);
+    ok(info.RegionSize == 0x2000, "wrong size %lx\n", info.RegionSize);
+    ok(info.State == MEM_COMMIT, "wrong state %x\n", info.State);
+    ok(info.Protect == PAGE_READWRITE, "wrong protect %x\n", info.Protect);
+    ok(info.Type == MEM_PRIVATE, "wrong type %x\n", info.Type);
+
+    ok(VirtualProtect(addr1, 0x1000, PAGE_READONLY | PAGE_NOCACHE, &old_prot), "VirtualProtect failed\n");
+    ok( old_prot == PAGE_READWRITE, "wrong protect %x\n", old_prot );
+    ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info), "VirtualQuery failed\n");
+    ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
+    ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
+    ok(info.AllocationProtect == PAGE_READWRITE, "wrong protect %x\n", info.AllocationProtect);
+    ok(info.RegionSize == 0x1000, "wrong size %lx\n", info.RegionSize);
+    ok(info.State == MEM_COMMIT, "wrong state %x\n", info.State);
+    ok(info.Protect == PAGE_READONLY || broken(info.Protect == (PAGE_READONLY | PAGE_NOCACHE)),
+       "wrong protect %x\n", info.Protect);
+    ok(info.Type == MEM_PRIVATE, "wrong type %x\n", info.Type);
+
+    ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
+
     /* memory returned by VirtualAlloc should be aligned to 64k */
     addr1 = VirtualAlloc(0, 0x2000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
     ok(addr1 != NULL, "VirtualAlloc failed\n");
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index 990b754..f398fcc 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -2369,6 +2369,8 @@ NTSTATUS WINAPI NtProtectVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T
                     if (!view->mapping || is_compatible_protection( view, new_vprot ))
                     {
                         new_vprot |= VPROT_COMMITTED;
+                        if (view->protect & VPROT_NOCACHE) new_vprot |= VPROT_NOCACHE;
+                        else new_vprot &= ~VPROT_NOCACHE;
                         if (old_prot) *old_prot = VIRTUAL_GetWin32Prot( vprot );
                         if (!VIRTUAL_SetProt( view, base, size, new_vprot )) status = STATUS_ACCESS_DENIED;
                     }




More information about the wine-cvs mailing list