[PATCH v3] ntdll: Fix treating valid affinity mask requests as invalid in NtSetInformationThread()

Roger Zoellner zoellner.roger at gmail.com
Mon Sep 10 19:41:09 CDT 2018


Wine currently treats valid affinity mask requests as invalid. Especially when the requested mask
has one or more bits set that are higher than the highest set bit in the current system/process
mask (which mostly means when requested mask > system mask)

Included are two additional test cases, that would fail with the current implementaion, but should succeed on Windows.


Signed-off-by: Roger Zoellner <zoellner.roger at gmail.com>
---
 dlls/ntdll/tests/info.c | 21 +++++++++++++++++++++
 dlls/ntdll/thread.c     |  7 ++++---
 2 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c
index 2ab12e4257..68beae3054 100644
--- a/dlls/ntdll/tests/info.c
+++ b/dlls/ntdll/tests/info.c
@@ -2040,6 +2040,27 @@ static void test_affinity(void)
     ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
     ok( tbi.AffinityMask == 1, "Unexpected thread affinity\n" );
 
+    /* NOTE: Pre-Vista does not allow bits to be set that are higher than the highest set bit in process affinity mask */
+    thread_affinity = (pbi.AffinityMask << 1) | pbi.AffinityMask;
+    status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
+    ok( broken(status == STATUS_INVALID_PARAMETER) || (status == STATUS_SUCCESS), "Expected STATUS_SUCCESS, got %08x\n", status );
+    if (status == STATUS_SUCCESS)
+    {
+        status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
+        ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status );
+        ok( tbi.AffinityMask == pbi.AffinityMask, "Unexpected thread affinity. Expected %lx, got %lx\n", pbi.AffinityMask, tbi.AffinityMask );
+    }
+
+    thread_affinity = ~(DWORD_PTR)0 - 1;
+    status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
+    ok( broken(status == STATUS_INVALID_PARAMETER) || (status == STATUS_SUCCESS), "Expected STATUS_SUCCESS, got %08x\n", status );
+    if (status == STATUS_SUCCESS)
+    {
+        status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
+        ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status );
+        ok( tbi.AffinityMask == (pbi.AffinityMask & (~(DWORD_PTR)0 - 1)), "Unexpected thread affinity. Expected %lx, got %lx\n", pbi.AffinityMask & (~(DWORD_PTR)0 - 1), tbi.AffinityMask );
+    }
+
     /* NOTE: Pre-Vista does not recognize the "all processors" flag (all bits set) */
     thread_affinity = ~(DWORD_PTR)0;
     status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index 59d64e174d..7a85704432 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -1289,9 +1289,10 @@ NTSTATUS WINAPI NtSetInformationThread( HANDLE handle, THREADINFOCLASS class,
 
             if (length != sizeof(ULONG_PTR)) return STATUS_INVALID_PARAMETER;
             req_aff = *(const ULONG_PTR *)data;
-            if ((ULONG)req_aff == ~0u) req_aff = affinity_mask;
-            else if (req_aff & ~affinity_mask) return STATUS_INVALID_PARAMETER;
-            else if (!req_aff) return STATUS_INVALID_PARAMETER;
+            
+            req_aff = req_aff & affinity_mask;
+            if (!req_aff) return STATUS_INVALID_PARAMETER;
+
             SERVER_START_REQ( set_thread_info )
             {
                 req->handle   = wine_server_obj_handle( handle );
-- 
2.18.0




More information about the wine-devel mailing list