From: Paul Gofman pgofman@codeweavers.com
--- dlls/kernelbase/tests/process.c | 14 +++ dlls/ntdll/tests/virtual.c | 150 +++++++++++++++++++++++++++++++- 2 files changed, 160 insertions(+), 4 deletions(-)
diff --git a/dlls/kernelbase/tests/process.c b/dlls/kernelbase/tests/process.c index b629b61ea5d..e5185a2587d 100644 --- a/dlls/kernelbase/tests/process.c +++ b/dlls/kernelbase/tests/process.c @@ -204,6 +204,20 @@ static void test_VirtualAlloc2(void) view2 = pMapViewOfFile3(section, NULL, placeholder2, 0, size, MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, NULL, 0); ok(!!view2, "Failed to map a section.\n");
+ memset(&info, 0, sizeof(info)); + VirtualQuery(placeholder1, &info, sizeof(info)); + ok(info.AllocationProtect == PAGE_READWRITE, "Unexpected protection %#lx.\n", info.AllocationProtect); + ok(info.State == MEM_COMMIT, "Unexpected state %#lx.\n", info.State); + ok(info.Type == MEM_MAPPED, "Unexpected type %#lx.\n", info.Type); + ok(info.RegionSize == size, "Unexpected size.\n"); + + memset(&info, 0, sizeof(info)); + VirtualQuery(placeholder2, &info, sizeof(info)); + ok(info.AllocationProtect == PAGE_READWRITE, "Unexpected protection %#lx.\n", info.AllocationProtect); + ok(info.State == MEM_COMMIT, "Unexpected state %#lx.\n", info.State); + ok(info.Type == MEM_MAPPED, "Unexpected type %#lx.\n", info.Type); + ok(info.RegionSize == size, "Unexpected size.\n"); + CloseHandle(section); UnmapViewOfFile(view1); UnmapViewOfFile(view2); diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c index 1718aaf30f9..45ba58868df 100644 --- a/dlls/ntdll/tests/virtual.c +++ b/dlls/ntdll/tests/virtual.c @@ -293,10 +293,14 @@ static void check_region_size_(void *p, SIZE_T s, unsigned int line)
static void test_NtAllocateVirtualMemoryEx(void) { + MEMORY_BASIC_INFORMATION mbi; MEM_EXTENDED_PARAMETER ext[2]; + void *addresses[16]; SIZE_T size, size2; char *p, *p1, *p2; + ULONG granularity; NTSTATUS status; + ULONG_PTR count; void *addr1;
if (!pNtAllocateVirtualMemoryEx) @@ -332,15 +336,129 @@ static void test_NtAllocateVirtualMemoryEx(void) status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr1, 0, &size, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, PAGE_NOACCESS); ok(status == STATUS_INVALID_PARAMETER, "Unexpected status %08lx.\n", status);
+ status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, + PAGE_READWRITE, NULL, 0); + ok(status == STATUS_INVALID_PARAMETER, "Unexpected status %08lx.\n", status); + status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, PAGE_NOACCESS, NULL, 0); ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
- size = 0; - status = NtFreeVirtualMemory(NtCurrentProcess(), &addr1, &size, MEM_RELEASE); - ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + size = 0x10000; + status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, MEM_RESERVE | MEM_COMMIT | MEM_REPLACE_PLACEHOLDER, + PAGE_READWRITE, NULL, 0); + ok(!status, "Unexpected status %08lx.\n", status); + + memset(addr1, 0xcc, size); + + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&addr1, &size, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); + ok(!status, "Unexpected status %08lx.\n", status); + + size = 0x10000; + status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, MEM_RESERVE | MEM_COMMIT | MEM_REPLACE_PLACEHOLDER, + PAGE_READONLY, NULL, 0); + ok(!status, "Unexpected status %08lx.\n", status); + + ok(!*(unsigned int *)addr1, "Got %#x.\n", *(unsigned int *)addr1); + + status = NtQueryVirtualMemory( NtCurrentProcess(), addr1, MemoryBasicInformation, &mbi, sizeof(mbi), &size ); + ok(!status, "Unexpected status %08lx.\n", status); + ok(mbi.AllocationProtect == PAGE_READONLY, "Unexpected protection %#lx.\n", mbi.AllocationProtect); + ok(mbi.State == MEM_COMMIT, "Unexpected state %#lx.\n", mbi.State); + ok(mbi.Type == MEM_PRIVATE, "Unexpected type %#lx.\n", mbi.Type); + ok(mbi.RegionSize == 0x10000, "Unexpected size.\n"); + + size = 0x10000; + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&addr1, &size, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); + ok(!status, "Unexpected status %08lx.\n", status); + + status = NtQueryVirtualMemory( NtCurrentProcess(), addr1, MemoryBasicInformation, &mbi, sizeof(mbi), &size ); + ok(!status, "Unexpected status %08lx.\n", status); + ok(mbi.AllocationProtect == PAGE_NOACCESS, "Unexpected protection %#lx.\n", mbi.AllocationProtect); + ok(mbi.State == MEM_RESERVE, "Unexpected state %#lx.\n", mbi.State); + ok(mbi.Type == MEM_PRIVATE, "Unexpected type %#lx.\n", mbi.Type); + ok(mbi.RegionSize == 0x10000, "Unexpected size.\n"); + + status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, + PAGE_NOACCESS, NULL, 0); + ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status); + + status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, MEM_RESERVE, + PAGE_NOACCESS, NULL, 0); + ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status); + + size = 0x1000; + status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, MEM_RESERVE | MEM_REPLACE_PLACEHOLDER, + PAGE_NOACCESS, NULL, 0); + ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status); + + size = 0x10000; + status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, MEM_COMMIT, PAGE_READWRITE, NULL, 0); + ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status); + + size = 0x10000; + status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, NULL, 0); + ok(status == STATUS_INVALID_PARAMETER, "Unexpected status %08lx.\n", status); + + size = 0x10000; + status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, MEM_COMMIT | MEM_REPLACE_PLACEHOLDER, + PAGE_READWRITE, NULL, 0); + ok(status == STATUS_INVALID_PARAMETER, "Unexpected status %08lx.\n", status); + + size = 0x10000; + status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, + MEM_WRITE_WATCH | MEM_RESERVE | MEM_REPLACE_PLACEHOLDER, + PAGE_READONLY, NULL, 0); + ok(!status || broken(status == STATUS_INVALID_PARAMETER) /* Win10 1809, the version where + NtAllocateVirtualMemoryEx is introduced */, "Unexpected status %08lx.\n", status); + + if (!status) + { + size = 0x10000; + status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, MEM_COMMIT, PAGE_READWRITE, NULL, 0); + ok(!status, "Unexpected status %08lx.\n", status); + + status = NtQueryVirtualMemory( NtCurrentProcess(), addr1, MemoryBasicInformation, &mbi, sizeof(mbi), &size ); + ok(!status, "Unexpected status %08lx.\n", status); + ok(mbi.AllocationProtect == PAGE_READONLY, "Unexpected protection %#lx.\n", mbi.AllocationProtect); + ok(mbi.State == MEM_COMMIT, "Unexpected state %#lx.\n", mbi.State); + ok(mbi.Type == MEM_PRIVATE, "Unexpected type %#lx.\n", mbi.Type); + ok(mbi.RegionSize == 0x10000, "Unexpected size.\n"); + + size = 0x10000; + count = ARRAY_SIZE(addresses); + status = NtGetWriteWatch( NtCurrentProcess(), WRITE_WATCH_FLAG_RESET, addr1, size, + addresses, &count, &granularity ); + ok(!status, "Unexpected status %08lx.\n", status); + ok(!count, "Unexpected count %u.\n", (unsigned int)count); + *((char *)addr1 + 0x1000) = 1; + count = ARRAY_SIZE(addresses); + status = NtGetWriteWatch( NtCurrentProcess(), WRITE_WATCH_FLAG_RESET, addr1, size, + addresses, &count, &granularity ); + ok(!status, "Unexpected status %08lx.\n", status); + ok(count == 1, "Unexpected count %u.\n", (unsigned int)count); + ok(addresses[0] == (char *)addr1 + 0x1000, "Unexpected address %p.\n", addresses[0]); + + size = 0; + status = NtFreeVirtualMemory(NtCurrentProcess(), &addr1, &size, MEM_RELEASE); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + }
/* Placeholder region splitting. */ + addr1 = NULL; + size = 0x10000; + status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, MEM_RESERVE, + PAGE_NOACCESS, NULL, 0); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + p = addr1; + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p, &size, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); + ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status); + ok(size == 0x10000, "Unexpected size %#Ix.\n", size); + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p, &size, MEM_RELEASE); + ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + ok(size == 0x10000, "Unexpected size %#Ix.\n", size); + ok(p == addr1, "Unexpected addr %p, expected %p.\n", p, addr1); +
/* Split in three regions. */ addr1 = NULL; @@ -349,12 +467,17 @@ static void test_NtAllocateVirtualMemoryEx(void) PAGE_NOACCESS, NULL, 0); ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
+ status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&addr1, &size, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); + ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status); + p = addr1; p1 = p + size / 2; p2 = p1 + size / 4; size2 = size / 4; status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + ok(size2 == 0x4000, "Unexpected size %#Ix.\n", size2); + ok(p1 == p + size / 2, "Unexpected addr %p, expected %p.\n", p, p + size / 2);
check_region_size(p, size / 2); check_region_size(p1, size / 4); @@ -362,10 +485,16 @@ static void test_NtAllocateVirtualMemoryEx(void)
status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p, &size2, MEM_RELEASE); ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + ok(size2 == 0x4000, "Unexpected size %#Ix.\n", size2); + ok(p == addr1, "Unexpected addr %p, expected %p.\n", p, addr1); status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE); ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + ok(size2 == 0x4000, "Unexpected size %#Ix.\n", size2); + ok(p1 == p + size / 2, "Unexpected addr %p, expected %p.\n", p1, p + size / 2); status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE); ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + ok(size2 == 0x4000, "Unexpected size %#Ix.\n", size2); + ok(p2 == p1 + size / 4, "Unexpected addr %p, expected %p.\n", p2, p1 + size / 4);
/* Split in two regions, specifying lower part. */ addr1 = NULL; @@ -374,12 +503,19 @@ static void test_NtAllocateVirtualMemoryEx(void) PAGE_NOACCESS, NULL, 0); ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
+ size2 = 0; + status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&addr1, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); + ok(status == STATUS_INVALID_PARAMETER_3, "Unexpected status %08lx.\n", status); + ok(!size2, "Unexpected size %#Ix.\n", size2); + p1 = addr1; p2 = p1 + size / 4; size2 = size / 4; status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); ok(p1 == addr1, "Unexpected address.\n"); + ok(size2 == 0x4000, "Unexpected size %#Ix.\n", size2); + ok(p1 == addr1, "Unexpected addr %p, expected %p.\n", p1, addr1);
check_region_size(p1, size / 4); check_region_size(p2, size - size / 4); @@ -394,6 +530,7 @@ static void test_NtAllocateVirtualMemoryEx(void) status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), &addr1, &size, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, PAGE_NOACCESS, NULL, 0); ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + ok(size == 0x10000, "Unexpected size %#Ix.\n", size);
p1 = addr1; p2 = p1 + size / 2; @@ -401,13 +538,18 @@ static void test_NtAllocateVirtualMemoryEx(void) size2 = size / 2; status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); - ok(p2 == p1 + size / 2, "Unexpected address.\n"); + ok(size2 == 0x8000, "Unexpected size %#Ix.\n", size2); + ok(p2 == p1 + size / 2, "Unexpected addr %p, expected %p.\n", p2, p1 + size / 2); check_region_size(p1, size / 2); check_region_size(p2, size / 2); status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE); ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + ok(size2 == 0x8000, "Unexpected size %#Ix.\n", size2); + ok(p1 == addr1, "Unexpected addr %p, expected %p.\n", p1, addr1); status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE); ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); + ok(size2 == 0x8000, "Unexpected size %#Ix.\n", size2); + ok(p2 == p1 + size / 2, "Unexpected addr %p, expected %p.\n", p2, p1 + size / 2);
memset( ext, 0, sizeof(ext) ); ext[0].Type = MemExtendedParameterAttributeFlags;