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");
291 ok(ret == WAIT_OBJECT_0 || broken(ret == WAIT_OBJECT_0+1 /* nt4,w2k */), "WaitForAllObjects 2 events %d\n", ret);
293 hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
294 ok(hEvent != NULL, "Can't create event, err=%u\n", GetLastError());
295 ret = DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &hRemoteEvent,
296 0, FALSE, DUPLICATE_SAME_ACCESS);
297 ok(ret != 0, "DuplicateHandle failed, err=%u\n", GetLastError());
299 /* create suspended remote thread with entry point SetEvent() */
300 SetLastError(0xdeadbeef);
301 hThread = CreateRemoteThread(hProcess, NULL, 0, threadFunc_SetEvent,
302 hRemoteEvent, CREATE_SUSPENDED, &tid);
303 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
305 win_skip("CreateRemoteThread is not implemented\n");
308 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
309 ok(tid != 0, "null tid\n");
310 ret = SuspendThread(hThread);
311 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
312 ret = ResumeThread(hThread);
313 ok(ret == 2, "ret=%u, err=%u\n", ret, GetLastError());
315 /* thread still suspended, so wait times out */
316 ret = WaitForSingleObject(hEvent, 1000);
317 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
319 ret = ResumeThread(hThread);
320 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
322 /* wait that doesn't time out */
323 ret = WaitForSingleObject(hEvent, 1000);
324 ok(ret == WAIT_OBJECT_0, "object not signaled, ret=%u\n", ret);
326 /* wait for thread end */
327 ret = WaitForSingleObject(hThread, 1000);
328 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
329 CloseHandle(hThread);
331 /* create and wait for remote thread with entry point CloseHandle() */
332 hThread = CreateRemoteThread(hProcess, NULL, 0,
333 threadFunc_CloseHandle,
334 hRemoteEvent, 0, &tid);
335 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
336 ret = WaitForSingleObject(hThread, 1000);
337 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
338 CloseHandle(hThread);
340 /* create remote thread with entry point SetEvent() */
341 hThread = CreateRemoteThread(hProcess, NULL, 0,
343 hRemoteEvent, 0, &tid);
344 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
346 /* closed handle, so wait times out */
347 ret = WaitForSingleObject(hEvent, 1000);
348 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
350 /* check that remote SetEvent() failed */
351 ret = GetExitCodeThread(hThread, &exitcode);
352 ok(ret != 0, "GetExitCodeThread failed, err=%u\n", GetLastError());
353 if (ret) ok(exitcode == 0, "SetEvent succeeded, expected to fail\n");
354 CloseHandle(hThread);
357 TerminateProcess(hProcess, 0);
359 CloseHandle(hProcess);
362 /* Check basic functionality of CreateThread and Tls* functions */
363 static VOID test_CreateThread_basic(void)
365 HANDLE thread[NUM_THREADS],event[NUM_THREADS];
366 DWORD threadid[NUM_THREADS],curthreadId;
367 DWORD threadmem[NUM_THREADS];
369 t1Struct tstruct[NUM_THREADS];
376 /* lstrlenA contains an exception handler so this makes sure exceptions work in the main thread */
377 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
379 /* Retrieve current Thread ID for later comparisons */
380 curthreadId=GetCurrentThreadId();
381 /* Allocate some local storage */
382 ok((tlsIndex=TlsAlloc())!=TLS_OUT_OF_INDEXES,"TlsAlloc failed\n");
383 /* Create events for thread synchronization */
384 for(i=0;i<NUM_THREADS;i++) {
386 /* Note that it doesn't matter what type of event we choose here. This
387 test isn't trying to thoroughly test events
389 event[i]=CreateEventA(NULL,TRUE,FALSE,NULL);
390 tstruct[i].threadnum=i;
391 tstruct[i].threadmem=threadmem;
392 tstruct[i].event=event;
395 /* Test that passing arguments to threads works okay */
396 for(i=0;i<NUM_THREADS;i++) {
397 thread[i] = CreateThread(NULL,0,threadFunc1,
398 &tstruct[i],0,&threadid[i]);
399 ok(thread[i]!=NULL,"Create Thread failed\n");
401 /* Test that the threads actually complete */
402 for(i=0;i<NUM_THREADS;i++) {
403 error=WaitForSingleObject(thread[i],5000);
404 ok(error==WAIT_OBJECT_0, "Thread did not complete within timelimit\n");
405 if(error!=WAIT_OBJECT_0) {
406 TerminateThread(thread[i],i+NUM_THREADS);
408 ok(GetExitCodeThread(thread[i],&exitCode),"Could not retrieve ext code\n");
409 ok(exitCode==i+NUM_THREADS,"Thread returned an incorrect exit code\n");
411 /* Test that each thread executed in its parent's address space
412 (it was able to change threadmem and pass that change back to its parent)
413 and that each thread id was independent). Note that we prove that the
414 threads actually execute concurrently by having them block on each other
417 for(i=0;i<NUM_THREADS;i++) {
419 for(j=i+1;j<NUM_THREADS;j++) {
420 if (threadmem[i]==threadmem[j]) {
424 ok(!error && threadmem[i]==threadid[i] && threadmem[i]!=curthreadId,
425 "Thread did not execute successfully\n");
426 ok(CloseHandle(thread[i])!=0,"CloseHandle failed\n");
429 SetLastError(0xCAFEF00D);
430 bRet = TlsFree(tlsIndex);
431 ok(bRet, "TlsFree failed: %08x\n", GetLastError());
432 ok(GetLastError()==0xCAFEF00D,
433 "GetLastError: expected 0xCAFEF00D, got %08x\n", GetLastError());
435 /* Test freeing an already freed TLS index */
436 SetLastError(0xCAFEF00D);
437 ok(TlsFree(tlsIndex)==0,"TlsFree succeeded\n");
438 ok(GetLastError()==ERROR_INVALID_PARAMETER,
439 "GetLastError: expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
441 /* Test how passing NULL as a pointer to threadid works */
442 SetLastError(0xFACEaBAD);
443 thread[0] = CreateThread(NULL,0,threadFunc2,NULL,0,&tid);
444 GLE = GetLastError();
445 if (thread[0]) { /* NT */
446 ok(GLE==0xFACEaBAD, "CreateThread set last error to %d, expected 4207848365\n", GLE);
447 ret = WaitForSingleObject(thread[0],100);
448 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
449 ret = GetExitCodeThread(thread[0],&exitCode);
450 ok(ret!=0, "GetExitCodeThread returned %d (expected nonzero)\n", ret);
451 ok(exitCode==99, "threadFunc2 exited with code: %d (expected 99)\n", exitCode);
452 ok(CloseHandle(thread[0])!=0,"Error closing thread handle\n");
455 ok(GLE==ERROR_INVALID_PARAMETER, "CreateThread set last error to %d, expected 87\n", GLE);
459 /* Check that using the CREATE_SUSPENDED flag works */
460 static VOID test_CreateThread_suspended(void)
467 thread = CreateThread(NULL,0,threadFunc2,NULL,
468 CREATE_SUSPENDED,&threadId);
469 ok(thread!=NULL,"Create Thread failed\n");
470 /* Check that the thread is suspended */
471 ok(SuspendThread(thread)==1,"Thread did not start suspended\n");
472 ok(ResumeThread(thread)==2,"Resume thread returned an invalid value\n");
473 /* Check that resume thread didn't actually start the thread. I can't think
474 of a better way of checking this than just waiting. I am not sure if this
475 will work on slow computers.
477 ok(WaitForSingleObject(thread,1000)==WAIT_TIMEOUT,
478 "ResumeThread should not have actually started the thread\n");
479 /* Now actually resume the thread and make sure that it actually completes*/
480 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
481 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
482 "Thread did not resume\n");
483 if(error!=WAIT_OBJECT_0) {
484 TerminateThread(thread,1);
487 suspend_count = SuspendThread(thread);
488 ok(suspend_count == -1, "SuspendThread returned %d, expected -1\n", suspend_count);
490 suspend_count = ResumeThread(thread);
491 ok(suspend_count == 0 ||
492 broken(suspend_count == -1), /* win9x */
493 "ResumeThread returned %d, expected 0\n", suspend_count);
495 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
498 /* Check that SuspendThread and ResumeThread work */
499 static VOID test_SuspendThread(void)
501 HANDLE thread,access_thread;
502 DWORD threadId,exitCode,error;
505 thread = CreateThread(NULL,0,threadFunc3,NULL,
507 ok(thread!=NULL,"Create Thread failed\n");
508 /* Check that the thread is suspended */
509 /* Note that this is a polling method, and there is a race between
510 SuspendThread being called (in the child, and the loop below timing out,
511 so the test could fail on a heavily loaded or slow computer.
514 for(i=0;error==0 && i<100;i++) {
515 error=SuspendThread(thread);
516 ResumeThread(thread);
522 ok(error==1,"SuspendThread did not work\n");
523 /* check that access restrictions are obeyed */
525 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_SUSPEND_RESUME),
527 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
528 if (access_thread!=NULL) {
529 obey_ar(SuspendThread(access_thread)==~0U);
530 obey_ar(ResumeThread(access_thread)==~0U);
531 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
534 /* Double check that the thread really is suspended */
535 ok((error=GetExitCodeThread(thread,&exitCode))!=0 && exitCode==STILL_ACTIVE,
536 "Thread did not really suspend\n");
537 /* Resume the thread, and make sure it actually completes */
538 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
539 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
540 "Thread did not resume\n");
541 if(error!=WAIT_OBJECT_0) {
542 TerminateThread(thread,1);
544 /* Trying to suspend a terminated thread should fail */
545 error=SuspendThread(thread);
546 ok(error==~0U, "wrong return code: %d\n", error);
547 ok(GetLastError()==ERROR_ACCESS_DENIED || GetLastError()==ERROR_NO_MORE_ITEMS, "unexpected error code: %d\n", GetLastError());
549 ok(CloseHandle(thread)!=0,"CloseHandle Failed\n");
552 /* Check that TerminateThread works properly
554 static VOID test_TerminateThread(void)
556 HANDLE thread,access_thread,event;
557 DWORD threadId,exitCode;
558 event=CreateEventA(NULL,TRUE,FALSE,NULL);
559 thread = CreateThread(NULL,0,threadFunc4,event,0,&threadId);
560 ok(thread!=NULL,"Create Thread failed\n");
561 /* TerminateThread has a race condition in Wine. If the thread is terminated
562 before it starts, it leaves a process behind. Therefore, we wait for the
563 thread to signal that it has started. There is no easy way to force the
564 race to occur, so we don't try to find it.
566 ok(WaitForSingleObject(event,5000)==WAIT_OBJECT_0,
567 "TerminateThread didn't work\n");
568 /* check that access restrictions are obeyed */
570 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_TERMINATE),
572 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
573 if (access_thread!=NULL) {
574 obey_ar(TerminateThread(access_thread,99)==0);
575 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
578 /* terminate a job and make sure it terminates */
579 ok(TerminateThread(thread,99)!=0,"TerminateThread failed\n");
580 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
581 "TerminateThread didn't work\n");
582 ok(GetExitCodeThread(thread,&exitCode)!=STILL_ACTIVE,
583 "TerminateThread should not leave the thread 'STILL_ACTIVE'\n");
584 ok(exitCode==99, "TerminateThread returned invalid exit code\n");
585 ok(CloseHandle(thread)!=0,"Error Closing thread handle\n");
588 /* Check if CreateThread obeys the specified stack size. This code does
589 not work properly, and is currently disabled
591 static VOID test_CreateThread_stack(void)
594 /* The only way I know of to test the stack size is to use alloca
595 and __try/__except. However, this is probably not portable,
596 and I couldn't get it to work under Wine anyhow. However, here
597 is the code which should allow for testing that CreateThread
598 respects the stack-size limit
601 DWORD threadId,exitCode;
604 sysInfo.dwPageSize=0;
605 GetSystemInfo(&sysInfo);
606 ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
607 thread = CreateThread(NULL,sysInfo.dwPageSize,
608 threadFunc5,&exitCode,
610 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
611 "TerminateThread didn't work\n");
612 ok(exitCode==1,"CreateThread did not obey stack-size-limit\n");
613 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
617 /* Check whether setting/retrieving thread priorities works */
618 static VOID test_thread_priority(void)
620 HANDLE curthread,access_thread;
621 DWORD curthreadId,exitCode;
622 int min_priority=-2,max_priority=2;
626 curthread=GetCurrentThread();
627 curthreadId=GetCurrentThreadId();
628 /* Check thread priority */
629 /* NOTE: on Win2k/XP priority can be from -7 to 6. All other platforms it
630 is -2 to 2. However, even on a real Win2k system, using thread
631 priorities beyond the -2 to 2 range does not work. If you want to try
632 anyway, enable USE_EXTENDED_PRIORITIES
634 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_NORMAL,
635 "GetThreadPriority Failed\n");
638 /* check that access control is obeyed */
639 access_thread=pOpenThread(THREAD_ALL_ACCESS &
640 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
642 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
643 if (access_thread!=NULL) {
644 obey_ar(SetThreadPriority(access_thread,1)==0);
645 obey_ar(GetThreadPriority(access_thread)==THREAD_PRIORITY_ERROR_RETURN);
646 obey_ar(GetExitCodeThread(access_thread,&exitCode)==0);
647 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
650 #if USE_EXTENDED_PRIORITIES
651 min_priority=-7; max_priority=6;
653 for(i=min_priority;i<=max_priority;i++) {
654 ok(SetThreadPriority(curthread,i)!=0,
655 "SetThreadPriority Failed for priority: %d\n",i);
656 ok(GetThreadPriority(curthread)==i,
657 "GetThreadPriority Failed for priority: %d\n",i);
659 ok(SetThreadPriority(curthread,THREAD_PRIORITY_TIME_CRITICAL)!=0,
660 "SetThreadPriority Failed\n");
661 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_TIME_CRITICAL,
662 "GetThreadPriority Failed\n");
663 ok(SetThreadPriority(curthread,THREAD_PRIORITY_IDLE)!=0,
664 "SetThreadPriority Failed\n");
665 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_IDLE,
666 "GetThreadPriority Failed\n");
667 ok(SetThreadPriority(curthread,0)!=0,"SetThreadPriority Failed\n");
669 /* Check that the thread priority is not changed if SetThreadPriority
670 is called with a value outside of the max/min range */
671 SetThreadPriority(curthread,min_priority);
672 SetLastError(0xdeadbeef);
673 rc = SetThreadPriority(curthread,min_priority-1);
675 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
676 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
677 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
678 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
680 ok(GetThreadPriority(curthread)==min_priority,
681 "GetThreadPriority didn't return min_priority\n");
683 SetThreadPriority(curthread,max_priority);
684 SetLastError(0xdeadbeef);
685 rc = SetThreadPriority(curthread,max_priority+1);
687 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
688 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
689 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
690 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
692 ok(GetThreadPriority(curthread)==max_priority,
693 "GetThreadPriority didn't return max_priority\n");
695 /* Check thread priority boost */
696 if (!pGetThreadPriorityBoost || !pSetThreadPriorityBoost)
699 SetLastError(0xdeadbeef);
700 rc=pGetThreadPriorityBoost(curthread,&disabled);
701 if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
703 win_skip("GetThreadPriorityBoost is not implemented on WinME\n");
707 ok(rc!=0,"error=%d\n",GetLastError());
710 /* check that access control is obeyed */
711 access_thread=pOpenThread(THREAD_ALL_ACCESS &
712 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
714 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
715 if (access_thread!=NULL) {
716 obey_ar(pSetThreadPriorityBoost(access_thread,1)==0);
717 todo_wine obey_ar(pGetThreadPriorityBoost(access_thread,&disabled)==0);
718 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
723 rc = pSetThreadPriorityBoost(curthread,1);
724 ok( rc != 0, "error=%d\n",GetLastError());
725 rc=pGetThreadPriorityBoost(curthread,&disabled);
726 ok(rc!=0 && disabled==1,
727 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
729 rc = pSetThreadPriorityBoost(curthread,0);
730 ok( rc != 0, "error=%d\n",GetLastError());
732 rc=pGetThreadPriorityBoost(curthread,&disabled);
733 ok(rc!=0 && disabled==0,
734 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
737 /* check the GetThreadTimes function */
738 static VOID test_GetThreadTimes(void)
740 HANDLE thread,access_thread=NULL;
741 FILETIME creationTime,exitTime,kernelTime,userTime;
745 thread = CreateThread(NULL,0,threadFunc2,NULL,
746 CREATE_SUSPENDED,&threadId);
748 ok(thread!=NULL,"Create Thread failed\n");
749 /* check that access control is obeyed */
751 access_thread=pOpenThread(THREAD_ALL_ACCESS &
752 (~THREAD_QUERY_INFORMATION), 0,threadId);
753 ok(access_thread!=NULL,
754 "OpenThread returned an invalid handle\n");
756 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
757 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
758 "ResumeThread didn't work\n");
759 creationTime.dwLowDateTime=99; creationTime.dwHighDateTime=99;
760 exitTime.dwLowDateTime=99; exitTime.dwHighDateTime=99;
761 kernelTime.dwLowDateTime=99; kernelTime.dwHighDateTime=99;
762 userTime.dwLowDateTime=99; userTime.dwHighDateTime=99;
763 /* GetThreadTimes should set all of the parameters passed to it */
764 error=GetThreadTimes(thread,&creationTime,&exitTime,
765 &kernelTime,&userTime);
767 if (error == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
768 win_skip("GetThreadTimes is not implemented\n");
770 ok(error!=0,"GetThreadTimes failed\n");
771 ok(creationTime.dwLowDateTime!=99 || creationTime.dwHighDateTime!=99,
772 "creationTime was invalid\n");
773 ok(exitTime.dwLowDateTime!=99 || exitTime.dwHighDateTime!=99,
774 "exitTime was invalid\n");
775 ok(kernelTime.dwLowDateTime!=99 || kernelTime.dwHighDateTime!=99,
776 "kernelTimewas invalid\n");
777 ok(userTime.dwLowDateTime!=99 || userTime.dwHighDateTime!=99,
778 "userTime was invalid\n");
779 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
780 if(access_thread!=NULL)
782 error=GetThreadTimes(access_thread,&creationTime,&exitTime,
783 &kernelTime,&userTime);
787 if(access_thread!=NULL) {
788 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
792 /* Check the processor affinity functions */
793 /* NOTE: These functions should also be checked that they obey access control
795 static VOID test_thread_processor(void)
797 HANDLE curthread,curproc;
798 DWORD_PTR processMask,systemMask,retMask;
803 if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
805 sysInfo.dwNumberOfProcessors=0;
806 GetSystemInfo(&sysInfo);
807 ok(sysInfo.dwNumberOfProcessors>0,
808 "GetSystemInfo failed to return a valid # of processors\n");
809 /* Use the current Thread/process for all tests */
810 curthread=GetCurrentThread();
811 ok(curthread!=NULL,"GetCurrentThread failed\n");
812 curproc=GetCurrentProcess();
813 ok(curproc!=NULL,"GetCurrentProcess failed\n");
814 /* Check the Affinity Mask functions */
815 ok(GetProcessAffinityMask(curproc,&processMask,&systemMask)!=0,
816 "GetProcessAffinityMask failed\n");
817 ok(SetThreadAffinityMask(curthread,processMask)==processMask,
818 "SetThreadAffinityMask failed\n");
819 ok(SetThreadAffinityMask(curthread,processMask+1)==0,
820 "SetThreadAffinityMask passed for an illegal processor\n");
821 /* NOTE: Pre-Vista does not recognize the "all processors" flag (all bits set) */
822 retMask = SetThreadAffinityMask(curthread,~0);
823 ok(broken(retMask==0) || retMask==processMask,
824 "SetThreadAffinityMask(thread,-1) failed to request all processors.\n");
825 if (retMask == processMask && sizeof(ULONG_PTR) > sizeof(ULONG))
827 /* only the low 32-bits matter */
828 retMask = SetThreadAffinityMask(curthread,~(ULONG_PTR)0);
829 ok(retMask == processMask, "SetThreadAffinityMask failed\n");
830 retMask = SetThreadAffinityMask(curthread,~(ULONG_PTR)0 >> 3);
831 ok(retMask == processMask, "SetThreadAffinityMask failed\n");
832 retMask = SetThreadAffinityMask(curthread,~(ULONG_PTR)1);
833 ok(retMask == 0, "SetThreadAffinityMask succeeded\n");
835 /* NOTE: This only works on WinNT/2000/XP) */
836 if (pSetThreadIdealProcessor) {
837 SetLastError(0xdeadbeef);
838 error=pSetThreadIdealProcessor(curthread,0);
839 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
841 win_skip("SetThreadIdealProcessor is not implemented\n");
844 ok(error!=-1, "SetThreadIdealProcessor failed\n");
848 SetLastError(0xdeadbeef);
849 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
851 ok(error!=-1, "SetThreadIdealProcessor failed for %u on Wow64\n", MAXIMUM_PROCESSORS+1);
853 SetLastError(0xdeadbeef);
854 error=pSetThreadIdealProcessor(curthread,65);
855 ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
856 ok(GetLastError()==ERROR_INVALID_PARAMETER,
857 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
861 SetLastError(0xdeadbeef);
862 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
863 ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
864 ok(GetLastError()==ERROR_INVALID_PARAMETER,
865 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
868 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS);
869 ok(error!=-1, "SetThreadIdealProcessor failed\n");
873 static VOID test_GetThreadExitCode(void)
875 DWORD exitCode, threadid;
879 ret = GetExitCodeThread((HANDLE)0x2bad2bad,&exitCode);
880 ok(ret==0, "GetExitCodeThread returned non zero value: %d\n", ret);
881 GLE = GetLastError();
882 ok(GLE==ERROR_INVALID_HANDLE, "GetLastError returned %d (expected 6)\n", GLE);
884 thread = CreateThread(NULL,0,threadFunc2,NULL,0,&threadid);
885 ret = WaitForSingleObject(thread,100);
886 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
887 ret = GetExitCodeThread(thread,&exitCode);
888 ok(ret==exitCode || ret==1,
889 "GetExitCodeThread returned %d (expected 1 or %d)\n", ret, exitCode);
890 ok(exitCode==99, "threadFunc2 exited with code %d (expected 99)\n", exitCode);
891 ok(CloseHandle(thread)!=0,"Error closing thread handle\n");
896 static int test_value = 0;
899 static void WINAPI set_test_val( int val )
905 static DWORD WINAPI threadFunc6(LPVOID p)
909 test_value *= (int)p;
913 static void test_SetThreadContext(void)
922 SetLastError(0xdeadbeef);
923 event = CreateEvent( NULL, TRUE, FALSE, NULL );
924 thread = CreateThread( NULL, 0, threadFunc6, (void *)2, 0, &threadid );
925 ok( thread != NULL, "CreateThread failed : (%d)\n", GetLastError() );
928 trace("Thread creation failed, skipping rest of test\n");
931 WaitForSingleObject( event, INFINITE );
932 SuspendThread( thread );
933 CloseHandle( event );
935 ctx.ContextFlags = CONTEXT_FULL;
936 SetLastError(0xdeadbeef);
937 ret = GetThreadContext( thread, &ctx );
938 ok( ret, "GetThreadContext failed : (%u)\n", GetLastError() );
942 /* simulate a call to set_test_val(10) */
943 stack = (int *)ctx.Esp;
946 ctx.Esp -= 2 * sizeof(int *);
947 ctx.Eip = (DWORD)set_test_val;
948 SetLastError(0xdeadbeef);
949 ret = SetThreadContext( thread, &ctx );
950 ok( ret, "SetThreadContext failed : (%d)\n", GetLastError() );
953 SetLastError(0xdeadbeef);
954 prevcount = ResumeThread( thread );
955 ok ( prevcount == 1, "Previous suspend count (%d) instead of 1, last error : (%d)\n",
956 prevcount, GetLastError() );
958 WaitForSingleObject( thread, INFINITE );
959 ok( test_value == 10, "test_value %d\n", test_value );
961 ctx.ContextFlags = CONTEXT_FULL;
962 SetLastError(0xdeadbeef);
963 ret = GetThreadContext( thread, &ctx );
964 ok( (!ret && (GetLastError() == ERROR_GEN_FAILURE)) ||
965 (!ret && broken(GetLastError() == ERROR_INVALID_HANDLE)) || /* win2k */
966 broken(ret), /* 32bit application on NT 5.x 64bit */
967 "got %d with %u (expected FALSE with ERROR_GEN_FAILURE)\n",
968 ret, GetLastError() );
970 SetLastError(0xdeadbeef);
971 ret = SetThreadContext( thread, &ctx );
972 ok( (!ret && ((GetLastError() == ERROR_GEN_FAILURE) || (GetLastError() == ERROR_ACCESS_DENIED))) ||
973 (!ret && broken(GetLastError() == ERROR_INVALID_HANDLE)) || /* win2k */
974 broken(ret), /* 32bit application on NT 5.x 64bit */
975 "got %d with %u (expected FALSE with ERROR_GEN_FAILURE or ERROR_ACCESS_DENIED)\n",
976 ret, GetLastError() );
978 CloseHandle( thread );
981 #endif /* __i386__ */
983 static HANDLE finish_event;
984 static LONG times_executed;
986 static DWORD CALLBACK work_function(void *p)
988 LONG executed = InterlockedIncrement(×_executed);
991 SetEvent(finish_event);
995 static void test_QueueUserWorkItem(void)
1001 /* QueueUserWorkItem not present on win9x */
1002 if (!pQueueUserWorkItem) return;
1004 finish_event = CreateEvent(NULL, TRUE, FALSE, NULL);
1006 before = GetTickCount();
1008 for (i = 0; i < 100; i++)
1010 BOOL ret = pQueueUserWorkItem(work_function, (void *)i, WT_EXECUTEDEFAULT);
1011 ok(ret, "QueueUserWorkItem failed with error %d\n", GetLastError());
1014 wait_result = WaitForSingleObject(finish_event, 10000);
1016 after = GetTickCount();
1017 trace("100 QueueUserWorkItem calls took %dms\n", after - before);
1018 ok(wait_result == WAIT_OBJECT_0, "wait failed with error 0x%x\n", wait_result);
1020 ok(times_executed == 100, "didn't execute all of the work items\n");
1023 static void CALLBACK signaled_function(PVOID p, BOOLEAN TimerOrWaitFired)
1027 ok(!TimerOrWaitFired, "wait shouldn't have timed out\n");
1030 static void CALLBACK timeout_function(PVOID p, BOOLEAN TimerOrWaitFired)
1034 ok(TimerOrWaitFired, "wait should have timed out\n");
1037 static void test_RegisterWaitForSingleObject(void)
1042 HANDLE complete_event;
1044 if (!pRegisterWaitForSingleObject || !pUnregisterWait)
1046 win_skip("RegisterWaitForSingleObject or UnregisterWait not implemented\n");
1050 /* test signaled case */
1052 handle = CreateEvent(NULL, TRUE, TRUE, NULL);
1053 complete_event = CreateEvent(NULL, FALSE, FALSE, NULL);
1055 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1056 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1058 WaitForSingleObject(complete_event, INFINITE);
1059 /* give worker thread chance to complete */
1062 ret = pUnregisterWait(wait_handle);
1063 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1065 /* test cancel case */
1069 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1070 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1072 ret = pUnregisterWait(wait_handle);
1073 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1075 /* test timeout case */
1077 ret = pRegisterWaitForSingleObject(&wait_handle, handle, timeout_function, complete_event, 0, WT_EXECUTEONLYONCE);
1078 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1080 WaitForSingleObject(complete_event, INFINITE);
1081 /* give worker thread chance to complete */
1084 ret = pUnregisterWait(wait_handle);
1085 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1088 static DWORD TLS_main;
1089 static DWORD TLS_index0, TLS_index1;
1091 static DWORD WINAPI TLS_InheritanceProc(LPVOID p)
1093 /* We should NOT inherit the TLS values from our parent or from the
1097 val = TlsGetValue(TLS_main);
1098 ok(val == NULL, "TLS inheritance failed\n");
1100 val = TlsGetValue(TLS_index0);
1101 ok(val == NULL, "TLS inheritance failed\n");
1103 val = TlsGetValue(TLS_index1);
1104 ok(val == NULL, "TLS inheritance failed\n");
1109 /* Basic TLS usage test. Make sure we can create slots and the values we
1110 store in them are separate among threads. Also test TLS value
1111 inheritance with TLS_InheritanceProc. */
1112 static DWORD WINAPI TLS_ThreadProc(LPVOID p)
1114 LONG_PTR id = (LONG_PTR) p;
1118 if (sync_threads_and_run_one(0, id))
1120 TLS_index0 = TlsAlloc();
1121 ok(TLS_index0 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1125 if (sync_threads_and_run_one(1, id))
1127 TLS_index1 = TlsAlloc();
1128 ok(TLS_index1 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1130 /* Slot indices should be different even if created in different
1132 ok(TLS_index0 != TLS_index1, "TlsAlloc failed\n");
1134 /* Both slots should be initialized to NULL */
1135 val = TlsGetValue(TLS_index0);
1136 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1137 ok(val == NULL, "TLS slot not initialized correctly\n");
1139 val = TlsGetValue(TLS_index1);
1140 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1141 ok(val == NULL, "TLS slot not initialized correctly\n");
1145 if (sync_threads_and_run_one(0, id))
1147 val = TlsGetValue(TLS_index0);
1148 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1149 ok(val == NULL, "TLS slot not initialized correctly\n");
1151 val = TlsGetValue(TLS_index1);
1152 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1153 ok(val == NULL, "TLS slot not initialized correctly\n");
1155 ret = TlsSetValue(TLS_index0, (LPVOID) 1);
1156 ok(ret, "TlsSetValue failed\n");
1158 ret = TlsSetValue(TLS_index1, (LPVOID) 2);
1159 ok(ret, "TlsSetValue failed\n");
1161 val = TlsGetValue(TLS_index0);
1162 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1163 ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1165 val = TlsGetValue(TLS_index1);
1166 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1167 ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1171 if (sync_threads_and_run_one(1, id))
1173 val = TlsGetValue(TLS_index0);
1174 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1175 ok(val == NULL, "TLS slot not initialized correctly\n");
1177 val = TlsGetValue(TLS_index1);
1178 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1179 ok(val == NULL, "TLS slot not initialized correctly\n");
1181 ret = TlsSetValue(TLS_index0, (LPVOID) 3);
1182 ok(ret, "TlsSetValue failed\n");
1184 ret = TlsSetValue(TLS_index1, (LPVOID) 4);
1185 ok(ret, "TlsSetValue failed\n");
1187 val = TlsGetValue(TLS_index0);
1188 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1189 ok(val == (LPVOID) 3, "TLS slot not initialized correctly\n");
1191 val = TlsGetValue(TLS_index1);
1192 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1193 ok(val == (LPVOID) 4, "TLS slot not initialized correctly\n");
1197 if (sync_threads_and_run_one(0, id))
1202 val = TlsGetValue(TLS_index0);
1203 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1204 ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1206 val = TlsGetValue(TLS_index1);
1207 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1208 ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1210 thread = CreateThread(NULL, 0, TLS_InheritanceProc, 0, 0, &tid);
1211 ok(thread != NULL, "CreateThread failed\n");
1212 waitret = WaitForSingleObject(thread, 60000);
1213 ok(waitret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
1214 CloseHandle(thread);
1216 ret = TlsFree(TLS_index0);
1217 ok(ret, "TlsFree failed\n");
1221 if (sync_threads_and_run_one(1, id))
1223 ret = TlsFree(TLS_index1);
1224 ok(ret, "TlsFree failed\n");
1231 static void test_TLS(void)
1238 init_thread_sync_helpers();
1240 /* Allocate a TLS slot in the main thread to test for inheritance. */
1241 TLS_main = TlsAlloc();
1242 ok(TLS_main != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1243 suc = TlsSetValue(TLS_main, (LPVOID) 4114);
1244 ok(suc, "TlsSetValue failed\n");
1246 for (i = 0; i < 2; ++i)
1250 threads[i] = CreateThread(NULL, 0, TLS_ThreadProc, (LPVOID) i, 0, &tid);
1251 ok(threads[i] != NULL, "CreateThread failed\n");
1254 ret = WaitForMultipleObjects(2, threads, TRUE, 60000);
1255 ok(ret == WAIT_OBJECT_0 || broken(ret == WAIT_OBJECT_0+1 /* nt4,w2k */), "WaitForAllObjects 2 threads %d\n",ret);
1257 for (i = 0; i < 2; ++i)
1258 CloseHandle(threads[i]);
1260 suc = TlsFree(TLS_main);
1261 ok(suc, "TlsFree failed\n");
1262 cleanup_thread_sync_helpers();
1265 static void test_ThreadErrorMode(void)
1272 if (!pSetThreadErrorMode || !pGetThreadErrorMode)
1274 win_skip("SetThreadErrorMode and/or GetThreadErrorMode unavailable (added in Windows 7)\n");
1278 if (!pRtlGetThreadErrorMode) {
1279 win_skip("RtlGetThreadErrorMode not available\n");
1283 oldmode = pGetThreadErrorMode();
1285 ret = pSetThreadErrorMode(0, &mode);
1286 ok(ret, "SetThreadErrorMode failed\n");
1288 "SetThreadErrorMode returned old mode 0x%x, expected 0x%x\n",
1290 mode = pGetThreadErrorMode();
1291 ok(mode == 0, "GetThreadErrorMode returned mode 0x%x, expected 0\n", mode);
1292 rtlmode = pRtlGetThreadErrorMode();
1294 "RtlGetThreadErrorMode returned mode 0x%x, expected 0\n", mode);
1296 ret = pSetThreadErrorMode(SEM_FAILCRITICALERRORS, &mode);
1297 ok(ret, "SetThreadErrorMode failed\n");
1299 "SetThreadErrorMode returned old mode 0x%x, expected 0\n", mode);
1300 mode = pGetThreadErrorMode();
1301 ok(mode == SEM_FAILCRITICALERRORS,
1302 "GetThreadErrorMode returned mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1304 rtlmode = pRtlGetThreadErrorMode();
1306 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x10\n", mode);
1308 ret = pSetThreadErrorMode(SEM_NOGPFAULTERRORBOX, &mode);
1309 ok(ret, "SetThreadErrorMode failed\n");
1310 ok(mode == SEM_FAILCRITICALERRORS,
1311 "SetThreadErrorMode returned old mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1313 mode = pGetThreadErrorMode();
1314 ok(mode == SEM_NOGPFAULTERRORBOX,
1315 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOGPFAULTERRORBOX\n",
1317 rtlmode = pRtlGetThreadErrorMode();
1319 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x20\n", mode);
1321 ret = pSetThreadErrorMode(SEM_NOOPENFILEERRORBOX, NULL);
1322 ok(ret, "SetThreadErrorMode failed\n");
1323 mode = pGetThreadErrorMode();
1324 ok(mode == SEM_NOOPENFILEERRORBOX,
1325 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOOPENFILEERRORBOX\n",
1327 rtlmode = pRtlGetThreadErrorMode();
1329 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x40\n", rtlmode);
1331 for (mode = 1; mode; mode <<= 1)
1333 ret = pSetThreadErrorMode(mode, NULL);
1334 if (mode & (SEM_FAILCRITICALERRORS |
1335 SEM_NOGPFAULTERRORBOX |
1336 SEM_NOOPENFILEERRORBOX))
1339 "SetThreadErrorMode(0x%x,NULL) failed with error %d\n",
1340 mode, GetLastError());
1344 DWORD GLE = GetLastError();
1346 "SetThreadErrorMode(0x%x,NULL) succeeded, expected failure\n",
1348 ok(GLE == ERROR_INVALID_PARAMETER,
1349 "SetThreadErrorMode(0x%x,NULL) failed with %d, "
1350 "expected ERROR_INVALID_PARAMETER\n",
1355 pSetThreadErrorMode(oldmode, NULL);
1358 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
1359 static inline void set_fpu_cw(WORD cw)
1361 __asm__ volatile ("fnclex; fldcw %0" : : "m" (cw));
1364 static inline WORD get_fpu_cw(void)
1367 __asm__ volatile ("fnstcw %0" : "=m" (cw));
1371 struct fpu_thread_ctx
1377 static DWORD WINAPI fpu_thread(void *param)
1379 struct fpu_thread_ctx *ctx = param;
1382 ctx->cw = get_fpu_cw();
1384 ret = SetEvent(ctx->finished);
1385 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
1390 static WORD get_thread_fpu_cw(void)
1392 struct fpu_thread_ctx ctx;
1396 ctx.finished = CreateEvent(NULL, FALSE, FALSE, NULL);
1397 ok(!!ctx.finished, "Failed to create event, last error %#x.\n", GetLastError());
1399 thread = CreateThread(NULL, 0, fpu_thread, &ctx, 0, &tid);
1400 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
1402 res = WaitForSingleObject(ctx.finished, INFINITE);
1403 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
1405 res = CloseHandle(ctx.finished);
1406 ok(!!res, "Failed to close event handle, last error %#x.\n", GetLastError());
1411 static void test_thread_fpu_cw(void)
1413 WORD initial_cw, cw;
1415 initial_cw = get_fpu_cw();
1416 ok(initial_cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", initial_cw);
1418 cw = get_thread_fpu_cw();
1419 ok(cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", cw);
1423 ok(cw == 0xf60, "Expected FPU control word 0xf60, got %#x.\n", cw);
1425 cw = get_thread_fpu_cw();
1426 ok(cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", cw);
1429 ok(cw == 0xf60, "Expected FPU control word 0xf60, got %#x.\n", cw);
1431 set_fpu_cw(initial_cw);
1433 ok(cw == initial_cw, "Expected FPU control word %#x, got %#x.\n", initial_cw, cw);
1443 argc = winetest_get_mainargs( &argv );
1444 /* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
1445 so that the compile passes
1447 lib=GetModuleHandleA("kernel32.dll");
1448 ok(lib!=NULL,"Couldn't get a handle for kernel32.dll\n");
1449 pGetThreadPriorityBoost=(void *)GetProcAddress(lib,"GetThreadPriorityBoost");
1450 pOpenThread=(void *)GetProcAddress(lib,"OpenThread");
1451 pQueueUserWorkItem=(void *)GetProcAddress(lib,"QueueUserWorkItem");
1452 pSetThreadIdealProcessor=(void *)GetProcAddress(lib,"SetThreadIdealProcessor");
1453 pSetThreadPriorityBoost=(void *)GetProcAddress(lib,"SetThreadPriorityBoost");
1454 pRegisterWaitForSingleObject=(void *)GetProcAddress(lib,"RegisterWaitForSingleObject");
1455 pUnregisterWait=(void *)GetProcAddress(lib,"UnregisterWait");
1456 pIsWow64Process=(void *)GetProcAddress(lib,"IsWow64Process");
1457 pSetThreadErrorMode=(void *)GetProcAddress(lib,"SetThreadErrorMode");
1458 pGetThreadErrorMode=(void *)GetProcAddress(lib,"GetThreadErrorMode");
1460 ntdll=GetModuleHandleA("ntdll.dll");
1463 pRtlGetThreadErrorMode=(void *)GetProcAddress(ntdll,"RtlGetThreadErrorMode");
1468 if (!strcmp(argv[2], "sleep"))
1470 HANDLE hAddrEvents[2];
1471 create_function_addr_events(hAddrEvents);
1472 SetEvent(hAddrEvents[0]);
1473 SetEvent(hAddrEvents[1]);
1474 Sleep(5000); /* spawned process runs for at most 5 seconds */
1481 hThread = CreateThread(NULL, 0, threadFunc2, NULL, 0, &tid);
1482 ok(hThread != NULL, "CreateThread failed, error %u\n",
1484 ok(WaitForSingleObject(hThread, 200) == WAIT_OBJECT_0,
1485 "Thread did not exit in time\n");
1486 if (hThread == NULL) break;
1487 CloseHandle(hThread);
1492 test_CreateRemoteThread();
1493 test_CreateThread_basic();
1494 test_CreateThread_suspended();
1495 test_SuspendThread();
1496 test_TerminateThread();
1497 test_CreateThread_stack();
1498 test_thread_priority();
1499 test_GetThreadTimes();
1500 test_thread_processor();
1501 test_GetThreadExitCode();
1503 test_SetThreadContext();
1505 test_QueueUserWorkItem();
1506 test_RegisterWaitForSingleObject();
1508 test_ThreadErrorMode();
1509 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
1510 test_thread_fpu_cw();