[PATCH] psapi/tests: Add more tests for working set watches.
Paul Gofman
pgofman at codeweavers.com
Wed Dec 8 11:44:29 CST 2021
Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
dlls/psapi/tests/psapi_main.c | 156 ++++++++++++++++++++++++++++------
1 file changed, 128 insertions(+), 28 deletions(-)
diff --git a/dlls/psapi/tests/psapi_main.c b/dlls/psapi/tests/psapi_main.c
index c4a740310a4..e383168fde1 100644
--- a/dlls/psapi/tests/psapi_main.c
+++ b/dlls/psapi/tests/psapi_main.c
@@ -55,7 +55,7 @@ static BOOL init_func_ptrs(void)
return TRUE;
}
-static HANDLE hpSR, hpQI, hpVR, hpQV;
+static HANDLE hpSR, hpQI, hpVR, hpQV, hp_vm_op;
static const HANDLE hBad = (HANDLE)0xdeadbeef;
static void test_EnumProcesses(void)
@@ -693,14 +693,65 @@ static void test_GetModuleBaseName(void)
"szModPath=\"%s\" szModBaseName=\"%s\"\n", szModPath, szModBaseName);
}
+static PSAPI_WS_WATCH_INFORMATION wswi[4096];
+
+static void ws_get_watches(void)
+{
+ BOOL ret;
+
+ SetLastError(0xdeadbeef);
+ ret = GetWsChanges(hpQI, wswi, sizeof(wswi));
+ ok(ret == 1, "Got unexpected ret %u, error %u.\n", ret, GetLastError());
+}
+
+#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 *pc_start, void *pc_end, BOOL expect)
+{
+ static const ULONG_PTR mask = ~(ULONG_PTR)0xfff;
+ unsigned int i;
+
+ for(i = 0; wswi[i].FaultingVa; i++)
+ {
+ if (((ULONG_PTR)wswi[i].FaultingVa & mask) == ((ULONG_PTR)addr & mask))
+ {
+ ok_(__FILE__, line)(expect, "Got unexpected FaultingVa %p.\n", wswi[i].FaultingVa);
+ if (expect)
+ {
+ ok_(__FILE__, line)((void *)wswi[i].FaultingVa == addr, "Got unexpected addr %p, expected %p.\n",
+ (void *)wswi[i].FaultingVa, addr);
+ }
+ ok_(__FILE__, line)(wswi[i].FaultingPc >= pc_start && wswi[i].FaultingPc < pc_end,
+ "Got unexpected FaultingPc %p, start %p.\n", wswi[i].FaultingPc, pc_start);
+ return;
+ }
+ }
+ ok_(__FILE__, line)(!expect, "Page not found.\n");
+}
+
static void test_ws_functions(void)
{
- PSAPI_WS_WATCH_INFORMATION wswi[4096];
+ static const BOOL is_win32 = sizeof(void *) == sizeof(int);
+ static const unsigned int page_count = 16;
+ void *kernel_start, *kernel_end;
+ unsigned int value;
HANDLE ws_handle;
- char *addr;
unsigned int i;
+ HANDLE file;
+ DWORD size;
+ char *addr;
BOOL ret;
+ if (is_win32)
+ {
+ kernel_start = (void *)0x80000000;
+ kernel_end = (void *)0xffffffff;
+ }
+ else
+ {
+ kernel_start = (void *)0xffff000000000000;
+ kernel_end = (void *)0xffffffffffffffff;
+ }
+
ws_handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_SET_QUOTA |
PROCESS_SET_INFORMATION, FALSE, GetCurrentProcessId());
ok(!!ws_handle, "got error %u\n", GetLastError());
@@ -717,6 +768,10 @@ static void test_ws_functions(void)
ret = EmptyWorkingSet(ws_handle);
ok(ret == 1, "failed with %d\n", GetLastError());
+ addr = VirtualAlloc(NULL, page_count * 0x1000, MEM_COMMIT, PAGE_READWRITE);
+ ok(!!addr, "VirtualAlloc failed, error %u.\n", GetLastError());
+ addr[0x1002] = 0;
+
SetLastError( 0xdeadbeef );
ret = InitializeProcessForWsWatch( NULL );
todo_wine ok( !ret, "InitializeProcessForWsWatch succeeded\n" );
@@ -732,35 +787,77 @@ static void test_ws_functions(void)
SetLastError(0xdeadbeef);
ret = InitializeProcessForWsWatch(ws_handle);
ok(ret == 1, "failed with %d\n", GetLastError());
-
- addr = VirtualAlloc(NULL, 1, MEM_COMMIT, PAGE_READWRITE);
- if(!addr)
+
+ ret = GetWsChanges(hpQI, wswi, sizeof(wswi));
+ todo_wine ok(ret == 1 || (!ret && GetLastError() == ERROR_NO_MORE_ITEMS), "failed with %d\n", GetLastError());
+ if (!ret && GetLastError() != ERROR_NO_MORE_ITEMS)
return;
- *addr = 0; /* make sure it's paged in (needed on wow64) */
- if(!VirtualLock(addr, 1))
- {
- trace("locking failed (error=%d) - skipping test\n", GetLastError());
- goto free_page;
- }
+ file = CreateFileA("test.tmp", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
+ ok(file != INVALID_HANDLE_VALUE, "CreateFile failed, GetLastError() %u.\n", GetLastError());
+ ws_get_watches();
+
+ ws_watch_check_page(addr + 0x1003, test_ws_functions, (char *)test_ws_functions + 0x10000, FALSE);
+
+ *addr = 0;
+ addr[0x1002] = 0;
+ value = addr[0x2fff];
+ ok(!value, "Got unexpected value %#x.\n", value);
+
+ ret = ReadProcessMemory(hpVR, addr + 0x3002, &value, sizeof(value), NULL);
+ ok(ret, "Got unexpected ret %u, error %u.\n", ret, GetLastError());
+ ret = WriteProcessMemory(hp_vm_op, addr + 0x4000, &value, 1, NULL);
+ ok(ret, "Got unexpected ret %u, error %u.\n", ret, GetLastError());
+
+ ret = WriteFile(file, addr + 0x5000, 1, &size, NULL);
+ ok(ret, "Got unexpected ret %u, error %u.\n", ret, GetLastError());
+
+ ret = ReadFile(file, addr + 0x6002, 2, &size, NULL);
+ ok(ret, "Got unexpected ret %u, error %u.\n", ret, GetLastError());
+ ok(!size, "Got unexpected size %u.\n", size);
+
+ ws_get_watches();
+ ws_watch_check_page(addr + 1, test_ws_functions, (char *)test_ws_functions + 0x10000, TRUE);
+ /* Faulted before InitializeProcessForWsWatch(). */
+ ws_watch_check_page(addr + 0x1003, NULL, NULL, FALSE);
+ ws_watch_check_page(addr + 0x2fff, test_ws_functions, (char *)test_ws_functions + 0x10000, TRUE);
+ ws_watch_check_page(addr + (is_win32 ? 0x3003 : 0x3005), kernel_start, kernel_end, !wow64);
+ ws_watch_check_page(addr + 0x4001, kernel_start, kernel_end, !wow64);
+ ws_watch_check_page(addr + 0x5001, kernel_start, kernel_end, !wow64);
+ ws_watch_check_page(addr + 0x6003, kernel_start, kernel_end, !wow64);
+ for (i = 7; i < page_count; ++i)
+ ws_watch_check_page(addr + 0x1000 * i, NULL, NULL, FALSE);
+
+ ret = VirtualFree(addr, page_count * 0x1000, MEM_DECOMMIT);
+ ok(ret, "Got unexpected ret %u, error %u.\n", ret, GetLastError());
+
+ addr = VirtualAlloc(addr, page_count * 0x1000, MEM_COMMIT, PAGE_READWRITE);
+ ok(!!addr, "VirtualAlloc failed, error %u.\n", GetLastError());
+
+ *addr = 0;
+ addr[0x1000] = 1;
+ ws_get_watches();
+ ws_watch_check_page(addr + 1, test_ws_functions, (char *)test_ws_functions + 0x10000, TRUE);
+ ws_watch_check_page(addr + 0x1001, test_ws_functions, (char *)test_ws_functions + 0x10000, TRUE);
+ for (i = 2; i < page_count; ++i)
+ ws_watch_check_page(addr + 0x1000 * i, NULL, NULL, FALSE);
+
+ ret = VirtualLock(addr, 1);
+ ok(ret, "Got unexpected ret %u, error %u.\n", ret, GetLastError());
+
+ ret = EmptyWorkingSet(ws_handle);
+ ok(ret, "Got unexpected ret %u, error %u.\n", ret, GetLastError());
+ *addr = 0;
+ addr[0x1000] = 1;
+ ws_get_watches();
+ ws_watch_check_page(addr, NULL, NULL, FALSE);
+ ws_watch_check_page(addr + 0x1001, test_ws_functions, (char *)test_ws_functions + 0x10000, TRUE);
+ for (i = 2; i < page_count; ++i)
+ ws_watch_check_page(addr + 0x1000 * i, NULL, NULL, FALSE);
- SetLastError(0xdeadbeef);
- ret = GetWsChanges(hpQI, wswi, sizeof(wswi));
- todo_wine ok(ret == 1, "failed with %d\n", GetLastError());
- if(ret == 1)
- {
- for(i = 0; wswi[i].FaultingVa; i++)
- if(((ULONG_PTR)wswi[i].FaultingVa & ~0xfffL) == (ULONG_PTR)addr)
- {
- todo_wine ok(ret == 1, "GetWsChanges found our page\n");
- goto free_page;
- }
-
- todo_wine ok(0, "GetWsChanges didn't find our page\n");
- }
-
-free_page:
VirtualFree(addr, 0, MEM_RELEASE);
+ CloseHandle(file);
+ DeleteFileA("test.tmp");
}
static void check_QueryWorkingSetEx(PVOID addr, const char *desc, DWORD expected_valid,
@@ -859,6 +956,9 @@ START_TEST(psapi_main)
if (pIsWow64Process)
IsWow64Process(GetCurrentProcess(), &wow64);
+ hp_vm_op = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, pid);
+ ok(!!hp_vm_op, "got error %u\n", GetLastError());
+
hpSR = OpenProcess(STANDARD_RIGHTS_REQUIRED, FALSE, pid);
ok(!!hpSR, "got error %u\n", GetLastError());
hpQI = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
--
2.33.1
More information about the wine-devel
mailing list