d3dx9: Implement ID3DXBaseEffect::GetAnnotation().
[wine/multimedia.git] / dlls / kernel32 / tests / thread.c
blob25b55acbdfbf9c1ac1437ddb78b6e0dd01b75591
1 /*
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
24 #include <assert.h>
25 #include <stdarg.h>
26 #include <stdio.h>
28 #include "wine/test.h"
29 #include <windef.h>
30 #include <winbase.h>
31 #include <winnt.h>
32 #include <winerror.h>
34 /* Specify the number of simultaneous threads to test */
35 #define NUM_THREADS 4
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 */
39 #define CHECK_STACK 0
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
47 #if CHECK_STACK
48 # ifdef __try
49 # define __TRY __try
50 # define __EXCEPT __except
51 # define __ENDTRY
52 # else
53 # include "wine/exception.h"
54 # endif
55 #endif
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)
71 char **argv;
72 char cmdline[MAX_PATH];
73 PROCESS_INFORMATION pi;
74 BOOL ret;
75 STARTUPINFO si = { 0 };
76 si.cb = sizeof(si);
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());
84 return pi.hProcess;
87 /* Functions not tested yet:
88 AttachThreadInput
89 SetThreadContext
90 SwitchToThread
92 In addition there are no checks that the inheritance works properly in
93 CreateThread
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");
109 num_synced = -1;
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);
116 if (num == 1)
118 ResetEvent( stop_event );
119 SetEvent( start_event );
121 else
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);
133 if (num == -1)
135 ResetEvent( start_event );
136 SetEvent( stop_event );
138 else
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;
153 typedef struct {
154 int threadnum;
155 HANDLE *event;
156 DWORD *threadmem;
157 } t1Struct;
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 */
163 #define obey_ar(x) \
164 (obeying_ars == 0 \
165 ? ((x) \
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;
180 int i;
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)
208 return 99;
211 static DWORD WINAPI threadFunc3(LPVOID p)
213 HANDLE thread;
214 thread=GetCurrentThread();
215 SuspendThread(thread);
216 return 99;
219 static DWORD WINAPI threadFunc4(LPVOID p)
221 HANDLE event = p;
222 if(event != NULL) {
223 SetEvent(event);
225 Sleep(99000);
226 return 0;
229 #if CHECK_STACK
230 static DWORD WINAPI threadFunc5(LPVOID p)
232 DWORD *exitCode = p;
233 SYSTEM_INFO sysInfo;
234 sysInfo.dwPageSize=0;
235 GetSystemInfo(&sysInfo);
236 *exitCode=0;
237 __TRY
239 alloca(2*sysInfo.dwPageSize);
241 __EXCEPT(1) {
242 *exitCode=1;
244 __ENDTRY
245 return 0;
247 #endif
249 static DWORD WINAPI threadFunc_SetEvent(LPVOID p)
251 SetEvent(p);
252 return 0;
255 static DWORD WINAPI threadFunc_CloseHandle(LPVOID p)
257 CloseHandle(p);
258 return 0;
261 static void create_function_addr_events(HANDLE events[2])
263 char buffer[256];
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");
289 return;
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");
305 goto cleanup;
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,
341 threadFunc_SetEvent,
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);
355 cleanup:
356 TerminateProcess(hProcess, 0);
357 CloseHandle(hEvent);
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];
367 DWORD exitCode;
368 t1Struct tstruct[NUM_THREADS];
369 int error;
370 DWORD i,j;
371 DWORD GLE, ret;
372 DWORD tid;
373 BOOL bRet;
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++) {
384 threadmem[i]=0;
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
414 in threadFunc1
416 for(i=0;i<NUM_THREADS;i++) {
417 error=0;
418 for(j=i+1;j<NUM_THREADS;j++) {
419 if (threadmem[i]==threadmem[j]) {
420 error=1;
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");
453 else { /* 9x */
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)
461 HANDLE thread;
462 DWORD threadId;
463 DWORD suspend_count;
464 int error;
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;
502 int i;
504 thread = CreateThread(NULL,0,threadFunc3,NULL,
505 0,&threadId);
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.
512 error=0;
513 for(i=0;error==0 && i<100;i++) {
514 error=SuspendThread(thread);
515 ResumeThread(thread);
516 if(error==0) {
517 Sleep(50);
518 i++;
521 ok(error==1,"SuspendThread did not work\n");
522 /* check that access restrictions are obeyed */
523 if (pOpenThread) {
524 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_SUSPEND_RESUME),
525 0,threadId);
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 */
568 if (pOpenThread) {
569 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_TERMINATE),
570 0,threadId);
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)
592 #if CHECK_STACK
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
599 HANDLE thread;
600 DWORD threadId,exitCode;
602 SYSTEM_INFO sysInfo;
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,
608 0,&threadId);
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");
613 #endif
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;
622 BOOL disabled,rc;
623 int i;
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");
636 if (pOpenThread) {
637 /* check that access control is obeyed */
638 access_thread=pOpenThread(THREAD_ALL_ACCESS &
639 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
640 0,curthreadId);
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;
651 #endif
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",
678 GetLastError());
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",
690 GetLastError());
691 ok(GetThreadPriority(curthread)==max_priority,
692 "GetThreadPriority didn't return max_priority\n");
694 /* Check thread priority boost */
695 if (!pGetThreadPriorityBoost || !pSetThreadPriorityBoost)
696 return; /* Win9x */
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");
703 return;
706 ok(rc!=0,"error=%d\n",GetLastError());
708 if (pOpenThread) {
709 /* check that access control is obeyed */
710 access_thread=pOpenThread(THREAD_ALL_ACCESS &
711 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
712 0,curthreadId);
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");
721 todo_wine {
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;
741 DWORD threadId;
742 int error;
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 */
749 if (pOpenThread) {
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");
768 else {
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);
783 obey_ar(error==0);
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;
798 SYSTEM_INFO sysInfo;
799 int error=0;
800 BOOL is_wow64;
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");
841 return;
843 ok(error!=-1, "SetThreadIdealProcessor failed\n");
845 if (is_wow64)
847 SetLastError(0xdeadbeef);
848 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
849 todo_wine
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());
858 else
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;
875 DWORD GLE, ret;
876 HANDLE thread;
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");
893 #ifdef __i386__
895 static int test_value = 0;
896 static HANDLE event;
898 static void WINAPI set_test_val( int val )
900 test_value += val;
903 static DWORD WINAPI threadFunc6(LPVOID p)
905 SetEvent( event );
906 Sleep( 1000 );
907 test_value *= (int)p;
908 return 0;
911 static void test_SetThreadContext(void)
913 CONTEXT ctx;
914 int *stack;
915 HANDLE thread;
916 DWORD threadid;
917 DWORD prevcount;
918 BOOL ret;
920 SetLastError(0xdeadbeef);
921 event = CreateEvent( NULL, TRUE, FALSE, NULL );
922 thread = CreateThread( NULL, 0, threadFunc6, (void *)2, 0, &threadid );
923 ok( thread != NULL, "CreateThread failed : (%d)\n", GetLastError() );
924 if (!thread)
926 trace("Thread creation failed, skipping rest of test\n");
927 return;
929 WaitForSingleObject( event, INFINITE );
930 SuspendThread( thread );
931 CloseHandle( event );
933 ctx.ContextFlags = CONTEXT_FULL;
934 SetLastError(0xdeadbeef);
935 ret = GetThreadContext( thread, &ctx );
936 ok( ret, "GetThreadContext failed : (%u)\n", GetLastError() );
938 if (ret)
940 /* simulate a call to set_test_val(10) */
941 stack = (int *)ctx.Esp;
942 stack[-1] = 10;
943 stack[-2] = ctx.Eip;
944 ctx.Esp -= 2 * sizeof(int *);
945 ctx.Eip = (DWORD)set_test_val;
946 SetLastError(0xdeadbeef);
947 ret = SetThreadContext( thread, &ctx );
948 ok( ret, "SetThreadContext failed : (%d)\n", GetLastError() );
951 SetLastError(0xdeadbeef);
952 prevcount = ResumeThread( thread );
953 ok ( prevcount == 1, "Previous suspend count (%d) instead of 1, last error : (%d)\n",
954 prevcount, GetLastError() );
956 WaitForSingleObject( thread, INFINITE );
957 ok( test_value == 20, "test_value %d instead of 20\n", test_value );
960 #endif /* __i386__ */
962 static HANDLE finish_event;
963 static LONG times_executed;
965 static DWORD CALLBACK work_function(void *p)
967 LONG executed = InterlockedIncrement(&times_executed);
969 if (executed == 100)
970 SetEvent(finish_event);
971 return 0;
974 static void test_QueueUserWorkItem(void)
976 INT_PTR i;
977 DWORD wait_result;
978 DWORD before, after;
980 /* QueueUserWorkItem not present on win9x */
981 if (!pQueueUserWorkItem) return;
983 finish_event = CreateEvent(NULL, TRUE, FALSE, NULL);
985 before = GetTickCount();
987 for (i = 0; i < 100; i++)
989 BOOL ret = pQueueUserWorkItem(work_function, (void *)i, WT_EXECUTEDEFAULT);
990 ok(ret, "QueueUserWorkItem failed with error %d\n", GetLastError());
993 wait_result = WaitForSingleObject(finish_event, 10000);
995 after = GetTickCount();
996 trace("100 QueueUserWorkItem calls took %dms\n", after - before);
997 ok(wait_result == WAIT_OBJECT_0, "wait failed with error 0x%x\n", wait_result);
999 ok(times_executed == 100, "didn't execute all of the work items\n");
1002 static void CALLBACK signaled_function(PVOID p, BOOLEAN TimerOrWaitFired)
1004 HANDLE event = p;
1005 SetEvent(event);
1006 ok(!TimerOrWaitFired, "wait shouldn't have timed out\n");
1009 static void CALLBACK timeout_function(PVOID p, BOOLEAN TimerOrWaitFired)
1011 HANDLE event = p;
1012 SetEvent(event);
1013 ok(TimerOrWaitFired, "wait should have timed out\n");
1016 static void test_RegisterWaitForSingleObject(void)
1018 BOOL ret;
1019 HANDLE wait_handle;
1020 HANDLE handle;
1021 HANDLE complete_event;
1023 if (!pRegisterWaitForSingleObject || !pUnregisterWait)
1025 win_skip("RegisterWaitForSingleObject or UnregisterWait not implemented\n");
1026 return;
1029 /* test signaled case */
1031 handle = CreateEvent(NULL, TRUE, TRUE, NULL);
1032 complete_event = CreateEvent(NULL, FALSE, FALSE, NULL);
1034 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1035 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1037 WaitForSingleObject(complete_event, INFINITE);
1038 /* give worker thread chance to complete */
1039 Sleep(100);
1041 ret = pUnregisterWait(wait_handle);
1042 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1044 /* test cancel case */
1046 ResetEvent(handle);
1048 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1049 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1051 ret = pUnregisterWait(wait_handle);
1052 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1054 /* test timeout case */
1056 ret = pRegisterWaitForSingleObject(&wait_handle, handle, timeout_function, complete_event, 0, WT_EXECUTEONLYONCE);
1057 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1059 WaitForSingleObject(complete_event, INFINITE);
1060 /* give worker thread chance to complete */
1061 Sleep(100);
1063 ret = pUnregisterWait(wait_handle);
1064 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1067 static DWORD TLS_main;
1068 static DWORD TLS_index0, TLS_index1;
1070 static DWORD WINAPI TLS_InheritanceProc(LPVOID p)
1072 /* We should NOT inherit the TLS values from our parent or from the
1073 main thread. */
1074 LPVOID val;
1076 val = TlsGetValue(TLS_main);
1077 ok(val == NULL, "TLS inheritance failed\n");
1079 val = TlsGetValue(TLS_index0);
1080 ok(val == NULL, "TLS inheritance failed\n");
1082 val = TlsGetValue(TLS_index1);
1083 ok(val == NULL, "TLS inheritance failed\n");
1085 return 0;
1088 /* Basic TLS usage test. Make sure we can create slots and the values we
1089 store in them are separate among threads. Also test TLS value
1090 inheritance with TLS_InheritanceProc. */
1091 static DWORD WINAPI TLS_ThreadProc(LPVOID p)
1093 LONG_PTR id = (LONG_PTR) p;
1094 LPVOID val;
1095 BOOL ret;
1097 if (sync_threads_and_run_one(0, id))
1099 TLS_index0 = TlsAlloc();
1100 ok(TLS_index0 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1102 resync_after_run();
1104 if (sync_threads_and_run_one(1, id))
1106 TLS_index1 = TlsAlloc();
1107 ok(TLS_index1 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1109 /* Slot indices should be different even if created in different
1110 threads. */
1111 ok(TLS_index0 != TLS_index1, "TlsAlloc failed\n");
1113 /* Both slots should be initialized to NULL */
1114 val = TlsGetValue(TLS_index0);
1115 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1116 ok(val == NULL, "TLS slot not initialized correctly\n");
1118 val = TlsGetValue(TLS_index1);
1119 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1120 ok(val == NULL, "TLS slot not initialized correctly\n");
1122 resync_after_run();
1124 if (sync_threads_and_run_one(0, id))
1126 val = TlsGetValue(TLS_index0);
1127 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1128 ok(val == NULL, "TLS slot not initialized correctly\n");
1130 val = TlsGetValue(TLS_index1);
1131 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1132 ok(val == NULL, "TLS slot not initialized correctly\n");
1134 ret = TlsSetValue(TLS_index0, (LPVOID) 1);
1135 ok(ret, "TlsSetValue failed\n");
1137 ret = TlsSetValue(TLS_index1, (LPVOID) 2);
1138 ok(ret, "TlsSetValue failed\n");
1140 val = TlsGetValue(TLS_index0);
1141 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1142 ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1144 val = TlsGetValue(TLS_index1);
1145 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1146 ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1148 resync_after_run();
1150 if (sync_threads_and_run_one(1, id))
1152 val = TlsGetValue(TLS_index0);
1153 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1154 ok(val == NULL, "TLS slot not initialized correctly\n");
1156 val = TlsGetValue(TLS_index1);
1157 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1158 ok(val == NULL, "TLS slot not initialized correctly\n");
1160 ret = TlsSetValue(TLS_index0, (LPVOID) 3);
1161 ok(ret, "TlsSetValue failed\n");
1163 ret = TlsSetValue(TLS_index1, (LPVOID) 4);
1164 ok(ret, "TlsSetValue failed\n");
1166 val = TlsGetValue(TLS_index0);
1167 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1168 ok(val == (LPVOID) 3, "TLS slot not initialized correctly\n");
1170 val = TlsGetValue(TLS_index1);
1171 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1172 ok(val == (LPVOID) 4, "TLS slot not initialized correctly\n");
1174 resync_after_run();
1176 if (sync_threads_and_run_one(0, id))
1178 HANDLE thread;
1179 DWORD waitret, tid;
1181 val = TlsGetValue(TLS_index0);
1182 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1183 ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1185 val = TlsGetValue(TLS_index1);
1186 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1187 ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1189 thread = CreateThread(NULL, 0, TLS_InheritanceProc, 0, 0, &tid);
1190 ok(thread != NULL, "CreateThread failed\n");
1191 waitret = WaitForSingleObject(thread, 60000);
1192 ok(waitret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
1193 CloseHandle(thread);
1195 ret = TlsFree(TLS_index0);
1196 ok(ret, "TlsFree failed\n");
1198 resync_after_run();
1200 if (sync_threads_and_run_one(1, id))
1202 ret = TlsFree(TLS_index1);
1203 ok(ret, "TlsFree failed\n");
1205 resync_after_run();
1207 return 0;
1210 static void test_TLS(void)
1212 HANDLE threads[2];
1213 LONG_PTR i;
1214 DWORD ret;
1215 BOOL suc;
1217 init_thread_sync_helpers();
1219 /* Allocate a TLS slot in the main thread to test for inheritance. */
1220 TLS_main = TlsAlloc();
1221 ok(TLS_main != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1222 suc = TlsSetValue(TLS_main, (LPVOID) 4114);
1223 ok(suc, "TlsSetValue failed\n");
1225 for (i = 0; i < 2; ++i)
1227 DWORD tid;
1229 threads[i] = CreateThread(NULL, 0, TLS_ThreadProc, (LPVOID) i, 0, &tid);
1230 ok(threads[i] != NULL, "CreateThread failed\n");
1233 ret = WaitForMultipleObjects(2, threads, TRUE, 60000);
1234 ok(ret == WAIT_OBJECT_0 || ret == WAIT_OBJECT_0+1 /* nt4 */, "WaitForMultipleObjects failed %u\n",ret);
1236 for (i = 0; i < 2; ++i)
1237 CloseHandle(threads[i]);
1239 suc = TlsFree(TLS_main);
1240 ok(suc, "TlsFree failed\n");
1241 cleanup_thread_sync_helpers();
1244 static void test_ThreadErrorMode(void)
1246 DWORD oldmode;
1247 DWORD mode;
1248 DWORD rtlmode;
1249 BOOL ret;
1251 if (!pSetThreadErrorMode || !pGetThreadErrorMode)
1253 win_skip("SetThreadErrorMode and/or GetThreadErrorMode unavailable (added in Windows 7)\n");
1254 return;
1257 if (!pRtlGetThreadErrorMode) {
1258 win_skip("RtlGetThreadErrorMode not available\n");
1259 return;
1262 oldmode = pGetThreadErrorMode();
1264 ret = pSetThreadErrorMode(0, &mode);
1265 ok(ret, "SetThreadErrorMode failed\n");
1266 ok(mode == oldmode,
1267 "SetThreadErrorMode returned old mode 0x%x, expected 0x%x\n",
1268 mode, oldmode);
1269 mode = pGetThreadErrorMode();
1270 ok(mode == 0, "GetThreadErrorMode returned mode 0x%x, expected 0\n", mode);
1271 rtlmode = pRtlGetThreadErrorMode();
1272 ok(rtlmode == 0,
1273 "RtlGetThreadErrorMode returned mode 0x%x, expected 0\n", mode);
1275 ret = pSetThreadErrorMode(SEM_FAILCRITICALERRORS, &mode);
1276 ok(ret, "SetThreadErrorMode failed\n");
1277 ok(mode == 0,
1278 "SetThreadErrorMode returned old mode 0x%x, expected 0\n", mode);
1279 mode = pGetThreadErrorMode();
1280 ok(mode == SEM_FAILCRITICALERRORS,
1281 "GetThreadErrorMode returned mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1282 mode);
1283 rtlmode = pRtlGetThreadErrorMode();
1284 ok(rtlmode == 0x10,
1285 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x10\n", mode);
1287 ret = pSetThreadErrorMode(SEM_NOGPFAULTERRORBOX, &mode);
1288 ok(ret, "SetThreadErrorMode failed\n");
1289 ok(mode == SEM_FAILCRITICALERRORS,
1290 "SetThreadErrorMode returned old mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1291 mode);
1292 mode = pGetThreadErrorMode();
1293 ok(mode == SEM_NOGPFAULTERRORBOX,
1294 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOGPFAULTERRORBOX\n",
1295 mode);
1296 rtlmode = pRtlGetThreadErrorMode();
1297 ok(rtlmode == 0x20,
1298 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x20\n", mode);
1300 ret = pSetThreadErrorMode(SEM_NOOPENFILEERRORBOX, NULL);
1301 ok(ret, "SetThreadErrorMode failed\n");
1302 mode = pGetThreadErrorMode();
1303 ok(mode == SEM_NOOPENFILEERRORBOX,
1304 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOOPENFILEERRORBOX\n",
1305 mode);
1306 rtlmode = pRtlGetThreadErrorMode();
1307 ok(rtlmode == 0x40,
1308 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x40\n", rtlmode);
1310 for (mode = 1; mode; mode <<= 1)
1312 ret = pSetThreadErrorMode(mode, NULL);
1313 if (mode & (SEM_FAILCRITICALERRORS |
1314 SEM_NOGPFAULTERRORBOX |
1315 SEM_NOOPENFILEERRORBOX))
1317 ok(ret,
1318 "SetThreadErrorMode(0x%x,NULL) failed with error %d\n",
1319 mode, GetLastError());
1321 else
1323 DWORD GLE = GetLastError();
1324 ok(!ret,
1325 "SetThreadErrorMode(0x%x,NULL) succeeded, expected failure\n",
1326 mode);
1327 ok(GLE == ERROR_INVALID_PARAMETER,
1328 "SetThreadErrorMode(0x%x,NULL) failed with %d, "
1329 "expected ERROR_INVALID_PARAMETER\n",
1330 mode, GLE);
1334 pSetThreadErrorMode(oldmode, NULL);
1337 static inline void set_fpu_cw(WORD cw)
1339 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
1340 __asm__ volatile ("fnclex; fldcw %0" : : "m" (cw));
1341 #endif
1344 static inline WORD get_fpu_cw(void)
1346 WORD cw = 0;
1347 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
1348 __asm__ volatile ("fnstcw %0" : "=m" (cw));
1349 #endif
1350 return cw;
1353 struct fpu_thread_ctx
1355 WORD cw;
1356 HANDLE finished;
1359 static DWORD WINAPI fpu_thread(void *param)
1361 struct fpu_thread_ctx *ctx = param;
1362 BOOL ret;
1364 ctx->cw = get_fpu_cw();
1366 ret = SetEvent(ctx->finished);
1367 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
1369 return 0;
1372 static WORD get_thread_fpu_cw(void)
1374 struct fpu_thread_ctx ctx;
1375 DWORD tid, res;
1376 HANDLE thread;
1378 ctx.finished = CreateEvent(NULL, FALSE, FALSE, NULL);
1379 ok(!!ctx.finished, "Failed to create event, last error %#x.\n", GetLastError());
1381 thread = CreateThread(NULL, 0, fpu_thread, &ctx, 0, &tid);
1382 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
1384 res = WaitForSingleObject(ctx.finished, INFINITE);
1385 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
1387 res = CloseHandle(ctx.finished);
1388 ok(!!res, "Failed to close event handle, last error %#x.\n", GetLastError());
1390 return ctx.cw;
1393 static void test_thread_fpu_cw(void)
1395 WORD initial_cw, cw;
1397 initial_cw = get_fpu_cw();
1398 ok(initial_cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", initial_cw);
1400 cw = get_thread_fpu_cw();
1401 ok(cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", cw);
1403 set_fpu_cw(0xf60);
1404 cw = get_fpu_cw();
1405 ok(cw == 0xf60, "Expected FPU control word 0xf60, got %#x.\n", cw);
1407 cw = get_thread_fpu_cw();
1408 ok(cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", cw);
1410 cw = get_fpu_cw();
1411 ok(cw == 0xf60, "Expected FPU control word 0xf60, got %#x.\n", cw);
1413 set_fpu_cw(initial_cw);
1414 cw = get_fpu_cw();
1415 ok(cw == initial_cw, "Expected FPU control word %#x, got %#x.\n", initial_cw, cw);
1418 START_TEST(thread)
1420 HINSTANCE lib;
1421 HINSTANCE ntdll;
1422 int argc;
1423 char **argv;
1424 argc = winetest_get_mainargs( &argv );
1425 /* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
1426 so that the compile passes
1428 lib=GetModuleHandleA("kernel32.dll");
1429 ok(lib!=NULL,"Couldn't get a handle for kernel32.dll\n");
1430 pGetThreadPriorityBoost=(void *)GetProcAddress(lib,"GetThreadPriorityBoost");
1431 pOpenThread=(void *)GetProcAddress(lib,"OpenThread");
1432 pQueueUserWorkItem=(void *)GetProcAddress(lib,"QueueUserWorkItem");
1433 pSetThreadIdealProcessor=(void *)GetProcAddress(lib,"SetThreadIdealProcessor");
1434 pSetThreadPriorityBoost=(void *)GetProcAddress(lib,"SetThreadPriorityBoost");
1435 pRegisterWaitForSingleObject=(void *)GetProcAddress(lib,"RegisterWaitForSingleObject");
1436 pUnregisterWait=(void *)GetProcAddress(lib,"UnregisterWait");
1437 pIsWow64Process=(void *)GetProcAddress(lib,"IsWow64Process");
1438 pSetThreadErrorMode=(void *)GetProcAddress(lib,"SetThreadErrorMode");
1439 pGetThreadErrorMode=(void *)GetProcAddress(lib,"GetThreadErrorMode");
1441 ntdll=GetModuleHandleA("ntdll.dll");
1442 if (ntdll)
1444 pRtlGetThreadErrorMode=(void *)GetProcAddress(ntdll,"RtlGetThreadErrorMode");
1447 if (argc >= 3)
1449 if (!strcmp(argv[2], "sleep"))
1451 HANDLE hAddrEvents[2];
1452 create_function_addr_events(hAddrEvents);
1453 SetEvent(hAddrEvents[0]);
1454 SetEvent(hAddrEvents[1]);
1455 Sleep(5000); /* spawned process runs for at most 5 seconds */
1456 return;
1458 while (1)
1460 HANDLE hThread;
1461 DWORD tid;
1462 hThread = CreateThread(NULL, 0, threadFunc2, NULL, 0, &tid);
1463 ok(hThread != NULL, "CreateThread failed, error %u\n",
1464 GetLastError());
1465 ok(WaitForSingleObject(hThread, 200) == WAIT_OBJECT_0,
1466 "Thread did not exit in time\n");
1467 if (hThread == NULL) break;
1468 CloseHandle(hThread);
1470 return;
1473 test_CreateRemoteThread();
1474 test_CreateThread_basic();
1475 test_CreateThread_suspended();
1476 test_SuspendThread();
1477 test_TerminateThread();
1478 test_CreateThread_stack();
1479 test_thread_priority();
1480 test_GetThreadTimes();
1481 test_thread_processor();
1482 test_GetThreadExitCode();
1483 #ifdef __i386__
1484 test_SetThreadContext();
1485 #endif
1486 test_QueueUserWorkItem();
1487 test_RegisterWaitForSingleObject();
1488 test_TLS();
1489 test_ThreadErrorMode();
1490 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
1491 test_thread_fpu_cw();
1492 #endif