1 /* 2 * Unit test suite for thread functions. 3 * 4 * Copyright 2002 Geoffrey Hausheer 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include "precomp.h" 22 23 /* THREAD_ALL_ACCESS in Vista+ PSDKs is incompatible with older Windows versions */ 24 #define THREAD_ALL_ACCESS_NT4 (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3ff) 25 26 /* Specify the number of simultaneous threads to test */ 27 #define NUM_THREADS 4 28 /* Specify whether to test the extended priorities for Win2k/XP */ 29 #define USE_EXTENDED_PRIORITIES 0 30 /* Specify whether to test the stack allocation in CreateThread */ 31 #define CHECK_STACK 0 32 33 /* Set CHECK_STACK to 1 if you want to try to test the stack-limit from 34 CreateThread. So far I have been unable to make this work, and 35 I am in doubt as to how portable it is. Also, according to MSDN, 36 you shouldn't mix C-run-time-libraries (i.e. alloca) with CreateThread. 37 Anyhow, the check is currently commented out 38 */ 39 #if CHECK_STACK 40 # ifdef __try 41 # define __TRY __try 42 # define __EXCEPT __except 43 # define __ENDTRY 44 # else 45 # include "wine/exception.h" 46 # endif 47 #endif 48 49 #ifdef __i386__ 50 #define ARCH "x86" 51 #elif defined __x86_64__ 52 #define ARCH "amd64" 53 #elif defined __arm__ 54 #define ARCH "arm" 55 #elif defined __aarch64__ 56 #define ARCH "arm64" 57 #else 58 #define ARCH "none" 59 #endif 60 61 static BOOL (WINAPI *pGetThreadPriorityBoost)(HANDLE,PBOOL); 62 static HANDLE (WINAPI *pOpenThread)(DWORD,BOOL,DWORD); 63 static BOOL (WINAPI *pQueueUserWorkItem)(LPTHREAD_START_ROUTINE,PVOID,ULONG); 64 static DWORD (WINAPI *pSetThreadIdealProcessor)(HANDLE,DWORD); 65 static BOOL (WINAPI *pSetThreadPriorityBoost)(HANDLE,BOOL); 66 static BOOL (WINAPI *pRegisterWaitForSingleObject)(PHANDLE,HANDLE,WAITORTIMERCALLBACK,PVOID,ULONG,ULONG); 67 static BOOL (WINAPI *pUnregisterWait)(HANDLE); 68 static BOOL (WINAPI *pIsWow64Process)(HANDLE,PBOOL); 69 static BOOL (WINAPI *pSetThreadErrorMode)(DWORD,PDWORD); 70 static DWORD (WINAPI *pGetThreadErrorMode)(void); 71 static DWORD (WINAPI *pRtlGetThreadErrorMode)(void); 72 static BOOL (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*); 73 static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW); 74 static BOOL (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR); 75 static BOOL (WINAPI *pGetCurrentActCtx)(HANDLE *); 76 static void (WINAPI *pReleaseActCtx)(HANDLE); 77 static PTP_POOL (WINAPI *pCreateThreadpool)(PVOID); 78 static void (WINAPI *pCloseThreadpool)(PTP_POOL); 79 static PTP_WORK (WINAPI *pCreateThreadpoolWork)(PTP_WORK_CALLBACK,PVOID,PTP_CALLBACK_ENVIRON); 80 static void (WINAPI *pSubmitThreadpoolWork)(PTP_WORK); 81 static void (WINAPI *pWaitForThreadpoolWorkCallbacks)(PTP_WORK,BOOL); 82 static void (WINAPI *pCloseThreadpoolWork)(PTP_WORK); 83 static NTSTATUS (WINAPI *pNtQueryInformationThread)(HANDLE,THREADINFOCLASS,PVOID,ULONG,PULONG); 84 static BOOL (WINAPI *pGetThreadGroupAffinity)(HANDLE,GROUP_AFFINITY*); 85 static BOOL (WINAPI *pSetThreadGroupAffinity)(HANDLE,const GROUP_AFFINITY*,GROUP_AFFINITY*); 86 static NTSTATUS (WINAPI *pNtSetInformationThread)(HANDLE,THREADINFOCLASS,LPCVOID,ULONG); 87 static NTSTATUS (WINAPI *pNtSetLdtEntries)(ULONG,ULONG,ULONG,ULONG,ULONG,ULONG); 88 89 static HANDLE create_target_process(const char *arg) 90 { 91 char **argv; 92 char cmdline[MAX_PATH]; 93 PROCESS_INFORMATION pi; 94 BOOL ret; 95 STARTUPINFOA si = { 0 }; 96 si.cb = sizeof(si); 97 98 winetest_get_mainargs( &argv ); 99 sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg); 100 ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 101 ok(ret, "error: %u\n", GetLastError()); 102 ret = CloseHandle(pi.hThread); 103 ok(ret, "error %u\n", GetLastError()); 104 return pi.hProcess; 105 } 106 107 /* Functions not tested yet: 108 AttachThreadInput 109 SetThreadContext 110 SwitchToThread 111 112 In addition there are no checks that the inheritance works properly in 113 CreateThread 114 */ 115 116 /* Functions to ensure that from a group of threads, only one executes 117 certain chunks of code at a time, and we know which one is executing 118 it. It basically makes multithreaded execution linear, which defeats 119 the purpose of multiple threads, but makes testing easy. */ 120 static HANDLE start_event, stop_event; 121 static LONG num_synced; 122 123 static void init_thread_sync_helpers(void) 124 { 125 start_event = CreateEventW(NULL, TRUE, FALSE, NULL); 126 ok(start_event != NULL, "CreateEvent failed\n"); 127 stop_event = CreateEventW(NULL, TRUE, FALSE, NULL); 128 ok(stop_event != NULL, "CreateEvent failed\n"); 129 num_synced = -1; 130 } 131 132 static BOOL sync_threads_and_run_one(DWORD sync_id, DWORD my_id) 133 { 134 LONG num = InterlockedIncrement(&num_synced); 135 assert(-1 <= num && num <= 1); 136 if (num == 1) 137 { 138 ResetEvent( stop_event ); 139 SetEvent( start_event ); 140 } 141 else 142 { 143 DWORD ret = WaitForSingleObject(start_event, 10000); 144 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed %x\n",ret); 145 } 146 return sync_id == my_id; 147 } 148 149 static void resync_after_run(void) 150 { 151 LONG num = InterlockedDecrement(&num_synced); 152 assert(-1 <= num && num <= 1); 153 if (num == -1) 154 { 155 ResetEvent( start_event ); 156 SetEvent( stop_event ); 157 } 158 else 159 { 160 DWORD ret = WaitForSingleObject(stop_event, 10000); 161 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 162 } 163 } 164 165 static void cleanup_thread_sync_helpers(void) 166 { 167 CloseHandle(start_event); 168 CloseHandle(stop_event); 169 } 170 171 static DWORD tlsIndex; 172 173 typedef struct { 174 int threadnum; 175 HANDLE *event; 176 DWORD *threadmem; 177 } t1Struct; 178 179 /* WinME supports OpenThread but doesn't know about access restrictions so 180 we require them to be either completely ignored or always obeyed. 181 */ 182 static INT obeying_ars = 0; /* -1 == no, 0 == dunno yet, 1 == yes */ 183 #define obey_ar(x) \ 184 (obeying_ars == 0 \ 185 ? ((x) \ 186 ? (obeying_ars = +1) \ 187 : ((obeying_ars = -1), \ 188 trace("not restricted, assuming consistent behaviour\n"))) \ 189 : (obeying_ars < 0) \ 190 ? ok(!(x), "access restrictions obeyed\n") \ 191 : ok( (x), "access restrictions not obeyed\n")) 192 193 /* Basic test that simultaneous threads can access shared memory, 194 that the thread local storage routines work correctly, and that 195 threads actually run concurrently 196 */ 197 static DWORD WINAPI threadFunc1(LPVOID p) 198 { 199 t1Struct *tstruct = p; 200 int i; 201 /* write our thread # into shared memory */ 202 tstruct->threadmem[tstruct->threadnum]=GetCurrentThreadId(); 203 ok(TlsSetValue(tlsIndex,(LPVOID)(INT_PTR)(tstruct->threadnum+1))!=0, 204 "TlsSetValue failed\n"); 205 /* The threads synchronize before terminating. This is done by 206 Signaling an event, and waiting for all events to occur 207 */ 208 SetEvent(tstruct->event[tstruct->threadnum]); 209 WaitForMultipleObjects(NUM_THREADS,tstruct->event,TRUE,INFINITE); 210 /* Double check that all threads really did run by validating that 211 they have all written to the shared memory. There should be no race 212 here, since all threads were synchronized after the write.*/ 213 for (i = 0; i < NUM_THREADS; i++) 214 ok(tstruct->threadmem[i] != 0, "expected threadmem[%d] != 0\n", i); 215 216 /* lstrlenA contains an exception handler so this makes sure exceptions work in threads */ 217 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" ); 218 219 /* Check that no one changed our tls memory */ 220 ok((INT_PTR)TlsGetValue(tlsIndex)-1==tstruct->threadnum, 221 "TlsGetValue failed\n"); 222 return NUM_THREADS+tstruct->threadnum; 223 } 224 225 static DWORD WINAPI threadFunc2(LPVOID p) 226 { 227 return 99; 228 } 229 230 static DWORD WINAPI threadFunc3(LPVOID p) 231 { 232 HANDLE thread; 233 thread=GetCurrentThread(); 234 SuspendThread(thread); 235 return 99; 236 } 237 238 static DWORD WINAPI threadFunc4(LPVOID p) 239 { 240 HANDLE event = p; 241 if(event != NULL) { 242 SetEvent(event); 243 } 244 Sleep(99000); 245 return 0; 246 } 247 248 #if CHECK_STACK 249 static DWORD WINAPI threadFunc5(LPVOID p) 250 { 251 DWORD *exitCode = p; 252 SYSTEM_INFO sysInfo; 253 sysInfo.dwPageSize=0; 254 GetSystemInfo(&sysInfo); 255 *exitCode=0; 256 __TRY 257 { 258 alloca(2*sysInfo.dwPageSize); 259 } 260 __EXCEPT(1) { 261 *exitCode=1; 262 } 263 __ENDTRY 264 return 0; 265 } 266 #endif 267 268 static DWORD WINAPI threadFunc_SetEvent(LPVOID p) 269 { 270 SetEvent(p); 271 return 0; 272 } 273 274 static DWORD WINAPI threadFunc_CloseHandle(LPVOID p) 275 { 276 CloseHandle(p); 277 return 0; 278 } 279 280 struct thread_actctx_param 281 { 282 HANDLE thread_context; 283 HANDLE handle; 284 }; 285 286 static DWORD WINAPI thread_actctx_func(void *p) 287 { 288 struct thread_actctx_param *param = (struct thread_actctx_param*)p; 289 HANDLE cur; 290 BOOL ret; 291 292 cur = (void*)0xdeadbeef; 293 ret = pGetCurrentActCtx(&cur); 294 ok(ret, "thread GetCurrentActCtx failed, %u\n", GetLastError()); 295 ok(cur == param->handle, "got %p, expected %p\n", cur, param->handle); 296 param->thread_context = cur; 297 298 return 0; 299 } 300 301 static void create_function_addr_events(HANDLE events[2]) 302 { 303 char buffer[256]; 304 305 sprintf(buffer, "threadFunc_SetEvent %p", threadFunc_SetEvent); 306 events[0] = CreateEventA(NULL, FALSE, FALSE, buffer); 307 308 sprintf(buffer, "threadFunc_CloseHandle %p", threadFunc_CloseHandle); 309 events[1] = CreateEventA(NULL, FALSE, FALSE, buffer); 310 } 311 312 /* check CreateRemoteThread */ 313 static VOID test_CreateRemoteThread(void) 314 { 315 HANDLE hProcess, hThread, hEvent, hRemoteEvent; 316 DWORD tid, ret, exitcode; 317 HANDLE hAddrEvents[2]; 318 319 hProcess = create_target_process("sleep"); 320 ok(hProcess != NULL, "Can't start process\n"); 321 322 /* ensure threadFunc_SetEvent & threadFunc_CloseHandle are the same 323 * address as in the child process */ 324 create_function_addr_events(hAddrEvents); 325 ret = WaitForMultipleObjects(2, hAddrEvents, TRUE, 5000); 326 if (ret == WAIT_TIMEOUT) 327 { 328 skip("child process wasn't mapped at same address, so can't do CreateRemoteThread tests.\n"); 329 return; 330 } 331 ok(ret == WAIT_OBJECT_0 || broken(ret == WAIT_OBJECT_0+1 /* nt4,w2k */), "WaitForAllObjects 2 events %d\n", ret); 332 333 hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); 334 ok(hEvent != NULL, "Can't create event, err=%u\n", GetLastError()); 335 ret = DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &hRemoteEvent, 336 0, FALSE, DUPLICATE_SAME_ACCESS); 337 ok(ret != 0, "DuplicateHandle failed, err=%u\n", GetLastError()); 338 339 /* create suspended remote thread with entry point SetEvent() */ 340 SetLastError(0xdeadbeef); 341 hThread = CreateRemoteThread(hProcess, NULL, 0, threadFunc_SetEvent, 342 hRemoteEvent, CREATE_SUSPENDED, &tid); 343 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 344 { 345 win_skip("CreateRemoteThread is not implemented\n"); 346 goto cleanup; 347 } 348 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError()); 349 ok(tid != 0, "null tid\n"); 350 ret = SuspendThread(hThread); 351 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError()); 352 ret = ResumeThread(hThread); 353 ok(ret == 2, "ret=%u, err=%u\n", ret, GetLastError()); 354 355 /* thread still suspended, so wait times out */ 356 ret = WaitForSingleObject(hEvent, 1000); 357 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret); 358 359 ret = ResumeThread(hThread); 360 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError()); 361 362 /* wait that doesn't time out */ 363 ret = WaitForSingleObject(hEvent, 1000); 364 ok(ret == WAIT_OBJECT_0, "object not signaled, ret=%u\n", ret); 365 366 /* wait for thread end */ 367 ret = WaitForSingleObject(hThread, 1000); 368 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret); 369 CloseHandle(hThread); 370 371 /* create and wait for remote thread with entry point CloseHandle() */ 372 hThread = CreateRemoteThread(hProcess, NULL, 0, 373 threadFunc_CloseHandle, 374 hRemoteEvent, 0, &tid); 375 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError()); 376 ret = WaitForSingleObject(hThread, 1000); 377 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret); 378 CloseHandle(hThread); 379 380 /* create remote thread with entry point SetEvent() */ 381 hThread = CreateRemoteThread(hProcess, NULL, 0, 382 threadFunc_SetEvent, 383 hRemoteEvent, 0, &tid); 384 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError()); 385 386 /* closed handle, so wait times out */ 387 ret = WaitForSingleObject(hEvent, 1000); 388 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret); 389 390 /* check that remote SetEvent() failed */ 391 ret = GetExitCodeThread(hThread, &exitcode); 392 ok(ret != 0, "GetExitCodeThread failed, err=%u\n", GetLastError()); 393 if (ret) ok(exitcode == 0, "SetEvent succeeded, expected to fail\n"); 394 CloseHandle(hThread); 395 396 cleanup: 397 TerminateProcess(hProcess, 0); 398 CloseHandle(hEvent); 399 CloseHandle(hProcess); 400 } 401 402 /* Check basic functionality of CreateThread and Tls* functions */ 403 static VOID test_CreateThread_basic(void) 404 { 405 HANDLE thread[NUM_THREADS],event[NUM_THREADS]; 406 DWORD threadid[NUM_THREADS],curthreadId; 407 DWORD threadmem[NUM_THREADS]; 408 DWORD exitCode; 409 t1Struct tstruct[NUM_THREADS]; 410 int error; 411 DWORD i,j; 412 DWORD GLE, ret; 413 DWORD tid; 414 BOOL bRet; 415 416 /* lstrlenA contains an exception handler so this makes sure exceptions work in the main thread */ 417 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" ); 418 419 /* Retrieve current Thread ID for later comparisons */ 420 curthreadId=GetCurrentThreadId(); 421 /* Allocate some local storage */ 422 ok((tlsIndex=TlsAlloc())!=TLS_OUT_OF_INDEXES,"TlsAlloc failed\n"); 423 /* Create events for thread synchronization */ 424 for(i=0;i<NUM_THREADS;i++) { 425 threadmem[i]=0; 426 /* Note that it doesn't matter what type of event we choose here. This 427 test isn't trying to thoroughly test events 428 */ 429 event[i]=CreateEventA(NULL,TRUE,FALSE,NULL); 430 tstruct[i].threadnum=i; 431 tstruct[i].threadmem=threadmem; 432 tstruct[i].event=event; 433 } 434 435 /* Test that passing arguments to threads works okay */ 436 for(i=0;i<NUM_THREADS;i++) { 437 thread[i] = CreateThread(NULL,0,threadFunc1, 438 &tstruct[i],0,&threadid[i]); 439 ok(thread[i]!=NULL,"Create Thread failed\n"); 440 } 441 /* Test that the threads actually complete */ 442 for(i=0;i<NUM_THREADS;i++) { 443 error=WaitForSingleObject(thread[i],5000); 444 ok(error==WAIT_OBJECT_0, "Thread did not complete within timelimit\n"); 445 if(error!=WAIT_OBJECT_0) { 446 TerminateThread(thread[i],i+NUM_THREADS); 447 } 448 ok(GetExitCodeThread(thread[i],&exitCode),"Could not retrieve ext code\n"); 449 ok(exitCode==i+NUM_THREADS,"Thread returned an incorrect exit code\n"); 450 } 451 /* Test that each thread executed in its parent's address space 452 (it was able to change threadmem and pass that change back to its parent) 453 and that each thread id was independent). Note that we prove that the 454 threads actually execute concurrently by having them block on each other 455 in threadFunc1 456 */ 457 for(i=0;i<NUM_THREADS;i++) { 458 error=0; 459 for(j=i+1;j<NUM_THREADS;j++) { 460 if (threadmem[i]==threadmem[j]) { 461 error=1; 462 } 463 } 464 ok(!error && threadmem[i]==threadid[i] && threadmem[i]!=curthreadId, 465 "Thread did not execute successfully\n"); 466 ok(CloseHandle(thread[i])!=0,"CloseHandle failed\n"); 467 } 468 469 SetLastError(0xCAFEF00D); 470 bRet = TlsFree(tlsIndex); 471 ok(bRet, "TlsFree failed: %08x\n", GetLastError()); 472 ok(GetLastError()==0xCAFEF00D, 473 "GetLastError: expected 0xCAFEF00D, got %08x\n", GetLastError()); 474 475 /* Test freeing an already freed TLS index */ 476 SetLastError(0xCAFEF00D); 477 ok(TlsFree(tlsIndex)==0,"TlsFree succeeded\n"); 478 ok(GetLastError()==ERROR_INVALID_PARAMETER, 479 "GetLastError: expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError()); 480 481 /* Test how passing NULL as a pointer to threadid works */ 482 SetLastError(0xFACEaBAD); 483 thread[0] = CreateThread(NULL,0,threadFunc2,NULL,0,&tid); 484 GLE = GetLastError(); 485 if (thread[0]) { /* NT */ 486 ok(GLE==0xFACEaBAD, "CreateThread set last error to %d, expected 4207848365\n", GLE); 487 ret = WaitForSingleObject(thread[0],100); 488 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n"); 489 ret = GetExitCodeThread(thread[0],&exitCode); 490 ok(ret!=0, "GetExitCodeThread returned %d (expected nonzero)\n", ret); 491 ok(exitCode==99, "threadFunc2 exited with code: %d (expected 99)\n", exitCode); 492 ok(CloseHandle(thread[0])!=0,"Error closing thread handle\n"); 493 } 494 else { /* 9x */ 495 ok(GLE==ERROR_INVALID_PARAMETER, "CreateThread set last error to %d, expected 87\n", GLE); 496 } 497 } 498 499 /* Check that using the CREATE_SUSPENDED flag works */ 500 static VOID test_CreateThread_suspended(void) 501 { 502 HANDLE thread; 503 DWORD threadId; 504 DWORD suspend_count; 505 int error; 506 507 thread = CreateThread(NULL,0,threadFunc2,NULL, 508 CREATE_SUSPENDED,&threadId); 509 ok(thread!=NULL,"Create Thread failed\n"); 510 /* Check that the thread is suspended */ 511 ok(SuspendThread(thread)==1,"Thread did not start suspended\n"); 512 ok(ResumeThread(thread)==2,"Resume thread returned an invalid value\n"); 513 /* Check that resume thread didn't actually start the thread. I can't think 514 of a better way of checking this than just waiting. I am not sure if this 515 will work on slow computers. 516 */ 517 ok(WaitForSingleObject(thread,1000)==WAIT_TIMEOUT, 518 "ResumeThread should not have actually started the thread\n"); 519 /* Now actually resume the thread and make sure that it actually completes*/ 520 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n"); 521 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0, 522 "Thread did not resume\n"); 523 if(error!=WAIT_OBJECT_0) { 524 TerminateThread(thread,1); 525 } 526 527 suspend_count = SuspendThread(thread); 528 ok(suspend_count == -1, "SuspendThread returned %d, expected -1\n", suspend_count); 529 530 suspend_count = ResumeThread(thread); 531 ok(suspend_count == 0 || 532 broken(suspend_count == -1), /* win9x */ 533 "ResumeThread returned %d, expected 0\n", suspend_count); 534 535 ok(CloseHandle(thread)!=0,"CloseHandle failed\n"); 536 } 537 538 /* Check that SuspendThread and ResumeThread work */ 539 static VOID test_SuspendThread(void) 540 { 541 HANDLE thread,access_thread; 542 DWORD threadId,exitCode,error; 543 int i; 544 545 thread = CreateThread(NULL,0,threadFunc3,NULL, 546 0,&threadId); 547 ok(thread!=NULL,"Create Thread failed\n"); 548 /* Check that the thread is suspended */ 549 /* Note that this is a polling method, and there is a race between 550 SuspendThread being called (in the child, and the loop below timing out, 551 so the test could fail on a heavily loaded or slow computer. 552 */ 553 error=0; 554 for(i=0;error==0 && i<100;i++) { 555 error=SuspendThread(thread); 556 ResumeThread(thread); 557 if(error==0) { 558 Sleep(50); 559 i++; 560 } 561 } 562 ok(error==1,"SuspendThread did not work\n"); 563 /* check that access restrictions are obeyed */ 564 if (pOpenThread) { 565 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 & (~THREAD_SUSPEND_RESUME), 566 0,threadId); 567 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n"); 568 if (access_thread!=NULL) { 569 obey_ar(SuspendThread(access_thread)==~0U); 570 obey_ar(ResumeThread(access_thread)==~0U); 571 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n"); 572 } 573 } 574 /* Double check that the thread really is suspended */ 575 ok((error=GetExitCodeThread(thread,&exitCode))!=0 && exitCode==STILL_ACTIVE, 576 "Thread did not really suspend\n"); 577 /* Resume the thread, and make sure it actually completes */ 578 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n"); 579 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0, 580 "Thread did not resume\n"); 581 if(error!=WAIT_OBJECT_0) { 582 TerminateThread(thread,1); 583 } 584 /* Trying to suspend a terminated thread should fail */ 585 error=SuspendThread(thread); 586 ok(error==~0U, "wrong return code: %d\n", error); 587 ok(GetLastError()==ERROR_ACCESS_DENIED || GetLastError()==ERROR_NO_MORE_ITEMS, "unexpected error code: %d\n", GetLastError()); 588 589 ok(CloseHandle(thread)!=0,"CloseHandle Failed\n"); 590 } 591 592 /* Check that TerminateThread works properly 593 */ 594 static VOID test_TerminateThread(void) 595 { 596 HANDLE thread,access_thread,event; 597 DWORD threadId,exitCode; 598 event=CreateEventA(NULL,TRUE,FALSE,NULL); 599 thread = CreateThread(NULL,0,threadFunc4,event,0,&threadId); 600 ok(thread!=NULL,"Create Thread failed\n"); 601 /* TerminateThread has a race condition in Wine. If the thread is terminated 602 before it starts, it leaves a process behind. Therefore, we wait for the 603 thread to signal that it has started. There is no easy way to force the 604 race to occur, so we don't try to find it. 605 */ 606 ok(WaitForSingleObject(event,5000)==WAIT_OBJECT_0, 607 "TerminateThread didn't work\n"); 608 /* check that access restrictions are obeyed */ 609 if (pOpenThread) { 610 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 & (~THREAD_TERMINATE), 611 0,threadId); 612 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n"); 613 if (access_thread!=NULL) { 614 obey_ar(TerminateThread(access_thread,99)==0); 615 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n"); 616 } 617 } 618 /* terminate a job and make sure it terminates */ 619 ok(TerminateThread(thread,99)!=0,"TerminateThread failed\n"); 620 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0, 621 "TerminateThread didn't work\n"); 622 ok(GetExitCodeThread(thread,&exitCode)!=STILL_ACTIVE, 623 "TerminateThread should not leave the thread 'STILL_ACTIVE'\n"); 624 ok(exitCode==99, "TerminateThread returned invalid exit code\n"); 625 ok(CloseHandle(thread)!=0,"Error Closing thread handle\n"); 626 } 627 628 /* Check if CreateThread obeys the specified stack size. This code does 629 not work properly, and is currently disabled 630 */ 631 static VOID test_CreateThread_stack(void) 632 { 633 #if CHECK_STACK 634 /* The only way I know of to test the stack size is to use alloca 635 and __try/__except. However, this is probably not portable, 636 and I couldn't get it to work under Wine anyhow. However, here 637 is the code which should allow for testing that CreateThread 638 respects the stack-size limit 639 */ 640 HANDLE thread; 641 DWORD threadId,exitCode; 642 643 SYSTEM_INFO sysInfo; 644 sysInfo.dwPageSize=0; 645 GetSystemInfo(&sysInfo); 646 ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n"); 647 thread = CreateThread(NULL,sysInfo.dwPageSize, 648 threadFunc5,&exitCode, 649 0,&threadId); 650 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0, 651 "TerminateThread didn't work\n"); 652 ok(exitCode==1,"CreateThread did not obey stack-size-limit\n"); 653 ok(CloseHandle(thread)!=0,"CloseHandle failed\n"); 654 #endif 655 } 656 657 /* Check whether setting/retrieving thread priorities works */ 658 static VOID test_thread_priority(void) 659 { 660 HANDLE curthread,access_thread; 661 DWORD curthreadId,exitCode; 662 int min_priority=-2,max_priority=2; 663 BOOL disabled,rc; 664 int i; 665 666 curthread=GetCurrentThread(); 667 curthreadId=GetCurrentThreadId(); 668 /* Check thread priority */ 669 /* NOTE: on Win2k/XP priority can be from -7 to 6. All other platforms it 670 is -2 to 2. However, even on a real Win2k system, using thread 671 priorities beyond the -2 to 2 range does not work. If you want to try 672 anyway, enable USE_EXTENDED_PRIORITIES 673 */ 674 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_NORMAL, 675 "GetThreadPriority Failed\n"); 676 677 if (pOpenThread) { 678 /* check that access control is obeyed */ 679 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 & 680 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION), 681 0,curthreadId); 682 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n"); 683 if (access_thread!=NULL) { 684 obey_ar(SetThreadPriority(access_thread,1)==0); 685 obey_ar(GetThreadPriority(access_thread)==THREAD_PRIORITY_ERROR_RETURN); 686 obey_ar(GetExitCodeThread(access_thread,&exitCode)==0); 687 ok(CloseHandle(access_thread),"Error Closing thread handle\n"); 688 } 689 } 690 #if USE_EXTENDED_PRIORITIES 691 min_priority=-7; max_priority=6; 692 #endif 693 for(i=min_priority;i<=max_priority;i++) { 694 ok(SetThreadPriority(curthread,i)!=0, 695 "SetThreadPriority Failed for priority: %d\n",i); 696 ok(GetThreadPriority(curthread)==i, 697 "GetThreadPriority Failed for priority: %d\n",i); 698 } 699 ok(SetThreadPriority(curthread,THREAD_PRIORITY_TIME_CRITICAL)!=0, 700 "SetThreadPriority Failed\n"); 701 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_TIME_CRITICAL, 702 "GetThreadPriority Failed\n"); 703 ok(SetThreadPriority(curthread,THREAD_PRIORITY_IDLE)!=0, 704 "SetThreadPriority Failed\n"); 705 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_IDLE, 706 "GetThreadPriority Failed\n"); 707 ok(SetThreadPriority(curthread,0)!=0,"SetThreadPriority Failed\n"); 708 709 /* Check that the thread priority is not changed if SetThreadPriority 710 is called with a value outside of the max/min range */ 711 SetThreadPriority(curthread,min_priority); 712 SetLastError(0xdeadbeef); 713 rc = SetThreadPriority(curthread,min_priority-1); 714 715 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n"); 716 ok(GetLastError() == ERROR_INVALID_PARAMETER || 717 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */, 718 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n", 719 GetLastError()); 720 ok(GetThreadPriority(curthread)==min_priority, 721 "GetThreadPriority didn't return min_priority\n"); 722 723 SetThreadPriority(curthread,max_priority); 724 SetLastError(0xdeadbeef); 725 rc = SetThreadPriority(curthread,max_priority+1); 726 727 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n"); 728 ok(GetLastError() == ERROR_INVALID_PARAMETER || 729 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */, 730 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n", 731 GetLastError()); 732 ok(GetThreadPriority(curthread)==max_priority, 733 "GetThreadPriority didn't return max_priority\n"); 734 735 /* Check thread priority boost */ 736 if (!pGetThreadPriorityBoost || !pSetThreadPriorityBoost) 737 return; /* Win9x */ 738 739 SetLastError(0xdeadbeef); 740 rc=pGetThreadPriorityBoost(curthread,&disabled); 741 if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED) 742 { 743 win_skip("GetThreadPriorityBoost is not implemented on WinME\n"); 744 return; 745 } 746 747 ok(rc!=0,"error=%d\n",GetLastError()); 748 749 if (pOpenThread) { 750 /* check that access control is obeyed */ 751 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 & 752 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION), 753 0,curthreadId); 754 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n"); 755 if (access_thread!=NULL) { 756 todo_wine obey_ar(pSetThreadPriorityBoost(access_thread,1)==0); 757 todo_wine obey_ar(pGetThreadPriorityBoost(access_thread,&disabled)==0); 758 ok(CloseHandle(access_thread),"Error Closing thread handle\n"); 759 } 760 } 761 762 rc = pSetThreadPriorityBoost(curthread,1); 763 ok( rc != 0, "error=%d\n",GetLastError()); 764 todo_wine { 765 rc=pGetThreadPriorityBoost(curthread,&disabled); 766 ok(rc!=0 && disabled==1, 767 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled); 768 } 769 770 rc = pSetThreadPriorityBoost(curthread,0); 771 ok( rc != 0, "error=%d\n",GetLastError()); 772 rc=pGetThreadPriorityBoost(curthread,&disabled); 773 ok(rc!=0 && disabled==0, 774 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled); 775 } 776 777 /* check the GetThreadTimes function */ 778 static VOID test_GetThreadTimes(void) 779 { 780 HANDLE thread,access_thread=NULL; 781 FILETIME creationTime,exitTime,kernelTime,userTime; 782 DWORD threadId; 783 int error; 784 785 thread = CreateThread(NULL,0,threadFunc2,NULL, 786 CREATE_SUSPENDED,&threadId); 787 788 ok(thread!=NULL,"Create Thread failed\n"); 789 /* check that access control is obeyed */ 790 if (pOpenThread) { 791 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 & 792 (~THREAD_QUERY_INFORMATION), 0,threadId); 793 ok(access_thread!=NULL, 794 "OpenThread returned an invalid handle\n"); 795 } 796 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n"); 797 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0, 798 "ResumeThread didn't work\n"); 799 creationTime.dwLowDateTime=99; creationTime.dwHighDateTime=99; 800 exitTime.dwLowDateTime=99; exitTime.dwHighDateTime=99; 801 kernelTime.dwLowDateTime=99; kernelTime.dwHighDateTime=99; 802 userTime.dwLowDateTime=99; userTime.dwHighDateTime=99; 803 /* GetThreadTimes should set all of the parameters passed to it */ 804 error=GetThreadTimes(thread,&creationTime,&exitTime, 805 &kernelTime,&userTime); 806 807 if (error == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 808 win_skip("GetThreadTimes is not implemented\n"); 809 else { 810 ok(error!=0,"GetThreadTimes failed\n"); 811 ok(creationTime.dwLowDateTime!=99 || creationTime.dwHighDateTime!=99, 812 "creationTime was invalid\n"); 813 ok(exitTime.dwLowDateTime!=99 || exitTime.dwHighDateTime!=99, 814 "exitTime was invalid\n"); 815 ok(kernelTime.dwLowDateTime!=99 || kernelTime.dwHighDateTime!=99, 816 "kernelTimewas invalid\n"); 817 ok(userTime.dwLowDateTime!=99 || userTime.dwHighDateTime!=99, 818 "userTime was invalid\n"); 819 ok(CloseHandle(thread)!=0,"CloseHandle failed\n"); 820 if(access_thread!=NULL) 821 { 822 error=GetThreadTimes(access_thread,&creationTime,&exitTime, 823 &kernelTime,&userTime); 824 obey_ar(error==0); 825 } 826 } 827 if(access_thread!=NULL) { 828 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n"); 829 } 830 } 831 832 /* Check the processor affinity functions */ 833 /* NOTE: These functions should also be checked that they obey access control 834 */ 835 static VOID test_thread_processor(void) 836 { 837 HANDLE curthread,curproc; 838 DWORD_PTR processMask,systemMask,retMask; 839 SYSTEM_INFO sysInfo; 840 int error=0; 841 BOOL is_wow64; 842 843 if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE; 844 845 sysInfo.dwNumberOfProcessors=0; 846 GetSystemInfo(&sysInfo); 847 ok(sysInfo.dwNumberOfProcessors>0, 848 "GetSystemInfo failed to return a valid # of processors\n"); 849 /* Use the current Thread/process for all tests */ 850 curthread=GetCurrentThread(); 851 ok(curthread!=NULL,"GetCurrentThread failed\n"); 852 curproc=GetCurrentProcess(); 853 ok(curproc!=NULL,"GetCurrentProcess failed\n"); 854 /* Check the Affinity Mask functions */ 855 ok(GetProcessAffinityMask(curproc,&processMask,&systemMask)!=0, 856 "GetProcessAffinityMask failed\n"); 857 ok(SetThreadAffinityMask(curthread,processMask)==processMask, 858 "SetThreadAffinityMask failed\n"); 859 ok(SetThreadAffinityMask(curthread,processMask+1)==0, 860 "SetThreadAffinityMask passed for an illegal processor\n"); 861 /* NOTE: Pre-Vista does not recognize the "all processors" flag (all bits set) */ 862 retMask = SetThreadAffinityMask(curthread,~0); 863 ok(broken(retMask==0) || retMask==processMask, 864 "SetThreadAffinityMask(thread,-1) failed to request all processors.\n"); 865 866 if (retMask == processMask) 867 { 868 /* Show that the "all processors" flag is handled in ntdll */ 869 DWORD_PTR mask = ~0u; 870 NTSTATUS status = pNtSetInformationThread(curthread, ThreadAffinityMask, &mask, sizeof(mask)); 871 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS in NtSetInformationThread, got %x\n", status); 872 } 873 874 if (retMask == processMask && sizeof(ULONG_PTR) > sizeof(ULONG)) 875 { 876 /* only the low 32-bits matter */ 877 retMask = SetThreadAffinityMask(curthread,~(ULONG_PTR)0); 878 ok(retMask == processMask, "SetThreadAffinityMask failed\n"); 879 retMask = SetThreadAffinityMask(curthread,~(ULONG_PTR)0 >> 3); 880 ok(retMask == processMask, "SetThreadAffinityMask failed\n"); 881 } 882 /* NOTE: This only works on WinNT/2000/XP) */ 883 if (pSetThreadIdealProcessor) 884 { 885 SetLastError(0xdeadbeef); 886 error=pSetThreadIdealProcessor(curthread,0); 887 if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) 888 { 889 ok(error!=-1, "SetThreadIdealProcessor failed\n"); 890 891 if (is_wow64) 892 { 893 SetLastError(0xdeadbeef); 894 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1); 895 todo_wine 896 ok(error!=-1, "SetThreadIdealProcessor failed for %u on Wow64\n", MAXIMUM_PROCESSORS+1); 897 898 SetLastError(0xdeadbeef); 899 error=pSetThreadIdealProcessor(curthread,65); 900 ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n"); 901 ok(GetLastError()==ERROR_INVALID_PARAMETER, 902 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 903 } 904 else 905 { 906 SetLastError(0xdeadbeef); 907 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1); 908 ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n"); 909 ok(GetLastError()==ERROR_INVALID_PARAMETER, 910 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 911 } 912 913 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS); 914 ok(error!=-1, "SetThreadIdealProcessor failed\n"); 915 } 916 else 917 win_skip("SetThreadIdealProcessor is not implemented\n"); 918 } 919 920 if (pGetThreadGroupAffinity && pSetThreadGroupAffinity) 921 { 922 GROUP_AFFINITY affinity, affinity_new; 923 NTSTATUS status; 924 925 memset(&affinity, 0, sizeof(affinity)); 926 ok(pGetThreadGroupAffinity(curthread, &affinity), "GetThreadGroupAffinity failed\n"); 927 928 SetLastError(0xdeadbeef); 929 ok(!pGetThreadGroupAffinity(curthread, NULL), "GetThreadGroupAffinity succeeded\n"); 930 ok(GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == ERROR_NOACCESS), /* Win 7 and 8 */ 931 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 932 ok(affinity.Group == 0, "Expected group 0 got %u\n", affinity.Group); 933 934 memset(&affinity_new, 0, sizeof(affinity_new)); 935 affinity_new.Group = 0; 936 affinity_new.Mask = affinity.Mask; 937 ok(pSetThreadGroupAffinity(curthread, &affinity_new, &affinity), "SetThreadGroupAffinity failed\n"); 938 ok(affinity_new.Mask == affinity.Mask, "Expected old affinity mask %lx, got %lx\n", 939 affinity_new.Mask, affinity.Mask); 940 941 /* show that the "all processors" flag is not supported for SetThreadGroupAffinity */ 942 affinity_new.Group = 0; 943 affinity_new.Mask = ~0u; 944 SetLastError(0xdeadbeef); 945 ok(!pSetThreadGroupAffinity(curthread, &affinity_new, NULL), "SetThreadGroupAffinity succeeded\n"); 946 ok(GetLastError() == ERROR_INVALID_PARAMETER, 947 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 948 949 affinity_new.Group = 1; /* assumes that you have less than 64 logical processors */ 950 affinity_new.Mask = 0x1; 951 SetLastError(0xdeadbeef); 952 ok(!pSetThreadGroupAffinity(curthread, &affinity_new, NULL), "SetThreadGroupAffinity succeeded\n"); 953 ok(GetLastError() == ERROR_INVALID_PARAMETER, 954 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 955 956 SetLastError(0xdeadbeef); 957 ok(!pSetThreadGroupAffinity(curthread, NULL, NULL), "SetThreadGroupAffinity succeeded\n"); 958 ok(GetLastError() == ERROR_NOACCESS, 959 "Expected ERROR_NOACCESS, got %d\n", GetLastError()); 960 961 /* show that the access violation was detected in ntdll */ 962 status = pNtSetInformationThread(curthread, ThreadGroupInformation, NULL, sizeof(affinity_new)); 963 ok(status == STATUS_ACCESS_VIOLATION, 964 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", status); 965 966 /* restore original mask */ 967 affinity_new.Group = 0; 968 affinity_new.Mask = affinity.Mask; 969 SetLastError(0xdeadbeef); 970 ok(pSetThreadGroupAffinity(curthread, &affinity_new, &affinity), "SetThreadGroupAffinity failed\n"); 971 ok(affinity_new.Mask == affinity.Mask, "Expected old affinity mask %lx, got %lx\n", 972 affinity_new.Mask, affinity.Mask); 973 } 974 else 975 win_skip("Get/SetThreadGroupAffinity not available\n"); 976 } 977 978 static VOID test_GetThreadExitCode(void) 979 { 980 DWORD exitCode, threadid; 981 DWORD GLE, ret; 982 HANDLE thread; 983 984 ret = GetExitCodeThread((HANDLE)0x2bad2bad,&exitCode); 985 ok(ret==0, "GetExitCodeThread returned non zero value: %d\n", ret); 986 GLE = GetLastError(); 987 ok(GLE==ERROR_INVALID_HANDLE, "GetLastError returned %d (expected 6)\n", GLE); 988 989 thread = CreateThread(NULL,0,threadFunc2,NULL,0,&threadid); 990 ret = WaitForSingleObject(thread,100); 991 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n"); 992 ret = GetExitCodeThread(thread,&exitCode); 993 ok(ret==exitCode || ret==1, 994 "GetExitCodeThread returned %d (expected 1 or %d)\n", ret, exitCode); 995 ok(exitCode==99, "threadFunc2 exited with code %d (expected 99)\n", exitCode); 996 ok(CloseHandle(thread)!=0,"Error closing thread handle\n"); 997 } 998 999 #ifdef __i386__ 1000 1001 static int test_value = 0; 1002 static HANDLE event; 1003 1004 static void WINAPI set_test_val( int val ) 1005 { 1006 test_value += val; 1007 ExitThread(0); 1008 } 1009 1010 static DWORD WINAPI threadFunc6(LPVOID p) 1011 { 1012 SetEvent( event ); 1013 Sleep( 1000 ); 1014 test_value *= (int)p; 1015 return 0; 1016 } 1017 1018 static void test_SetThreadContext(void) 1019 { 1020 CONTEXT ctx; 1021 int *stack; 1022 HANDLE thread; 1023 DWORD threadid; 1024 DWORD prevcount; 1025 BOOL ret; 1026 1027 SetLastError(0xdeadbeef); 1028 event = CreateEventW( NULL, TRUE, FALSE, NULL ); 1029 thread = CreateThread( NULL, 0, threadFunc6, (void *)2, 0, &threadid ); 1030 ok( thread != NULL, "CreateThread failed : (%d)\n", GetLastError() ); 1031 if (!thread) 1032 { 1033 trace("Thread creation failed, skipping rest of test\n"); 1034 return; 1035 } 1036 WaitForSingleObject( event, INFINITE ); 1037 SuspendThread( thread ); 1038 CloseHandle( event ); 1039 1040 ctx.ContextFlags = CONTEXT_FULL; 1041 SetLastError(0xdeadbeef); 1042 ret = GetThreadContext( thread, &ctx ); 1043 ok( ret, "GetThreadContext failed : (%u)\n", GetLastError() ); 1044 1045 if (ret) 1046 { 1047 /* simulate a call to set_test_val(10) */ 1048 stack = (int *)ctx.Esp; 1049 stack[-1] = 10; 1050 stack[-2] = ctx.Eip; 1051 ctx.Esp -= 2 * sizeof(int *); 1052 ctx.Eip = (DWORD)set_test_val; 1053 SetLastError(0xdeadbeef); 1054 ret = SetThreadContext( thread, &ctx ); 1055 ok( ret, "SetThreadContext failed : (%d)\n", GetLastError() ); 1056 } 1057 1058 SetLastError(0xdeadbeef); 1059 prevcount = ResumeThread( thread ); 1060 ok ( prevcount == 1, "Previous suspend count (%d) instead of 1, last error : (%d)\n", 1061 prevcount, GetLastError() ); 1062 1063 WaitForSingleObject( thread, INFINITE ); 1064 ok( test_value == 10, "test_value %d\n", test_value ); 1065 1066 ctx.ContextFlags = CONTEXT_FULL; 1067 SetLastError(0xdeadbeef); 1068 ret = GetThreadContext( thread, &ctx ); 1069 ok( (!ret && ((GetLastError() == ERROR_GEN_FAILURE) || (GetLastError() == ERROR_ACCESS_DENIED))) || 1070 (!ret && broken(GetLastError() == ERROR_INVALID_HANDLE)) || /* win2k */ 1071 broken(ret), /* 32bit application on NT 5.x 64bit */ 1072 "got %d with %u (expected FALSE with ERROR_GEN_FAILURE or ERROR_ACCESS_DENIED)\n", 1073 ret, GetLastError() ); 1074 1075 SetLastError(0xdeadbeef); 1076 ret = SetThreadContext( thread, &ctx ); 1077 ok( (!ret && ((GetLastError() == ERROR_GEN_FAILURE) || (GetLastError() == ERROR_ACCESS_DENIED))) || 1078 (!ret && broken(GetLastError() == ERROR_INVALID_HANDLE)) || /* win2k */ 1079 broken(ret), /* 32bit application on NT 5.x 64bit */ 1080 "got %d with %u (expected FALSE with ERROR_GEN_FAILURE or ERROR_ACCESS_DENIED)\n", 1081 ret, GetLastError() ); 1082 1083 CloseHandle( thread ); 1084 } 1085 1086 static void test_GetThreadSelectorEntry(void) 1087 { 1088 LDT_ENTRY entry; 1089 CONTEXT ctx; 1090 DWORD limit; 1091 void *base; 1092 BOOL ret; 1093 1094 memset(&ctx, 0x11, sizeof(ctx)); 1095 ctx.ContextFlags = CONTEXT_SEGMENTS | CONTEXT_CONTROL; 1096 ret = GetThreadContext(GetCurrentThread(), &ctx); 1097 ok(ret, "GetThreadContext error %u\n", GetLastError()); 1098 ok(!HIWORD(ctx.SegCs), "expected HIWORD(SegCs) == 0, got %u\n", ctx.SegCs); 1099 ok(!HIWORD(ctx.SegDs), "expected HIWORD(SegDs) == 0, got %u\n", ctx.SegDs); 1100 ok(!HIWORD(ctx.SegFs), "expected HIWORD(SegFs) == 0, got %u\n", ctx.SegFs); 1101 1102 ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegCs, &entry); 1103 ok(ret, "GetThreadSelectorEntry(SegCs) error %u\n", GetLastError()); 1104 ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegDs, &entry); 1105 ok(ret, "GetThreadSelectorEntry(SegDs) error %u\n", GetLastError()); 1106 1107 memset(&entry, 0x11, sizeof(entry)); 1108 ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegFs, &entry); 1109 ok(ret, "GetThreadSelectorEntry(SegFs) error %u\n", GetLastError()); 1110 entry.HighWord.Bits.Type &= ~1; /* ignore accessed bit */ 1111 1112 base = (void *)((entry.HighWord.Bits.BaseHi << 24) | (entry.HighWord.Bits.BaseMid << 16) | entry.BaseLow); 1113 limit = (entry.HighWord.Bits.LimitHi << 16) | entry.LimitLow; 1114 1115 ok(base == NtCurrentTeb(), "expected %p, got %p\n", NtCurrentTeb(), base); 1116 ok(limit == 0x0fff || limit == 0x4000, "expected 0x0fff or 0x4000, got %#x\n", limit); 1117 ok(entry.HighWord.Bits.Type == 0x12, "expected 0x12, got %#x\n", entry.HighWord.Bits.Type); 1118 ok(entry.HighWord.Bits.Dpl == 3, "expected 3, got %u\n", entry.HighWord.Bits.Dpl); 1119 ok(entry.HighWord.Bits.Pres == 1, "expected 1, got %u\n", entry.HighWord.Bits.Pres); 1120 ok(entry.HighWord.Bits.Sys == 0, "expected 0, got %u\n", entry.HighWord.Bits.Sys); 1121 ok(entry.HighWord.Bits.Reserved_0 == 0, "expected 0, got %u\n", entry.HighWord.Bits.Reserved_0); 1122 ok(entry.HighWord.Bits.Default_Big == 1, "expected 1, got %u\n", entry.HighWord.Bits.Default_Big); 1123 ok(entry.HighWord.Bits.Granularity == 0, "expected 0, got %u\n", entry.HighWord.Bits.Granularity); 1124 } 1125 1126 static void test_NtSetLdtEntries(void) 1127 { 1128 THREAD_DESCRIPTOR_INFORMATION tdi; 1129 LDT_ENTRY ds_entry; 1130 CONTEXT ctx; 1131 DWORD ret; 1132 union 1133 { 1134 LDT_ENTRY entry; 1135 DWORD dw[2]; 1136 } sel; 1137 1138 if (!pNtSetLdtEntries) 1139 { 1140 win_skip("NtSetLdtEntries is not available on this platform\n"); 1141 return; 1142 } 1143 1144 if (pNtSetLdtEntries(0, 0, 0, 0, 0, 0) == STATUS_NOT_IMPLEMENTED) /* WoW64 */ 1145 { 1146 win_skip("NtSetLdtEntries is not implemented on this platform\n"); 1147 return; 1148 } 1149 1150 ret = pNtSetLdtEntries(0, 0, 0, 0, 0, 0); 1151 ok(!ret, "NtSetLdtEntries failed: %08x\n", ret); 1152 1153 ctx.ContextFlags = CONTEXT_SEGMENTS; 1154 ret = GetThreadContext(GetCurrentThread(), &ctx); 1155 ok(ret, "GetThreadContext failed\n"); 1156 1157 tdi.Selector = ctx.SegDs; 1158 ret = pNtQueryInformationThread(GetCurrentThread(), ThreadDescriptorTableEntry, &tdi, sizeof(tdi), &ret); 1159 ok(!ret, "NtQueryInformationThread failed: %08x\n", ret); 1160 ds_entry = tdi.Entry; 1161 1162 tdi.Selector = 0x000f; 1163 ret = pNtQueryInformationThread(GetCurrentThread(), ThreadDescriptorTableEntry, &tdi, sizeof(tdi), &ret); 1164 ok(ret == STATUS_ACCESS_VIOLATION, "got %08x\n", ret); 1165 1166 tdi.Selector = 0x001f; 1167 ret = pNtQueryInformationThread(GetCurrentThread(), ThreadDescriptorTableEntry, &tdi, sizeof(tdi), &ret); 1168 ok(ret == STATUS_ACCESS_VIOLATION, "NtQueryInformationThread returned %08x\n", ret); 1169 1170 ret = GetThreadSelectorEntry(GetCurrentThread(), 0x000f, &sel.entry); 1171 ok(!ret, "GetThreadSelectorEntry should fail\n"); 1172 1173 ret = GetThreadSelectorEntry(GetCurrentThread(), 0x001f, &sel.entry); 1174 ok(!ret, "GetThreadSelectorEntry should fail\n"); 1175 1176 memset(&sel.entry, 0x9a, sizeof(sel.entry)); 1177 ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegDs, &sel.entry); 1178 ok(ret, "GetThreadSelectorEntry failed\n"); 1179 ok(!memcmp(&ds_entry, &sel.entry, sizeof(ds_entry)), "entries do not match\n"); 1180 1181 ret = pNtSetLdtEntries(0x000f, sel.dw[0], sel.dw[1], 0x001f, sel.dw[0], sel.dw[1]); 1182 ok(!ret || broken(ret == STATUS_INVALID_LDT_DESCRIPTOR) /*XP*/, "NtSetLdtEntries failed: %08x\n", ret); 1183 1184 if (!ret) 1185 { 1186 memset(&sel.entry, 0x9a, sizeof(sel.entry)); 1187 ret = GetThreadSelectorEntry(GetCurrentThread(), 0x000f, &sel.entry); 1188 ok(ret, "GetThreadSelectorEntry failed\n"); 1189 ok(!memcmp(&ds_entry, &sel.entry, sizeof(ds_entry)), "entries do not match\n"); 1190 1191 memset(&sel.entry, 0x9a, sizeof(sel.entry)); 1192 ret = GetThreadSelectorEntry(GetCurrentThread(), 0x001f, &sel.entry); 1193 ok(ret, "GetThreadSelectorEntry failed\n"); 1194 ok(!memcmp(&ds_entry, &sel.entry, sizeof(ds_entry)), "entries do not match\n"); 1195 } 1196 } 1197 1198 #endif /* __i386__ */ 1199 1200 static HANDLE finish_event; 1201 static LONG times_executed; 1202 1203 static DWORD CALLBACK work_function(void *p) 1204 { 1205 LONG executed = InterlockedIncrement(×_executed); 1206 1207 if (executed == 100) 1208 SetEvent(finish_event); 1209 return 0; 1210 } 1211 1212 static void test_QueueUserWorkItem(void) 1213 { 1214 INT_PTR i; 1215 DWORD wait_result; 1216 DWORD before, after; 1217 1218 /* QueueUserWorkItem not present on win9x */ 1219 if (!pQueueUserWorkItem) return; 1220 1221 finish_event = CreateEventW(NULL, TRUE, FALSE, NULL); 1222 1223 before = GetTickCount(); 1224 1225 for (i = 0; i < 100; i++) 1226 { 1227 BOOL ret = pQueueUserWorkItem(work_function, (void *)i, WT_EXECUTEDEFAULT); 1228 ok(ret, "QueueUserWorkItem failed with error %d\n", GetLastError()); 1229 } 1230 1231 wait_result = WaitForSingleObject(finish_event, 10000); 1232 1233 after = GetTickCount(); 1234 trace("100 QueueUserWorkItem calls took %dms\n", after - before); 1235 ok(wait_result == WAIT_OBJECT_0, "wait failed with error 0x%x\n", wait_result); 1236 1237 ok(times_executed == 100, "didn't execute all of the work items\n"); 1238 } 1239 1240 static void CALLBACK signaled_function(PVOID p, BOOLEAN TimerOrWaitFired) 1241 { 1242 HANDLE event = p; 1243 SetEvent(event); 1244 ok(!TimerOrWaitFired, "wait shouldn't have timed out\n"); 1245 } 1246 1247 static void CALLBACK timeout_function(PVOID p, BOOLEAN TimerOrWaitFired) 1248 { 1249 HANDLE event = p; 1250 SetEvent(event); 1251 ok(TimerOrWaitFired, "wait should have timed out\n"); 1252 } 1253 1254 static void test_RegisterWaitForSingleObject(void) 1255 { 1256 BOOL ret; 1257 HANDLE wait_handle; 1258 HANDLE handle; 1259 HANDLE complete_event; 1260 1261 if (!pRegisterWaitForSingleObject || !pUnregisterWait) 1262 { 1263 win_skip("RegisterWaitForSingleObject or UnregisterWait not implemented\n"); 1264 return; 1265 } 1266 1267 /* test signaled case */ 1268 1269 handle = CreateEventW(NULL, TRUE, TRUE, NULL); 1270 complete_event = CreateEventW(NULL, FALSE, FALSE, NULL); 1271 1272 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE); 1273 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError()); 1274 1275 WaitForSingleObject(complete_event, INFINITE); 1276 /* give worker thread chance to complete */ 1277 Sleep(100); 1278 1279 ret = pUnregisterWait(wait_handle); 1280 ok(ret, "UnregisterWait failed with error %d\n", GetLastError()); 1281 1282 /* test cancel case */ 1283 1284 ResetEvent(handle); 1285 1286 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE); 1287 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError()); 1288 1289 ret = pUnregisterWait(wait_handle); 1290 ok(ret, "UnregisterWait failed with error %d\n", GetLastError()); 1291 1292 /* test timeout case */ 1293 1294 ret = pRegisterWaitForSingleObject(&wait_handle, handle, timeout_function, complete_event, 0, WT_EXECUTEONLYONCE); 1295 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError()); 1296 1297 WaitForSingleObject(complete_event, INFINITE); 1298 /* give worker thread chance to complete */ 1299 Sleep(100); 1300 1301 ret = pUnregisterWait(wait_handle); 1302 ok(ret, "UnregisterWait failed with error %d\n", GetLastError()); 1303 1304 SetLastError(0xdeadbeef); 1305 ret = pUnregisterWait(NULL); 1306 ok(!ret, "Expected UnregisterWait to fail\n"); 1307 ok(GetLastError() == ERROR_INVALID_HANDLE, 1308 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 1309 } 1310 1311 static DWORD LS_main; 1312 static DWORD LS_index0, LS_index1; 1313 static DWORD LS_OutOfIndexesValue; 1314 1315 /* Function pointers to the FLS/TLS functions to test in LS_ThreadProc() */ 1316 static DWORD (WINAPI *LS_AllocFunc)(void); 1317 static PVOID (WINAPI *LS_GetValueFunc)(DWORD); 1318 static BOOL (WINAPI *LS_SetValueFunc)(DWORD, PVOID); 1319 static BOOL (WINAPI *LS_FreeFunc)(DWORD); 1320 1321 /* Names of the functions tested in LS_ThreadProc(), for error messages */ 1322 static const char* LS_AllocFuncName = ""; 1323 static const char* LS_GetValueFuncName = ""; 1324 static const char* LS_SetValueFuncName = ""; 1325 static const char* LS_FreeFuncName = ""; 1326 1327 /* FLS entry points, dynamically loaded in platforms that support them */ 1328 static DWORD (WINAPI *pFlsAlloc)(PFLS_CALLBACK_FUNCTION); 1329 static BOOL (WINAPI *pFlsFree)(DWORD); 1330 static PVOID (WINAPI *pFlsGetValue)(DWORD); 1331 static BOOL (WINAPI *pFlsSetValue)(DWORD,PVOID); 1332 1333 /* A thunk function to make FlsAlloc compatible with the signature of TlsAlloc */ 1334 static DWORD WINAPI FLS_AllocFuncThunk(void) 1335 { 1336 return pFlsAlloc(NULL); 1337 } 1338 1339 static DWORD WINAPI LS_InheritanceProc(LPVOID p) 1340 { 1341 /* We should NOT inherit the FLS/TLS values from our parent or from the 1342 main thread. */ 1343 LPVOID val; 1344 1345 val = LS_GetValueFunc(LS_main); 1346 ok(val == NULL, "%s inheritance failed\n", LS_GetValueFuncName); 1347 1348 val = LS_GetValueFunc(LS_index0); 1349 ok(val == NULL, "%s inheritance failed\n", LS_GetValueFuncName); 1350 1351 val = LS_GetValueFunc(LS_index1); 1352 ok(val == NULL, "%s inheritance failed\n", LS_GetValueFuncName); 1353 1354 return 0; 1355 } 1356 1357 /* Basic FLS/TLS usage test. Make sure we can create slots and the values we 1358 store in them are separate among threads. Also test FLS/TLS value 1359 inheritance with LS_InheritanceProc. */ 1360 static DWORD WINAPI LS_ThreadProc(LPVOID p) 1361 { 1362 LONG_PTR id = (LONG_PTR) p; 1363 LPVOID val; 1364 BOOL ret; 1365 1366 if (sync_threads_and_run_one(0, id)) 1367 { 1368 LS_index0 = LS_AllocFunc(); 1369 ok(LS_index0 != LS_OutOfIndexesValue, "%s failed\n", LS_AllocFuncName); 1370 } 1371 resync_after_run(); 1372 1373 if (sync_threads_and_run_one(1, id)) 1374 { 1375 LS_index1 = LS_AllocFunc(); 1376 ok(LS_index1 != LS_OutOfIndexesValue, "%s failed\n", LS_AllocFuncName); 1377 1378 /* Slot indices should be different even if created in different 1379 threads. */ 1380 ok(LS_index0 != LS_index1, "%s failed\n", LS_AllocFuncName); 1381 1382 /* Both slots should be initialized to NULL */ 1383 val = LS_GetValueFunc(LS_index0); 1384 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName); 1385 ok(val == NULL, "Slot not initialized correctly\n"); 1386 1387 val = LS_GetValueFunc(LS_index1); 1388 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName); 1389 ok(val == NULL, "Slot not initialized correctly\n"); 1390 } 1391 resync_after_run(); 1392 1393 if (sync_threads_and_run_one(0, id)) 1394 { 1395 val = LS_GetValueFunc(LS_index0); 1396 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName); 1397 ok(val == NULL, "Slot not initialized correctly\n"); 1398 1399 val = LS_GetValueFunc(LS_index1); 1400 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName); 1401 ok(val == NULL, "Slot not initialized correctly\n"); 1402 1403 ret = LS_SetValueFunc(LS_index0, (LPVOID) 1); 1404 ok(ret, "%s failed\n", LS_SetValueFuncName); 1405 1406 ret = LS_SetValueFunc(LS_index1, (LPVOID) 2); 1407 ok(ret, "%s failed\n", LS_SetValueFuncName); 1408 1409 val = LS_GetValueFunc(LS_index0); 1410 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName); 1411 ok(val == (LPVOID) 1, "Slot not initialized correctly\n"); 1412 1413 val = LS_GetValueFunc(LS_index1); 1414 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName); 1415 ok(val == (LPVOID) 2, "Slot not initialized correctly\n"); 1416 } 1417 resync_after_run(); 1418 1419 if (sync_threads_and_run_one(1, id)) 1420 { 1421 val = LS_GetValueFunc(LS_index0); 1422 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName); 1423 ok(val == NULL, "Slot not initialized correctly\n"); 1424 1425 val = LS_GetValueFunc(LS_index1); 1426 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName); 1427 ok(val == NULL, "Slot not initialized correctly\n"); 1428 1429 ret = LS_SetValueFunc(LS_index0, (LPVOID) 3); 1430 ok(ret, "%s failed\n", LS_SetValueFuncName); 1431 1432 ret = LS_SetValueFunc(LS_index1, (LPVOID) 4); 1433 ok(ret, "%s failed\n", LS_SetValueFuncName); 1434 1435 val = LS_GetValueFunc(LS_index0); 1436 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName); 1437 ok(val == (LPVOID) 3, "Slot not initialized correctly\n"); 1438 1439 val = LS_GetValueFunc(LS_index1); 1440 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName); 1441 ok(val == (LPVOID) 4, "Slot not initialized correctly\n"); 1442 } 1443 resync_after_run(); 1444 1445 if (sync_threads_and_run_one(0, id)) 1446 { 1447 HANDLE thread; 1448 DWORD waitret, tid; 1449 1450 val = LS_GetValueFunc(LS_index0); 1451 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName); 1452 ok(val == (LPVOID) 1, "Slot not initialized correctly\n"); 1453 1454 val = LS_GetValueFunc(LS_index1); 1455 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName); 1456 ok(val == (LPVOID) 2, "Slot not initialized correctly\n"); 1457 1458 thread = CreateThread(NULL, 0, LS_InheritanceProc, 0, 0, &tid); 1459 ok(thread != NULL, "CreateThread failed\n"); 1460 waitret = WaitForSingleObject(thread, 60000); 1461 ok(waitret == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 1462 CloseHandle(thread); 1463 1464 ret = LS_FreeFunc(LS_index0); 1465 ok(ret, "%s failed\n", LS_FreeFuncName); 1466 } 1467 resync_after_run(); 1468 1469 if (sync_threads_and_run_one(1, id)) 1470 { 1471 ret = LS_FreeFunc(LS_index1); 1472 ok(ret, "%s failed\n", LS_FreeFuncName); 1473 } 1474 resync_after_run(); 1475 1476 return 0; 1477 } 1478 1479 static void run_LS_tests(void) 1480 { 1481 HANDLE threads[2]; 1482 LONG_PTR i; 1483 DWORD ret; 1484 BOOL suc; 1485 1486 init_thread_sync_helpers(); 1487 1488 /* Allocate a slot in the main thread to test for inheritance. */ 1489 LS_main = LS_AllocFunc(); 1490 ok(LS_main != LS_OutOfIndexesValue, "%s failed\n", LS_AllocFuncName); 1491 suc = LS_SetValueFunc(LS_main, (LPVOID) 4114); 1492 ok(suc, "%s failed\n", LS_SetValueFuncName); 1493 1494 for (i = 0; i < 2; ++i) 1495 { 1496 DWORD tid; 1497 1498 threads[i] = CreateThread(NULL, 0, LS_ThreadProc, (LPVOID) i, 0, &tid); 1499 ok(threads[i] != NULL, "CreateThread failed\n"); 1500 } 1501 1502 ret = WaitForMultipleObjects(2, threads, TRUE, 60000); 1503 ok(ret == WAIT_OBJECT_0 || broken(ret == WAIT_OBJECT_0+1 /* nt4,w2k */), "WaitForAllObjects 2 threads %d\n",ret); 1504 1505 for (i = 0; i < 2; ++i) 1506 CloseHandle(threads[i]); 1507 1508 suc = LS_FreeFunc(LS_main); 1509 ok(suc, "%s failed\n", LS_FreeFuncName); 1510 cleanup_thread_sync_helpers(); 1511 } 1512 1513 static void test_TLS(void) 1514 { 1515 LS_OutOfIndexesValue = TLS_OUT_OF_INDEXES; 1516 1517 LS_AllocFunc = &TlsAlloc; 1518 LS_GetValueFunc = &TlsGetValue; 1519 LS_SetValueFunc = &TlsSetValue; 1520 LS_FreeFunc = &TlsFree; 1521 1522 LS_AllocFuncName = "TlsAlloc"; 1523 LS_GetValueFuncName = "TlsGetValue"; 1524 LS_SetValueFuncName = "TlsSetValue"; 1525 LS_FreeFuncName = "TlsFree"; 1526 1527 run_LS_tests(); 1528 } 1529 1530 static void test_FLS(void) 1531 { 1532 if (!pFlsAlloc || !pFlsFree || !pFlsGetValue || !pFlsSetValue) 1533 { 1534 win_skip("Fiber Local Storage not supported\n"); 1535 return; 1536 } 1537 1538 LS_OutOfIndexesValue = FLS_OUT_OF_INDEXES; 1539 1540 LS_AllocFunc = &FLS_AllocFuncThunk; 1541 LS_GetValueFunc = pFlsGetValue; 1542 LS_SetValueFunc = pFlsSetValue; 1543 LS_FreeFunc = pFlsFree; 1544 1545 LS_AllocFuncName = "FlsAlloc"; 1546 LS_GetValueFuncName = "FlsGetValue"; 1547 LS_SetValueFuncName = "FlsSetValue"; 1548 LS_FreeFuncName = "FlsFree"; 1549 1550 run_LS_tests(); 1551 } 1552 1553 static void test_ThreadErrorMode(void) 1554 { 1555 DWORD oldmode; 1556 DWORD mode; 1557 DWORD rtlmode; 1558 BOOL ret; 1559 1560 if (!pSetThreadErrorMode || !pGetThreadErrorMode) 1561 { 1562 win_skip("SetThreadErrorMode and/or GetThreadErrorMode unavailable (added in Windows 7)\n"); 1563 return; 1564 } 1565 1566 if (!pRtlGetThreadErrorMode) { 1567 win_skip("RtlGetThreadErrorMode not available\n"); 1568 return; 1569 } 1570 1571 oldmode = pGetThreadErrorMode(); 1572 1573 ret = pSetThreadErrorMode(0, &mode); 1574 ok(ret, "SetThreadErrorMode failed\n"); 1575 ok(mode == oldmode, 1576 "SetThreadErrorMode returned old mode 0x%x, expected 0x%x\n", 1577 mode, oldmode); 1578 mode = pGetThreadErrorMode(); 1579 ok(mode == 0, "GetThreadErrorMode returned mode 0x%x, expected 0\n", mode); 1580 rtlmode = pRtlGetThreadErrorMode(); 1581 ok(rtlmode == 0, 1582 "RtlGetThreadErrorMode returned mode 0x%x, expected 0\n", mode); 1583 1584 ret = pSetThreadErrorMode(SEM_FAILCRITICALERRORS, &mode); 1585 ok(ret, "SetThreadErrorMode failed\n"); 1586 ok(mode == 0, 1587 "SetThreadErrorMode returned old mode 0x%x, expected 0\n", mode); 1588 mode = pGetThreadErrorMode(); 1589 ok(mode == SEM_FAILCRITICALERRORS, 1590 "GetThreadErrorMode returned mode 0x%x, expected SEM_FAILCRITICALERRORS\n", 1591 mode); 1592 rtlmode = pRtlGetThreadErrorMode(); 1593 ok(rtlmode == 0x10, 1594 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x10\n", mode); 1595 1596 ret = pSetThreadErrorMode(SEM_NOGPFAULTERRORBOX, &mode); 1597 ok(ret, "SetThreadErrorMode failed\n"); 1598 ok(mode == SEM_FAILCRITICALERRORS, 1599 "SetThreadErrorMode returned old mode 0x%x, expected SEM_FAILCRITICALERRORS\n", 1600 mode); 1601 mode = pGetThreadErrorMode(); 1602 ok(mode == SEM_NOGPFAULTERRORBOX, 1603 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOGPFAULTERRORBOX\n", 1604 mode); 1605 rtlmode = pRtlGetThreadErrorMode(); 1606 ok(rtlmode == 0x20, 1607 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x20\n", mode); 1608 1609 ret = pSetThreadErrorMode(SEM_NOOPENFILEERRORBOX, NULL); 1610 ok(ret, "SetThreadErrorMode failed\n"); 1611 mode = pGetThreadErrorMode(); 1612 ok(mode == SEM_NOOPENFILEERRORBOX, 1613 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOOPENFILEERRORBOX\n", 1614 mode); 1615 rtlmode = pRtlGetThreadErrorMode(); 1616 ok(rtlmode == 0x40, 1617 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x40\n", rtlmode); 1618 1619 for (mode = 1; mode; mode <<= 1) 1620 { 1621 ret = pSetThreadErrorMode(mode, NULL); 1622 if (mode & (SEM_FAILCRITICALERRORS | 1623 SEM_NOGPFAULTERRORBOX | 1624 SEM_NOOPENFILEERRORBOX)) 1625 { 1626 ok(ret, 1627 "SetThreadErrorMode(0x%x,NULL) failed with error %d\n", 1628 mode, GetLastError()); 1629 } 1630 else 1631 { 1632 DWORD GLE = GetLastError(); 1633 ok(!ret, 1634 "SetThreadErrorMode(0x%x,NULL) succeeded, expected failure\n", 1635 mode); 1636 ok(GLE == ERROR_INVALID_PARAMETER, 1637 "SetThreadErrorMode(0x%x,NULL) failed with %d, " 1638 "expected ERROR_INVALID_PARAMETER\n", 1639 mode, GLE); 1640 } 1641 } 1642 1643 pSetThreadErrorMode(oldmode, NULL); 1644 } 1645 1646 #if (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) || (defined(_MSC_VER) && defined(__i386__)) 1647 static inline void set_fpu_cw(WORD cw) 1648 { 1649 #ifdef _MSC_VER 1650 __asm { fnclex } 1651 __asm { fldcw [cw] } 1652 #else 1653 __asm__ volatile ("fnclex; fldcw %0" : : "m" (cw)); 1654 #endif 1655 } 1656 1657 static inline WORD get_fpu_cw(void) 1658 { 1659 WORD cw = 0; 1660 #ifdef _MSC_VER 1661 __asm { fnstcw [cw] } 1662 #else 1663 __asm__ volatile ("fnstcw %0" : "=m" (cw)); 1664 #endif 1665 return cw; 1666 } 1667 1668 struct fpu_thread_ctx 1669 { 1670 WORD cw; 1671 HANDLE finished; 1672 }; 1673 1674 static DWORD WINAPI fpu_thread(void *param) 1675 { 1676 struct fpu_thread_ctx *ctx = param; 1677 BOOL ret; 1678 1679 ctx->cw = get_fpu_cw(); 1680 1681 ret = SetEvent(ctx->finished); 1682 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError()); 1683 1684 return 0; 1685 } 1686 1687 static WORD get_thread_fpu_cw(void) 1688 { 1689 struct fpu_thread_ctx ctx; 1690 DWORD tid, res; 1691 HANDLE thread; 1692 1693 ctx.finished = CreateEventW(NULL, FALSE, FALSE, NULL); 1694 ok(!!ctx.finished, "Failed to create event, last error %#x.\n", GetLastError()); 1695 1696 thread = CreateThread(NULL, 0, fpu_thread, &ctx, 0, &tid); 1697 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError()); 1698 1699 res = WaitForSingleObject(ctx.finished, INFINITE); 1700 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError()); 1701 1702 res = CloseHandle(ctx.finished); 1703 ok(!!res, "Failed to close event handle, last error %#x.\n", GetLastError()); 1704 1705 return ctx.cw; 1706 } 1707 1708 static void test_thread_fpu_cw(void) 1709 { 1710 WORD initial_cw, cw; 1711 1712 initial_cw = get_fpu_cw(); 1713 ok(initial_cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", initial_cw); 1714 1715 cw = get_thread_fpu_cw(); 1716 ok(cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", cw); 1717 1718 set_fpu_cw(0xf60); 1719 cw = get_fpu_cw(); 1720 ok(cw == 0xf60, "Expected FPU control word 0xf60, got %#x.\n", cw); 1721 1722 cw = get_thread_fpu_cw(); 1723 ok(cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", cw); 1724 1725 cw = get_fpu_cw(); 1726 ok(cw == 0xf60, "Expected FPU control word 0xf60, got %#x.\n", cw); 1727 1728 set_fpu_cw(initial_cw); 1729 cw = get_fpu_cw(); 1730 ok(cw == initial_cw, "Expected FPU control word %#x, got %#x.\n", initial_cw, cw); 1731 } 1732 #endif 1733 1734 static const char manifest_dep[] = 1735 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">" 1736 "<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH "\"/>" 1737 " <file name=\"testdep.dll\" />" 1738 "</assembly>"; 1739 1740 static const char manifest_main[] = 1741 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">" 1742 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />" 1743 "<dependency>" 1744 " <dependentAssembly>" 1745 " <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH "\" />" 1746 " </dependentAssembly>" 1747 "</dependency>" 1748 "</assembly>"; 1749 1750 static void create_manifest_file(const char *filename, const char *manifest) 1751 { 1752 WCHAR path[MAX_PATH]; 1753 HANDLE file; 1754 DWORD size; 1755 1756 MultiByteToWideChar( CP_ACP, 0, filename, -1, path, MAX_PATH ); 1757 file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 1758 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError()); 1759 WriteFile(file, manifest, strlen(manifest), &size, NULL); 1760 CloseHandle(file); 1761 } 1762 1763 static HANDLE test_create(const char *file) 1764 { 1765 WCHAR path[MAX_PATH]; 1766 ACTCTXW actctx; 1767 HANDLE handle; 1768 1769 MultiByteToWideChar(CP_ACP, 0, file, -1, path, MAX_PATH); 1770 memset(&actctx, 0, sizeof(ACTCTXW)); 1771 actctx.cbSize = sizeof(ACTCTXW); 1772 actctx.lpSource = path; 1773 1774 handle = pCreateActCtxW(&actctx); 1775 ok(handle != INVALID_HANDLE_VALUE, "failed to create context, error %u\n", GetLastError()); 1776 1777 ok(actctx.cbSize == sizeof(actctx), "cbSize=%d\n", actctx.cbSize); 1778 ok(actctx.dwFlags == 0, "dwFlags=%d\n", actctx.dwFlags); 1779 ok(actctx.lpSource == path, "lpSource=%p\n", actctx.lpSource); 1780 ok(actctx.wProcessorArchitecture == 0, "wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture); 1781 ok(actctx.wLangId == 0, "wLangId=%d\n", actctx.wLangId); 1782 ok(actctx.lpAssemblyDirectory == NULL, "lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory); 1783 ok(actctx.lpResourceName == NULL, "lpResourceName=%p\n", actctx.lpResourceName); 1784 ok(actctx.lpApplicationName == NULL, "lpApplicationName=%p\n", actctx.lpApplicationName); 1785 ok(actctx.hModule == NULL, "hModule=%p\n", actctx.hModule); 1786 1787 return handle; 1788 } 1789 1790 static void test_thread_actctx(void) 1791 { 1792 struct thread_actctx_param param; 1793 HANDLE thread, handle, context; 1794 ULONG_PTR cookie; 1795 DWORD tid, ret; 1796 BOOL b; 1797 1798 if (!pActivateActCtx) 1799 { 1800 win_skip("skipping activation context tests\n"); 1801 return; 1802 } 1803 1804 create_manifest_file("testdep1.manifest", manifest_dep); 1805 create_manifest_file("main.manifest", manifest_main); 1806 1807 context = test_create("main.manifest"); 1808 DeleteFileA("testdep1.manifest"); 1809 DeleteFileA("main.manifest"); 1810 1811 handle = (void*)0xdeadbeef; 1812 b = pGetCurrentActCtx(&handle); 1813 ok(b, "GetCurrentActCtx failed: %u\n", GetLastError()); 1814 ok(handle == 0, "active context %p\n", handle); 1815 1816 /* without active context */ 1817 param.thread_context = (void*)0xdeadbeef; 1818 param.handle = NULL; 1819 thread = CreateThread(NULL, 0, thread_actctx_func, ¶m, 0, &tid); 1820 ok(thread != NULL, "failed, got %u\n", GetLastError()); 1821 1822 ret = WaitForSingleObject(thread, 1000); 1823 ok(ret == WAIT_OBJECT_0, "wait timeout\n"); 1824 ok(param.thread_context == NULL, "got wrong thread context %p\n", param.thread_context); 1825 CloseHandle(thread); 1826 1827 b = pActivateActCtx(context, &cookie); 1828 ok(b, "activation failed: %u\n", GetLastError()); 1829 1830 handle = 0; 1831 b = pGetCurrentActCtx(&handle); 1832 ok(b, "GetCurrentActCtx failed: %u\n", GetLastError()); 1833 ok(handle != 0, "no active context\n"); 1834 pReleaseActCtx(handle); 1835 1836 param.handle = NULL; 1837 b = pGetCurrentActCtx(¶m.handle); 1838 ok(b && param.handle != NULL, "failed to get context, %u\n", GetLastError()); 1839 1840 param.thread_context = (void*)0xdeadbeef; 1841 thread = CreateThread(NULL, 0, thread_actctx_func, ¶m, 0, &tid); 1842 ok(thread != NULL, "failed, got %u\n", GetLastError()); 1843 1844 ret = WaitForSingleObject(thread, 1000); 1845 ok(ret == WAIT_OBJECT_0, "wait timeout\n"); 1846 ok(param.thread_context == context, "got wrong thread context %p, %p\n", param.thread_context, context); 1847 pReleaseActCtx(param.thread_context); 1848 CloseHandle(thread); 1849 1850 /* similar test for CreateRemoteThread() */ 1851 param.thread_context = (void*)0xdeadbeef; 1852 thread = CreateRemoteThread(GetCurrentProcess(), NULL, 0, thread_actctx_func, ¶m, 0, &tid); 1853 ok(thread != NULL, "failed, got %u\n", GetLastError()); 1854 1855 ret = WaitForSingleObject(thread, 1000); 1856 ok(ret == WAIT_OBJECT_0, "wait timeout\n"); 1857 ok(param.thread_context == context, "got wrong thread context %p, %p\n", param.thread_context, context); 1858 pReleaseActCtx(param.thread_context); 1859 CloseHandle(thread); 1860 1861 pReleaseActCtx(param.handle); 1862 1863 b = pDeactivateActCtx(0, cookie); 1864 ok(b, "DeactivateActCtx failed: %u\n", GetLastError()); 1865 pReleaseActCtx(context); 1866 } 1867 1868 1869 static void WINAPI threadpool_workcallback(PTP_CALLBACK_INSTANCE instance, void *context, PTP_WORK work) { 1870 int *foo = (int*)context; 1871 1872 (*foo)++; 1873 } 1874 1875 1876 static void test_threadpool(void) 1877 { 1878 PTP_POOL pool; 1879 PTP_WORK work; 1880 int workcalled = 0; 1881 1882 if (!pCreateThreadpool) { 1883 win_skip("thread pool apis not supported.\n"); 1884 return; 1885 } 1886 1887 work = pCreateThreadpoolWork(threadpool_workcallback, &workcalled, NULL); 1888 ok (work != NULL, "Error %d in CreateThreadpoolWork\n", GetLastError()); 1889 pSubmitThreadpoolWork(work); 1890 pWaitForThreadpoolWorkCallbacks(work, FALSE); 1891 pCloseThreadpoolWork(work); 1892 1893 ok (workcalled == 1, "expected work to be called once, got %d\n", workcalled); 1894 1895 pool = pCreateThreadpool(NULL); 1896 ok (pool != NULL, "CreateThreadpool failed\n"); 1897 pCloseThreadpool(pool); 1898 } 1899 1900 static void test_reserved_tls(void) 1901 { 1902 void *val; 1903 DWORD tls; 1904 BOOL ret; 1905 1906 /* This seems to be a WinXP SP2+ feature. */ 1907 if(!pIsWow64Process) { 1908 win_skip("Skipping reserved TLS slot on too old Windows.\n"); 1909 return; 1910 } 1911 1912 val = TlsGetValue(0); 1913 ok(!val, "TlsGetValue(0) = %p\n", val); 1914 1915 /* Also make sure that there is a TLS allocated. */ 1916 tls = TlsAlloc(); 1917 ok(tls && tls != TLS_OUT_OF_INDEXES, "tls = %x\n", tls); 1918 TlsSetValue(tls, (void*)1); 1919 1920 val = TlsGetValue(0); 1921 ok(!val, "TlsGetValue(0) = %p\n", val); 1922 1923 TlsFree(tls); 1924 1925 /* The following is too ugly to be run by default */ 1926 if(0) { 1927 /* Set TLS index 0 value and see that this works and doesn't cause problems 1928 * for remaining tests. */ 1929 ret = TlsSetValue(0, (void*)1); 1930 ok(ret, "TlsSetValue(0, 1) failed: %u\n", GetLastError()); 1931 1932 val = TlsGetValue(0); 1933 ok(val == (void*)1, "TlsGetValue(0) = %p\n", val); 1934 } 1935 } 1936 1937 static void test_thread_info(void) 1938 { 1939 char buf[4096]; 1940 static const ULONG info_size[] = 1941 { 1942 sizeof(THREAD_BASIC_INFORMATION), /* ThreadBasicInformation */ 1943 sizeof(KERNEL_USER_TIMES), /* ThreadTimes */ 1944 sizeof(ULONG), /* ThreadPriority */ 1945 sizeof(ULONG), /* ThreadBasePriority */ 1946 sizeof(ULONG_PTR), /* ThreadAffinityMask */ 1947 sizeof(HANDLE), /* ThreadImpersonationToken */ 1948 sizeof(THREAD_DESCRIPTOR_INFORMATION), /* ThreadDescriptorTableEntry */ 1949 sizeof(BOOLEAN), /* ThreadEnableAlignmentFaultFixup */ 1950 0, /* ThreadEventPair_Reusable */ 1951 sizeof(ULONG_PTR), /* ThreadQuerySetWin32StartAddress */ 1952 sizeof(ULONG), /* ThreadZeroTlsCell */ 1953 sizeof(LARGE_INTEGER), /* ThreadPerformanceCount */ 1954 sizeof(ULONG), /* ThreadAmILastThread */ 1955 sizeof(ULONG), /* ThreadIdealProcessor */ 1956 sizeof(ULONG), /* ThreadPriorityBoost */ 1957 sizeof(ULONG_PTR), /* ThreadSetTlsArrayAddress */ 1958 sizeof(ULONG), /* ThreadIsIoPending */ 1959 sizeof(BOOLEAN), /* ThreadHideFromDebugger */ 1960 /* FIXME: Add remaining classes */ 1961 }; 1962 HANDLE thread; 1963 ULONG i, status, ret_len; 1964 1965 if (!pOpenThread) 1966 { 1967 win_skip("OpenThread is not available on this platform\n"); 1968 return; 1969 } 1970 1971 if (!pNtQueryInformationThread) 1972 { 1973 win_skip("NtQueryInformationThread is not available on this platform\n"); 1974 return; 1975 } 1976 1977 thread = pOpenThread(THREAD_QUERY_LIMITED_INFORMATION, FALSE, GetCurrentThreadId()); 1978 if (!thread) 1979 { 1980 win_skip("THREAD_QUERY_LIMITED_INFORMATION is not supported on this platform\n"); 1981 return; 1982 } 1983 1984 for (i = 0; i < sizeof(info_size)/sizeof(info_size[0]); i++) 1985 { 1986 memset(buf, 0, sizeof(buf)); 1987 1988 #ifdef __i386__ 1989 if (i == ThreadDescriptorTableEntry) 1990 { 1991 CONTEXT ctx; 1992 THREAD_DESCRIPTOR_INFORMATION *tdi = (void *)buf; 1993 1994 ctx.ContextFlags = CONTEXT_SEGMENTS; 1995 GetThreadContext(GetCurrentThread(), &ctx); 1996 tdi->Selector = ctx.SegDs; 1997 } 1998 #endif 1999 ret_len = 0; 2000 status = pNtQueryInformationThread(thread, i, buf, info_size[i], &ret_len); 2001 if (status == STATUS_NOT_IMPLEMENTED) continue; 2002 if (status == STATUS_INVALID_INFO_CLASS) continue; 2003 if (status == STATUS_UNSUCCESSFUL) continue; 2004 2005 switch (i) 2006 { 2007 case ThreadBasicInformation: 2008 case ThreadAmILastThread: 2009 case ThreadPriorityBoost: 2010 ok(status == STATUS_SUCCESS, "for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i, status, ret_len); 2011 break; 2012 2013 #ifdef __i386__ 2014 case ThreadDescriptorTableEntry: 2015 ok(status == STATUS_SUCCESS || broken(status == STATUS_ACCESS_DENIED) /* testbot VM is broken */, 2016 "for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i, status, ret_len); 2017 break; 2018 #endif 2019 2020 case ThreadTimes: 2021 todo_wine 2022 ok(status == STATUS_SUCCESS, "for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i, status, ret_len); 2023 break; 2024 2025 case ThreadAffinityMask: 2026 case ThreadQuerySetWin32StartAddress: 2027 case ThreadIsIoPending: 2028 todo_wine 2029 ok(status == STATUS_ACCESS_DENIED, "for info %u expected STATUS_ACCESS_DENIED, got %08x (ret_len %u)\n", i, status, ret_len); 2030 break; 2031 2032 default: 2033 ok(status == STATUS_ACCESS_DENIED, "for info %u expected STATUS_ACCESS_DENIED, got %08x (ret_len %u)\n", i, status, ret_len); 2034 break; 2035 } 2036 } 2037 2038 CloseHandle(thread); 2039 } 2040 2041 static void init_funcs(void) 2042 { 2043 HMODULE hKernel32 = GetModuleHandleA("kernel32.dll"); 2044 HMODULE ntdll = GetModuleHandleA("ntdll.dll"); 2045 2046 /* Neither Cygwin nor mingW export OpenThread, so do a dynamic check 2047 so that the compile passes */ 2048 2049 #define X(f) p##f = (void*)GetProcAddress(hKernel32, #f) 2050 X(GetThreadPriorityBoost); 2051 X(OpenThread); 2052 X(QueueUserWorkItem); 2053 X(SetThreadIdealProcessor); 2054 X(SetThreadPriorityBoost); 2055 X(RegisterWaitForSingleObject); 2056 X(UnregisterWait); 2057 X(IsWow64Process); 2058 X(SetThreadErrorMode); 2059 X(GetThreadErrorMode); 2060 X(ActivateActCtx); 2061 X(CreateActCtxW); 2062 X(DeactivateActCtx); 2063 X(GetCurrentActCtx); 2064 X(ReleaseActCtx); 2065 2066 X(CreateThreadpool); 2067 X(CloseThreadpool); 2068 X(CreateThreadpoolWork); 2069 X(SubmitThreadpoolWork); 2070 X(WaitForThreadpoolWorkCallbacks); 2071 X(CloseThreadpoolWork); 2072 2073 X(GetThreadGroupAffinity); 2074 X(SetThreadGroupAffinity); 2075 2076 X(FlsAlloc); 2077 X(FlsFree); 2078 X(FlsSetValue); 2079 X(FlsGetValue); 2080 #undef X 2081 2082 #define X(f) p##f = (void*)GetProcAddress(ntdll, #f) 2083 if (ntdll) 2084 { 2085 X(NtQueryInformationThread); 2086 X(RtlGetThreadErrorMode); 2087 X(NtSetInformationThread); 2088 X(NtSetLdtEntries); 2089 } 2090 #undef X 2091 } 2092 2093 START_TEST(thread) 2094 { 2095 int argc; 2096 char **argv; 2097 argc = winetest_get_mainargs( &argv ); 2098 2099 init_funcs(); 2100 2101 if (argc >= 3) 2102 { 2103 if (!strcmp(argv[2], "sleep")) 2104 { 2105 HANDLE hAddrEvents[2]; 2106 create_function_addr_events(hAddrEvents); 2107 SetEvent(hAddrEvents[0]); 2108 SetEvent(hAddrEvents[1]); 2109 Sleep(5000); /* spawned process runs for at most 5 seconds */ 2110 return; 2111 } 2112 while (1) 2113 { 2114 HANDLE hThread; 2115 DWORD tid; 2116 hThread = CreateThread(NULL, 0, threadFunc2, NULL, 0, &tid); 2117 ok(hThread != NULL, "CreateThread failed, error %u\n", 2118 GetLastError()); 2119 ok(WaitForSingleObject(hThread, 200) == WAIT_OBJECT_0, 2120 "Thread did not exit in time\n"); 2121 if (hThread == NULL) break; 2122 CloseHandle(hThread); 2123 } 2124 return; 2125 } 2126 2127 test_thread_info(); 2128 test_reserved_tls(); 2129 test_CreateRemoteThread(); 2130 test_CreateThread_basic(); 2131 test_CreateThread_suspended(); 2132 test_SuspendThread(); 2133 test_TerminateThread(); 2134 test_CreateThread_stack(); 2135 test_thread_priority(); 2136 test_GetThreadTimes(); 2137 test_thread_processor(); 2138 test_GetThreadExitCode(); 2139 #ifdef __i386__ 2140 test_SetThreadContext(); 2141 test_GetThreadSelectorEntry(); 2142 test_NtSetLdtEntries(); 2143 #endif 2144 test_QueueUserWorkItem(); 2145 test_RegisterWaitForSingleObject(); 2146 test_TLS(); 2147 test_FLS(); 2148 test_ThreadErrorMode(); 2149 #if (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) || (defined(_MSC_VER) && defined(__i386__)) 2150 test_thread_fpu_cw(); 2151 #endif 2152 test_thread_actctx(); 2153 2154 test_threadpool(); 2155 } 2156