Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/ntdll/tests/virtual.c | 116 +++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+)
diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c index adc9b1ae6dc..c41a50c5da7 100644 --- a/dlls/ntdll/tests/virtual.c +++ b/dlls/ntdll/tests/virtual.c @@ -24,6 +24,7 @@ #define WIN32_NO_STATUS #include "windef.h" #include "winternl.h" +#include "psapi.h" #include "wine/test.h" #include "ddk/wdm.h"
@@ -1132,6 +1133,120 @@ static void test_syscalls(void) UnmapViewOfFile( ptr ); }
+#define ws_watch_check_page(a, b, c, d) ws_watch_check_page_(__LINE__, a, b, c, d) +static void ws_watch_check_page_(unsigned int line, void *addr, void *info, unsigned int info_count, BOOL extended) +{ + static const ULONG_PTR mask = ~(ULONG_PTR)0xfff; + PSAPI_WS_WATCH_INFORMATION_EX *ws; + unsigned int i, size; + + size = extended ? sizeof(PSAPI_WS_WATCH_INFORMATION_EX) : sizeof(PSAPI_WS_WATCH_INFORMATION); + + ok_(__FILE__, line)(info_count, "Got zero info_count.\n"); + if (!info_count) + return; + ws = (PSAPI_WS_WATCH_INFORMATION_EX *)((char *)info + size * (info_count - 1)); + ok_(__FILE__, line)(!ws->BasicInfo.FaultingVa || broken(ws->BasicInfo.FaultingVa == (void *)1) /* Win8 */, + "Got unexpected FaultingVa %p.\n", ws->BasicInfo.FaultingVa); + ok_(__FILE__, line)(!ws->BasicInfo.FaultingPc, "Got unexpected FaultingPc %p.\n", ws->BasicInfo.FaultingPc); + if (extended) + { + ok_(__FILE__, line)(!ws->Flags, "Got unexpected Flags %#lx.\n", ws->Flags); + ok_(__FILE__, line)(!ws->FaultingThreadId, "Got unexpected Flags %#lx.\n", ws->FaultingThreadId); + } + + for(i = 0; i < info_count; ++i) + { + ws = (PSAPI_WS_WATCH_INFORMATION_EX *)((char *)info + size * i); + if (((ULONG_PTR)ws->BasicInfo.FaultingVa & mask) != ((ULONG_PTR)addr & mask)) + continue; + + if (extended) + { + ok_(__FILE__, line)(!ws->Flags, "Got unexpected flags %#lx.\n", ws->Flags); + ok_(__FILE__, line)(ws->FaultingThreadId == GetCurrentThreadId(), + "Got unexpected FaultingThreadId %#lx.\n", ws->FaultingThreadId); + } + return; + } + ok_(__FILE__, line)(0, "Page not found.\n"); +} + +static void test_ws_watches(void) +{ + PSAPI_WS_WATCH_INFORMATION_EX ws_ex[1024]; + PSAPI_WS_WATCH_INFORMATION *ws; + unsigned int value; + NTSTATUS status; + ULONG size; + char *addr; + BOOL ret; + + status = NtSetInformationProcess(GetCurrentProcess(), ProcessWorkingSetWatch, (void *)0xdeadbeef, 1); + todo_wine ok(status == STATUS_DATATYPE_MISALIGNMENT, "Got unexpected status %#x.\n", status); + + status = NtSetInformationProcess(GetCurrentProcess(), ProcessWorkingSetWatchEx, (void *)0xdeadbeef, 1); + todo_wine ok(status == STATUS_DATATYPE_MISALIGNMENT, "Got unexpected status %#x.\n", status); + + status = NtSetInformationProcess(GetCurrentProcess(), ProcessWorkingSetWatch, (void *)0xdeadbee8, 1); + todo_wine ok(!status || broken(status == STATUS_ACCESS_VIOLATION) /* before Win10 */, + "Got unexpected status %#x.\n", status); + + status = NtSetInformationProcess(GetCurrentProcess(), ProcessWorkingSetWatch, (void *)0xdeadbee8, 0); + todo_wine ok(status == STATUS_PORT_ALREADY_SET || broken(!status) /* before Win10, as previous attempt failed */, + "Got unexpected status %#x.\n", status); + + status = NtSetInformationProcess(GetCurrentProcess(), ProcessWorkingSetWatchEx, NULL, 0); + todo_wine ok(status == STATUS_PORT_ALREADY_SET, "Got unexpected status %#x.\n", status); + + addr = VirtualAlloc(NULL, 4 * 0x1000, MEM_COMMIT, PAGE_READWRITE); + ok(!!addr, "VirtualAlloc failed, error %u.\n", GetLastError()); + + *addr = 1; + ret = ReadProcessMemory(GetCurrentProcess(), addr + 0x1000, &value, sizeof(value), NULL); + ok(ret, "Got unexpected ret %u, error %u.\n", ret, GetLastError()); + addr[0x2000] = 3; + + ws = (PSAPI_WS_WATCH_INFORMATION *)ws_ex; + + size = 0xdeadbeef; + status = NtQueryInformationProcess(GetCurrentProcess(), ProcessWorkingSetWatchEx, NULL, 0, &size); + todo_wine ok(status == STATUS_BUFFER_TOO_SMALL, "Got unexpected status %#x.\n", status); + todo_wine ok(size && !(size % sizeof(PSAPI_WS_WATCH_INFORMATION_EX)), "Got unexpected size %u.\n", size); + + size = 0xdeadbeef; + status = NtQueryInformationProcess(GetCurrentProcess(), ProcessWorkingSetWatch, NULL, 0, &size); + todo_wine ok(status == STATUS_BUFFER_TOO_SMALL, "Got unexpected status %#x.\n", status); + todo_wine ok(size && !(size % sizeof(PSAPI_WS_WATCH_INFORMATION)), "Got unexpected size %u.\n", size); + + memset(ws, 0xcc, sizeof(*ws)); + status = NtQueryInformationProcess(GetCurrentProcess(), ProcessWorkingSetWatch, ws, + sizeof(PSAPI_WS_WATCH_INFORMATION), &size); + todo_wine ok(status == STATUS_BUFFER_TOO_SMALL, "Got unexpected status %#x.\n", status); + ok(ws->FaultingVa == (void *)(ULONG_PTR)0xcccccccccccccccc, "Got unexpected FaultingVa %p.\n", ws->FaultingVa); + + memset(ws_ex, 0xcc, sizeof(ws_ex)); + size = 0; + status = NtQueryInformationProcess(GetCurrentProcess(), ProcessWorkingSetWatchEx, ws_ex, sizeof(ws_ex), &size); + todo_wine ok(!status, "Got unexpected status %#x.\n", status); + todo_wine ws_watch_check_page(addr, ws_ex, size / sizeof(PSAPI_WS_WATCH_INFORMATION_EX), TRUE); + if (!is_wow64) + todo_wine ws_watch_check_page(addr + 0x1000, ws_ex, size / sizeof(PSAPI_WS_WATCH_INFORMATION_EX), TRUE); + todo_wine ws_watch_check_page(addr + 0x2000, ws_ex, size / sizeof(PSAPI_WS_WATCH_INFORMATION_EX), TRUE); + + EmptyWorkingSet(GetCurrentProcess()); + + ok(*addr == 1, "Got unexpected *addr %#x.\n", *addr); + ok(addr[0x2000] == 3, "Got unexpected *addr %#x.\n", *addr); + memset(ws_ex, 0xcc, sizeof(ws_ex)); + status = NtQueryInformationProcess(GetCurrentProcess(), ProcessWorkingSetWatch, ws, sizeof(ws_ex), &size); + todo_wine ok(!status, "Got unexpected status %#x.\n", status); + todo_wine ws_watch_check_page(addr, ws_ex, size / sizeof(PSAPI_WS_WATCH_INFORMATION), FALSE); + todo_wine ws_watch_check_page(addr + 0x2000, ws_ex, size / sizeof(PSAPI_WS_WATCH_INFORMATION), FALSE); + + VirtualFree(addr, 0, MEM_RELEASE); +} + START_TEST(virtual) { HMODULE mod; @@ -1171,4 +1286,5 @@ START_TEST(virtual) test_NtMapViewOfSection(); test_user_shared_data(); test_syscalls(); + test_ws_watches(); }