Module: wine Branch: master Commit: 08acac0864521e1f6886682ad1ac06fa61e3c351 URL: http://source.winehq.org/git/wine.git/?a=commit;h=08acac0864521e1f6886682ad1...
Author: Alexandre Julliard julliard@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@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; }