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

Roger Zoellner zoellner.roger at gmail.com
Mon Sep 10 10:25:16 CDT 2018


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

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

This patch supercedes
https://source.winehq.org/patches/data/150846
https://source.winehq.org/patches/data/150824

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

diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c
index 2ab12e4257..e297606ef2 100644
--- a/dlls/ntdll/tests/info.c
+++ b/dlls/ntdll/tests/info.c
@@ -2040,6 +2040,20 @@ static void test_affinity(void)
     ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
     ok( tbi.AffinityMask == 1, "Unexpected thread affinity\n" );
 
+    thread_affinity = (pbi.AffinityMask << 1) | pbi.AffinityMask;
+    status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
+    ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
+    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( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
+    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..b0ad0e8259 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -1211,6 +1211,7 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class,
  *              NtSetInformationThread  (NTDLL.@)
  *              ZwSetInformationThread  (NTDLL.@)
  */
+
 NTSTATUS WINAPI NtSetInformationThread( HANDLE handle, THREADINFOCLASS class,
                                         LPCVOID data, ULONG length )
 {
@@ -1289,9 +1290,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;
+
+            if (!(req_aff & affinity_mask)) return STATUS_INVALID_PARAMETER;
+            req_aff = req_aff & affinity_mask;
+
             SERVER_START_REQ( set_thread_info )
             {
                 req->handle   = wine_server_obj_handle( handle );
-- 
2.18.0




More information about the wine-devel mailing list