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