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;
75 STARTUPINFO si = { 0 };
78 winetest_get_mainargs( &argv );
79 sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
80 ret = CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
81 ok(ret, "error: %u\n", GetLastError());
82 ret = CloseHandle(pi.hThread);
83 ok(ret, "error %u\n", GetLastError());
87 /* Functions not tested yet:
92 In addition there are no checks that the inheritance works properly in
96 /* Functions to ensure that from a group of threads, only one executes
97 certain chunks of code at a time, and we know which one is executing
98 it. It basically makes multithreaded execution linear, which defeats
99 the purpose of multiple threads, but makes testing easy. */
100 static HANDLE start_event, stop_event;
101 static LONG num_synced;
103 static void init_thread_sync_helpers(void)
105 start_event = CreateEvent(NULL, TRUE, FALSE, NULL);
106 ok(start_event != NULL, "CreateEvent failed\n");
107 stop_event = CreateEvent(NULL, TRUE, FALSE, NULL);
108 ok(stop_event != NULL, "CreateEvent failed\n");
112 static BOOL sync_threads_and_run_one(DWORD sync_id, DWORD my_id)
114 LONG num = InterlockedIncrement(&num_synced);
115 assert(-1 <= num && num <= 1);
118 ResetEvent( stop_event );
119 SetEvent( start_event );
123 DWORD ret = WaitForSingleObject(start_event, 10000);
124 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed %x\n",ret);
126 return sync_id == my_id;
129 static void resync_after_run(void)
131 LONG num = InterlockedDecrement(&num_synced);
132 assert(-1 <= num && num <= 1);
135 ResetEvent( start_event );
136 SetEvent( stop_event );
140 DWORD ret = WaitForSingleObject(stop_event, 10000);
141 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
145 static void cleanup_thread_sync_helpers(void)
147 CloseHandle(start_event);
148 CloseHandle(stop_event);
151 static DWORD tlsIndex;
159 /* WinME supports OpenThread but doesn't know about access restrictions so
160 we require them to be either completely ignored or always obeyed.
162 static INT obeying_ars = 0; /* -1 == no, 0 == dunno yet, 1 == yes */
166 ? (obeying_ars = +1) \
167 : ((obeying_ars = -1), \
168 trace("not restricted, assuming consistent behaviour\n"))) \
169 : (obeying_ars < 0) \
170 ? ok(!(x), "access restrictions obeyed\n") \
171 : ok( (x), "access restrictions not obeyed\n"))
173 /* Basic test that simultaneous threads can access shared memory,
174 that the thread local storage routines work correctly, and that
175 threads actually run concurrently
177 static DWORD WINAPI threadFunc1(LPVOID p)
179 t1Struct *tstruct = p;
181 /* write our thread # into shared memory */
182 tstruct->threadmem[tstruct->threadnum]=GetCurrentThreadId();
183 ok(TlsSetValue(tlsIndex,(LPVOID)(INT_PTR)(tstruct->threadnum+1))!=0,
184 "TlsSetValue failed\n");
185 /* The threads synchronize before terminating. This is done by
186 Signaling an event, and waiting for all events to occur
188 SetEvent(tstruct->event[tstruct->threadnum]);
189 WaitForMultipleObjects(NUM_THREADS,tstruct->event,TRUE,INFINITE);
190 /* Double check that all threads really did run by validating that
191 they have all written to the shared memory. There should be no race
192 here, since all threads were synchronized after the write.*/
193 for(i=0;i<NUM_THREADS;i++) {
194 while(tstruct->threadmem[i]==0) ;
197 /* lstrlenA contains an exception handler so this makes sure exceptions work in threads */
198 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
200 /* Check that no one changed our tls memory */
201 ok((INT_PTR)TlsGetValue(tlsIndex)-1==tstruct->threadnum,
202 "TlsGetValue failed\n");
203 return NUM_THREADS+tstruct->threadnum;
206 static DWORD WINAPI threadFunc2(LPVOID p)
211 static DWORD WINAPI threadFunc3(LPVOID p)
214 thread=GetCurrentThread();
215 SuspendThread(thread);
219 static DWORD WINAPI threadFunc4(LPVOID p)
230 static DWORD WINAPI threadFunc5(LPVOID p)
234 sysInfo.dwPageSize=0;
235 GetSystemInfo(&sysInfo);
239 alloca(2*sysInfo.dwPageSize);
249 static DWORD WINAPI threadFunc_SetEvent(LPVOID p)
255 static DWORD WINAPI threadFunc_CloseHandle(LPVOID p)
261 static void create_function_addr_events(HANDLE events[2])
265 sprintf(buffer, "threadFunc_SetEvent %p", threadFunc_SetEvent);
266 events[0] = CreateEvent(NULL, FALSE, FALSE, buffer);
268 sprintf(buffer, "threadFunc_CloseHandle %p", threadFunc_CloseHandle);
269 events[1] = CreateEvent(NULL, FALSE, FALSE, buffer);
272 /* check CreateRemoteThread */
273 static VOID test_CreateRemoteThread(void)
275 HANDLE hProcess, hThread, hEvent, hRemoteEvent;
276 DWORD tid, ret, exitcode;
277 HANDLE hAddrEvents[2];
279 hProcess = create_target_process("sleep");
280 ok(hProcess != NULL, "Can't start process\n");
282 /* ensure threadFunc_SetEvent & threadFunc_CloseHandle are the same
283 * address as in the child process */
284 create_function_addr_events(hAddrEvents);
285 ret = WaitForMultipleObjects(2, hAddrEvents, TRUE, 5000);
286 if (ret == WAIT_TIMEOUT)
288 skip("child process wasn't mapped at same address, so can't do CreateRemoteThread tests.\n");
292 hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
293 ok(hEvent != NULL, "Can't create event, err=%u\n", GetLastError());
294 ret = DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &hRemoteEvent,
295 0, FALSE, DUPLICATE_SAME_ACCESS);
296 ok(ret != 0, "DuplicateHandle failed, err=%u\n", GetLastError());
298 /* create suspended remote thread with entry point SetEvent() */
299 SetLastError(0xdeadbeef);
300 hThread = CreateRemoteThread(hProcess, NULL, 0, threadFunc_SetEvent,
301 hRemoteEvent, CREATE_SUSPENDED, &tid);
302 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
304 win_skip("CreateRemoteThread is not implemented\n");
307 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
308 ok(tid != 0, "null tid\n");
309 ret = SuspendThread(hThread);
310 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
311 ret = ResumeThread(hThread);
312 ok(ret == 2, "ret=%u, err=%u\n", ret, GetLastError());
314 /* thread still suspended, so wait times out */
315 ret = WaitForSingleObject(hEvent, 1000);
316 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
318 ret = ResumeThread(hThread);
319 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
321 /* wait that doesn't time out */
322 ret = WaitForSingleObject(hEvent, 1000);
323 ok(ret == WAIT_OBJECT_0, "object not signaled, ret=%u\n", ret);
325 /* wait for thread end */
326 ret = WaitForSingleObject(hThread, 1000);
327 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
328 CloseHandle(hThread);
330 /* create and wait for remote thread with entry point CloseHandle() */
331 hThread = CreateRemoteThread(hProcess, NULL, 0,
332 threadFunc_CloseHandle,
333 hRemoteEvent, 0, &tid);
334 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
335 ret = WaitForSingleObject(hThread, 1000);
336 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
337 CloseHandle(hThread);
339 /* create remote thread with entry point SetEvent() */
340 hThread = CreateRemoteThread(hProcess, NULL, 0,
342 hRemoteEvent, 0, &tid);
343 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
345 /* closed handle, so wait times out */
346 ret = WaitForSingleObject(hEvent, 1000);
347 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
349 /* check that remote SetEvent() failed */
350 ret = GetExitCodeThread(hThread, &exitcode);
351 ok(ret != 0, "GetExitCodeThread failed, err=%u\n", GetLastError());
352 if (ret) ok(exitcode == 0, "SetEvent succeeded, expected to fail\n");
353 CloseHandle(hThread);
356 TerminateProcess(hProcess, 0);
358 CloseHandle(hProcess);
361 /* Check basic functionality of CreateThread and Tls* functions */
362 static VOID test_CreateThread_basic(void)
364 HANDLE thread[NUM_THREADS],event[NUM_THREADS];
365 DWORD threadid[NUM_THREADS],curthreadId;
366 DWORD threadmem[NUM_THREADS];
368 t1Struct tstruct[NUM_THREADS];
375 /* lstrlenA contains an exception handler so this makes sure exceptions work in the main thread */
376 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
378 /* Retrieve current Thread ID for later comparisons */
379 curthreadId=GetCurrentThreadId();
380 /* Allocate some local storage */
381 ok((tlsIndex=TlsAlloc())!=TLS_OUT_OF_INDEXES,"TlsAlloc failed\n");
382 /* Create events for thread synchronization */
383 for(i=0;i<NUM_THREADS;i++) {
385 /* Note that it doesn't matter what type of event we choose here. This
386 test isn't trying to thoroughly test events
388 event[i]=CreateEventA(NULL,TRUE,FALSE,NULL);
389 tstruct[i].threadnum=i;
390 tstruct[i].threadmem=threadmem;
391 tstruct[i].event=event;
394 /* Test that passing arguments to threads works okay */
395 for(i=0;i<NUM_THREADS;i++) {
396 thread[i] = CreateThread(NULL,0,threadFunc1,
397 &tstruct[i],0,&threadid[i]);
398 ok(thread[i]!=NULL,"Create Thread failed\n");
400 /* Test that the threads actually complete */
401 for(i=0;i<NUM_THREADS;i++) {
402 error=WaitForSingleObject(thread[i],5000);
403 ok(error==WAIT_OBJECT_0, "Thread did not complete within timelimit\n");
404 if(error!=WAIT_OBJECT_0) {
405 TerminateThread(thread[i],i+NUM_THREADS);
407 ok(GetExitCodeThread(thread[i],&exitCode),"Could not retrieve ext code\n");
408 ok(exitCode==i+NUM_THREADS,"Thread returned an incorrect exit code\n");
410 /* Test that each thread executed in its parent's address space
411 (it was able to change threadmem and pass that change back to its parent)
412 and that each thread id was independent). Note that we prove that the
413 threads actually execute concurrently by having them block on each other
416 for(i=0;i<NUM_THREADS;i++) {
418 for(j=i+1;j<NUM_THREADS;j++) {
419 if (threadmem[i]==threadmem[j]) {
423 ok(!error && threadmem[i]==threadid[i] && threadmem[i]!=curthreadId,
424 "Thread did not execute successfully\n");
425 ok(CloseHandle(thread[i])!=0,"CloseHandle failed\n");
428 SetLastError(0xCAFEF00D);
429 bRet = TlsFree(tlsIndex);
430 ok(bRet, "TlsFree failed: %08x\n", GetLastError());
431 ok(GetLastError()==0xCAFEF00D,
432 "GetLastError: expected 0xCAFEF00D, got %08x\n", GetLastError());
434 /* Test freeing an already freed TLS index */
435 SetLastError(0xCAFEF00D);
436 ok(TlsFree(tlsIndex)==0,"TlsFree succeeded\n");
437 ok(GetLastError()==ERROR_INVALID_PARAMETER,
438 "GetLastError: expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
440 /* Test how passing NULL as a pointer to threadid works */
441 SetLastError(0xFACEaBAD);
442 thread[0] = CreateThread(NULL,0,threadFunc2,NULL,0,&tid);
443 GLE = GetLastError();
444 if (thread[0]) { /* NT */
445 ok(GLE==0xFACEaBAD, "CreateThread set last error to %d, expected 4207848365\n", GLE);
446 ret = WaitForSingleObject(thread[0],100);
447 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
448 ret = GetExitCodeThread(thread[0],&exitCode);
449 ok(ret!=0, "GetExitCodeThread returned %d (expected nonzero)\n", ret);
450 ok(exitCode==99, "threadFunc2 exited with code: %d (expected 99)\n", exitCode);
451 ok(CloseHandle(thread[0])!=0,"Error closing thread handle\n");
454 ok(GLE==ERROR_INVALID_PARAMETER, "CreateThread set last error to %d, expected 87\n", GLE);
458 /* Check that using the CREATE_SUSPENDED flag works */
459 static VOID test_CreateThread_suspended(void)
466 thread = CreateThread(NULL,0,threadFunc2,NULL,
467 CREATE_SUSPENDED,&threadId);
468 ok(thread!=NULL,"Create Thread failed\n");
469 /* Check that the thread is suspended */
470 ok(SuspendThread(thread)==1,"Thread did not start suspended\n");
471 ok(ResumeThread(thread)==2,"Resume thread returned an invalid value\n");
472 /* Check that resume thread didn't actually start the thread. I can't think
473 of a better way of checking this than just waiting. I am not sure if this
474 will work on slow computers.
476 ok(WaitForSingleObject(thread,1000)==WAIT_TIMEOUT,
477 "ResumeThread should not have actually started the thread\n");
478 /* Now actually resume the thread and make sure that it actually completes*/
479 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
480 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
481 "Thread did not resume\n");
482 if(error!=WAIT_OBJECT_0) {
483 TerminateThread(thread,1);
486 suspend_count = SuspendThread(thread);
487 ok(suspend_count == -1, "SuspendThread returned %d, expected -1\n", suspend_count);
489 suspend_count = ResumeThread(thread);
490 ok(suspend_count == 0 ||
491 broken(suspend_count == -1), /* win9x */
492 "ResumeThread returned %d, expected 0\n", suspend_count);
494 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
497 /* Check that SuspendThread and ResumeThread work */
498 static VOID test_SuspendThread(void)
500 HANDLE thread,access_thread;
501 DWORD threadId,exitCode,error;
504 thread = CreateThread(NULL,0,threadFunc3,NULL,
506 ok(thread!=NULL,"Create Thread failed\n");
507 /* Check that the thread is suspended */
508 /* Note that this is a polling method, and there is a race between
509 SuspendThread being called (in the child, and the loop below timing out,
510 so the test could fail on a heavily loaded or slow computer.
513 for(i=0;error==0 && i<100;i++) {
514 error=SuspendThread(thread);
515 ResumeThread(thread);
521 ok(error==1,"SuspendThread did not work\n");
522 /* check that access restrictions are obeyed */
524 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_SUSPEND_RESUME),
526 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
527 if (access_thread!=NULL) {
528 obey_ar(SuspendThread(access_thread)==~0U);
529 obey_ar(ResumeThread(access_thread)==~0U);
530 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
533 /* Double check that the thread really is suspended */
534 ok((error=GetExitCodeThread(thread,&exitCode))!=0 && exitCode==STILL_ACTIVE,
535 "Thread did not really suspend\n");
536 /* Resume the thread, and make sure it actually completes */
537 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
538 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
539 "Thread did not resume\n");
540 if(error!=WAIT_OBJECT_0) {
541 TerminateThread(thread,1);
543 /* Trying to suspend a terminated thread should fail */
544 error=SuspendThread(thread);
545 ok(error==~0U, "wrong return code: %d\n", error);
546 ok(GetLastError()==ERROR_ACCESS_DENIED || GetLastError()==ERROR_NO_MORE_ITEMS, "unexpected error code: %d\n", GetLastError());
548 ok(CloseHandle(thread)!=0,"CloseHandle Failed\n");
551 /* Check that TerminateThread works properly
553 static VOID test_TerminateThread(void)
555 HANDLE thread,access_thread,event;
556 DWORD threadId,exitCode;
557 event=CreateEventA(NULL,TRUE,FALSE,NULL);
558 thread = CreateThread(NULL,0,threadFunc4,event,0,&threadId);
559 ok(thread!=NULL,"Create Thread failed\n");
560 /* TerminateThread has a race condition in Wine. If the thread is terminated
561 before it starts, it leaves a process behind. Therefore, we wait for the
562 thread to signal that it has started. There is no easy way to force the
563 race to occur, so we don't try to find it.
565 ok(WaitForSingleObject(event,5000)==WAIT_OBJECT_0,
566 "TerminateThread didn't work\n");
567 /* check that access restrictions are obeyed */
569 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_TERMINATE),
571 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
572 if (access_thread!=NULL) {
573 obey_ar(TerminateThread(access_thread,99)==0);
574 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
577 /* terminate a job and make sure it terminates */
578 ok(TerminateThread(thread,99)!=0,"TerminateThread failed\n");
579 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
580 "TerminateThread didn't work\n");
581 ok(GetExitCodeThread(thread,&exitCode)!=STILL_ACTIVE,
582 "TerminateThread should not leave the thread 'STILL_ACTIVE'\n");
583 ok(exitCode==99, "TerminateThread returned invalid exit code\n");
584 ok(CloseHandle(thread)!=0,"Error Closing thread handle\n");
587 /* Check if CreateThread obeys the specified stack size. This code does
588 not work properly, and is currently disabled
590 static VOID test_CreateThread_stack(void)
593 /* The only way I know of to test the stack size is to use alloca
594 and __try/__except. However, this is probably not portable,
595 and I couldn't get it to work under Wine anyhow. However, here
596 is the code which should allow for testing that CreateThread
597 respects the stack-size limit
600 DWORD threadId,exitCode;
603 sysInfo.dwPageSize=0;
604 GetSystemInfo(&sysInfo);
605 ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
606 thread = CreateThread(NULL,sysInfo.dwPageSize,
607 threadFunc5,&exitCode,
609 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
610 "TerminateThread didn't work\n");
611 ok(exitCode==1,"CreateThread did not obey stack-size-limit\n");
612 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
616 /* Check whether setting/retrieving thread priorities works */
617 static VOID test_thread_priority(void)
619 HANDLE curthread,access_thread;
620 DWORD curthreadId,exitCode;
621 int min_priority=-2,max_priority=2;
625 curthread=GetCurrentThread();
626 curthreadId=GetCurrentThreadId();
627 /* Check thread priority */
628 /* NOTE: on Win2k/XP priority can be from -7 to 6. All other platforms it
629 is -2 to 2. However, even on a real Win2k system, using thread
630 priorities beyond the -2 to 2 range does not work. If you want to try
631 anyway, enable USE_EXTENDED_PRIORITIES
633 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_NORMAL,
634 "GetThreadPriority Failed\n");
637 /* check that access control is obeyed */
638 access_thread=pOpenThread(THREAD_ALL_ACCESS &
639 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
641 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
642 if (access_thread!=NULL) {
643 obey_ar(SetThreadPriority(access_thread,1)==0);
644 obey_ar(GetThreadPriority(access_thread)==THREAD_PRIORITY_ERROR_RETURN);
645 obey_ar(GetExitCodeThread(access_thread,&exitCode)==0);
646 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
649 #if USE_EXTENDED_PRIORITIES
650 min_priority=-7; max_priority=6;
652 for(i=min_priority;i<=max_priority;i++) {
653 ok(SetThreadPriority(curthread,i)!=0,
654 "SetThreadPriority Failed for priority: %d\n",i);
655 ok(GetThreadPriority(curthread)==i,
656 "GetThreadPriority Failed for priority: %d\n",i);
658 ok(SetThreadPriority(curthread,THREAD_PRIORITY_TIME_CRITICAL)!=0,
659 "SetThreadPriority Failed\n");
660 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_TIME_CRITICAL,
661 "GetThreadPriority Failed\n");
662 ok(SetThreadPriority(curthread,THREAD_PRIORITY_IDLE)!=0,
663 "SetThreadPriority Failed\n");
664 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_IDLE,
665 "GetThreadPriority Failed\n");
666 ok(SetThreadPriority(curthread,0)!=0,"SetThreadPriority Failed\n");
668 /* Check that the thread priority is not changed if SetThreadPriority
669 is called with a value outside of the max/min range */
670 SetThreadPriority(curthread,min_priority);
671 SetLastError(0xdeadbeef);
672 rc = SetThreadPriority(curthread,min_priority-1);
674 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
675 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
676 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
677 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
679 ok(GetThreadPriority(curthread)==min_priority,
680 "GetThreadPriority didn't return min_priority\n");
682 SetThreadPriority(curthread,max_priority);
683 SetLastError(0xdeadbeef);
684 rc = SetThreadPriority(curthread,max_priority+1);
686 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
687 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
688 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
689 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
691 ok(GetThreadPriority(curthread)==max_priority,
692 "GetThreadPriority didn't return max_priority\n");
694 /* Check thread priority boost */
695 if (!pGetThreadPriorityBoost || !pSetThreadPriorityBoost)
698 SetLastError(0xdeadbeef);
699 rc=pGetThreadPriorityBoost(curthread,&disabled);
700 if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
702 win_skip("GetThreadPriorityBoost is not implemented on WinME\n");
706 ok(rc!=0,"error=%d\n",GetLastError());
709 /* check that access control is obeyed */
710 access_thread=pOpenThread(THREAD_ALL_ACCESS &
711 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
713 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
714 if (access_thread!=NULL) {
715 obey_ar(pSetThreadPriorityBoost(access_thread,1)==0);
716 todo_wine obey_ar(pGetThreadPriorityBoost(access_thread,&disabled)==0);
717 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
722 rc = pSetThreadPriorityBoost(curthread,1);
723 ok( rc != 0, "error=%d\n",GetLastError());
724 rc=pGetThreadPriorityBoost(curthread,&disabled);
725 ok(rc!=0 && disabled==1,
726 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
728 rc = pSetThreadPriorityBoost(curthread,0);
729 ok( rc != 0, "error=%d\n",GetLastError());
731 rc=pGetThreadPriorityBoost(curthread,&disabled);
732 ok(rc!=0 && disabled==0,
733 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
736 /* check the GetThreadTimes function */
737 static VOID test_GetThreadTimes(void)
739 HANDLE thread,access_thread=NULL;
740 FILETIME creationTime,exitTime,kernelTime,userTime;
744 thread = CreateThread(NULL,0,threadFunc2,NULL,
745 CREATE_SUSPENDED,&threadId);
747 ok(thread!=NULL,"Create Thread failed\n");
748 /* check that access control is obeyed */
750 access_thread=pOpenThread(THREAD_ALL_ACCESS &
751 (~THREAD_QUERY_INFORMATION), 0,threadId);
752 ok(access_thread!=NULL,
753 "OpenThread returned an invalid handle\n");
755 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
756 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
757 "ResumeThread didn't work\n");
758 creationTime.dwLowDateTime=99; creationTime.dwHighDateTime=99;
759 exitTime.dwLowDateTime=99; exitTime.dwHighDateTime=99;
760 kernelTime.dwLowDateTime=99; kernelTime.dwHighDateTime=99;
761 userTime.dwLowDateTime=99; userTime.dwHighDateTime=99;
762 /* GetThreadTimes should set all of the parameters passed to it */
763 error=GetThreadTimes(thread,&creationTime,&exitTime,
764 &kernelTime,&userTime);
766 if (error == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
767 win_skip("GetThreadTimes is not implemented\n");
769 ok(error!=0,"GetThreadTimes failed\n");
770 ok(creationTime.dwLowDateTime!=99 || creationTime.dwHighDateTime!=99,
771 "creationTime was invalid\n");
772 ok(exitTime.dwLowDateTime!=99 || exitTime.dwHighDateTime!=99,
773 "exitTime was invalid\n");
774 ok(kernelTime.dwLowDateTime!=99 || kernelTime.dwHighDateTime!=99,
775 "kernelTimewas invalid\n");
776 ok(userTime.dwLowDateTime!=99 || userTime.dwHighDateTime!=99,
777 "userTime was invalid\n");
778 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
779 if(access_thread!=NULL)
781 error=GetThreadTimes(access_thread,&creationTime,&exitTime,
782 &kernelTime,&userTime);
786 if(access_thread!=NULL) {
787 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
791 /* Check the processor affinity functions */
792 /* NOTE: These functions should also be checked that they obey access control
794 static VOID test_thread_processor(void)
796 HANDLE curthread,curproc;
797 DWORD_PTR processMask,systemMask,retMask;
802 if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
804 sysInfo.dwNumberOfProcessors=0;
805 GetSystemInfo(&sysInfo);
806 ok(sysInfo.dwNumberOfProcessors>0,
807 "GetSystemInfo failed to return a valid # of processors\n");
808 /* Use the current Thread/process for all tests */
809 curthread=GetCurrentThread();
810 ok(curthread!=NULL,"GetCurrentThread failed\n");
811 curproc=GetCurrentProcess();
812 ok(curproc!=NULL,"GetCurrentProcess failed\n");
813 /* Check the Affinity Mask functions */
814 ok(GetProcessAffinityMask(curproc,&processMask,&systemMask)!=0,
815 "GetProcessAffinityMask failed\n");
816 ok(SetThreadAffinityMask(curthread,processMask)==processMask,
817 "SetThreadAffinityMask failed\n");
818 ok(SetThreadAffinityMask(curthread,processMask+1)==0,
819 "SetThreadAffinityMask passed for an illegal processor\n");
820 /* NOTE: Pre-Vista does not recognize the "all processors" flag (all bits set) */
821 retMask = SetThreadAffinityMask(curthread,~0);
822 ok(broken(retMask==0) || retMask==processMask,
823 "SetThreadAffinityMask(thread,-1) failed to request all processors.\n");
824 if (retMask == processMask && sizeof(ULONG_PTR) > sizeof(ULONG))
826 /* only the low 32-bits matter */
827 retMask = SetThreadAffinityMask(curthread,~(ULONG_PTR)0);
828 ok(retMask == processMask, "SetThreadAffinityMask failed\n");
829 retMask = SetThreadAffinityMask(curthread,~(ULONG_PTR)0 >> 3);
830 ok(retMask == processMask, "SetThreadAffinityMask failed\n");
831 retMask = SetThreadAffinityMask(curthread,~(ULONG_PTR)1);
832 ok(retMask == 0, "SetThreadAffinityMask succeeded\n");
834 /* NOTE: This only works on WinNT/2000/XP) */
835 if (pSetThreadIdealProcessor) {
836 SetLastError(0xdeadbeef);
837 error=pSetThreadIdealProcessor(curthread,0);
838 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
840 win_skip("SetThreadIdealProcessor is not implemented\n");
843 ok(error!=-1, "SetThreadIdealProcessor failed\n");
847 SetLastError(0xdeadbeef);
848 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
850 ok(error!=-1, "SetThreadIdealProcessor failed for %u on Wow64\n", MAXIMUM_PROCESSORS+1);
852 SetLastError(0xdeadbeef);
853 error=pSetThreadIdealProcessor(curthread,65);
854 ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
855 ok(GetLastError()==ERROR_INVALID_PARAMETER,
856 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
860 SetLastError(0xdeadbeef);
861 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
862 ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
863 ok(GetLastError()==ERROR_INVALID_PARAMETER,
864 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
867 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS);
868 ok(error!=-1, "SetThreadIdealProcessor failed\n");
872 static VOID test_GetThreadExitCode(void)
874 DWORD exitCode, threadid;
878 ret = GetExitCodeThread((HANDLE)0x2bad2bad,&exitCode);
879 ok(ret==0, "GetExitCodeThread returned non zero value: %d\n", ret);
880 GLE = GetLastError();
881 ok(GLE==ERROR_INVALID_HANDLE, "GetLastError returned %d (expected 6)\n", GLE);
883 thread = CreateThread(NULL,0,threadFunc2,NULL,0,&threadid);
884 ret = WaitForSingleObject(thread,100);
885 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
886 ret = GetExitCodeThread(thread,&exitCode);
887 ok(ret==exitCode || ret==1,
888 "GetExitCodeThread returned %d (expected 1 or %d)\n", ret, exitCode);
889 ok(exitCode==99, "threadFunc2 exited with code %d (expected 99)\n", exitCode);
890 ok(CloseHandle(thread)!=0,"Error closing thread handle\n");
895 static int test_value = 0;
898 static void WINAPI set_test_val( int val )
904 static DWORD WINAPI threadFunc6(LPVOID p)
908 test_value *= (int)p;
912 static void test_SetThreadContext(void)
921 SetLastError(0xdeadbeef);
922 event = CreateEvent( NULL, TRUE, FALSE, NULL );
923 thread = CreateThread( NULL, 0, threadFunc6, (void *)2, 0, &threadid );
924 ok( thread != NULL, "CreateThread failed : (%d)\n", GetLastError() );
927 trace("Thread creation failed, skipping rest of test\n");
930 WaitForSingleObject( event, INFINITE );
931 SuspendThread( thread );
932 CloseHandle( event );
934 ctx.ContextFlags = CONTEXT_FULL;
935 SetLastError(0xdeadbeef);
936 ret = GetThreadContext( thread, &ctx );
937 ok( ret, "GetThreadContext failed : (%u)\n", GetLastError() );
941 /* simulate a call to set_test_val(10) */
942 stack = (int *)ctx.Esp;
945 ctx.Esp -= 2 * sizeof(int *);
946 ctx.Eip = (DWORD)set_test_val;
947 SetLastError(0xdeadbeef);
948 ret = SetThreadContext( thread, &ctx );
949 ok( ret, "SetThreadContext failed : (%d)\n", GetLastError() );
952 SetLastError(0xdeadbeef);
953 prevcount = ResumeThread( thread );
954 ok ( prevcount == 1, "Previous suspend count (%d) instead of 1, last error : (%d)\n",
955 prevcount, GetLastError() );
957 WaitForSingleObject( thread, INFINITE );
958 ok( test_value == 10, "test_value %d\n", test_value );
960 ctx.ContextFlags = CONTEXT_FULL;
961 SetLastError(0xdeadbeef);
962 ret = GetThreadContext( thread, &ctx );
963 ok( !ret, "GetThreadContext succeeded\n" );
964 ok( GetLastError() == ERROR_GEN_FAILURE || broken(GetLastError() == ERROR_INVALID_HANDLE), /* win2k */
965 "wrong error %u\n", GetLastError() );
967 SetLastError(0xdeadbeef);
968 ret = SetThreadContext( thread, &ctx );
969 ok( !ret, "SetThreadContext succeeded\n" );
970 ok( GetLastError() == ERROR_GEN_FAILURE || GetLastError() == ERROR_ACCESS_DENIED ||
971 broken(GetLastError() == ERROR_INVALID_HANDLE), /* win2k */
972 "wrong error %u\n", GetLastError() );
974 CloseHandle( thread );
977 #endif /* __i386__ */
979 static HANDLE finish_event;
980 static LONG times_executed;
982 static DWORD CALLBACK work_function(void *p)
984 LONG executed = InterlockedIncrement(×_executed);
987 SetEvent(finish_event);
991 static void test_QueueUserWorkItem(void)
997 /* QueueUserWorkItem not present on win9x */
998 if (!pQueueUserWorkItem) return;
1000 finish_event = CreateEvent(NULL, TRUE, FALSE, NULL);
1002 before = GetTickCount();
1004 for (i = 0; i < 100; i++)
1006 BOOL ret = pQueueUserWorkItem(work_function, (void *)i, WT_EXECUTEDEFAULT);
1007 ok(ret, "QueueUserWorkItem failed with error %d\n", GetLastError());
1010 wait_result = WaitForSingleObject(finish_event, 10000);
1012 after = GetTickCount();
1013 trace("100 QueueUserWorkItem calls took %dms\n", after - before);
1014 ok(wait_result == WAIT_OBJECT_0, "wait failed with error 0x%x\n", wait_result);
1016 ok(times_executed == 100, "didn't execute all of the work items\n");
1019 static void CALLBACK signaled_function(PVOID p, BOOLEAN TimerOrWaitFired)
1023 ok(!TimerOrWaitFired, "wait shouldn't have timed out\n");
1026 static void CALLBACK timeout_function(PVOID p, BOOLEAN TimerOrWaitFired)
1030 ok(TimerOrWaitFired, "wait should have timed out\n");
1033 static void test_RegisterWaitForSingleObject(void)
1038 HANDLE complete_event;
1040 if (!pRegisterWaitForSingleObject || !pUnregisterWait)
1042 win_skip("RegisterWaitForSingleObject or UnregisterWait not implemented\n");
1046 /* test signaled case */
1048 handle = CreateEvent(NULL, TRUE, TRUE, NULL);
1049 complete_event = CreateEvent(NULL, FALSE, FALSE, NULL);
1051 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1052 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1054 WaitForSingleObject(complete_event, INFINITE);
1055 /* give worker thread chance to complete */
1058 ret = pUnregisterWait(wait_handle);
1059 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1061 /* test cancel case */
1065 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1066 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1068 ret = pUnregisterWait(wait_handle);
1069 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1071 /* test timeout case */
1073 ret = pRegisterWaitForSingleObject(&wait_handle, handle, timeout_function, complete_event, 0, WT_EXECUTEONLYONCE);
1074 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1076 WaitForSingleObject(complete_event, INFINITE);
1077 /* give worker thread chance to complete */
1080 ret = pUnregisterWait(wait_handle);
1081 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1084 static DWORD TLS_main;
1085 static DWORD TLS_index0, TLS_index1;
1087 static DWORD WINAPI TLS_InheritanceProc(LPVOID p)
1089 /* We should NOT inherit the TLS values from our parent or from the
1093 val = TlsGetValue(TLS_main);
1094 ok(val == NULL, "TLS inheritance failed\n");
1096 val = TlsGetValue(TLS_index0);
1097 ok(val == NULL, "TLS inheritance failed\n");
1099 val = TlsGetValue(TLS_index1);
1100 ok(val == NULL, "TLS inheritance failed\n");
1105 /* Basic TLS usage test. Make sure we can create slots and the values we
1106 store in them are separate among threads. Also test TLS value
1107 inheritance with TLS_InheritanceProc. */
1108 static DWORD WINAPI TLS_ThreadProc(LPVOID p)
1110 LONG_PTR id = (LONG_PTR) p;
1114 if (sync_threads_and_run_one(0, id))
1116 TLS_index0 = TlsAlloc();
1117 ok(TLS_index0 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1121 if (sync_threads_and_run_one(1, id))
1123 TLS_index1 = TlsAlloc();
1124 ok(TLS_index1 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1126 /* Slot indices should be different even if created in different
1128 ok(TLS_index0 != TLS_index1, "TlsAlloc failed\n");
1130 /* Both slots should be initialized to NULL */
1131 val = TlsGetValue(TLS_index0);
1132 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1133 ok(val == NULL, "TLS slot not initialized correctly\n");
1135 val = TlsGetValue(TLS_index1);
1136 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1137 ok(val == NULL, "TLS slot not initialized correctly\n");
1141 if (sync_threads_and_run_one(0, id))
1143 val = TlsGetValue(TLS_index0);
1144 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1145 ok(val == NULL, "TLS slot not initialized correctly\n");
1147 val = TlsGetValue(TLS_index1);
1148 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1149 ok(val == NULL, "TLS slot not initialized correctly\n");
1151 ret = TlsSetValue(TLS_index0, (LPVOID) 1);
1152 ok(ret, "TlsSetValue failed\n");
1154 ret = TlsSetValue(TLS_index1, (LPVOID) 2);
1155 ok(ret, "TlsSetValue failed\n");
1157 val = TlsGetValue(TLS_index0);
1158 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1159 ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1161 val = TlsGetValue(TLS_index1);
1162 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1163 ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1167 if (sync_threads_and_run_one(1, id))
1169 val = TlsGetValue(TLS_index0);
1170 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1171 ok(val == NULL, "TLS slot not initialized correctly\n");
1173 val = TlsGetValue(TLS_index1);
1174 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1175 ok(val == NULL, "TLS slot not initialized correctly\n");
1177 ret = TlsSetValue(TLS_index0, (LPVOID) 3);
1178 ok(ret, "TlsSetValue failed\n");
1180 ret = TlsSetValue(TLS_index1, (LPVOID) 4);
1181 ok(ret, "TlsSetValue failed\n");
1183 val = TlsGetValue(TLS_index0);
1184 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1185 ok(val == (LPVOID) 3, "TLS slot not initialized correctly\n");
1187 val = TlsGetValue(TLS_index1);
1188 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1189 ok(val == (LPVOID) 4, "TLS slot not initialized correctly\n");
1193 if (sync_threads_and_run_one(0, id))
1198 val = TlsGetValue(TLS_index0);
1199 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1200 ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1202 val = TlsGetValue(TLS_index1);
1203 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1204 ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1206 thread = CreateThread(NULL, 0, TLS_InheritanceProc, 0, 0, &tid);
1207 ok(thread != NULL, "CreateThread failed\n");
1208 waitret = WaitForSingleObject(thread, 60000);
1209 ok(waitret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
1210 CloseHandle(thread);
1212 ret = TlsFree(TLS_index0);
1213 ok(ret, "TlsFree failed\n");
1217 if (sync_threads_and_run_one(1, id))
1219 ret = TlsFree(TLS_index1);
1220 ok(ret, "TlsFree failed\n");
1227 static void test_TLS(void)
1234 init_thread_sync_helpers();
1236 /* Allocate a TLS slot in the main thread to test for inheritance. */
1237 TLS_main = TlsAlloc();
1238 ok(TLS_main != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1239 suc = TlsSetValue(TLS_main, (LPVOID) 4114);
1240 ok(suc, "TlsSetValue failed\n");
1242 for (i = 0; i < 2; ++i)
1246 threads[i] = CreateThread(NULL, 0, TLS_ThreadProc, (LPVOID) i, 0, &tid);
1247 ok(threads[i] != NULL, "CreateThread failed\n");
1250 ret = WaitForMultipleObjects(2, threads, TRUE, 60000);
1251 ok(ret == WAIT_OBJECT_0 || ret == WAIT_OBJECT_0+1 /* nt4 */, "WaitForMultipleObjects failed %u\n",ret);
1253 for (i = 0; i < 2; ++i)
1254 CloseHandle(threads[i]);
1256 suc = TlsFree(TLS_main);
1257 ok(suc, "TlsFree failed\n");
1258 cleanup_thread_sync_helpers();
1261 static void test_ThreadErrorMode(void)
1268 if (!pSetThreadErrorMode || !pGetThreadErrorMode)
1270 win_skip("SetThreadErrorMode and/or GetThreadErrorMode unavailable (added in Windows 7)\n");
1274 if (!pRtlGetThreadErrorMode) {
1275 win_skip("RtlGetThreadErrorMode not available\n");
1279 oldmode = pGetThreadErrorMode();
1281 ret = pSetThreadErrorMode(0, &mode);
1282 ok(ret, "SetThreadErrorMode failed\n");
1284 "SetThreadErrorMode returned old mode 0x%x, expected 0x%x\n",
1286 mode = pGetThreadErrorMode();
1287 ok(mode == 0, "GetThreadErrorMode returned mode 0x%x, expected 0\n", mode);
1288 rtlmode = pRtlGetThreadErrorMode();
1290 "RtlGetThreadErrorMode returned mode 0x%x, expected 0\n", mode);
1292 ret = pSetThreadErrorMode(SEM_FAILCRITICALERRORS, &mode);
1293 ok(ret, "SetThreadErrorMode failed\n");
1295 "SetThreadErrorMode returned old mode 0x%x, expected 0\n", mode);
1296 mode = pGetThreadErrorMode();
1297 ok(mode == SEM_FAILCRITICALERRORS,
1298 "GetThreadErrorMode returned mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1300 rtlmode = pRtlGetThreadErrorMode();
1302 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x10\n", mode);
1304 ret = pSetThreadErrorMode(SEM_NOGPFAULTERRORBOX, &mode);
1305 ok(ret, "SetThreadErrorMode failed\n");
1306 ok(mode == SEM_FAILCRITICALERRORS,
1307 "SetThreadErrorMode returned old mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1309 mode = pGetThreadErrorMode();
1310 ok(mode == SEM_NOGPFAULTERRORBOX,
1311 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOGPFAULTERRORBOX\n",
1313 rtlmode = pRtlGetThreadErrorMode();
1315 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x20\n", mode);
1317 ret = pSetThreadErrorMode(SEM_NOOPENFILEERRORBOX, NULL);
1318 ok(ret, "SetThreadErrorMode failed\n");
1319 mode = pGetThreadErrorMode();
1320 ok(mode == SEM_NOOPENFILEERRORBOX,
1321 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOOPENFILEERRORBOX\n",
1323 rtlmode = pRtlGetThreadErrorMode();
1325 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x40\n", rtlmode);
1327 for (mode = 1; mode; mode <<= 1)
1329 ret = pSetThreadErrorMode(mode, NULL);
1330 if (mode & (SEM_FAILCRITICALERRORS |
1331 SEM_NOGPFAULTERRORBOX |
1332 SEM_NOOPENFILEERRORBOX))
1335 "SetThreadErrorMode(0x%x,NULL) failed with error %d\n",
1336 mode, GetLastError());
1340 DWORD GLE = GetLastError();
1342 "SetThreadErrorMode(0x%x,NULL) succeeded, expected failure\n",
1344 ok(GLE == ERROR_INVALID_PARAMETER,
1345 "SetThreadErrorMode(0x%x,NULL) failed with %d, "
1346 "expected ERROR_INVALID_PARAMETER\n",
1351 pSetThreadErrorMode(oldmode, NULL);
1354 static inline void set_fpu_cw(WORD cw)
1356 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
1357 __asm__ volatile ("fnclex; fldcw %0" : : "m" (cw));
1361 static inline WORD get_fpu_cw(void)
1364 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
1365 __asm__ volatile ("fnstcw %0" : "=m" (cw));
1370 struct fpu_thread_ctx
1376 static DWORD WINAPI fpu_thread(void *param)
1378 struct fpu_thread_ctx *ctx = param;
1381 ctx->cw = get_fpu_cw();
1383 ret = SetEvent(ctx->finished);
1384 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
1389 static WORD get_thread_fpu_cw(void)
1391 struct fpu_thread_ctx ctx;
1395 ctx.finished = CreateEvent(NULL, FALSE, FALSE, NULL);
1396 ok(!!ctx.finished, "Failed to create event, last error %#x.\n", GetLastError());
1398 thread = CreateThread(NULL, 0, fpu_thread, &ctx, 0, &tid);
1399 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
1401 res = WaitForSingleObject(ctx.finished, INFINITE);
1402 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
1404 res = CloseHandle(ctx.finished);
1405 ok(!!res, "Failed to close event handle, last error %#x.\n", GetLastError());
1410 static void test_thread_fpu_cw(void)
1412 WORD initial_cw, cw;
1414 initial_cw = get_fpu_cw();
1415 ok(initial_cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", initial_cw);
1417 cw = get_thread_fpu_cw();
1418 ok(cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", cw);
1422 ok(cw == 0xf60, "Expected FPU control word 0xf60, got %#x.\n", cw);
1424 cw = get_thread_fpu_cw();
1425 ok(cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", cw);
1428 ok(cw == 0xf60, "Expected FPU control word 0xf60, got %#x.\n", cw);
1430 set_fpu_cw(initial_cw);
1432 ok(cw == initial_cw, "Expected FPU control word %#x, got %#x.\n", initial_cw, cw);
1441 argc = winetest_get_mainargs( &argv );
1442 /* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
1443 so that the compile passes
1445 lib=GetModuleHandleA("kernel32.dll");
1446 ok(lib!=NULL,"Couldn't get a handle for kernel32.dll\n");
1447 pGetThreadPriorityBoost=(void *)GetProcAddress(lib,"GetThreadPriorityBoost");
1448 pOpenThread=(void *)GetProcAddress(lib,"OpenThread");
1449 pQueueUserWorkItem=(void *)GetProcAddress(lib,"QueueUserWorkItem");
1450 pSetThreadIdealProcessor=(void *)GetProcAddress(lib,"SetThreadIdealProcessor");
1451 pSetThreadPriorityBoost=(void *)GetProcAddress(lib,"SetThreadPriorityBoost");
1452 pRegisterWaitForSingleObject=(void *)GetProcAddress(lib,"RegisterWaitForSingleObject");
1453 pUnregisterWait=(void *)GetProcAddress(lib,"UnregisterWait");
1454 pIsWow64Process=(void *)GetProcAddress(lib,"IsWow64Process");
1455 pSetThreadErrorMode=(void *)GetProcAddress(lib,"SetThreadErrorMode");
1456 pGetThreadErrorMode=(void *)GetProcAddress(lib,"GetThreadErrorMode");
1458 ntdll=GetModuleHandleA("ntdll.dll");
1461 pRtlGetThreadErrorMode=(void *)GetProcAddress(ntdll,"RtlGetThreadErrorMode");
1466 if (!strcmp(argv[2], "sleep"))
1468 HANDLE hAddrEvents[2];
1469 create_function_addr_events(hAddrEvents);
1470 SetEvent(hAddrEvents[0]);
1471 SetEvent(hAddrEvents[1]);
1472 Sleep(5000); /* spawned process runs for at most 5 seconds */
1479 hThread = CreateThread(NULL, 0, threadFunc2, NULL, 0, &tid);
1480 ok(hThread != NULL, "CreateThread failed, error %u\n",
1482 ok(WaitForSingleObject(hThread, 200) == WAIT_OBJECT_0,
1483 "Thread did not exit in time\n");
1484 if (hThread == NULL) break;
1485 CloseHandle(hThread);
1490 test_CreateRemoteThread();
1491 test_CreateThread_basic();
1492 test_CreateThread_suspended();
1493 test_SuspendThread();
1494 test_TerminateThread();
1495 test_CreateThread_stack();
1496 test_thread_priority();
1497 test_GetThreadTimes();
1498 test_thread_processor();
1499 test_GetThreadExitCode();
1501 test_SetThreadContext();
1503 test_QueueUserWorkItem();
1504 test_RegisterWaitForSingleObject();
1506 test_ThreadErrorMode();
1507 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
1508 test_thread_fpu_cw();