2 * Unit test suite for thread functions.
4 * Copyright 2002 Geoffrey Hausheer
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 /* Define _WIN32_WINNT to get SetThreadIdealProcessor on Windows */
22 #define _WIN32_WINNT 0x0500
28 #include "wine/test.h"
34 /* Specify the number of simultaneous threads to test */
36 /* Specify whether to test the extended priorities for Win2k/XP */
37 #define USE_EXTENDED_PRIORITIES 0
38 /* Specify whether to test the stack allocation in CreateThread */
41 /* Set CHECK_STACK to 1 if you want to try to test the stack-limit from
42 CreateThread. So far I have been unable to make this work, and
43 I am in doubt as to how portable it is. Also, according to MSDN,
44 you shouldn't mix C-run-time-libraries (i.e. alloca) with CreateThread.
45 Anyhow, the check is currently commented out
50 # define __EXCEPT __except
53 # include "wine/exception.h"
57 static BOOL (WINAPI *pGetThreadPriorityBoost)(HANDLE,PBOOL);
58 static HANDLE (WINAPI *pOpenThread)(DWORD,BOOL,DWORD);
59 static BOOL (WINAPI *pQueueUserWorkItem)(LPTHREAD_START_ROUTINE,PVOID,ULONG);
60 static DWORD (WINAPI *pSetThreadIdealProcessor)(HANDLE,DWORD);
61 static BOOL (WINAPI *pSetThreadPriorityBoost)(HANDLE,BOOL);
62 static BOOL (WINAPI *pRegisterWaitForSingleObject)(PHANDLE,HANDLE,WAITORTIMERCALLBACK,PVOID,ULONG,ULONG);
63 static BOOL (WINAPI *pUnregisterWait)(HANDLE);
64 static BOOL (WINAPI *pIsWow64Process)(HANDLE,PBOOL);
65 static BOOL (WINAPI *pSetThreadErrorMode)(DWORD,PDWORD);
66 static DWORD (WINAPI *pGetThreadErrorMode)(void);
67 static DWORD (WINAPI *pRtlGetThreadErrorMode)(void);
69 static HANDLE create_target_process(const char *arg)
72 char cmdline[MAX_PATH];
73 PROCESS_INFORMATION pi;
74 STARTUPINFO si = { 0 };
77 winetest_get_mainargs( &argv );
78 sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
79 ok(CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL,
80 &si, &pi) != 0, "error: %u\n", GetLastError());
81 ok(CloseHandle(pi.hThread) != 0, "error %u\n", GetLastError());
85 /* Functions not tested yet:
90 In addition there are no checks that the inheritance works properly in
94 /* Functions to ensure that from a group of threads, only one executes
95 certain chunks of code at a time, and we know which one is executing
96 it. It basically makes multithreaded execution linear, which defeats
97 the purpose of multiple threads, but makes testing easy. */
98 static HANDLE start_event, stop_event;
99 static LONG num_synced;
101 static void init_thread_sync_helpers(void)
103 start_event = CreateEvent(NULL, TRUE, FALSE, NULL);
104 ok(start_event != NULL, "CreateEvent failed\n");
105 stop_event = CreateEvent(NULL, TRUE, FALSE, NULL);
106 ok(stop_event != NULL, "CreateEvent failed\n");
110 static BOOL sync_threads_and_run_one(DWORD sync_id, DWORD my_id)
112 LONG num = InterlockedIncrement(&num_synced);
113 assert(-1 <= num && num <= 1);
116 ResetEvent( stop_event );
117 SetEvent( start_event );
121 DWORD ret = WaitForSingleObject(start_event, 10000);
122 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed %x\n",ret);
124 return sync_id == my_id;
127 static void resync_after_run(void)
129 LONG num = InterlockedDecrement(&num_synced);
130 assert(-1 <= num && num <= 1);
133 ResetEvent( start_event );
134 SetEvent( stop_event );
138 DWORD ret = WaitForSingleObject(stop_event, 10000);
139 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
143 static void cleanup_thread_sync_helpers(void)
145 CloseHandle(start_event);
146 CloseHandle(stop_event);
157 /* WinME supports OpenThread but doesn't know about access restrictions so
158 we require them to be either completely ignored or always obeyed.
160 INT obeying_ars = 0; /* -1 == no, 0 == dunno yet, 1 == yes */
164 ? (obeying_ars = +1) \
165 : ((obeying_ars = -1), \
166 trace("not restricted, assuming consistent behaviour\n"))) \
167 : (obeying_ars < 0) \
168 ? ok(!(x), "access restrictions obeyed\n") \
169 : ok( (x), "access restrictions not obeyed\n"))
171 /* Basic test that simultaneous threads can access shared memory,
172 that the thread local storage routines work correctly, and that
173 threads actually run concurrently
175 static DWORD WINAPI threadFunc1(LPVOID p)
177 t1Struct *tstruct = p;
179 /* write our thread # into shared memory */
180 tstruct->threadmem[tstruct->threadnum]=GetCurrentThreadId();
181 ok(TlsSetValue(tlsIndex,(LPVOID)(INT_PTR)(tstruct->threadnum+1))!=0,
182 "TlsSetValue failed\n");
183 /* The threads synchronize before terminating. This is done by
184 Signaling an event, and waiting for all events to occur
186 SetEvent(tstruct->event[tstruct->threadnum]);
187 WaitForMultipleObjects(NUM_THREADS,tstruct->event,TRUE,INFINITE);
188 /* Double check that all threads really did run by validating that
189 they have all written to the shared memory. There should be no race
190 here, since all threads were synchronized after the write.*/
191 for(i=0;i<NUM_THREADS;i++) {
192 while(tstruct->threadmem[i]==0) ;
195 /* lstrlenA contains an exception handler so this makes sure exceptions work in threads */
196 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
198 /* Check that no one changed our tls memory */
199 ok((INT_PTR)TlsGetValue(tlsIndex)-1==tstruct->threadnum,
200 "TlsGetValue failed\n");
201 return NUM_THREADS+tstruct->threadnum;
204 static DWORD WINAPI threadFunc2(LPVOID p)
209 static DWORD WINAPI threadFunc3(LPVOID p)
212 thread=GetCurrentThread();
213 SuspendThread(thread);
217 static DWORD WINAPI threadFunc4(LPVOID p)
228 static DWORD WINAPI threadFunc5(LPVOID p)
232 sysInfo.dwPageSize=0;
233 GetSystemInfo(&sysInfo);
237 alloca(2*sysInfo.dwPageSize);
247 static DWORD WINAPI threadFunc_SetEvent(LPVOID p)
253 static DWORD WINAPI threadFunc_CloseHandle(LPVOID p)
259 static void create_function_addr_events(HANDLE events[2])
263 sprintf(buffer, "threadFunc_SetEvent %p", threadFunc_SetEvent);
264 events[0] = CreateEvent(NULL, FALSE, FALSE, buffer);
266 sprintf(buffer, "threadFunc_CloseHandle %p", threadFunc_CloseHandle);
267 events[1] = CreateEvent(NULL, FALSE, FALSE, buffer);
270 /* check CreateRemoteThread */
271 static VOID test_CreateRemoteThread(void)
273 HANDLE hProcess, hThread, hEvent, hRemoteEvent;
274 DWORD tid, ret, exitcode;
275 HANDLE hAddrEvents[2];
277 hProcess = create_target_process("sleep");
278 ok(hProcess != NULL, "Can't start process\n");
280 /* ensure threadFunc_SetEvent & threadFunc_CloseHandle are the same
281 * address as in the child process */
282 create_function_addr_events(hAddrEvents);
283 ret = WaitForMultipleObjects(2, hAddrEvents, TRUE, 5000);
284 if (ret == WAIT_TIMEOUT)
286 skip("child process wasn't mapped at same address, so can't do CreateRemoteThread tests.\n");
290 hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
291 ok(hEvent != NULL, "Can't create event, err=%u\n", GetLastError());
292 ret = DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &hRemoteEvent,
293 0, FALSE, DUPLICATE_SAME_ACCESS);
294 ok(ret != 0, "DuplicateHandle failed, err=%u\n", GetLastError());
296 /* create suspended remote thread with entry point SetEvent() */
297 SetLastError(0xdeadbeef);
298 hThread = CreateRemoteThread(hProcess, NULL, 0, threadFunc_SetEvent,
299 hRemoteEvent, CREATE_SUSPENDED, &tid);
300 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
302 win_skip("CreateRemoteThread is not implemented\n");
305 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
306 ok(tid != 0, "null tid\n");
307 ret = SuspendThread(hThread);
308 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
309 ret = ResumeThread(hThread);
310 ok(ret == 2, "ret=%u, err=%u\n", ret, GetLastError());
312 /* thread still suspended, so wait times out */
313 ret = WaitForSingleObject(hEvent, 100);
314 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
316 ret = ResumeThread(hThread);
317 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
319 /* wait that doesn't time out */
320 ret = WaitForSingleObject(hEvent, 100);
321 ok(ret == WAIT_OBJECT_0, "object not signaled, ret=%u\n", ret);
323 /* wait for thread end */
324 ret = WaitForSingleObject(hThread, 100);
325 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
326 CloseHandle(hThread);
328 /* create and wait for remote thread with entry point CloseHandle() */
329 hThread = CreateRemoteThread(hProcess, NULL, 0,
330 threadFunc_CloseHandle,
331 hRemoteEvent, 0, &tid);
332 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
333 ret = WaitForSingleObject(hThread, 100);
334 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
335 CloseHandle(hThread);
337 /* create remote thread with entry point SetEvent() */
338 hThread = CreateRemoteThread(hProcess, NULL, 0,
340 hRemoteEvent, 0, &tid);
341 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
343 /* closed handle, so wait times out */
344 ret = WaitForSingleObject(hEvent, 100);
345 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
347 /* check that remote SetEvent() failed */
348 ret = GetExitCodeThread(hThread, &exitcode);
349 ok(ret != 0, "GetExitCodeThread failed, err=%u\n", GetLastError());
350 if (ret) ok(exitcode == 0, "SetEvent succeeded, expected to fail\n");
351 CloseHandle(hThread);
354 TerminateProcess(hProcess, 0);
356 CloseHandle(hProcess);
359 /* Check basic functionality of CreateThread and Tls* functions */
360 static VOID test_CreateThread_basic(void)
362 HANDLE thread[NUM_THREADS],event[NUM_THREADS];
363 DWORD threadid[NUM_THREADS],curthreadId;
364 DWORD threadmem[NUM_THREADS];
366 t1Struct tstruct[NUM_THREADS];
372 /* lstrlenA contains an exception handler so this makes sure exceptions work in the main thread */
373 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
375 /* Retrieve current Thread ID for later comparisons */
376 curthreadId=GetCurrentThreadId();
377 /* Allocate some local storage */
378 ok((tlsIndex=TlsAlloc())!=TLS_OUT_OF_INDEXES,"TlsAlloc failed\n");
379 /* Create events for thread synchronization */
380 for(i=0;i<NUM_THREADS;i++) {
382 /* Note that it doesn't matter what type of event we choose here. This
383 test isn't trying to thoroughly test events
385 event[i]=CreateEventA(NULL,TRUE,FALSE,NULL);
386 tstruct[i].threadnum=i;
387 tstruct[i].threadmem=threadmem;
388 tstruct[i].event=event;
391 /* Test that passing arguments to threads works okay */
392 for(i=0;i<NUM_THREADS;i++) {
393 thread[i] = CreateThread(NULL,0,threadFunc1,
394 &tstruct[i],0,&threadid[i]);
395 ok(thread[i]!=NULL,"Create Thread failed\n");
397 /* Test that the threads actually complete */
398 for(i=0;i<NUM_THREADS;i++) {
399 error=WaitForSingleObject(thread[i],5000);
400 ok(error==WAIT_OBJECT_0, "Thread did not complete within timelimit\n");
401 if(error!=WAIT_OBJECT_0) {
402 TerminateThread(thread[i],i+NUM_THREADS);
404 ok(GetExitCodeThread(thread[i],&exitCode),"Could not retrieve ext code\n");
405 ok(exitCode==i+NUM_THREADS,"Thread returned an incorrect exit code\n");
407 /* Test that each thread executed in its parent's address space
408 (it was able to change threadmem and pass that change back to its parent)
409 and that each thread id was independent). Note that we prove that the
410 threads actually execute concurrently by having them block on each other
413 for(i=0;i<NUM_THREADS;i++) {
415 for(j=i+1;j<NUM_THREADS;j++) {
416 if (threadmem[i]==threadmem[j]) {
420 ok(!error && threadmem[i]==threadid[i] && threadmem[i]!=curthreadId,
421 "Thread did not execute successfully\n");
422 ok(CloseHandle(thread[i])!=0,"CloseHandle failed\n");
425 SetLastError(0xCAFEF00D);
426 ok(TlsFree(tlsIndex)!=0,"TlsFree failed: %08x\n", GetLastError());
427 ok(GetLastError()==0xCAFEF00D,
428 "GetLastError: expected 0xCAFEF00D, got %08x\n", GetLastError());
430 /* Test freeing an already freed TLS index */
431 SetLastError(0xCAFEF00D);
432 ok(TlsFree(tlsIndex)==0,"TlsFree succeeded\n");
433 ok(GetLastError()==ERROR_INVALID_PARAMETER,
434 "GetLastError: expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
436 /* Test how passing NULL as a pointer to threadid works */
437 SetLastError(0xFACEaBAD);
438 thread[0] = CreateThread(NULL,0,threadFunc2,NULL,0,&tid);
439 GLE = GetLastError();
440 if (thread[0]) { /* NT */
441 ok(GLE==0xFACEaBAD, "CreateThread set last error to %d, expected 4207848365\n", GLE);
442 ret = WaitForSingleObject(thread[0],100);
443 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
444 ret = GetExitCodeThread(thread[0],&exitCode);
445 ok(ret!=0, "GetExitCodeThread returned %d (expected nonzero)\n", ret);
446 ok(exitCode==99, "threadFunc2 exited with code: %d (expected 99)\n", exitCode);
447 ok(CloseHandle(thread[0])!=0,"Error closing thread handle\n");
450 ok(GLE==ERROR_INVALID_PARAMETER, "CreateThread set last error to %d, expected 87\n", GLE);
454 /* Check that using the CREATE_SUSPENDED flag works */
455 static VOID test_CreateThread_suspended(void)
462 thread = CreateThread(NULL,0,threadFunc2,NULL,
463 CREATE_SUSPENDED,&threadId);
464 ok(thread!=NULL,"Create Thread failed\n");
465 /* Check that the thread is suspended */
466 ok(SuspendThread(thread)==1,"Thread did not start suspended\n");
467 ok(ResumeThread(thread)==2,"Resume thread returned an invalid value\n");
468 /* Check that resume thread didn't actually start the thread. I can't think
469 of a better way of checking this than just waiting. I am not sure if this
470 will work on slow computers.
472 ok(WaitForSingleObject(thread,1000)==WAIT_TIMEOUT,
473 "ResumeThread should not have actually started the thread\n");
474 /* Now actually resume the thread and make sure that it actually completes*/
475 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
476 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
477 "Thread did not resume\n");
478 if(error!=WAIT_OBJECT_0) {
479 TerminateThread(thread,1);
482 suspend_count = SuspendThread(thread);
483 ok(suspend_count == -1, "SuspendThread returned %d, expected -1\n", suspend_count);
485 suspend_count = ResumeThread(thread);
486 ok(suspend_count == 0 ||
487 broken(suspend_count == -1), /* win9x */
488 "ResumeThread returned %d, expected 0\n", suspend_count);
490 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
493 /* Check that SuspendThread and ResumeThread work */
494 static VOID test_SuspendThread(void)
496 HANDLE thread,access_thread;
497 DWORD threadId,exitCode,error;
500 thread = CreateThread(NULL,0,threadFunc3,NULL,
502 ok(thread!=NULL,"Create Thread failed\n");
503 /* Check that the thread is suspended */
504 /* Note that this is a polling method, and there is a race between
505 SuspendThread being called (in the child, and the loop below timing out,
506 so the test could fail on a heavily loaded or slow computer.
509 for(i=0;error==0 && i<100;i++) {
510 error=SuspendThread(thread);
511 ResumeThread(thread);
517 ok(error==1,"SuspendThread did not work\n");
518 /* check that access restrictions are obeyed */
520 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_SUSPEND_RESUME),
522 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
523 if (access_thread!=NULL) {
524 obey_ar(SuspendThread(access_thread)==~0U);
525 obey_ar(ResumeThread(access_thread)==~0U);
526 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
529 /* Double check that the thread really is suspended */
530 ok((error=GetExitCodeThread(thread,&exitCode))!=0 && exitCode==STILL_ACTIVE,
531 "Thread did not really suspend\n");
532 /* Resume the thread, and make sure it actually completes */
533 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
534 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
535 "Thread did not resume\n");
536 if(error!=WAIT_OBJECT_0) {
537 TerminateThread(thread,1);
539 /* Trying to suspend a terminated thread should fail */
540 error=SuspendThread(thread);
541 ok(error==~0U, "wrong return code: %d\n", error);
542 ok(GetLastError()==ERROR_ACCESS_DENIED || GetLastError()==ERROR_NO_MORE_ITEMS, "unexpected error code: %d\n", GetLastError());
544 ok(CloseHandle(thread)!=0,"CloseHandle Failed\n");
547 /* Check that TerminateThread works properly
549 static VOID test_TerminateThread(void)
551 HANDLE thread,access_thread,event;
552 DWORD threadId,exitCode;
553 event=CreateEventA(NULL,TRUE,FALSE,NULL);
554 thread = CreateThread(NULL,0,threadFunc4,event,0,&threadId);
555 ok(thread!=NULL,"Create Thread failed\n");
556 /* TerminateThread has a race condition in Wine. If the thread is terminated
557 before it starts, it leaves a process behind. Therefore, we wait for the
558 thread to signal that it has started. There is no easy way to force the
559 race to occur, so we don't try to find it.
561 ok(WaitForSingleObject(event,5000)==WAIT_OBJECT_0,
562 "TerminateThread didn't work\n");
563 /* check that access restrictions are obeyed */
565 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_TERMINATE),
567 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
568 if (access_thread!=NULL) {
569 obey_ar(TerminateThread(access_thread,99)==0);
570 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
573 /* terminate a job and make sure it terminates */
574 ok(TerminateThread(thread,99)!=0,"TerminateThread failed\n");
575 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
576 "TerminateThread didn't work\n");
577 ok(GetExitCodeThread(thread,&exitCode)!=STILL_ACTIVE,
578 "TerminateThread should not leave the thread 'STILL_ACTIVE'\n");
579 ok(exitCode==99, "TerminateThread returned invalid exit code\n");
580 ok(CloseHandle(thread)!=0,"Error Closing thread handle\n");
583 /* Check if CreateThread obeys the specified stack size. This code does
584 not work properly, and is currently disabled
586 static VOID test_CreateThread_stack(void)
589 /* The only way I know of to test the stack size is to use alloca
590 and __try/__except. However, this is probably not portable,
591 and I couldn't get it to work under Wine anyhow. However, here
592 is the code which should allow for testing that CreateThread
593 respects the stack-size limit
596 DWORD threadId,exitCode;
599 sysInfo.dwPageSize=0;
600 GetSystemInfo(&sysInfo);
601 ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
602 thread = CreateThread(NULL,sysInfo.dwPageSize,
603 threadFunc5,&exitCode,
605 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
606 "TerminateThread didn't work\n");
607 ok(exitCode==1,"CreateThread did not obey stack-size-limit\n");
608 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
612 /* Check whether setting/retrieving thread priorities works */
613 static VOID test_thread_priority(void)
615 HANDLE curthread,access_thread;
616 DWORD curthreadId,exitCode;
617 int min_priority=-2,max_priority=2;
621 curthread=GetCurrentThread();
622 curthreadId=GetCurrentThreadId();
623 /* Check thread priority */
624 /* NOTE: on Win2k/XP priority can be from -7 to 6. All other platforms it
625 is -2 to 2. However, even on a real Win2k system, using thread
626 priorities beyond the -2 to 2 range does not work. If you want to try
627 anyway, enable USE_EXTENDED_PRIORITIES
629 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_NORMAL,
630 "GetThreadPriority Failed\n");
633 /* check that access control is obeyed */
634 access_thread=pOpenThread(THREAD_ALL_ACCESS &
635 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
637 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
638 if (access_thread!=NULL) {
639 obey_ar(SetThreadPriority(access_thread,1)==0);
640 obey_ar(GetThreadPriority(access_thread)==THREAD_PRIORITY_ERROR_RETURN);
641 obey_ar(GetExitCodeThread(access_thread,&exitCode)==0);
642 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
645 #if USE_EXTENDED_PRIORITIES
646 min_priority=-7; max_priority=6;
648 for(i=min_priority;i<=max_priority;i++) {
649 ok(SetThreadPriority(curthread,i)!=0,
650 "SetThreadPriority Failed for priority: %d\n",i);
651 ok(GetThreadPriority(curthread)==i,
652 "GetThreadPriority Failed for priority: %d\n",i);
654 ok(SetThreadPriority(curthread,THREAD_PRIORITY_TIME_CRITICAL)!=0,
655 "SetThreadPriority Failed\n");
656 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_TIME_CRITICAL,
657 "GetThreadPriority Failed\n");
658 ok(SetThreadPriority(curthread,THREAD_PRIORITY_IDLE)!=0,
659 "SetThreadPriority Failed\n");
660 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_IDLE,
661 "GetThreadPriority Failed\n");
662 ok(SetThreadPriority(curthread,0)!=0,"SetThreadPriority Failed\n");
664 /* Check that the thread priority is not changed if SetThreadPriority
665 is called with a value outside of the max/min range */
666 SetThreadPriority(curthread,min_priority);
667 SetLastError(0xdeadbeef);
668 rc = SetThreadPriority(curthread,min_priority-1);
670 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
671 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
672 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
673 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
675 ok(GetThreadPriority(curthread)==min_priority,
676 "GetThreadPriority didn't return min_priority\n");
678 SetThreadPriority(curthread,max_priority);
679 SetLastError(0xdeadbeef);
680 rc = SetThreadPriority(curthread,max_priority+1);
682 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
683 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
684 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
685 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
687 ok(GetThreadPriority(curthread)==max_priority,
688 "GetThreadPriority didn't return max_priority\n");
690 /* Check thread priority boost */
691 if (!pGetThreadPriorityBoost || !pSetThreadPriorityBoost)
694 SetLastError(0xdeadbeef);
695 rc=pGetThreadPriorityBoost(curthread,&disabled);
696 if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
698 win_skip("GetThreadPriorityBoost is not implemented on WinME\n");
702 ok(rc!=0,"error=%d\n",GetLastError());
705 /* check that access control is obeyed */
706 access_thread=pOpenThread(THREAD_ALL_ACCESS &
707 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
709 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
710 if (access_thread!=NULL) {
711 obey_ar(pSetThreadPriorityBoost(access_thread,1)==0);
712 todo_wine obey_ar(pGetThreadPriorityBoost(access_thread,&disabled)==0);
713 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
718 rc = pSetThreadPriorityBoost(curthread,1);
719 ok( rc != 0, "error=%d\n",GetLastError());
720 rc=pGetThreadPriorityBoost(curthread,&disabled);
721 ok(rc!=0 && disabled==1,
722 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
724 rc = pSetThreadPriorityBoost(curthread,0);
725 ok( rc != 0, "error=%d\n",GetLastError());
727 rc=pGetThreadPriorityBoost(curthread,&disabled);
728 ok(rc!=0 && disabled==0,
729 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
732 /* check the GetThreadTimes function */
733 static VOID test_GetThreadTimes(void)
735 HANDLE thread,access_thread=NULL;
736 FILETIME creationTime,exitTime,kernelTime,userTime;
740 thread = CreateThread(NULL,0,threadFunc2,NULL,
741 CREATE_SUSPENDED,&threadId);
743 ok(thread!=NULL,"Create Thread failed\n");
744 /* check that access control is obeyed */
746 access_thread=pOpenThread(THREAD_ALL_ACCESS &
747 (~THREAD_QUERY_INFORMATION), 0,threadId);
748 ok(access_thread!=NULL,
749 "OpenThread returned an invalid handle\n");
751 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
752 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
753 "ResumeThread didn't work\n");
754 creationTime.dwLowDateTime=99; creationTime.dwHighDateTime=99;
755 exitTime.dwLowDateTime=99; exitTime.dwHighDateTime=99;
756 kernelTime.dwLowDateTime=99; kernelTime.dwHighDateTime=99;
757 userTime.dwLowDateTime=99; userTime.dwHighDateTime=99;
758 /* GetThreadTimes should set all of the parameters passed to it */
759 error=GetThreadTimes(thread,&creationTime,&exitTime,
760 &kernelTime,&userTime);
762 if (error == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
763 win_skip("GetThreadTimes is not implemented\n");
765 ok(error!=0,"GetThreadTimes failed\n");
766 ok(creationTime.dwLowDateTime!=99 || creationTime.dwHighDateTime!=99,
767 "creationTime was invalid\n");
768 ok(exitTime.dwLowDateTime!=99 || exitTime.dwHighDateTime!=99,
769 "exitTime was invalid\n");
770 ok(kernelTime.dwLowDateTime!=99 || kernelTime.dwHighDateTime!=99,
771 "kernelTimewas invalid\n");
772 ok(userTime.dwLowDateTime!=99 || userTime.dwHighDateTime!=99,
773 "userTime was invalid\n");
774 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
775 if(access_thread!=NULL)
777 error=GetThreadTimes(access_thread,&creationTime,&exitTime,
778 &kernelTime,&userTime);
782 if(access_thread!=NULL) {
783 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
787 /* Check the processor affinity functions */
788 /* NOTE: These functions should also be checked that they obey access control
790 static VOID test_thread_processor(void)
792 HANDLE curthread,curproc;
793 DWORD_PTR processMask,systemMask,retMask;
798 if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
800 sysInfo.dwNumberOfProcessors=0;
801 GetSystemInfo(&sysInfo);
802 ok(sysInfo.dwNumberOfProcessors>0,
803 "GetSystemInfo failed to return a valid # of processors\n");
804 /* Use the current Thread/process for all tests */
805 curthread=GetCurrentThread();
806 ok(curthread!=NULL,"GetCurrentThread failed\n");
807 curproc=GetCurrentProcess();
808 ok(curproc!=NULL,"GetCurrentProcess failed\n");
809 /* Check the Affinity Mask functions */
810 ok(GetProcessAffinityMask(curproc,&processMask,&systemMask)!=0,
811 "GetProcessAffinityMask failed\n");
812 ok(SetThreadAffinityMask(curthread,processMask)==processMask,
813 "SetThreadAffinityMask failed\n");
814 ok(SetThreadAffinityMask(curthread,processMask+1)==0,
815 "SetThreadAffinityMask passed for an illegal processor\n");
816 /* NOTE: Pre-Vista does not recognize the "all processors" flag (all bits set) */
817 retMask = SetThreadAffinityMask(curthread,~0UL);
818 ok(broken(retMask==0) || retMask==processMask,
819 "SetThreadAffinityMask(thread,-1) failed to request all processors.\n");
820 /* NOTE: This only works on WinNT/2000/XP) */
821 if (pSetThreadIdealProcessor) {
822 SetLastError(0xdeadbeef);
823 error=pSetThreadIdealProcessor(curthread,0);
824 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
826 win_skip("SetThreadIdealProcessor is not implemented\n");
829 ok(error!=-1, "SetThreadIdealProcessor failed\n");
833 SetLastError(0xdeadbeef);
834 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
836 ok(error!=-1, "SetThreadIdealProcessor failed for %u on Wow64\n", MAXIMUM_PROCESSORS+1);
838 SetLastError(0xdeadbeef);
839 error=pSetThreadIdealProcessor(curthread,65);
840 ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
841 ok(GetLastError()==ERROR_INVALID_PARAMETER,
842 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
846 SetLastError(0xdeadbeef);
847 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
848 ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
849 ok(GetLastError()==ERROR_INVALID_PARAMETER,
850 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
853 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS);
854 ok(error==0, "SetThreadIdealProcessor returned an incorrect value\n");
858 static VOID test_GetThreadExitCode(void)
860 DWORD exitCode, threadid;
864 ret = GetExitCodeThread((HANDLE)0x2bad2bad,&exitCode);
865 ok(ret==0, "GetExitCodeThread returned non zero value: %d\n", ret);
866 GLE = GetLastError();
867 ok(GLE==ERROR_INVALID_HANDLE, "GetLastError returned %d (expected 6)\n", GLE);
869 thread = CreateThread(NULL,0,threadFunc2,NULL,0,&threadid);
870 ret = WaitForSingleObject(thread,100);
871 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
872 ret = GetExitCodeThread(thread,&exitCode);
873 ok(ret==exitCode || ret==1,
874 "GetExitCodeThread returned %d (expected 1 or %d)\n", ret, exitCode);
875 ok(exitCode==99, "threadFunc2 exited with code %d (expected 99)\n", exitCode);
876 ok(CloseHandle(thread)!=0,"Error closing thread handle\n");
881 static int test_value = 0;
884 static void WINAPI set_test_val( int val )
889 static DWORD WINAPI threadFunc6(LPVOID p)
893 test_value *= (int)p;
897 static void test_SetThreadContext(void)
906 SetLastError(0xdeadbeef);
907 event = CreateEvent( NULL, TRUE, FALSE, NULL );
908 thread = CreateThread( NULL, 0, threadFunc6, (void *)2, 0, &threadid );
909 ok( thread != NULL, "CreateThread failed : (%d)\n", GetLastError() );
912 trace("Thread creation failed, skipping rest of test\n");
915 WaitForSingleObject( event, INFINITE );
916 SuspendThread( thread );
917 CloseHandle( event );
919 ctx.ContextFlags = CONTEXT_FULL;
920 SetLastError(0xdeadbeef);
921 ret = GetThreadContext( thread, &ctx );
922 ok( ret, "GetThreadContext failed : (%u)\n", GetLastError() );
926 /* simulate a call to set_test_val(10) */
927 stack = (int *)ctx.Esp;
930 ctx.Esp -= 2 * sizeof(int *);
931 ctx.Eip = (DWORD)set_test_val;
932 SetLastError(0xdeadbeef);
933 ok( SetThreadContext( thread, &ctx ), "SetThreadContext failed : (%d)\n", GetLastError() );
936 SetLastError(0xdeadbeef);
937 prevcount = ResumeThread( thread );
938 ok ( prevcount == 1, "Previous suspend count (%d) instead of 1, last error : (%d)\n",
939 prevcount, GetLastError() );
941 WaitForSingleObject( thread, INFINITE );
942 ok( test_value == 20, "test_value %d instead of 20\n", test_value );
945 #endif /* __i386__ */
947 static HANDLE finish_event;
948 static LONG times_executed;
950 static DWORD CALLBACK work_function(void *p)
952 LONG executed = InterlockedIncrement(×_executed);
955 SetEvent(finish_event);
959 static void test_QueueUserWorkItem(void)
965 /* QueueUserWorkItem not present on win9x */
966 if (!pQueueUserWorkItem) return;
968 finish_event = CreateEvent(NULL, TRUE, FALSE, NULL);
970 before = GetTickCount();
972 for (i = 0; i < 100; i++)
974 BOOL ret = pQueueUserWorkItem(work_function, (void *)i, WT_EXECUTEDEFAULT);
975 ok(ret, "QueueUserWorkItem failed with error %d\n", GetLastError());
978 wait_result = WaitForSingleObject(finish_event, 10000);
980 after = GetTickCount();
981 trace("100 QueueUserWorkItem calls took %dms\n", after - before);
982 ok(wait_result == WAIT_OBJECT_0, "wait failed with error 0x%x\n", wait_result);
984 ok(times_executed == 100, "didn't execute all of the work items\n");
987 static void CALLBACK signaled_function(PVOID p, BOOLEAN TimerOrWaitFired)
991 ok(!TimerOrWaitFired, "wait shouldn't have timed out\n");
994 static void CALLBACK timeout_function(PVOID p, BOOLEAN TimerOrWaitFired)
998 ok(TimerOrWaitFired, "wait should have timed out\n");
1001 static void test_RegisterWaitForSingleObject(void)
1006 HANDLE complete_event;
1008 if (!pRegisterWaitForSingleObject || !pUnregisterWait)
1010 win_skip("RegisterWaitForSingleObject or UnregisterWait not implemented\n");
1014 /* test signaled case */
1016 handle = CreateEvent(NULL, TRUE, TRUE, NULL);
1017 complete_event = CreateEvent(NULL, FALSE, FALSE, NULL);
1019 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1020 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1022 WaitForSingleObject(complete_event, INFINITE);
1023 /* give worker thread chance to complete */
1026 ret = pUnregisterWait(wait_handle);
1027 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1029 /* test cancel case */
1033 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1034 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1036 ret = pUnregisterWait(wait_handle);
1037 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1039 /* test timeout case */
1041 ret = pRegisterWaitForSingleObject(&wait_handle, handle, timeout_function, complete_event, 0, WT_EXECUTEONLYONCE);
1042 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1044 WaitForSingleObject(complete_event, INFINITE);
1045 /* give worker thread chance to complete */
1048 ret = pUnregisterWait(wait_handle);
1049 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1052 static DWORD TLS_main;
1053 static DWORD TLS_index0, TLS_index1;
1055 static DWORD WINAPI TLS_InheritanceProc(LPVOID p)
1057 /* We should NOT inherit the TLS values from our parent or from the
1061 val = TlsGetValue(TLS_main);
1062 ok(val == NULL, "TLS inheritance failed\n");
1064 val = TlsGetValue(TLS_index0);
1065 ok(val == NULL, "TLS inheritance failed\n");
1067 val = TlsGetValue(TLS_index1);
1068 ok(val == NULL, "TLS inheritance failed\n");
1073 /* Basic TLS usage test. Make sure we can create slots and the values we
1074 store in them are separate among threads. Also test TLS value
1075 inheritance with TLS_InheritanceProc. */
1076 static DWORD WINAPI TLS_ThreadProc(LPVOID p)
1078 LONG_PTR id = (LONG_PTR) p;
1082 if (sync_threads_and_run_one(0, id))
1084 TLS_index0 = TlsAlloc();
1085 ok(TLS_index0 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1089 if (sync_threads_and_run_one(1, id))
1091 TLS_index1 = TlsAlloc();
1092 ok(TLS_index1 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1094 /* Slot indices should be different even if created in different
1096 ok(TLS_index0 != TLS_index1, "TlsAlloc failed\n");
1098 /* Both slots should be initialized to NULL */
1099 val = TlsGetValue(TLS_index0);
1100 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1101 ok(val == NULL, "TLS slot not initialized correctly\n");
1103 val = TlsGetValue(TLS_index1);
1104 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1105 ok(val == NULL, "TLS slot not initialized correctly\n");
1109 if (sync_threads_and_run_one(0, id))
1111 val = TlsGetValue(TLS_index0);
1112 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1113 ok(val == NULL, "TLS slot not initialized correctly\n");
1115 val = TlsGetValue(TLS_index1);
1116 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1117 ok(val == NULL, "TLS slot not initialized correctly\n");
1119 ret = TlsSetValue(TLS_index0, (LPVOID) 1);
1120 ok(ret, "TlsSetValue failed\n");
1122 ret = TlsSetValue(TLS_index1, (LPVOID) 2);
1123 ok(ret, "TlsSetValue failed\n");
1125 val = TlsGetValue(TLS_index0);
1126 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1127 ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1129 val = TlsGetValue(TLS_index1);
1130 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1131 ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1135 if (sync_threads_and_run_one(1, id))
1137 val = TlsGetValue(TLS_index0);
1138 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1139 ok(val == NULL, "TLS slot not initialized correctly\n");
1141 val = TlsGetValue(TLS_index1);
1142 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1143 ok(val == NULL, "TLS slot not initialized correctly\n");
1145 ret = TlsSetValue(TLS_index0, (LPVOID) 3);
1146 ok(ret, "TlsSetValue failed\n");
1148 ret = TlsSetValue(TLS_index1, (LPVOID) 4);
1149 ok(ret, "TlsSetValue failed\n");
1151 val = TlsGetValue(TLS_index0);
1152 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1153 ok(val == (LPVOID) 3, "TLS slot not initialized correctly\n");
1155 val = TlsGetValue(TLS_index1);
1156 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1157 ok(val == (LPVOID) 4, "TLS slot not initialized correctly\n");
1161 if (sync_threads_and_run_one(0, id))
1166 val = TlsGetValue(TLS_index0);
1167 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1168 ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1170 val = TlsGetValue(TLS_index1);
1171 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1172 ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1174 thread = CreateThread(NULL, 0, TLS_InheritanceProc, 0, 0, &tid);
1175 ok(thread != NULL, "CreateThread failed\n");
1176 waitret = WaitForSingleObject(thread, 60000);
1177 ok(waitret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
1178 CloseHandle(thread);
1180 ret = TlsFree(TLS_index0);
1181 ok(ret, "TlsFree failed\n");
1185 if (sync_threads_and_run_one(1, id))
1187 ret = TlsFree(TLS_index1);
1188 ok(ret, "TlsFree failed\n");
1195 static void test_TLS(void)
1202 init_thread_sync_helpers();
1204 /* Allocate a TLS slot in the main thread to test for inheritance. */
1205 TLS_main = TlsAlloc();
1206 ok(TLS_main != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1207 suc = TlsSetValue(TLS_main, (LPVOID) 4114);
1208 ok(suc, "TlsSetValue failed\n");
1210 for (i = 0; i < 2; ++i)
1214 threads[i] = CreateThread(NULL, 0, TLS_ThreadProc, (LPVOID) i, 0, &tid);
1215 ok(threads[i] != NULL, "CreateThread failed\n");
1218 ret = WaitForMultipleObjects(2, threads, TRUE, 60000);
1219 ok(ret == WAIT_OBJECT_0 || ret == WAIT_OBJECT_0+1 /* nt4 */, "WaitForMultipleObjects failed %u\n",ret);
1221 for (i = 0; i < 2; ++i)
1222 CloseHandle(threads[i]);
1224 suc = TlsFree(TLS_main);
1225 ok(suc, "TlsFree failed\n");
1226 cleanup_thread_sync_helpers();
1229 static void test_ThreadErrorMode(void)
1236 if (!pSetThreadErrorMode || !pGetThreadErrorMode)
1238 win_skip("SetThreadErrorMode and/or GetThreadErrorMode unavailable (added in Windows 7)\n");
1242 if (!pRtlGetThreadErrorMode) {
1243 win_skip("RtlGetThreadErrorMode not available\n");
1247 oldmode = pGetThreadErrorMode();
1249 ret = pSetThreadErrorMode(0, &mode);
1250 ok(ret, "SetThreadErrorMode failed\n");
1252 "SetThreadErrorMode returned old mode 0x%x, expected 0x%x\n",
1254 mode = pGetThreadErrorMode();
1255 ok(mode == 0, "GetThreadErrorMode returned mode 0x%x, expected 0\n", mode);
1256 rtlmode = pRtlGetThreadErrorMode();
1258 "RtlGetThreadErrorMode returned mode 0x%x, expected 0\n", mode);
1260 ret = pSetThreadErrorMode(SEM_FAILCRITICALERRORS, &mode);
1261 ok(ret, "SetThreadErrorMode failed\n");
1263 "SetThreadErrorMode returned old mode 0x%x, expected 0\n", mode);
1264 mode = pGetThreadErrorMode();
1265 ok(mode == SEM_FAILCRITICALERRORS,
1266 "GetThreadErrorMode returned mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1268 rtlmode = pRtlGetThreadErrorMode();
1270 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x10\n", mode);
1272 ret = pSetThreadErrorMode(SEM_NOGPFAULTERRORBOX, &mode);
1273 ok(ret, "SetThreadErrorMode failed\n");
1274 ok(mode == SEM_FAILCRITICALERRORS,
1275 "SetThreadErrorMode returned old mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1277 mode = pGetThreadErrorMode();
1278 ok(mode == SEM_NOGPFAULTERRORBOX,
1279 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOGPFAULTERRORBOX\n",
1281 rtlmode = pRtlGetThreadErrorMode();
1283 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x20\n", mode);
1285 ret = pSetThreadErrorMode(SEM_NOOPENFILEERRORBOX, NULL);
1286 ok(ret, "SetThreadErrorMode failed\n");
1287 mode = pGetThreadErrorMode();
1288 ok(mode == SEM_NOOPENFILEERRORBOX,
1289 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOOPENFILEERRORBOX\n",
1291 rtlmode = pRtlGetThreadErrorMode();
1293 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x40\n", rtlmode);
1295 for (mode = 1; mode; mode <<= 1)
1297 ret = pSetThreadErrorMode(mode, NULL);
1298 if (mode & (SEM_FAILCRITICALERRORS |
1299 SEM_NOGPFAULTERRORBOX |
1300 SEM_NOOPENFILEERRORBOX))
1303 "SetThreadErrorMode(0x%x,NULL) failed with error %d\n",
1304 mode, GetLastError());
1308 DWORD GLE = GetLastError();
1310 "SetThreadErrorMode(0x%x,NULL) succeeded, expected failure\n",
1312 ok(GLE == ERROR_INVALID_PARAMETER,
1313 "SetThreadErrorMode(0x%x,NULL) failed with %d, "
1314 "expected ERROR_INVALID_PARAMETER\n",
1319 pSetThreadErrorMode(oldmode, NULL);
1328 argc = winetest_get_mainargs( &argv );
1329 /* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
1330 so that the compile passes
1332 lib=GetModuleHandleA("kernel32.dll");
1333 ok(lib!=NULL,"Couldn't get a handle for kernel32.dll\n");
1334 pGetThreadPriorityBoost=(void *)GetProcAddress(lib,"GetThreadPriorityBoost");
1335 pOpenThread=(void *)GetProcAddress(lib,"OpenThread");
1336 pQueueUserWorkItem=(void *)GetProcAddress(lib,"QueueUserWorkItem");
1337 pSetThreadIdealProcessor=(void *)GetProcAddress(lib,"SetThreadIdealProcessor");
1338 pSetThreadPriorityBoost=(void *)GetProcAddress(lib,"SetThreadPriorityBoost");
1339 pRegisterWaitForSingleObject=(void *)GetProcAddress(lib,"RegisterWaitForSingleObject");
1340 pUnregisterWait=(void *)GetProcAddress(lib,"UnregisterWait");
1341 pIsWow64Process=(void *)GetProcAddress(lib,"IsWow64Process");
1342 pSetThreadErrorMode=(void *)GetProcAddress(lib,"SetThreadErrorMode");
1343 pGetThreadErrorMode=(void *)GetProcAddress(lib,"GetThreadErrorMode");
1345 ntdll=GetModuleHandleA("ntdll.dll");
1348 pRtlGetThreadErrorMode=(void *)GetProcAddress(ntdll,"RtlGetThreadErrorMode");
1353 if (!strcmp(argv[2], "sleep"))
1355 HANDLE hAddrEvents[2];
1356 create_function_addr_events(hAddrEvents);
1357 SetEvent(hAddrEvents[0]);
1358 SetEvent(hAddrEvents[1]);
1359 Sleep(5000); /* spawned process runs for at most 5 seconds */
1366 hThread = CreateThread(NULL, 0, threadFunc2, NULL, 0, &tid);
1367 ok(hThread != NULL, "CreateThread failed, error %u\n",
1369 ok(WaitForSingleObject(hThread, 200) == WAIT_OBJECT_0,
1370 "Thread did not exit in time\n");
1371 if (hThread == NULL) break;
1372 CloseHandle(hThread);
1377 test_CreateRemoteThread();
1378 test_CreateThread_basic();
1379 test_CreateThread_suspended();
1380 test_SuspendThread();
1381 test_TerminateThread();
1382 test_CreateThread_stack();
1383 test_thread_priority();
1384 test_GetThreadTimes();
1385 test_thread_processor();
1386 test_GetThreadExitCode();
1388 test_SetThreadContext();
1390 test_QueueUserWorkItem();
1391 test_RegisterWaitForSingleObject();
1393 test_ThreadErrorMode();