+static void test_affinity(void)
+{
+ NTSTATUS status;
+ PROCESS_BASIC_INFORMATION pbi;
+ DWORD_PTR proc_affinity, thread_affinity;
+ THREAD_BASIC_INFORMATION tbi;
+ SYSTEM_INFO si;
+
+ GetSystemInfo(&si);
+ status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), NULL );
+ ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
+ proc_affinity = (DWORD_PTR)pbi.Reserved2[0];
+ ok( proc_affinity == (1 << si.dwNumberOfProcessors) - 1, "Unexpected process affinity\n" );
+ proc_affinity = 1 << si.dwNumberOfProcessors;
+ status = pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask, &proc_affinity, sizeof(proc_affinity) );
+ ok( status == STATUS_INVALID_PARAMETER,
+ "Expected STATUS_INVALID_PARAMETER, got %08x\n", status);
+
+ proc_affinity = 0;
+ status = pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask, &proc_affinity, sizeof(proc_affinity) );
+ ok( status == STATUS_INVALID_PARAMETER,
+ "Expected STATUS_INVALID_PARAMETER, 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 == (1 << si.dwNumberOfProcessors) - 1, "Unexpected thread affinity\n" );
+ thread_affinity = 1 << si.dwNumberOfProcessors;
+ status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
+ ok( status == STATUS_INVALID_PARAMETER,
+ "Expected STATUS_INVALID_PARAMETER, got %08x\n", status);
+ thread_affinity = 0;
+ status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
+ ok( status == STATUS_INVALID_PARAMETER,
+ "Expected STATUS_INVALID_PARAMETER, got %08x\n", status);
+
+ thread_affinity = 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( tbi.AffinityMask == 1, "Unexpected thread affinity\n" );
+
+ /* NOTE: Pre-Vista does not recognize the "all processors" flag (all bits set) */
+ thread_affinity = ~0UL;
+ 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 (si.dwNumberOfProcessors <= 1)
+ {
+ skip("only one processor, skipping affinity testing\n");
+ return;
+ }
+
+ /* Test thread affinity mask resulting from "all processors" flag */
+ if (status == STATUS_SUCCESS)
+ {
+ status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
+ ok( broken(tbi.AffinityMask == 1) || tbi.AffinityMask == (1 << si.dwNumberOfProcessors) - 1,
+ "Unexpected thread affinity\n" );
+ }
+ else
+ skip("Cannot test thread affinity mask for 'all processors' flag\n");
+
+ proc_affinity = 2;
+ status = pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask, &proc_affinity, sizeof(proc_affinity) );
+ ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
+ status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), NULL );
+ ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
+ proc_affinity = (DWORD_PTR)pbi.Reserved2[0];
+ ok( proc_affinity == 2, "Unexpected process affinity\n" );
+ /* Setting the process affinity changes the thread affinity to match */
+ status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
+ ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
+ ok( tbi.AffinityMask == 2, "Unexpected thread affinity\n" );
+ /* The thread affinity is restricted to the process affinity */
+ thread_affinity = 1;
+ status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
+ ok( status == STATUS_INVALID_PARAMETER,
+ "Expected STATUS_INVALID_PARAMETER, got %08x\n", status);
+
+ proc_affinity = (1 << si.dwNumberOfProcessors) - 1;
+ status = pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask, &proc_affinity, sizeof(proc_affinity) );
+ ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
+ /* Resetting the process affinity also resets the thread affinity */
+ status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
+ ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
+ ok( tbi.AffinityMask == (1 << si.dwNumberOfProcessors) - 1,
+ "Unexpected thread affinity\n" );
+}
+