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