kernel: add VirtualAllocEx remote thread tests Thomas Kho --- dlls/kernel/tests/Makefile.in | 2 - dlls/kernel/tests/virtual.c | 149 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 150 insertions(+), 1 deletions(-) diff --git a/dlls/kernel/tests/Makefile.in b/dlls/kernel/tests/Makefile.in index bfeae14..5f6c12e 100644 --- a/dlls/kernel/tests/Makefile.in +++ b/dlls/kernel/tests/Makefile.in @@ -3,7 +3,7 @@ TOPOBJDIR = ../../.. SRCDIR = @srcdir@ VPATH = @srcdir@ TESTDLL = kernel32.dll -IMPORTS = kernel32 +IMPORTS = kernel32 user32 CTESTS = \ alloc.c \ diff --git a/dlls/kernel/tests/virtual.c b/dlls/kernel/tests/virtual.c index 2eac5a7..ec3a88a 100644 --- a/dlls/kernel/tests/virtual.c +++ b/dlls/kernel/tests/virtual.c @@ -23,8 +23,156 @@ #include #include "windef.h" #include "winbase.h" #include "winerror.h" +#include "winuser.h" #include "wine/test.h" +HANDLE create_process(char *program_name) +{ + DWORD d; + PROCESS_INFORMATION pi; + STARTUPINFO si = { 0 }; + si.cb = sizeof(si); + + ok(CreateProcess(NULL, program_name, NULL, NULL, FALSE, 0, NULL, NULL, + &si, &pi) != 0, "error: %lu\n", GetLastError()); + ok(CloseHandle(pi.hThread) != 0, "error %lu\n", GetLastError()); + d = WaitForInputIdle(pi.hProcess, 5000); + ok(d == 0, "WaitForInputIdle returned %lu, last error %lu\n", + d, GetLastError()); + return pi.hProcess; +} + +static void test_VirtualAllocEx(void) +{ + const unsigned int alloc_size = 1<<15; + char *src, *dst; + unsigned long bytes_written = 0, bytes_read = 0, i; + void *addr1, *addr2; + BOOL b; + DWORD old_prot; + MEMORY_BASIC_INFORMATION info; + HANDLE hProcess; + + hProcess = create_process("notepad.exe"); + ok(hProcess != NULL, "Can't start notepad.exe\n"); + + src = (char *) HeapAlloc( GetProcessHeap(), 0, alloc_size ); + dst = (char *) HeapAlloc( GetProcessHeap(), 0, alloc_size ); + for (i = 0; i < alloc_size; i++) + src[i] = 0xcafedead + i; + + addr1 = VirtualAllocEx(hProcess, NULL, alloc_size, MEM_COMMIT, + PAGE_EXECUTE_READWRITE); + todo_wine ok(addr1 != NULL, "VirtualAllocEx error %lu\n", GetLastError()); + b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written); + ok(b && (bytes_written == alloc_size), "%lu bytes written\n", + bytes_written); + b = ReadProcessMemory(hProcess, addr1, dst, alloc_size, &bytes_read); + ok(b && (bytes_read == alloc_size), "%lu bytes read\n", bytes_read); + ok(!memcmp(src, dst, alloc_size), "Data from remote process differs\n"); + b = VirtualFreeEx(hProcess, addr1, 0, MEM_RELEASE); + todo_wine ok(b != 0, "VirtualFreeEx, error %lu\n", GetLastError()); + + HeapFree( GetProcessHeap(), 0, src ); + HeapFree( GetProcessHeap(), 0, dst ); + + /* + * The following tests parallel those in test_VirtualAlloc() + */ + + SetLastError(0xdeadbeef); + addr1 = VirtualAllocEx(hProcess, 0, 0, MEM_RESERVE, PAGE_NOACCESS); + ok(addr1 == NULL, "VirtualAllocEx should fail on zero-sized allocation\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER /* NT */ || + GetLastError() == ERROR_NOT_ENOUGH_MEMORY, /* Win9x */ + "got %ld, expected ERROR_INVALID_PARAMETER\n", GetLastError()); + + addr1 = VirtualAllocEx(hProcess, 0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS); + todo_wine ok(addr1 != NULL, "VirtualAllocEx failed\n"); + + /* test a not committed memory */ + todo_wine ok(VirtualQueryEx(hProcess, addr1, &info, sizeof(info)) + == sizeof(info), "VirtualQueryEx failed\n"); + todo_wine ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, + addr1); + todo_wine ok(info.AllocationBase == addr1, "%p != %p\n", + info.AllocationBase, addr1); + todo_wine ok(info.AllocationProtect == PAGE_NOACCESS, + "%lx != PAGE_NOACCESS\n", info.AllocationProtect); + todo_wine ok(info.RegionSize == 0x10000, "%lx != 0x10000\n", + info.RegionSize); + todo_wine ok(info.State == MEM_RESERVE, "%lx != MEM_RESERVE\n", info.State); + /* NT reports Protect == 0 for a not committed memory block */ + todo_wine ok(info.Protect == 0 /* NT */ || + info.Protect == PAGE_NOACCESS, /* Win9x */ + "%lx != PAGE_NOACCESS\n", info.Protect); + todo_wine ok(info.Type == MEM_PRIVATE, "%lx != MEM_PRIVATE\n", info.Type); + + SetLastError(0xdeadbeef); + ok(!VirtualProtectEx(hProcess, addr1, 0xFFFC, PAGE_READONLY, &old_prot), + "VirtualProtectEx should fail on a not committed memory\n"); + todo_wine ok(GetLastError() == ERROR_INVALID_ADDRESS /* NT */ || + GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x */ + "got %ld, expected ERROR_INVALID_ADDRESS\n", GetLastError()); + + addr2 = VirtualAllocEx(hProcess, addr1, 0x1000, MEM_COMMIT, PAGE_NOACCESS); + ok(addr1 == addr2, "VirtualAllocEx failed\n"); + + /* test a committed memory */ + todo_wine ok(VirtualQueryEx(hProcess, addr1, &info, sizeof(info)) + == sizeof(info), + "VirtualQueryEx failed\n"); + todo_wine ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, + addr1); + todo_wine ok(info.AllocationBase == addr1, "%p != %p\n", + info.AllocationBase, addr1); + todo_wine ok(info.AllocationProtect == PAGE_NOACCESS, + "%lx != PAGE_NOACCESS\n", info.AllocationProtect); + todo_wine ok(info.RegionSize == 0x1000, "%lx != 0x1000\n", info.RegionSize); + todo_wine ok(info.State == MEM_COMMIT, "%lx != MEM_COMMIT\n", info.State); + /* this time NT reports PAGE_NOACCESS as well */ + todo_wine ok(info.Protect == PAGE_NOACCESS, "%lx != PAGE_NOACCESS\n", + info.Protect); + todo_wine ok(info.Type == MEM_PRIVATE, "%lx != MEM_PRIVATE\n", info.Type); + + /* this should fail, since not the whole range is committed yet */ + SetLastError(0xdeadbeef); + ok(!VirtualProtectEx(hProcess, addr1, 0xFFFC, PAGE_READONLY, &old_prot), + "VirtualProtectEx should fail on a not committed memory\n"); + todo_wine ok(GetLastError() == ERROR_INVALID_ADDRESS /* NT */ || + GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x */ + "got %ld, expected ERROR_INVALID_ADDRESS\n", GetLastError()); + + todo_wine ok(VirtualProtectEx(hProcess, addr1, 0x1000, PAGE_READONLY, + &old_prot), "VirtualProtectEx failed\n"); + todo_wine ok(old_prot == PAGE_NOACCESS, + "wrong old protection: got %04lx instead of PAGE_NOACCESS\n", old_prot); + + todo_wine ok(VirtualProtectEx(hProcess, addr1, 0x1000, PAGE_READWRITE, + &old_prot), "VirtualProtectEx failed\n"); + todo_wine ok(old_prot == PAGE_READONLY, + "wrong old protection: got %04lx instead of PAGE_READONLY\n", old_prot); + + ok(!VirtualFreeEx(hProcess, addr1, 0x10000, 0), + "VirtualFreeEx should fail with type 0\n"); + todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, + "got %ld, expected ERROR_INVALID_PARAMETER\n", GetLastError()); + + todo_wine ok(VirtualFreeEx(hProcess, addr1, 0x10000, MEM_DECOMMIT), + "VirtualFreeEx failed\n"); + + /* if the type is MEM_RELEASE, size must be 0 */ + ok(!VirtualFreeEx(hProcess, addr1, 1, MEM_RELEASE), + "VirtualFreeEx should fail\n"); + todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, + "got %ld, expected ERROR_INVALID_PARAMETER\n", GetLastError()); + + todo_wine ok(VirtualFreeEx(hProcess, addr1, 0, MEM_RELEASE), + "VirtualFreeEx failed\n"); + + TerminateProcess(hProcess, 0); +} + static void test_VirtualAlloc(void) { void *addr1, *addr2; @@ -263,6 +411,7 @@ static void test_MapViewOfFile(void) START_TEST(virtual) { + test_VirtualAllocEx(); test_VirtualAlloc(); test_MapViewOfFile(); }