From: Roger Zoellner Subject: [PATCH v3] ntdll: Fix treating valid affinity mask requests as invalid in NtSetInformationThread() Message-Id: <20180911004109.22288-1-zoellner.roger@gmail.com> Date: Tue, 11 Sep 2018 02:41:09 +0200 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 --- 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