2 * Unit test suite for thread functions.
4 * Copyright 2002 Geoffrey Hausheer
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.
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.
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
21 /* Define _WIN32_WINNT to get SetThreadIdealProcessor on Windows */
22 #define _WIN32_WINNT 0x0500
28 #include "wine/test.h"
34 /* Specify the number of simultaneous threads to test */
36 /* Specify whether to test the extended priorities for Win2k/XP */
37 #define USE_EXTENDED_PRIORITIES 0
38 /* Specify whether to test the stack allocation in CreateThread */
41 /* Set CHECK_STACK to 1 if you want to try to test the stack-limit from
42 CreateThread. So far I have been unable to make this work, and
43 I am in doubt as to how portable it is. Also, according to MSDN,
44 you shouldn't mix C-run-time-libraries (i.e. alloca) with CreateThread.
45 Anyhow, the check is currently commented out
50 # define __EXCEPT __except
53 # include "wine/exception.h"
57 static BOOL (WINAPI *pGetThreadPriorityBoost)(HANDLE,PBOOL);
58 static HANDLE (WINAPI *pOpenThread)(DWORD,BOOL,DWORD);
59 static BOOL (WINAPI *pQueueUserWorkItem)(LPTHREAD_START_ROUTINE,PVOID,ULONG);
60 static DWORD (WINAPI *pSetThreadIdealProcessor)(HANDLE,DWORD);
61 static BOOL (WINAPI *pSetThreadPriorityBoost)(HANDLE,BOOL);
62 static BOOL (WINAPI *pRegisterWaitForSingleObject)(PHANDLE,HANDLE,WAITORTIMERCALLBACK,PVOID,ULONG,ULONG);
63 static BOOL (WINAPI *pUnregisterWait)(HANDLE);
64 static BOOL (WINAPI *pIsWow64Process)(HANDLE,PBOOL);
65 static BOOL (WINAPI *pSetThreadErrorMode)(DWORD,PDWORD);
66 static DWORD (WINAPI *pGetThreadErrorMode)(void);
67 static DWORD (WINAPI *pRtlGetThreadErrorMode)(void);
69 static HANDLE create_target_process(const char *arg)
72 char cmdline[MAX_PATH];
73 PROCESS_INFORMATION pi;
74 STARTUPINFO si = { 0 };
77 winetest_get_mainargs( &argv );
78 sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
79 ok(CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL,
80 &si, &pi) != 0, "error: %u\n", GetLastError());
81 ok(CloseHandle(pi.hThread) != 0, "error %u\n", GetLastError());
85 /* Functions not tested yet:
90 In addition there are no checks that the inheritance works properly in
94 /* Functions to ensure that from a group of threads, only one executes
95 certain chunks of code at a time, and we know which one is executing
96 it. It basically makes multithreaded execution linear, which defeats
97 the purpose of multiple threads, but makes testing easy. */
98 static HANDLE start_event, stop_event;
99 static LONG num_synced;
101 static void init_thread_sync_helpers(void)
103 start_event = CreateEvent(NULL, TRUE, FALSE, NULL);
104 ok(start_event != NULL, "CreateEvent failed\n");
105 stop_event = CreateEvent(NULL, TRUE, FALSE, NULL);
106 ok(stop_event != NULL, "CreateEvent failed\n");
110 static BOOL sync_threads_and_run_one(DWORD sync_id, DWORD my_id)
112 LONG num = InterlockedIncrement(&num_synced);
113 assert(-1 <= num && num <= 1);
116 ResetEvent( stop_event );
117 SetEvent( start_event );
121 DWORD ret = WaitForSingleObject(start_event, 10000);
122 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed %x\n",ret);
124 return sync_id == my_id;
127 static void resync_after_run(void)
129 LONG num = InterlockedDecrement(&num_synced);
130 assert(-1 <= num && num <= 1);
133 ResetEvent( start_event );
134 SetEvent( stop_event );
138 DWORD ret = WaitForSingleObject(stop_event, 10000);
139 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
143 static void cleanup_thread_sync_helpers(void)
145 CloseHandle(start_event);
146 CloseHandle(stop_event);
157 /* WinME supports OpenThread but doesn't know about access restrictions so
158 we require them to be either completely ignored or always obeyed.
160 INT obeying_ars = 0; /* -1 == no, 0 == dunno yet, 1 == yes */
164 ? (obeying_ars = +1) \
165 : ((obeying_ars = -1), \
166 trace("not restricted, assuming consistent behaviour\n"))) \
167 : (obeying_ars < 0) \
168 ? ok(!(x), "access restrictions obeyed\n") \
169 : ok( (x), "access restrictions not obeyed\n"))
171 /* Basic test that simultaneous threads can access shared memory,
172 that the thread local storage routines work correctly, and that
173 threads actually run concurrently
175 static DWORD WINAPI threadFunc1(LPVOID p)
177 t1Struct *tstruct = p;
179 /* write our thread # into shared memory */
180 tstruct->threadmem[tstruct->threadnum]=GetCurrentThreadId();
181 ok(TlsSetValue(tlsIndex,(LPVOID)(INT_PTR)(tstruct->threadnum+1))!=0,
182 "TlsSetValue failed\n");
183 /* The threads synchronize before terminating. This is done by
184 Signaling an event, and waiting for all events to occur
186 SetEvent(tstruct->event[tstruct->threadnum]);
187 WaitForMultipleObjects(NUM_THREADS,tstruct->event,TRUE,INFINITE);
188 /* Double check that all threads really did run by validating that
189 they have all written to the shared memory. There should be no race
190 here, since all threads were synchronized after the write.*/
191 for(i=0;i<NUM_THREADS;i++) {
192 while(tstruct->threadmem[i]==0) ;
195 /* lstrlenA contains an exception handler so this makes sure exceptions work in threads */
196 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
198 /* Check that no one changed our tls memory */
199 ok((INT_PTR)TlsGetValue(tlsIndex)-1==tstruct->threadnum,
200 "TlsGetValue failed\n");
201 return NUM_THREADS+tstruct->threadnum;
204 static DWORD WINAPI threadFunc2(LPVOID p)
209 static DWORD WINAPI threadFunc3(LPVOID p)
212 thread=GetCurrentThread();
213 SuspendThread(thread);
217 static DWORD WINAPI threadFunc4(LPVOID p)
228 static DWORD WINAPI threadFunc5(LPVOID p)
232 sysInfo.dwPageSize=0;
233 GetSystemInfo(&sysInfo);
237 alloca(2*sysInfo.dwPageSize);
247 static DWORD WINAPI threadFunc_SetEvent(LPVOID p)
253 static DWORD WINAPI threadFunc_CloseHandle(LPVOID p)
259 static void create_function_addr_events(HANDLE events[2])
263 sprintf(buffer, "threadFunc_SetEvent %p", threadFunc_SetEvent);
264 events[0] = CreateEvent(NULL, FALSE, FALSE, buffer);
266 sprintf(buffer, "threadFunc_CloseHandle %p", threadFunc_CloseHandle);
267 events[1] = CreateEvent(NULL, FALSE, FALSE, buffer);
270 /* check CreateRemoteThread */
271 static VOID test_CreateRemoteThread(void)
273 HANDLE hProcess, hThread, hEvent, hRemoteEvent;
274 DWORD tid, ret, exitcode;
275 HANDLE hAddrEvents[2];
277 hProcess = create_target_process("sleep");
278 ok(hProcess != NULL, "Can't start process\n");
280 /* ensure threadFunc_SetEvent & threadFunc_CloseHandle are the same
281 * address as in the child process */
282 create_function_addr_events(hAddrEvents);
283 ret = WaitForMultipleObjects(2, hAddrEvents, TRUE, 5000);
284 if (ret == WAIT_TIMEOUT)
286 skip("child process wasn't mapped at same address, so can't do CreateRemoteThread tests.\n");
290 hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
291 ok(hEvent != NULL, "Can't create event, err=%u\n", GetLastError());
292 ret = DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &hRemoteEvent,
293 0, FALSE, DUPLICATE_SAME_ACCESS);
294 ok(ret != 0, "DuplicateHandle failed, err=%u\n", GetLastError());
296 /* create suspended remote thread with entry point SetEvent() */
297 SetLastError(0xdeadbeef);
298 hThread = CreateRemoteThread(hProcess, NULL, 0, threadFunc_SetEvent,
299 hRemoteEvent, CREATE_SUSPENDED, &tid);
300 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
302 win_skip("CreateRemoteThread is not implemented\n");
305 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
306 ok(tid != 0, "null tid\n");
307 ret = SuspendThread(hThread);
308 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
309 ret = ResumeThread(hThread);
310 ok(ret == 2, "ret=%u, err=%u\n", ret, GetLastError());
312 /* thread still suspended, so wait times out */
313 ret = WaitForSingleObject(hEvent, 100);
314 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
316 ret = ResumeThread(hThread);
317 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
319 /* wait that doesn't time out */
320 ret = WaitForSingleObject(hEvent, 100);
321 ok(ret == WAIT_OBJECT_0, "object not signaled, ret=%u\n", ret);
323 /* wait for thread end */
324 ret = WaitForSingleObject(hThread, 100);
325 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
326 CloseHandle(hThread);
328 /* create and wait for remote thread with entry point CloseHandle() */
329 hThread = CreateRemoteThread(hProcess, NULL, 0,
330 threadFunc_CloseHandle,
331 hRemoteEvent, 0, &tid);
332 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
333 ret = WaitForSingleObject(hThread, 100);
334 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
335 CloseHandle(hThread);
337 /* create remote thread with entry point SetEvent() */
338 hThread = CreateRemoteThread(hProcess, NULL, 0,
340 hRemoteEvent, 0, &tid);
341 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
343 /* closed handle, so wait times out */
344 ret = WaitForSingleObject(hEvent, 100);
345 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
347 /* check that remote SetEvent() failed */
348 ret = GetExitCodeThread(hThread, &exitcode);
349 ok(ret != 0, "GetExitCodeThread failed, err=%u\n", GetLastError());
350 if (ret) ok(exitcode == 0, "SetEvent succeeded, expected to fail\n");
351 CloseHandle(hThread);
354 TerminateProcess(hProcess, 0);
356 CloseHandle(hProcess);
359 /* Check basic functionality of CreateThread and Tls* functions */
360 static VOID test_CreateThread_basic(void)
362 HANDLE thread[NUM_THREADS],event[NUM_THREADS];
363 DWORD threadid[NUM_THREADS],curthreadId;
364 DWORD threadmem[NUM_THREADS];
366 t1Struct tstruct[NUM_THREADS];
372 /* lstrlenA contains an exception handler so this makes sure exceptions work in the main thread */
373 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
375 /* Retrieve current Thread ID for later comparisons */
376 curthreadId=GetCurrentThreadId();
377 /* Allocate some local storage */
378 ok((tlsIndex=TlsAlloc())!=TLS_OUT_OF_INDEXES,"TlsAlloc failed\n");
379 /* Create events for thread synchronization */
380 for(i=0;i<NUM_THREADS;i++) {
382 /* Note that it doesn't matter what type of event we choose here. This
383 test isn't trying to thoroughly test events
385 event[i]=CreateEventA(NULL,TRUE,FALSE,NULL);
386 tstruct[i].threadnum=i;
387 tstruct[i].threadmem=threadmem;
388 tstruct[i].event=event;
391 /* Test that passing arguments to threads works okay */
392 for(i=0;i<NUM_THREADS;i++) {
393 thread[i] = CreateThread(NULL,0,threadFunc1,
394 &tstruct[i],0,&threadid[i]);
395 ok(thread[i]!=NULL,"Create Thread failed\n");
397 /* Test that the threads actually complete */
398 for(i=0;i<NUM_THREADS;i++) {
399 error=WaitForSingleObject(thread[i],5000);
400 ok(error==WAIT_OBJECT_0, "Thread did not complete within timelimit\n");
401 if(error!=WAIT_OBJECT_0) {
402 TerminateThread(thread[i],i+NUM_THREADS);
404 ok(GetExitCodeThread(thread[i],&exitCode),"Could not retrieve ext code\n");
405 ok(exitCode==i+NUM_THREADS,"Thread returned an incorrect exit code\n");
407 /* Test that each thread executed in its parent's address space
408 (it was able to change threadmem and pass that change back to its parent)
409 and that each thread id was independent). Note that we prove that the
410 threads actually execute concurrently by having them block on each other
413 for(i=0;i<NUM_THREADS;i++) {
415 for(j=i+1;j<NUM_THREADS;j++) {
416 if (threadmem[i]==threadmem[j]) {
420 ok(!error && threadmem[i]==threadid[i] && threadmem[i]!=curthreadId,
421 "Thread did not execute successfully\n");
422 ok(CloseHandle(thread[i])!=0,"CloseHandle failed\n");
424 ok(TlsFree(tlsIndex)!=0,"TlsFree failed\n");
426 /* Test how passing NULL as a pointer to threadid works */
427 SetLastError(0xFACEaBAD);
428 thread[0] = CreateThread(NULL,0,threadFunc2,NULL,0,&tid);
429 GLE = GetLastError();
430 if (thread[0]) { /* NT */
431 ok(GLE==0xFACEaBAD, "CreateThread set last error to %d, expected 4207848365\n", GLE);
432 ret = WaitForSingleObject(thread[0],100);
433 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
434 ret = GetExitCodeThread(thread[0],&exitCode);
435 ok(ret!=0, "GetExitCodeThread returned %d (expected nonzero)\n", ret);
436 ok(exitCode==99, "threadFunc2 exited with code: %d (expected 99)\n", exitCode);
437 ok(CloseHandle(thread[0])!=0,"Error closing thread handle\n");
440 ok(GLE==ERROR_INVALID_PARAMETER, "CreateThread set last error to %d, expected 87\n", GLE);
444 /* Check that using the CREATE_SUSPENDED flag works */
445 static VOID test_CreateThread_suspended(void)
452 thread = CreateThread(NULL,0,threadFunc2,NULL,
453 CREATE_SUSPENDED,&threadId);
454 ok(thread!=NULL,"Create Thread failed\n");
455 /* Check that the thread is suspended */
456 ok(SuspendThread(thread)==1,"Thread did not start suspended\n");
457 ok(ResumeThread(thread)==2,"Resume thread returned an invalid value\n");
458 /* Check that resume thread didn't actually start the thread. I can't think
459 of a better way of checking this than just waiting. I am not sure if this
460 will work on slow computers.
462 ok(WaitForSingleObject(thread,1000)==WAIT_TIMEOUT,
463 "ResumeThread should not have actually started the thread\n");
464 /* Now actually resume the thread and make sure that it actually completes*/
465 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
466 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
467 "Thread did not resume\n");
468 if(error!=WAIT_OBJECT_0) {
469 TerminateThread(thread,1);
472 suspend_count = SuspendThread(thread);
473 ok(suspend_count == -1, "SuspendThread returned %d, expected -1\n", suspend_count);
475 suspend_count = ResumeThread(thread);
476 ok(suspend_count == 0 ||
477 broken(suspend_count == -1), /* win9x */
478 "ResumeThread returned %d, expected 0\n", suspend_count);
480 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
483 /* Check that SuspendThread and ResumeThread work */
484 static VOID test_SuspendThread(void)
486 HANDLE thread,access_thread;
487 DWORD threadId,exitCode,error;
490 thread = CreateThread(NULL,0,threadFunc3,NULL,
492 ok(thread!=NULL,"Create Thread failed\n");
493 /* Check that the thread is suspended */
494 /* Note that this is a polling method, and there is a race between
495 SuspendThread being called (in the child, and the loop below timing out,
496 so the test could fail on a heavily loaded or slow computer.
499 for(i=0;error==0 && i<100;i++) {
500 error=SuspendThread(thread);
501 ResumeThread(thread);
507 ok(error==1,"SuspendThread did not work\n");
508 /* check that access restrictions are obeyed */
510 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_SUSPEND_RESUME),
512 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
513 if (access_thread!=NULL) {
514 obey_ar(SuspendThread(access_thread)==~0U);
515 obey_ar(ResumeThread(access_thread)==~0U);
516 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
519 /* Double check that the thread really is suspended */
520 ok((error=GetExitCodeThread(thread,&exitCode))!=0 && exitCode==STILL_ACTIVE,
521 "Thread did not really suspend\n");
522 /* Resume the thread, and make sure it actually completes */
523 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
524 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
525 "Thread did not resume\n");
526 if(error!=WAIT_OBJECT_0) {
527 TerminateThread(thread,1);
529 /* Trying to suspend a terminated thread should fail */
530 error=SuspendThread(thread);
531 ok(error==~0U, "wrong return code: %d\n", error);
532 ok(GetLastError()==ERROR_ACCESS_DENIED || GetLastError()==ERROR_NO_MORE_ITEMS, "unexpected error code: %d\n", GetLastError());
534 ok(CloseHandle(thread)!=0,"CloseHandle Failed\n");
537 /* Check that TerminateThread works properly
539 static VOID test_TerminateThread(void)
541 HANDLE thread,access_thread,event;
542 DWORD threadId,exitCode;
543 event=CreateEventA(NULL,TRUE,FALSE,NULL);
544 thread = CreateThread(NULL,0,threadFunc4,event,0,&threadId);
545 ok(thread!=NULL,"Create Thread failed\n");
546 /* TerminateThread has a race condition in Wine. If the thread is terminated
547 before it starts, it leaves a process behind. Therefore, we wait for the
548 thread to signal that it has started. There is no easy way to force the
549 race to occur, so we don't try to find it.
551 ok(WaitForSingleObject(event,5000)==WAIT_OBJECT_0,
552 "TerminateThread didn't work\n");
553 /* check that access restrictions are obeyed */
555 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_TERMINATE),
557 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
558 if (access_thread!=NULL) {
559 obey_ar(TerminateThread(access_thread,99)==0);
560 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
563 /* terminate a job and make sure it terminates */
564 ok(TerminateThread(thread,99)!=0,"TerminateThread failed\n");
565 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
566 "TerminateThread didn't work\n");
567 ok(GetExitCodeThread(thread,&exitCode)!=STILL_ACTIVE,
568 "TerminateThread should not leave the thread 'STILL_ACTIVE'\n");
569 ok(exitCode==99, "TerminateThread returned invalid exit code\n");
570 ok(CloseHandle(thread)!=0,"Error Closing thread handle\n");
573 /* Check if CreateThread obeys the specified stack size. This code does
574 not work properly, and is currently disabled
576 static VOID test_CreateThread_stack(void)
579 /* The only way I know of to test the stack size is to use alloca
580 and __try/__except. However, this is probably not portable,
581 and I couldn't get it to work under Wine anyhow. However, here
582 is the code which should allow for testing that CreateThread
583 respects the stack-size limit
586 DWORD threadId,exitCode;
589 sysInfo.dwPageSize=0;
590 GetSystemInfo(&sysInfo);
591 ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
592 thread = CreateThread(NULL,sysInfo.dwPageSize,
593 threadFunc5,&exitCode,
595 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
596 "TerminateThread didn't work\n");
597 ok(exitCode==1,"CreateThread did not obey stack-size-limit\n");
598 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
602 /* Check whether setting/retrieving thread priorities works */
603 static VOID test_thread_priority(void)
605 HANDLE curthread,access_thread;
606 DWORD curthreadId,exitCode;
607 int min_priority=-2,max_priority=2;
611 curthread=GetCurrentThread();
612 curthreadId=GetCurrentThreadId();
613 /* Check thread priority */
614 /* NOTE: on Win2k/XP priority can be from -7 to 6. All other platforms it
615 is -2 to 2. However, even on a real Win2k system, using thread
616 priorities beyond the -2 to 2 range does not work. If you want to try
617 anyway, enable USE_EXTENDED_PRIORITIES
619 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_NORMAL,
620 "GetThreadPriority Failed\n");
623 /* check that access control is obeyed */
624 access_thread=pOpenThread(THREAD_ALL_ACCESS &
625 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
627 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
628 if (access_thread!=NULL) {
629 obey_ar(SetThreadPriority(access_thread,1)==0);
630 obey_ar(GetThreadPriority(access_thread)==THREAD_PRIORITY_ERROR_RETURN);
631 obey_ar(GetExitCodeThread(access_thread,&exitCode)==0);
632 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
635 #if USE_EXTENDED_PRIORITIES
636 min_priority=-7; max_priority=6;
638 for(i=min_priority;i<=max_priority;i++) {
639 ok(SetThreadPriority(curthread,i)!=0,
640 "SetThreadPriority Failed for priority: %d\n",i);
641 ok(GetThreadPriority(curthread)==i,
642 "GetThreadPriority Failed for priority: %d\n",i);
644 ok(SetThreadPriority(curthread,THREAD_PRIORITY_TIME_CRITICAL)!=0,
645 "SetThreadPriority Failed\n");
646 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_TIME_CRITICAL,
647 "GetThreadPriority Failed\n");
648 ok(SetThreadPriority(curthread,THREAD_PRIORITY_IDLE)!=0,
649 "SetThreadPriority Failed\n");
650 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_IDLE,
651 "GetThreadPriority Failed\n");
652 ok(SetThreadPriority(curthread,0)!=0,"SetThreadPriority Failed\n");
654 /* Check that the thread priority is not changed if SetThreadPriority
655 is called with a value outside of the max/min range */
656 SetThreadPriority(curthread,min_priority);
657 SetLastError(0xdeadbeef);
658 rc = SetThreadPriority(curthread,min_priority-1);
660 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
661 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
662 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
663 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
665 ok(GetThreadPriority(curthread)==min_priority,
666 "GetThreadPriority didn't return min_priority\n");
668 SetThreadPriority(curthread,max_priority);
669 SetLastError(0xdeadbeef);
670 rc = SetThreadPriority(curthread,max_priority+1);
672 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
673 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
674 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
675 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
677 ok(GetThreadPriority(curthread)==max_priority,
678 "GetThreadPriority didn't return max_priority\n");
680 /* Check thread priority boost */
681 if (!pGetThreadPriorityBoost || !pSetThreadPriorityBoost)
684 SetLastError(0xdeadbeef);
685 rc=pGetThreadPriorityBoost(curthread,&disabled);
686 if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
688 win_skip("GetThreadPriorityBoost is not implemented on WinME\n");
692 ok(rc!=0,"error=%d\n",GetLastError());
695 /* check that access control is obeyed */
696 access_thread=pOpenThread(THREAD_ALL_ACCESS &
697 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
699 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
700 if (access_thread!=NULL) {
701 obey_ar(pSetThreadPriorityBoost(access_thread,1)==0);
702 todo_wine obey_ar(pGetThreadPriorityBoost(access_thread,&disabled)==0);
703 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
708 rc = pSetThreadPriorityBoost(curthread,1);
709 ok( rc != 0, "error=%d\n",GetLastError());
710 rc=pGetThreadPriorityBoost(curthread,&disabled);
711 ok(rc!=0 && disabled==1,
712 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
714 rc = pSetThreadPriorityBoost(curthread,0);
715 ok( rc != 0, "error=%d\n",GetLastError());
717 rc=pGetThreadPriorityBoost(curthread,&disabled);
718 ok(rc!=0 && disabled==0,
719 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
722 /* check the GetThreadTimes function */
723 static VOID test_GetThreadTimes(void)
725 HANDLE thread,access_thread=NULL;
726 FILETIME creationTime,exitTime,kernelTime,userTime;
730 thread = CreateThread(NULL,0,threadFunc2,NULL,
731 CREATE_SUSPENDED,&threadId);
733 ok(thread!=NULL,"Create Thread failed\n");
734 /* check that access control is obeyed */
736 access_thread=pOpenThread(THREAD_ALL_ACCESS &
737 (~THREAD_QUERY_INFORMATION), 0,threadId);
738 ok(access_thread!=NULL,
739 "OpenThread returned an invalid handle\n");
741 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
742 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
743 "ResumeThread didn't work\n");
744 creationTime.dwLowDateTime=99; creationTime.dwHighDateTime=99;
745 exitTime.dwLowDateTime=99; exitTime.dwHighDateTime=99;
746 kernelTime.dwLowDateTime=99; kernelTime.dwHighDateTime=99;
747 userTime.dwLowDateTime=99; userTime.dwHighDateTime=99;
748 /* GetThreadTimes should set all of the parameters passed to it */
749 error=GetThreadTimes(thread,&creationTime,&exitTime,
750 &kernelTime,&userTime);
752 if (error == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
753 win_skip("GetThreadTimes is not implemented\n");
755 ok(error!=0,"GetThreadTimes failed\n");
756 ok(creationTime.dwLowDateTime!=99 || creationTime.dwHighDateTime!=99,
757 "creationTime was invalid\n");
758 ok(exitTime.dwLowDateTime!=99 || exitTime.dwHighDateTime!=99,
759 "exitTime was invalid\n");
760 ok(kernelTime.dwLowDateTime!=99 || kernelTime.dwHighDateTime!=99,
761 "kernelTimewas invalid\n");
762 ok(userTime.dwLowDateTime!=99 || userTime.dwHighDateTime!=99,
763 "userTime was invalid\n");
764 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
765 if(access_thread!=NULL)
767 error=GetThreadTimes(access_thread,&creationTime,&exitTime,
768 &kernelTime,&userTime);
772 if(access_thread!=NULL) {
773 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
777 /* Check the processor affinity functions */
778 /* NOTE: These functions should also be checked that they obey access control
780 static VOID test_thread_processor(void)
782 HANDLE curthread,curproc;
783 DWORD_PTR processMask,systemMask,retMask;
788 if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
790 sysInfo.dwNumberOfProcessors=0;
791 GetSystemInfo(&sysInfo);
792 ok(sysInfo.dwNumberOfProcessors>0,
793 "GetSystemInfo failed to return a valid # of processors\n");
794 /* Use the current Thread/process for all tests */
795 curthread=GetCurrentThread();
796 ok(curthread!=NULL,"GetCurrentThread failed\n");
797 curproc=GetCurrentProcess();
798 ok(curproc!=NULL,"GetCurrentProcess failed\n");
799 /* Check the Affinity Mask functions */
800 ok(GetProcessAffinityMask(curproc,&processMask,&systemMask)!=0,
801 "GetProcessAffinityMask failed\n");
802 ok(SetThreadAffinityMask(curthread,processMask)==processMask,
803 "SetThreadAffinityMask failed\n");
804 ok(SetThreadAffinityMask(curthread,processMask+1)==0,
805 "SetThreadAffinityMask passed for an illegal processor\n");
806 /* NOTE: Pre-Vista does not recognize the "all processors" flag (all bits set) */
807 retMask = SetThreadAffinityMask(curthread,~0UL);
808 ok(broken(retMask==0) || retMask==processMask,
809 "SetThreadAffinityMask(thread,-1) failed to request all processors.\n");
810 /* NOTE: This only works on WinNT/2000/XP) */
811 if (pSetThreadIdealProcessor) {
812 SetLastError(0xdeadbeef);
813 error=pSetThreadIdealProcessor(curthread,0);
814 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
816 win_skip("SetThreadIdealProcessor is not implemented\n");
819 ok(error!=-1, "SetThreadIdealProcessor failed\n");
823 SetLastError(0xdeadbeef);
824 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
826 ok(error!=-1, "SetThreadIdealProcessor failed for %u on Wow64\n", MAXIMUM_PROCESSORS+1);
828 SetLastError(0xdeadbeef);
829 error=pSetThreadIdealProcessor(curthread,65);
830 ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
831 ok(GetLastError()==ERROR_INVALID_PARAMETER,
832 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
836 SetLastError(0xdeadbeef);
837 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
838 ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
839 ok(GetLastError()==ERROR_INVALID_PARAMETER,
840 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
843 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS);
844 ok(error==0, "SetThreadIdealProcessor returned an incorrect value\n");
848 static VOID test_GetThreadExitCode(void)
850 DWORD exitCode, threadid;
854 ret = GetExitCodeThread((HANDLE)0x2bad2bad,&exitCode);
855 ok(ret==0, "GetExitCodeThread returned non zero value: %d\n", ret);
856 GLE = GetLastError();
857 ok(GLE==ERROR_INVALID_HANDLE, "GetLastError returned %d (expected 6)\n", GLE);
859 thread = CreateThread(NULL,0,threadFunc2,NULL,0,&threadid);
860 ret = WaitForSingleObject(thread,100);
861 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
862 ret = GetExitCodeThread(thread,&exitCode);
863 ok(ret==exitCode || ret==1,
864 "GetExitCodeThread returned %d (expected 1 or %d)\n", ret, exitCode);
865 ok(exitCode==99, "threadFunc2 exited with code %d (expected 99)\n", exitCode);
866 ok(CloseHandle(thread)!=0,"Error closing thread handle\n");
871 static int test_value = 0;
874 static void WINAPI set_test_val( int val )
879 static DWORD WINAPI threadFunc6(LPVOID p)
883 test_value *= (int)p;
887 static void test_SetThreadContext(void)
896 SetLastError(0xdeadbeef);
897 event = CreateEvent( NULL, TRUE, FALSE, NULL );
898 thread = CreateThread( NULL, 0, threadFunc6, (void *)2, 0, &threadid );
899 ok( thread != NULL, "CreateThread failed : (%d)\n", GetLastError() );
902 trace("Thread creation failed, skipping rest of test\n");
905 WaitForSingleObject( event, INFINITE );
906 SuspendThread( thread );
907 CloseHandle( event );
909 ctx.ContextFlags = CONTEXT_FULL;
910 SetLastError(0xdeadbeef);
911 ret = GetThreadContext( thread, &ctx );
912 ok( ret, "GetThreadContext failed : (%u)\n", GetLastError() );
916 /* simulate a call to set_test_val(10) */
917 stack = (int *)ctx.Esp;
920 ctx.Esp -= 2 * sizeof(int *);
921 ctx.Eip = (DWORD)set_test_val;
922 SetLastError(0xdeadbeef);
923 ok( SetThreadContext( thread, &ctx ), "SetThreadContext failed : (%d)\n", GetLastError() );
926 SetLastError(0xdeadbeef);
927 prevcount = ResumeThread( thread );
928 ok ( prevcount == 1, "Previous suspend count (%d) instead of 1, last error : (%d)\n",
929 prevcount, GetLastError() );
931 WaitForSingleObject( thread, INFINITE );
932 ok( test_value == 20, "test_value %d instead of 20\n", test_value );
935 #endif /* __i386__ */
937 static HANDLE finish_event;
938 static LONG times_executed;
940 static DWORD CALLBACK work_function(void *p)
942 LONG executed = InterlockedIncrement(×_executed);
945 SetEvent(finish_event);
949 static void test_QueueUserWorkItem(void)
955 /* QueueUserWorkItem not present on win9x */
956 if (!pQueueUserWorkItem) return;
958 finish_event = CreateEvent(NULL, TRUE, FALSE, NULL);
960 before = GetTickCount();
962 for (i = 0; i < 100; i++)
964 BOOL ret = pQueueUserWorkItem(work_function, (void *)i, WT_EXECUTEDEFAULT);
965 ok(ret, "QueueUserWorkItem failed with error %d\n", GetLastError());
968 wait_result = WaitForSingleObject(finish_event, 10000);
970 after = GetTickCount();
971 trace("100 QueueUserWorkItem calls took %dms\n", after - before);
972 ok(wait_result == WAIT_OBJECT_0, "wait failed with error 0x%x\n", wait_result);
974 ok(times_executed == 100, "didn't execute all of the work items\n");
977 static void CALLBACK signaled_function(PVOID p, BOOLEAN TimerOrWaitFired)
981 ok(!TimerOrWaitFired, "wait shouldn't have timed out\n");
984 static void CALLBACK timeout_function(PVOID p, BOOLEAN TimerOrWaitFired)
988 ok(TimerOrWaitFired, "wait should have timed out\n");
991 static void test_RegisterWaitForSingleObject(void)
996 HANDLE complete_event;
998 if (!pRegisterWaitForSingleObject || !pUnregisterWait)
1000 win_skip("RegisterWaitForSingleObject or UnregisterWait not implemented\n");
1004 /* test signaled case */
1006 handle = CreateEvent(NULL, TRUE, TRUE, NULL);
1007 complete_event = CreateEvent(NULL, FALSE, FALSE, NULL);
1009 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1010 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1012 WaitForSingleObject(complete_event, INFINITE);
1013 /* give worker thread chance to complete */
1016 ret = pUnregisterWait(wait_handle);
1017 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1019 /* test cancel case */
1023 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1024 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1026 ret = pUnregisterWait(wait_handle);
1027 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1029 /* test timeout case */
1031 ret = pRegisterWaitForSingleObject(&wait_handle, handle, timeout_function, complete_event, 0, WT_EXECUTEONLYONCE);
1032 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1034 WaitForSingleObject(complete_event, INFINITE);
1035 /* give worker thread chance to complete */
1038 ret = pUnregisterWait(wait_handle);
1039 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1042 static DWORD TLS_main;
1043 static DWORD TLS_index0, TLS_index1;
1045 static DWORD WINAPI TLS_InheritanceProc(LPVOID p)
1047 /* We should NOT inherit the TLS values from our parent or from the
1051 val = TlsGetValue(TLS_main);
1052 ok(val == NULL, "TLS inheritance failed\n");
1054 val = TlsGetValue(TLS_index0);
1055 ok(val == NULL, "TLS inheritance failed\n");
1057 val = TlsGetValue(TLS_index1);
1058 ok(val == NULL, "TLS inheritance failed\n");
1063 /* Basic TLS usage test. Make sure we can create slots and the values we
1064 store in them are separate among threads. Also test TLS value
1065 inheritance with TLS_InheritanceProc. */
1066 static DWORD WINAPI TLS_ThreadProc(LPVOID p)
1068 LONG_PTR id = (LONG_PTR) p;
1072 if (sync_threads_and_run_one(0, id))
1074 TLS_index0 = TlsAlloc();
1075 ok(TLS_index0 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1079 if (sync_threads_and_run_one(1, id))
1081 TLS_index1 = TlsAlloc();
1082 ok(TLS_index1 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1084 /* Slot indices should be different even if created in different
1086 ok(TLS_index0 != TLS_index1, "TlsAlloc failed\n");
1088 /* Both slots should be initialized to NULL */
1089 val = TlsGetValue(TLS_index0);
1090 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1091 ok(val == NULL, "TLS slot not initialized correctly\n");
1093 val = TlsGetValue(TLS_index1);
1094 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1095 ok(val == NULL, "TLS slot not initialized correctly\n");
1099 if (sync_threads_and_run_one(0, id))
1101 val = TlsGetValue(TLS_index0);
1102 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1103 ok(val == NULL, "TLS slot not initialized correctly\n");
1105 val = TlsGetValue(TLS_index1);
1106 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1107 ok(val == NULL, "TLS slot not initialized correctly\n");
1109 ret = TlsSetValue(TLS_index0, (LPVOID) 1);
1110 ok(ret, "TlsSetValue failed\n");
1112 ret = TlsSetValue(TLS_index1, (LPVOID) 2);
1113 ok(ret, "TlsSetValue failed\n");
1115 val = TlsGetValue(TLS_index0);
1116 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1117 ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1119 val = TlsGetValue(TLS_index1);
1120 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1121 ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1125 if (sync_threads_and_run_one(1, id))
1127 val = TlsGetValue(TLS_index0);
1128 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1129 ok(val == NULL, "TLS slot not initialized correctly\n");
1131 val = TlsGetValue(TLS_index1);
1132 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1133 ok(val == NULL, "TLS slot not initialized correctly\n");
1135 ret = TlsSetValue(TLS_index0, (LPVOID) 3);
1136 ok(ret, "TlsSetValue failed\n");
1138 ret = TlsSetValue(TLS_index1, (LPVOID) 4);
1139 ok(ret, "TlsSetValue failed\n");
1141 val = TlsGetValue(TLS_index0);
1142 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1143 ok(val == (LPVOID) 3, "TLS slot not initialized correctly\n");
1145 val = TlsGetValue(TLS_index1);
1146 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1147 ok(val == (LPVOID) 4, "TLS slot not initialized correctly\n");
1151 if (sync_threads_and_run_one(0, id))
1156 val = TlsGetValue(TLS_index0);
1157 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1158 ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1160 val = TlsGetValue(TLS_index1);
1161 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1162 ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1164 thread = CreateThread(NULL, 0, TLS_InheritanceProc, 0, 0, &tid);
1165 ok(thread != NULL, "CreateThread failed\n");
1166 waitret = WaitForSingleObject(thread, 60000);
1167 ok(waitret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
1168 CloseHandle(thread);
1170 ret = TlsFree(TLS_index0);
1171 ok(ret, "TlsFree failed\n");
1175 if (sync_threads_and_run_one(1, id))
1177 ret = TlsFree(TLS_index1);
1178 ok(ret, "TlsFree failed\n");
1185 static void test_TLS(void)
1192 init_thread_sync_helpers();
1194 /* Allocate a TLS slot in the main thread to test for inheritance. */
1195 TLS_main = TlsAlloc();
1196 ok(TLS_main != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1197 suc = TlsSetValue(TLS_main, (LPVOID) 4114);
1198 ok(suc, "TlsSetValue failed\n");
1200 for (i = 0; i < 2; ++i)
1204 threads[i] = CreateThread(NULL, 0, TLS_ThreadProc, (LPVOID) i, 0, &tid);
1205 ok(threads[i] != NULL, "CreateThread failed\n");
1208 ret = WaitForMultipleObjects(2, threads, TRUE, 60000);
1209 ok(ret == WAIT_OBJECT_0 || ret == WAIT_OBJECT_0+1 /* nt4 */, "WaitForMultipleObjects failed %u\n",ret);
1211 for (i = 0; i < 2; ++i)
1212 CloseHandle(threads[i]);
1214 suc = TlsFree(TLS_main);
1215 ok(suc, "TlsFree failed\n");
1216 cleanup_thread_sync_helpers();
1219 static void test_ThreadErrorMode(void)
1226 if (!pSetThreadErrorMode || !pGetThreadErrorMode)
1228 win_skip("SetThreadErrorMode and/or GetThreadErrorMode unavailable (added in Windows 7)\n");
1232 if (!pRtlGetThreadErrorMode) {
1233 win_skip("RtlGetThreadErrorMode not available\n");
1237 oldmode = pGetThreadErrorMode();
1239 ret = pSetThreadErrorMode(0, &mode);
1240 ok(ret, "SetThreadErrorMode failed\n");
1242 "SetThreadErrorMode returned old mode 0x%x, expected 0x%x\n",
1244 mode = pGetThreadErrorMode();
1245 ok(mode == 0, "GetThreadErrorMode returned mode 0x%x, expected 0\n", mode);
1246 rtlmode = pRtlGetThreadErrorMode();
1248 "RtlGetThreadErrorMode returned mode 0x%x, expected 0\n", mode);
1250 ret = pSetThreadErrorMode(SEM_FAILCRITICALERRORS, &mode);
1251 ok(ret, "SetThreadErrorMode failed\n");
1253 "SetThreadErrorMode returned old mode 0x%x, expected 0\n", mode);
1254 mode = pGetThreadErrorMode();
1255 ok(mode == SEM_FAILCRITICALERRORS,
1256 "GetThreadErrorMode returned mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1258 rtlmode = pRtlGetThreadErrorMode();
1260 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x10\n", mode);
1262 ret = pSetThreadErrorMode(SEM_NOGPFAULTERRORBOX, &mode);
1263 ok(ret, "SetThreadErrorMode failed\n");
1264 ok(mode == SEM_FAILCRITICALERRORS,
1265 "SetThreadErrorMode returned old mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1267 mode = pGetThreadErrorMode();
1268 ok(mode == SEM_NOGPFAULTERRORBOX,
1269 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOGPFAULTERRORBOX\n",
1271 rtlmode = pRtlGetThreadErrorMode();
1273 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x20\n", mode);
1275 ret = pSetThreadErrorMode(SEM_NOOPENFILEERRORBOX, NULL);
1276 ok(ret, "SetThreadErrorMode failed\n");
1277 mode = pGetThreadErrorMode();
1278 ok(mode == SEM_NOOPENFILEERRORBOX,
1279 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOOPENFILEERRORBOX\n",
1281 rtlmode = pRtlGetThreadErrorMode();
1283 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x40\n", rtlmode);
1285 for (mode = 1; mode; mode <<= 1)
1287 ret = pSetThreadErrorMode(mode, NULL);
1288 if (mode & (SEM_FAILCRITICALERRORS |
1289 SEM_NOGPFAULTERRORBOX |
1290 SEM_NOOPENFILEERRORBOX))
1293 "SetThreadErrorMode(0x%x,NULL) failed with error %d\n",
1294 mode, GetLastError());
1298 DWORD GLE = GetLastError();
1300 "SetThreadErrorMode(0x%x,NULL) succeeded, expected failure\n",
1302 ok(GLE == ERROR_INVALID_PARAMETER,
1303 "SetThreadErrorMode(0x%x,NULL) failed with %d, "
1304 "expected ERROR_INVALID_PARAMETER\n",
1309 pSetThreadErrorMode(oldmode, NULL);
1318 argc = winetest_get_mainargs( &argv );
1319 /* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
1320 so that the compile passes
1322 lib=GetModuleHandleA("kernel32.dll");
1323 ok(lib!=NULL,"Couldn't get a handle for kernel32.dll\n");
1324 pGetThreadPriorityBoost=(void *)GetProcAddress(lib,"GetThreadPriorityBoost");
1325 pOpenThread=(void *)GetProcAddress(lib,"OpenThread");
1326 pQueueUserWorkItem=(void *)GetProcAddress(lib,"QueueUserWorkItem");
1327 pSetThreadIdealProcessor=(void *)GetProcAddress(lib,"SetThreadIdealProcessor");
1328 pSetThreadPriorityBoost=(void *)GetProcAddress(lib,"SetThreadPriorityBoost");
1329 pRegisterWaitForSingleObject=(void *)GetProcAddress(lib,"RegisterWaitForSingleObject");
1330 pUnregisterWait=(void *)GetProcAddress(lib,"UnregisterWait");
1331 pIsWow64Process=(void *)GetProcAddress(lib,"IsWow64Process");
1332 pSetThreadErrorMode=(void *)GetProcAddress(lib,"SetThreadErrorMode");
1333 pGetThreadErrorMode=(void *)GetProcAddress(lib,"GetThreadErrorMode");
1335 ntdll=GetModuleHandleA("ntdll.dll");
1338 pRtlGetThreadErrorMode=(void *)GetProcAddress(ntdll,"RtlGetThreadErrorMode");
1343 if (!strcmp(argv[2], "sleep"))
1345 HANDLE hAddrEvents[2];
1346 create_function_addr_events(hAddrEvents);
1347 SetEvent(hAddrEvents[0]);
1348 SetEvent(hAddrEvents[1]);
1349 Sleep(5000); /* spawned process runs for at most 5 seconds */
1356 hThread = CreateThread(NULL, 0, threadFunc2, NULL, 0, &tid);
1357 ok(hThread != NULL, "CreateThread failed, error %u\n",
1359 ok(WaitForSingleObject(hThread, 200) == WAIT_OBJECT_0,
1360 "Thread did not exit in time\n");
1361 if (hThread == NULL) break;
1362 CloseHandle(hThread);
1367 test_CreateRemoteThread();
1368 test_CreateThread_basic();
1369 test_CreateThread_suspended();
1370 test_SuspendThread();
1371 test_TerminateThread();
1372 test_CreateThread_stack();
1373 test_thread_priority();
1374 test_GetThreadTimes();
1375 test_thread_processor();
1376 test_GetThreadExitCode();
1378 test_SetThreadContext();
1380 test_QueueUserWorkItem();
1381 test_RegisterWaitForSingleObject();
1383 test_ThreadErrorMode();