[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