kernel32/tests: Add tests for virtual memory alignment behaviour.
AT_ROUND_TO_PAGE is only available on 32-bit non-wow64 systems.
This commit is contained in:
parent
8abd5b76c4
commit
5204d89dc9
|
@ -47,7 +47,10 @@ static struct _TEB * (WINAPI *pNtCurrentTeb)(void);
|
|||
static PVOID (WINAPI *pRtlAddVectoredExceptionHandler)(ULONG, PVECTORED_EXCEPTION_HANDLER);
|
||||
static ULONG (WINAPI *pRtlRemoveVectoredExceptionHandler)(PVOID);
|
||||
static BOOL (WINAPI *pGetProcessDEPPolicy)(HANDLE, LPDWORD, PBOOL);
|
||||
static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
|
||||
static NTSTATUS (WINAPI *pNtProtectVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG, ULONG *);
|
||||
static NTSTATUS (WINAPI *pNtAllocateVirtualMemory)(HANDLE, PVOID *, ULONG, SIZE_T *, ULONG, ULONG);
|
||||
static NTSTATUS (WINAPI *pNtFreeVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG);
|
||||
|
||||
/* ############################### */
|
||||
|
||||
|
@ -237,6 +240,8 @@ static void test_VirtualAlloc(void)
|
|||
void *addr1, *addr2;
|
||||
DWORD old_prot;
|
||||
MEMORY_BASIC_INFORMATION info;
|
||||
NTSTATUS status;
|
||||
SIZE_T size;
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
addr1 = VirtualAlloc(0, 0, MEM_RESERVE, PAGE_NOACCESS);
|
||||
|
@ -372,6 +377,42 @@ static void test_VirtualAlloc(void)
|
|||
"got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
|
||||
|
||||
ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
|
||||
|
||||
addr1 = VirtualAlloc(0, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
ok(addr1 != NULL, "VirtualAlloc failed\n");
|
||||
ok(!((ULONG_PTR)addr1 & 0xffff), "returned memory %p is not aligned to 64k\n", addr1);
|
||||
|
||||
/* allocation conflicts because of 64k align */
|
||||
size = 0x1000;
|
||||
addr2 = (char *)addr1 + 0x1000;
|
||||
status = pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2, 0, &size,
|
||||
MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
ok(status == STATUS_CONFLICTING_ADDRESSES, "NtAllocateVirtualMemory returned %08x\n", status);
|
||||
|
||||
/* it should conflict, even when zero_bits is explicitly set */
|
||||
size = 0x1000;
|
||||
addr2 = (char *)addr1 + 0x1000;
|
||||
status = pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2, 12, &size,
|
||||
MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
todo_wine
|
||||
ok(status == STATUS_CONFLICTING_ADDRESSES, "NtAllocateVirtualMemory returned %08x\n", status);
|
||||
if (status == STATUS_SUCCESS) ok(VirtualFree(addr2, 0, MEM_RELEASE), "VirtualFree failed\n");
|
||||
|
||||
/* AT_ROUND_TO_PAGE flag is not supported for VirtualAlloc */
|
||||
SetLastError(0xdeadbeef);
|
||||
addr2 = VirtualAlloc(addr1, 0x1000, MEM_RESERVE | MEM_COMMIT | AT_ROUND_TO_PAGE, PAGE_EXECUTE_READWRITE);
|
||||
ok(!addr2, "VirtualAlloc unexpectedly succeeded\n");
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %d, expected ERROR_INVALID_PARAMETER\n", GetLastError());
|
||||
|
||||
/* AT_ROUND_TO_PAGE flag is not supported for NtAllocateVirtualMemory */
|
||||
size = 0x1000;
|
||||
addr2 = (char *)addr1 + 0x1000;
|
||||
status = pNtAllocateVirtualMemory(GetCurrentProcess(), &addr2, 0, &size, MEM_RESERVE |
|
||||
MEM_COMMIT | AT_ROUND_TO_PAGE, PAGE_EXECUTE_READWRITE);
|
||||
todo_wine
|
||||
ok(status == STATUS_INVALID_PARAMETER_5, "NtAllocateVirtualMemory returned %08x\n", status);
|
||||
|
||||
ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
|
||||
}
|
||||
|
||||
static void test_MapViewOfFile(void)
|
||||
|
@ -957,8 +998,8 @@ static void test_NtMapViewOfSection(void)
|
|||
static const char data[] = "test data for NtMapViewOfSection";
|
||||
char buffer[sizeof(data)];
|
||||
HANDLE file, mapping;
|
||||
void *ptr;
|
||||
BOOL ret;
|
||||
void *ptr, *ptr2;
|
||||
BOOL is_wow64, ret;
|
||||
DWORD status, written;
|
||||
SIZE_T size, result;
|
||||
LARGE_INTEGER offset;
|
||||
|
@ -988,12 +1029,165 @@ static void test_NtMapViewOfSection(void)
|
|||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
|
||||
ok( !status, "NtMapViewOfSection failed status %x\n", status );
|
||||
ok( !((ULONG_PTR)ptr & 0xffff), "returned memory %p is not aligned to 64k\n", ptr );
|
||||
|
||||
ret = ReadProcessMemory( hProcess, ptr, buffer, sizeof(buffer), &result );
|
||||
ok( ret, "ReadProcessMemory failed\n" );
|
||||
ok( result == sizeof(buffer), "ReadProcessMemory didn't read all data (%lx)\n", result );
|
||||
ok( !memcmp( buffer, data, sizeof(buffer) ), "Wrong data read\n" );
|
||||
|
||||
/* for some unknown reason NtMapViewOfSection fails with STATUS_NO_MEMORY when zero_bits != 0 ? */
|
||||
ptr2 = NULL;
|
||||
size = 0;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 12, 0, &offset, &size, 1, 0, PAGE_READWRITE );
|
||||
todo_wine
|
||||
ok( status == STATUS_NO_MEMORY, "NtMapViewOfSection returned %x\n", status );
|
||||
if (status == STATUS_SUCCESS)
|
||||
{
|
||||
status = pNtUnmapViewOfSection( hProcess, ptr2 );
|
||||
ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
|
||||
}
|
||||
|
||||
ptr2 = NULL;
|
||||
size = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 16, 0, &offset, &size, 1, 0, PAGE_READWRITE );
|
||||
todo_wine
|
||||
ok( status == STATUS_NO_MEMORY, "NtMapViewOfSection returned %x\n", status );
|
||||
if (status == STATUS_SUCCESS)
|
||||
{
|
||||
status = pNtUnmapViewOfSection( hProcess, ptr2 );
|
||||
ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
|
||||
}
|
||||
|
||||
/* mapping at the same page conflicts */
|
||||
ptr2 = ptr;
|
||||
size = 0;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
|
||||
ok( status == STATUS_CONFLICTING_ADDRESSES, "NtMapViewOfSection returned %x\n", status );
|
||||
|
||||
/* offset has to be aligned */
|
||||
ptr2 = ptr;
|
||||
size = 0;
|
||||
offset.QuadPart = 1;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
|
||||
todo_wine
|
||||
ok( status == STATUS_MAPPED_ALIGNMENT, "NtMapViewOfSection returned %x\n", status );
|
||||
|
||||
/* ptr has to be aligned */
|
||||
ptr2 = (char *)ptr + 42;
|
||||
size = 0;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
|
||||
todo_wine
|
||||
ok( status == STATUS_MAPPED_ALIGNMENT, "NtMapViewOfSection returned %x\n", status );
|
||||
|
||||
/* still not 64k aligned */
|
||||
ptr2 = (char *)ptr + 0x1000;
|
||||
size = 0;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset, &size, 1, 0, PAGE_READWRITE );
|
||||
todo_wine
|
||||
ok( status == STATUS_MAPPED_ALIGNMENT, "NtMapViewOfSection returned %x\n", status );
|
||||
|
||||
/* zero_bits != 0 is not allowed when an address is set */
|
||||
ptr2 = (char *)ptr + 0x1000;
|
||||
size = 0;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 12, 0, &offset, &size, 1, 0, PAGE_READWRITE );
|
||||
todo_wine
|
||||
ok( status == STATUS_INVALID_PARAMETER_4, "NtMapViewOfSection returned %x\n", status );
|
||||
if (status == STATUS_SUCCESS)
|
||||
{
|
||||
status = pNtUnmapViewOfSection( hProcess, ptr2 );
|
||||
ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
|
||||
}
|
||||
|
||||
ptr2 = (char *)ptr + 0x1000;
|
||||
size = 0;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 16, 0, &offset, &size, 1, 0, PAGE_READWRITE );
|
||||
todo_wine
|
||||
ok( status == STATUS_INVALID_PARAMETER_4, "NtMapViewOfSection returned %x\n", status );
|
||||
if (status == STATUS_SUCCESS)
|
||||
{
|
||||
status = pNtUnmapViewOfSection( hProcess, ptr2 );
|
||||
ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
|
||||
}
|
||||
|
||||
if (sizeof(void *) == sizeof(int) && (!pIsWow64Process ||
|
||||
!pIsWow64Process( GetCurrentProcess(), &is_wow64 ) || !is_wow64))
|
||||
{
|
||||
/* new memory region conflicts with previous mapping */
|
||||
ptr2 = ptr;
|
||||
size = 0;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
|
||||
&size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE );
|
||||
ok( status == STATUS_CONFLICTING_ADDRESSES, "NtMapViewOfSection returned %x\n", status );
|
||||
|
||||
ptr2 = (char *)ptr + 42;
|
||||
size = 0;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
|
||||
&size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE );
|
||||
todo_wine
|
||||
ok( status == STATUS_CONFLICTING_ADDRESSES, "NtMapViewOfSection returned %x\n", status );
|
||||
|
||||
/* in contrary to regular NtMapViewOfSection, only 4kb align is enforced */
|
||||
ptr2 = (char *)ptr + 0x1000;
|
||||
size = 0;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
|
||||
&size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE );
|
||||
todo_wine
|
||||
ok( status == STATUS_SUCCESS, "NtMapViewOfSection returned %x\n", status );
|
||||
ok( (char *)ptr2 == (char *)ptr + 0x1000,
|
||||
"expected address %p, got %p\n", (char *)ptr + 0x1000, ptr2 );
|
||||
status = pNtUnmapViewOfSection( hProcess, ptr2 );
|
||||
todo_wine
|
||||
ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
|
||||
|
||||
/* the address is rounded down if not on a page boundary */
|
||||
ptr2 = (char *)ptr + 0x1001;
|
||||
size = 0;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
|
||||
&size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE );
|
||||
todo_wine
|
||||
ok( status == STATUS_SUCCESS, "NtMapViewOfSection returned %x\n", status );
|
||||
todo_wine
|
||||
ok( (char *)ptr2 == (char *)ptr + 0x1000,
|
||||
"expected address %p, got %p\n", (char *)ptr + 0x1000, ptr2 );
|
||||
status = pNtUnmapViewOfSection( hProcess, ptr2 );
|
||||
todo_wine
|
||||
ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
|
||||
|
||||
ptr2 = (char *)ptr + 0x2000;
|
||||
size = 0;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
|
||||
&size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE );
|
||||
todo_wine
|
||||
ok( status == STATUS_SUCCESS, "NtMapViewOfSection returned %x\n", status );
|
||||
ok( (char *)ptr2 == (char *)ptr + 0x2000,
|
||||
"expected address %p, got %p\n", (char *)ptr + 0x2000, ptr2 );
|
||||
status = pNtUnmapViewOfSection( hProcess, ptr2 );
|
||||
todo_wine
|
||||
ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr2 = (char *)ptr + 0x1000;
|
||||
size = 0;
|
||||
offset.QuadPart = 0;
|
||||
status = pNtMapViewOfSection( mapping, hProcess, &ptr2, 0, 0, &offset,
|
||||
&size, 1, AT_ROUND_TO_PAGE, PAGE_READWRITE );
|
||||
todo_wine
|
||||
ok( status == STATUS_INVALID_PARAMETER_9, "NtMapViewOfSection returned %x\n", status );
|
||||
}
|
||||
|
||||
status = pNtUnmapViewOfSection( hProcess, ptr );
|
||||
ok( !status, "NtUnmapViewOfSection failed status %x\n", status );
|
||||
|
||||
|
@ -3495,6 +3689,7 @@ START_TEST(virtual)
|
|||
pGetWriteWatch = (void *) GetProcAddress(hkernel32, "GetWriteWatch");
|
||||
pResetWriteWatch = (void *) GetProcAddress(hkernel32, "ResetWriteWatch");
|
||||
pGetProcessDEPPolicy = (void *)GetProcAddress( hkernel32, "GetProcessDEPPolicy" );
|
||||
pIsWow64Process = (void *)GetProcAddress( hkernel32, "IsWow64Process" );
|
||||
pNtAreMappedFilesTheSame = (void *)GetProcAddress( hntdll, "NtAreMappedFilesTheSame" );
|
||||
pNtMapViewOfSection = (void *)GetProcAddress( hntdll, "NtMapViewOfSection" );
|
||||
pNtUnmapViewOfSection = (void *)GetProcAddress( hntdll, "NtUnmapViewOfSection" );
|
||||
|
@ -3502,6 +3697,8 @@ START_TEST(virtual)
|
|||
pRtlAddVectoredExceptionHandler = (void *)GetProcAddress( hntdll, "RtlAddVectoredExceptionHandler" );
|
||||
pRtlRemoveVectoredExceptionHandler = (void *)GetProcAddress( hntdll, "RtlRemoveVectoredExceptionHandler" );
|
||||
pNtProtectVirtualMemory = (void *)GetProcAddress( hntdll, "NtProtectVirtualMemory" );
|
||||
pNtAllocateVirtualMemory = (void *)GetProcAddress( hntdll, "NtAllocateVirtualMemory" );
|
||||
pNtFreeVirtualMemory = (void *)GetProcAddress( hntdll, "NtFreeVirtualMemory" );
|
||||
|
||||
test_shared_memory(FALSE);
|
||||
test_shared_memory_ro(FALSE, FILE_MAP_READ|FILE_MAP_WRITE);
|
||||
|
|
|
@ -736,6 +736,7 @@ typedef struct _MEMORY_BASIC_INFORMATION
|
|||
|
||||
#define WRITE_WATCH_FLAG_RESET 0x00000001
|
||||
|
||||
#define AT_ROUND_TO_PAGE 0x40000000
|
||||
|
||||
#define MINCHAR 0x80
|
||||
#define MAXCHAR 0x7f
|
||||
|
|
Loading…
Reference in New Issue