Signed-off-by: Paul Gofman <pgofman(a)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();
}
--
2.33.1