winspool.drv: Remove a todo that succeeds now.
[wine] / dlls / kernel32 / tests / thread.c
1 /*
2  * Unit test suite for thread functions.
3  *
4  * Copyright 2002 Geoffrey Hausheer
5  *
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.
10  *
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.
15  *
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
19  */
20
21 /* Define _WIN32_WINNT to get SetThreadIdealProcessor on Windows */
22 #define _WIN32_WINNT 0x0500
23
24 #include <assert.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27
28 #include "wine/test.h"
29 #include <windef.h>
30 #include <winbase.h>
31 #include <winnt.h>
32 #include <winerror.h>
33
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
40
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
46 */
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
56
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);
68
69 static HANDLE create_target_process(const char *arg)
70 {
71     char **argv;
72     char cmdline[MAX_PATH];
73     PROCESS_INFORMATION pi;
74     BOOL ret;
75     STARTUPINFO si = { 0 };
76     si.cb = sizeof(si);
77
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;
85 }
86
87 /* Functions not tested yet:
88   AttachThreadInput
89   SetThreadContext
90   SwitchToThread
91
92 In addition there are no checks that the inheritance works properly in
93 CreateThread
94 */
95
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;
102
103 static void init_thread_sync_helpers(void)
104 {
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;
110 }
111
112 static BOOL sync_threads_and_run_one(DWORD sync_id, DWORD my_id)
113 {
114   LONG num = InterlockedIncrement(&num_synced);
115   assert(-1 <= num && num <= 1);
116   if (num == 1)
117   {
118       ResetEvent( stop_event );
119       SetEvent( start_event );
120   }
121   else
122   {
123     DWORD ret = WaitForSingleObject(start_event, 10000);
124     ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed %x\n",ret);
125   }
126   return sync_id == my_id;
127 }
128
129 static void resync_after_run(void)
130 {
131   LONG num = InterlockedDecrement(&num_synced);
132   assert(-1 <= num && num <= 1);
133   if (num == -1)
134   {
135       ResetEvent( start_event );
136       SetEvent( stop_event );
137   }
138   else
139   {
140     DWORD ret = WaitForSingleObject(stop_event, 10000);
141     ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
142   }
143 }
144
145 static void cleanup_thread_sync_helpers(void)
146 {
147   CloseHandle(start_event);
148   CloseHandle(stop_event);
149 }
150
151 static DWORD tlsIndex;
152
153 typedef struct {
154   int threadnum;
155   HANDLE *event;
156   DWORD *threadmem;
157 } t1Struct;
158
159 /* WinME supports OpenThread but doesn't know about access restrictions so
160    we require them to be either completely ignored or always obeyed.
161 */
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"))
172
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
176 */
177 static DWORD WINAPI threadFunc1(LPVOID p)
178 {
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
187 */
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) ;
195    }
196
197    /* lstrlenA contains an exception handler so this makes sure exceptions work in threads */
198    ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
199
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;
204 }
205
206 static DWORD WINAPI threadFunc2(LPVOID p)
207 {
208    return 99;
209 }
210
211 static DWORD WINAPI threadFunc3(LPVOID p)
212 {
213    HANDLE thread;
214    thread=GetCurrentThread();
215    SuspendThread(thread);
216    return 99;
217 }
218
219 static DWORD WINAPI threadFunc4(LPVOID p)
220 {
221    HANDLE event = p;
222    if(event != NULL) {
223      SetEvent(event);
224    }
225    Sleep(99000);
226    return 0;
227 }
228
229 #if CHECK_STACK
230 static DWORD WINAPI threadFunc5(LPVOID p)
231 {
232   DWORD *exitCode = p;
233   SYSTEM_INFO sysInfo;
234   sysInfo.dwPageSize=0;
235   GetSystemInfo(&sysInfo);
236   *exitCode=0;
237    __TRY
238    {
239      alloca(2*sysInfo.dwPageSize);
240    }
241     __EXCEPT(1) {
242      *exitCode=1;
243    }
244    __ENDTRY
245    return 0;
246 }
247 #endif
248
249 static DWORD WINAPI threadFunc_SetEvent(LPVOID p)
250 {
251     SetEvent(p);
252     return 0;
253 }
254
255 static DWORD WINAPI threadFunc_CloseHandle(LPVOID p)
256 {
257     CloseHandle(p);
258     return 0;
259 }
260
261 static void create_function_addr_events(HANDLE events[2])
262 {
263     char buffer[256];
264
265     sprintf(buffer, "threadFunc_SetEvent %p", threadFunc_SetEvent);
266     events[0] = CreateEvent(NULL, FALSE, FALSE, buffer);
267
268     sprintf(buffer, "threadFunc_CloseHandle %p", threadFunc_CloseHandle);
269     events[1] = CreateEvent(NULL, FALSE, FALSE, buffer);
270 }
271
272 /* check CreateRemoteThread */
273 static VOID test_CreateRemoteThread(void)
274 {
275     HANDLE hProcess, hThread, hEvent, hRemoteEvent;
276     DWORD tid, ret, exitcode;
277     HANDLE hAddrEvents[2];
278
279     hProcess = create_target_process("sleep");
280     ok(hProcess != NULL, "Can't start process\n");
281
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)
287     {
288         skip("child process wasn't mapped at same address, so can't do CreateRemoteThread tests.\n");
289         return;
290     }
291     ok(ret == WAIT_OBJECT_0 || broken(ret == WAIT_OBJECT_0+1 /* nt4,w2k */), "WaitForAllObjects 2 events %d\n", ret);
292
293     hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
294     ok(hEvent != NULL, "Can't create event, err=%u\n", GetLastError());
295     ret = DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &hRemoteEvent,
296                           0, FALSE, DUPLICATE_SAME_ACCESS);
297     ok(ret != 0, "DuplicateHandle failed, err=%u\n", GetLastError());
298
299     /* create suspended remote thread with entry point SetEvent() */
300     SetLastError(0xdeadbeef);
301     hThread = CreateRemoteThread(hProcess, NULL, 0, threadFunc_SetEvent,
302                                  hRemoteEvent, CREATE_SUSPENDED, &tid);
303     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
304     {
305         win_skip("CreateRemoteThread is not implemented\n");
306         goto cleanup;
307     }
308     ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
309     ok(tid != 0, "null tid\n");
310     ret = SuspendThread(hThread);
311     ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
312     ret = ResumeThread(hThread);
313     ok(ret == 2, "ret=%u, err=%u\n", ret, GetLastError());
314
315     /* thread still suspended, so wait times out */
316     ret = WaitForSingleObject(hEvent, 1000);
317     ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
318
319     ret = ResumeThread(hThread);
320     ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
321
322     /* wait that doesn't time out */
323     ret = WaitForSingleObject(hEvent, 1000);
324     ok(ret == WAIT_OBJECT_0, "object not signaled, ret=%u\n", ret);
325
326     /* wait for thread end */
327     ret = WaitForSingleObject(hThread, 1000);
328     ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
329     CloseHandle(hThread);
330
331     /* create and wait for remote thread with entry point CloseHandle() */
332     hThread = CreateRemoteThread(hProcess, NULL, 0,
333                                  threadFunc_CloseHandle,
334                                  hRemoteEvent, 0, &tid);
335     ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
336     ret = WaitForSingleObject(hThread, 1000);
337     ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
338     CloseHandle(hThread);
339
340     /* create remote thread with entry point SetEvent() */
341     hThread = CreateRemoteThread(hProcess, NULL, 0,
342                                  threadFunc_SetEvent,
343                                  hRemoteEvent, 0, &tid);
344     ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
345
346     /* closed handle, so wait times out */
347     ret = WaitForSingleObject(hEvent, 1000);
348     ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
349
350     /* check that remote SetEvent() failed */
351     ret = GetExitCodeThread(hThread, &exitcode);
352     ok(ret != 0, "GetExitCodeThread failed, err=%u\n", GetLastError());
353     if (ret) ok(exitcode == 0, "SetEvent succeeded, expected to fail\n");
354     CloseHandle(hThread);
355
356 cleanup:
357     TerminateProcess(hProcess, 0);
358     CloseHandle(hEvent);
359     CloseHandle(hProcess);
360 }
361
362 /* Check basic functionality of CreateThread and Tls* functions */
363 static VOID test_CreateThread_basic(void)
364 {
365    HANDLE thread[NUM_THREADS],event[NUM_THREADS];
366    DWORD threadid[NUM_THREADS],curthreadId;
367    DWORD threadmem[NUM_THREADS];
368    DWORD exitCode;
369    t1Struct tstruct[NUM_THREADS];
370    int error;
371    DWORD i,j;
372    DWORD GLE, ret;
373    DWORD tid;
374    BOOL bRet;
375
376    /* lstrlenA contains an exception handler so this makes sure exceptions work in the main thread */
377    ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
378
379 /* Retrieve current Thread ID for later comparisons */
380   curthreadId=GetCurrentThreadId();
381 /* Allocate some local storage */
382   ok((tlsIndex=TlsAlloc())!=TLS_OUT_OF_INDEXES,"TlsAlloc failed\n");
383 /* Create events for thread synchronization */
384   for(i=0;i<NUM_THREADS;i++) {
385     threadmem[i]=0;
386 /* Note that it doesn't matter what type of event we choose here.  This
387    test isn't trying to thoroughly test events
388 */
389     event[i]=CreateEventA(NULL,TRUE,FALSE,NULL);
390     tstruct[i].threadnum=i;
391     tstruct[i].threadmem=threadmem;
392     tstruct[i].event=event;
393   }
394
395 /* Test that passing arguments to threads works okay */
396   for(i=0;i<NUM_THREADS;i++) {
397     thread[i] = CreateThread(NULL,0,threadFunc1,
398                              &tstruct[i],0,&threadid[i]);
399     ok(thread[i]!=NULL,"Create Thread failed\n");
400   }
401 /* Test that the threads actually complete */
402   for(i=0;i<NUM_THREADS;i++) {
403     error=WaitForSingleObject(thread[i],5000);
404     ok(error==WAIT_OBJECT_0, "Thread did not complete within timelimit\n");
405     if(error!=WAIT_OBJECT_0) {
406       TerminateThread(thread[i],i+NUM_THREADS);
407     }
408     ok(GetExitCodeThread(thread[i],&exitCode),"Could not retrieve ext code\n");
409     ok(exitCode==i+NUM_THREADS,"Thread returned an incorrect exit code\n");
410   }
411 /* Test that each thread executed in its parent's address space
412    (it was able to change threadmem and pass that change back to its parent)
413    and that each thread id was independent).  Note that we prove that the
414    threads actually execute concurrently by having them block on each other
415    in threadFunc1
416 */
417   for(i=0;i<NUM_THREADS;i++) {
418     error=0;
419     for(j=i+1;j<NUM_THREADS;j++) {
420       if (threadmem[i]==threadmem[j]) {
421         error=1;
422       }
423     }
424     ok(!error && threadmem[i]==threadid[i] && threadmem[i]!=curthreadId,
425          "Thread did not execute successfully\n");
426     ok(CloseHandle(thread[i])!=0,"CloseHandle failed\n");
427   }
428
429   SetLastError(0xCAFEF00D);
430   bRet = TlsFree(tlsIndex);
431   ok(bRet, "TlsFree failed: %08x\n", GetLastError());
432   ok(GetLastError()==0xCAFEF00D,
433      "GetLastError: expected 0xCAFEF00D, got %08x\n", GetLastError());
434
435   /* Test freeing an already freed TLS index */
436   SetLastError(0xCAFEF00D);
437   ok(TlsFree(tlsIndex)==0,"TlsFree succeeded\n");
438   ok(GetLastError()==ERROR_INVALID_PARAMETER,
439      "GetLastError: expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
440
441   /* Test how passing NULL as a pointer to threadid works */
442   SetLastError(0xFACEaBAD);
443   thread[0] = CreateThread(NULL,0,threadFunc2,NULL,0,&tid);
444   GLE = GetLastError();
445   if (thread[0]) { /* NT */
446     ok(GLE==0xFACEaBAD, "CreateThread set last error to %d, expected 4207848365\n", GLE);
447     ret = WaitForSingleObject(thread[0],100);
448     ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
449     ret = GetExitCodeThread(thread[0],&exitCode);
450     ok(ret!=0, "GetExitCodeThread returned %d (expected nonzero)\n", ret);
451     ok(exitCode==99, "threadFunc2 exited with code: %d (expected 99)\n", exitCode);
452     ok(CloseHandle(thread[0])!=0,"Error closing thread handle\n");
453   }
454   else { /* 9x */
455     ok(GLE==ERROR_INVALID_PARAMETER, "CreateThread set last error to %d, expected 87\n", GLE);
456   }
457 }
458
459 /* Check that using the CREATE_SUSPENDED flag works */
460 static VOID test_CreateThread_suspended(void)
461 {
462   HANDLE thread;
463   DWORD threadId;
464   DWORD suspend_count;
465   int error;
466
467   thread = CreateThread(NULL,0,threadFunc2,NULL,
468                         CREATE_SUSPENDED,&threadId);
469   ok(thread!=NULL,"Create Thread failed\n");
470 /* Check that the thread is suspended */
471   ok(SuspendThread(thread)==1,"Thread did not start suspended\n");
472   ok(ResumeThread(thread)==2,"Resume thread returned an invalid value\n");
473 /* Check that resume thread didn't actually start the thread.  I can't think
474    of a better way of checking this than just waiting.  I am not sure if this
475    will work on slow computers.
476 */
477   ok(WaitForSingleObject(thread,1000)==WAIT_TIMEOUT,
478      "ResumeThread should not have actually started the thread\n");
479 /* Now actually resume the thread and make sure that it actually completes*/
480   ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
481   ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
482      "Thread did not resume\n");
483   if(error!=WAIT_OBJECT_0) {
484     TerminateThread(thread,1);
485   }
486
487   suspend_count = SuspendThread(thread);
488   ok(suspend_count == -1, "SuspendThread returned %d, expected -1\n", suspend_count);
489
490   suspend_count = ResumeThread(thread);
491   ok(suspend_count == 0 ||
492      broken(suspend_count == -1), /* win9x */
493      "ResumeThread returned %d, expected 0\n", suspend_count);
494
495   ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
496 }
497
498 /* Check that SuspendThread and ResumeThread work */
499 static VOID test_SuspendThread(void)
500 {
501   HANDLE thread,access_thread;
502   DWORD threadId,exitCode,error;
503   int i;
504
505   thread = CreateThread(NULL,0,threadFunc3,NULL,
506                         0,&threadId);
507   ok(thread!=NULL,"Create Thread failed\n");
508 /* Check that the thread is suspended */
509 /* Note that this is a polling method, and there is a race between
510    SuspendThread being called (in the child, and the loop below timing out,
511    so the test could fail on a heavily loaded or slow computer.
512 */
513   error=0;
514   for(i=0;error==0 && i<100;i++) {
515     error=SuspendThread(thread);
516     ResumeThread(thread);
517     if(error==0) {
518       Sleep(50);
519       i++;
520     }
521   }
522   ok(error==1,"SuspendThread did not work\n");
523 /* check that access restrictions are obeyed */
524   if (pOpenThread) {
525     access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_SUSPEND_RESUME),
526                            0,threadId);
527     ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
528     if (access_thread!=NULL) {
529       obey_ar(SuspendThread(access_thread)==~0U);
530       obey_ar(ResumeThread(access_thread)==~0U);
531       ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
532     }
533   }
534 /* Double check that the thread really is suspended */
535   ok((error=GetExitCodeThread(thread,&exitCode))!=0 && exitCode==STILL_ACTIVE,
536      "Thread did not really suspend\n");
537 /* Resume the thread, and make sure it actually completes */
538   ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
539   ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
540      "Thread did not resume\n");
541   if(error!=WAIT_OBJECT_0) {
542     TerminateThread(thread,1);
543   }
544   /* Trying to suspend a terminated thread should fail */
545   error=SuspendThread(thread);
546   ok(error==~0U, "wrong return code: %d\n", error);
547   ok(GetLastError()==ERROR_ACCESS_DENIED || GetLastError()==ERROR_NO_MORE_ITEMS, "unexpected error code: %d\n", GetLastError());
548
549   ok(CloseHandle(thread)!=0,"CloseHandle Failed\n");
550 }
551
552 /* Check that TerminateThread works properly
553 */
554 static VOID test_TerminateThread(void)
555 {
556   HANDLE thread,access_thread,event;
557   DWORD threadId,exitCode;
558   event=CreateEventA(NULL,TRUE,FALSE,NULL);
559   thread = CreateThread(NULL,0,threadFunc4,event,0,&threadId);
560   ok(thread!=NULL,"Create Thread failed\n");
561 /* TerminateThread has a race condition in Wine.  If the thread is terminated
562    before it starts, it leaves a process behind.  Therefore, we wait for the
563    thread to signal that it has started.  There is no easy way to force the
564    race to occur, so we don't try to find it.
565 */
566   ok(WaitForSingleObject(event,5000)==WAIT_OBJECT_0,
567      "TerminateThread didn't work\n");
568 /* check that access restrictions are obeyed */
569   if (pOpenThread) {
570     access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_TERMINATE),
571                              0,threadId);
572     ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
573     if (access_thread!=NULL) {
574       obey_ar(TerminateThread(access_thread,99)==0);
575       ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
576     }
577   }
578 /* terminate a job and make sure it terminates */
579   ok(TerminateThread(thread,99)!=0,"TerminateThread failed\n");
580   ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
581      "TerminateThread didn't work\n");
582   ok(GetExitCodeThread(thread,&exitCode)!=STILL_ACTIVE,
583      "TerminateThread should not leave the thread 'STILL_ACTIVE'\n");
584   ok(exitCode==99, "TerminateThread returned invalid exit code\n");
585   ok(CloseHandle(thread)!=0,"Error Closing thread handle\n");
586 }
587
588 /* Check if CreateThread obeys the specified stack size.  This code does
589    not work properly, and is currently disabled
590 */
591 static VOID test_CreateThread_stack(void)
592 {
593 #if CHECK_STACK
594 /* The only way I know of to test the stack size is to use alloca
595    and __try/__except.  However, this is probably not portable,
596    and I couldn't get it to work under Wine anyhow.  However, here
597    is the code which should allow for testing that CreateThread
598    respects the stack-size limit
599 */
600      HANDLE thread;
601      DWORD threadId,exitCode;
602
603      SYSTEM_INFO sysInfo;
604      sysInfo.dwPageSize=0;
605      GetSystemInfo(&sysInfo);
606      ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
607      thread = CreateThread(NULL,sysInfo.dwPageSize,
608                            threadFunc5,&exitCode,
609                            0,&threadId);
610      ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
611         "TerminateThread didn't work\n");
612      ok(exitCode==1,"CreateThread did not obey stack-size-limit\n");
613      ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
614 #endif
615 }
616
617 /* Check whether setting/retrieving thread priorities works */
618 static VOID test_thread_priority(void)
619 {
620    HANDLE curthread,access_thread;
621    DWORD curthreadId,exitCode;
622    int min_priority=-2,max_priority=2;
623    BOOL disabled,rc;
624    int i;
625
626    curthread=GetCurrentThread();
627    curthreadId=GetCurrentThreadId();
628 /* Check thread priority */
629 /* NOTE: on Win2k/XP priority can be from -7 to 6.  All other platforms it
630          is -2 to 2.  However, even on a real Win2k system, using thread
631          priorities beyond the -2 to 2 range does not work.  If you want to try
632          anyway, enable USE_EXTENDED_PRIORITIES
633 */
634    ok(GetThreadPriority(curthread)==THREAD_PRIORITY_NORMAL,
635       "GetThreadPriority Failed\n");
636
637    if (pOpenThread) {
638 /* check that access control is obeyed */
639      access_thread=pOpenThread(THREAD_ALL_ACCESS &
640                        (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
641                        0,curthreadId);
642      ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
643      if (access_thread!=NULL) {
644        obey_ar(SetThreadPriority(access_thread,1)==0);
645        obey_ar(GetThreadPriority(access_thread)==THREAD_PRIORITY_ERROR_RETURN);
646        obey_ar(GetExitCodeThread(access_thread,&exitCode)==0);
647        ok(CloseHandle(access_thread),"Error Closing thread handle\n");
648      }
649    }
650 #if USE_EXTENDED_PRIORITIES
651    min_priority=-7; max_priority=6;
652 #endif
653    for(i=min_priority;i<=max_priority;i++) {
654      ok(SetThreadPriority(curthread,i)!=0,
655         "SetThreadPriority Failed for priority: %d\n",i);
656      ok(GetThreadPriority(curthread)==i,
657         "GetThreadPriority Failed for priority: %d\n",i);
658    }
659    ok(SetThreadPriority(curthread,THREAD_PRIORITY_TIME_CRITICAL)!=0,
660       "SetThreadPriority Failed\n");
661    ok(GetThreadPriority(curthread)==THREAD_PRIORITY_TIME_CRITICAL,
662       "GetThreadPriority Failed\n");
663    ok(SetThreadPriority(curthread,THREAD_PRIORITY_IDLE)!=0,
664        "SetThreadPriority Failed\n");
665    ok(GetThreadPriority(curthread)==THREAD_PRIORITY_IDLE,
666        "GetThreadPriority Failed\n");
667    ok(SetThreadPriority(curthread,0)!=0,"SetThreadPriority Failed\n");
668
669 /* Check that the thread priority is not changed if SetThreadPriority
670    is called with a value outside of the max/min range */
671    SetThreadPriority(curthread,min_priority);
672    SetLastError(0xdeadbeef);
673    rc = SetThreadPriority(curthread,min_priority-1);
674
675    ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
676    ok(GetLastError() == ERROR_INVALID_PARAMETER ||
677       GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
678       "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
679       GetLastError());
680    ok(GetThreadPriority(curthread)==min_priority,
681       "GetThreadPriority didn't return min_priority\n");
682
683    SetThreadPriority(curthread,max_priority);
684    SetLastError(0xdeadbeef);
685    rc = SetThreadPriority(curthread,max_priority+1);
686
687    ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
688    ok(GetLastError() == ERROR_INVALID_PARAMETER ||
689       GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
690       "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
691       GetLastError());
692    ok(GetThreadPriority(curthread)==max_priority,
693       "GetThreadPriority didn't return max_priority\n");
694
695 /* Check thread priority boost */
696    if (!pGetThreadPriorityBoost || !pSetThreadPriorityBoost) 
697      return; /* Win9x */
698
699    SetLastError(0xdeadbeef);
700    rc=pGetThreadPriorityBoost(curthread,&disabled);
701    if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
702    {
703       win_skip("GetThreadPriorityBoost is not implemented on WinME\n");
704       return;
705    }
706
707    ok(rc!=0,"error=%d\n",GetLastError());
708
709    if (pOpenThread) {
710 /* check that access control is obeyed */
711      access_thread=pOpenThread(THREAD_ALL_ACCESS &
712                        (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
713                        0,curthreadId);
714      ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
715      if (access_thread!=NULL) {
716        obey_ar(pSetThreadPriorityBoost(access_thread,1)==0);
717        todo_wine obey_ar(pGetThreadPriorityBoost(access_thread,&disabled)==0);
718        ok(CloseHandle(access_thread),"Error Closing thread handle\n");
719      }
720    }
721
722    todo_wine {
723      rc = pSetThreadPriorityBoost(curthread,1);
724      ok( rc != 0, "error=%d\n",GetLastError());
725      rc=pGetThreadPriorityBoost(curthread,&disabled);
726      ok(rc!=0 && disabled==1,
727         "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
728
729      rc = pSetThreadPriorityBoost(curthread,0);
730      ok( rc != 0, "error=%d\n",GetLastError());
731    }
732    rc=pGetThreadPriorityBoost(curthread,&disabled);
733    ok(rc!=0 && disabled==0,
734       "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
735 }
736
737 /* check the GetThreadTimes function */
738 static VOID test_GetThreadTimes(void)
739 {
740      HANDLE thread,access_thread=NULL;
741      FILETIME creationTime,exitTime,kernelTime,userTime;
742      DWORD threadId;
743      int error;
744
745      thread = CreateThread(NULL,0,threadFunc2,NULL,
746                            CREATE_SUSPENDED,&threadId);
747
748      ok(thread!=NULL,"Create Thread failed\n");
749 /* check that access control is obeyed */
750      if (pOpenThread) {
751        access_thread=pOpenThread(THREAD_ALL_ACCESS &
752                                    (~THREAD_QUERY_INFORMATION), 0,threadId);
753        ok(access_thread!=NULL,
754           "OpenThread returned an invalid handle\n");
755      }
756      ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
757      ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
758         "ResumeThread didn't work\n");
759      creationTime.dwLowDateTime=99; creationTime.dwHighDateTime=99;
760      exitTime.dwLowDateTime=99;     exitTime.dwHighDateTime=99;
761      kernelTime.dwLowDateTime=99;   kernelTime.dwHighDateTime=99;
762      userTime.dwLowDateTime=99;     userTime.dwHighDateTime=99;
763 /* GetThreadTimes should set all of the parameters passed to it */
764      error=GetThreadTimes(thread,&creationTime,&exitTime,
765                           &kernelTime,&userTime);
766
767      if (error == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
768        win_skip("GetThreadTimes is not implemented\n");
769      else {
770        ok(error!=0,"GetThreadTimes failed\n");
771        ok(creationTime.dwLowDateTime!=99 || creationTime.dwHighDateTime!=99,
772           "creationTime was invalid\n");
773        ok(exitTime.dwLowDateTime!=99 || exitTime.dwHighDateTime!=99,
774           "exitTime was invalid\n");
775        ok(kernelTime.dwLowDateTime!=99 || kernelTime.dwHighDateTime!=99,
776           "kernelTimewas invalid\n");
777        ok(userTime.dwLowDateTime!=99 || userTime.dwHighDateTime!=99,
778           "userTime was invalid\n");
779        ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
780        if(access_thread!=NULL)
781        {
782          error=GetThreadTimes(access_thread,&creationTime,&exitTime,
783                               &kernelTime,&userTime);
784          obey_ar(error==0);
785        }
786      }
787      if(access_thread!=NULL) {
788        ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
789      }
790 }
791
792 /* Check the processor affinity functions */
793 /* NOTE: These functions should also be checked that they obey access control
794 */
795 static VOID test_thread_processor(void)
796 {
797    HANDLE curthread,curproc;
798    DWORD_PTR processMask,systemMask,retMask;
799    SYSTEM_INFO sysInfo;
800    int error=0;
801    BOOL is_wow64;
802
803    if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
804
805    sysInfo.dwNumberOfProcessors=0;
806    GetSystemInfo(&sysInfo);
807    ok(sysInfo.dwNumberOfProcessors>0,
808       "GetSystemInfo failed to return a valid # of processors\n");
809 /* Use the current Thread/process for all tests */
810    curthread=GetCurrentThread();
811    ok(curthread!=NULL,"GetCurrentThread failed\n");
812    curproc=GetCurrentProcess();
813    ok(curproc!=NULL,"GetCurrentProcess failed\n");
814 /* Check the Affinity Mask functions */
815    ok(GetProcessAffinityMask(curproc,&processMask,&systemMask)!=0,
816       "GetProcessAffinityMask failed\n");
817    ok(SetThreadAffinityMask(curthread,processMask)==processMask,
818       "SetThreadAffinityMask failed\n");
819    ok(SetThreadAffinityMask(curthread,processMask+1)==0,
820       "SetThreadAffinityMask passed for an illegal processor\n");
821 /* NOTE: Pre-Vista does not recognize the "all processors" flag (all bits set) */
822    retMask = SetThreadAffinityMask(curthread,~0);
823    ok(broken(retMask==0) || retMask==processMask,
824       "SetThreadAffinityMask(thread,-1) failed to request all processors.\n");
825    if (retMask == processMask && sizeof(ULONG_PTR) > sizeof(ULONG))
826    {
827        /* only the low 32-bits matter */
828        retMask = SetThreadAffinityMask(curthread,~(ULONG_PTR)0);
829        ok(retMask == processMask, "SetThreadAffinityMask failed\n");
830        retMask = SetThreadAffinityMask(curthread,~(ULONG_PTR)0 >> 3);
831        ok(retMask == processMask, "SetThreadAffinityMask failed\n");
832        retMask = SetThreadAffinityMask(curthread,~(ULONG_PTR)1);
833        ok(retMask == 0, "SetThreadAffinityMask succeeded\n");
834    }
835 /* NOTE: This only works on WinNT/2000/XP) */
836    if (pSetThreadIdealProcessor) {
837      SetLastError(0xdeadbeef);
838      error=pSetThreadIdealProcessor(curthread,0);
839      if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
840      {
841        win_skip("SetThreadIdealProcessor is not implemented\n");
842        return;
843      }
844      ok(error!=-1, "SetThreadIdealProcessor failed\n");
845
846      if (is_wow64)
847      {
848          SetLastError(0xdeadbeef);
849          error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
850          todo_wine
851          ok(error!=-1, "SetThreadIdealProcessor failed for %u on Wow64\n", MAXIMUM_PROCESSORS+1);
852
853          SetLastError(0xdeadbeef);
854          error=pSetThreadIdealProcessor(curthread,65);
855          ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
856          ok(GetLastError()==ERROR_INVALID_PARAMETER,
857             "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
858      }
859      else
860      {
861          SetLastError(0xdeadbeef);
862          error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
863          ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
864          ok(GetLastError()==ERROR_INVALID_PARAMETER,
865             "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
866      }
867
868      error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS);
869      ok(error!=-1, "SetThreadIdealProcessor failed\n");
870    }
871 }
872
873 static VOID test_GetThreadExitCode(void)
874 {
875     DWORD exitCode, threadid;
876     DWORD GLE, ret;
877     HANDLE thread;
878
879     ret = GetExitCodeThread((HANDLE)0x2bad2bad,&exitCode);
880     ok(ret==0, "GetExitCodeThread returned non zero value: %d\n", ret);
881     GLE = GetLastError();
882     ok(GLE==ERROR_INVALID_HANDLE, "GetLastError returned %d (expected 6)\n", GLE);
883
884     thread = CreateThread(NULL,0,threadFunc2,NULL,0,&threadid);
885     ret = WaitForSingleObject(thread,100);
886     ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
887     ret = GetExitCodeThread(thread,&exitCode);
888     ok(ret==exitCode || ret==1, 
889        "GetExitCodeThread returned %d (expected 1 or %d)\n", ret, exitCode);
890     ok(exitCode==99, "threadFunc2 exited with code %d (expected 99)\n", exitCode);
891     ok(CloseHandle(thread)!=0,"Error closing thread handle\n");
892 }
893
894 #ifdef __i386__
895
896 static int test_value = 0;
897 static HANDLE event;
898
899 static void WINAPI set_test_val( int val )
900 {
901     test_value += val;
902     ExitThread(0);
903 }
904
905 static DWORD WINAPI threadFunc6(LPVOID p)
906 {
907     SetEvent( event );
908     Sleep( 1000 );
909     test_value *= (int)p;
910     return 0;
911 }
912
913 static void test_SetThreadContext(void)
914 {
915     CONTEXT ctx;
916     int *stack;
917     HANDLE thread;
918     DWORD threadid;
919     DWORD prevcount;
920     BOOL ret;
921
922     SetLastError(0xdeadbeef);
923     event = CreateEvent( NULL, TRUE, FALSE, NULL );
924     thread = CreateThread( NULL, 0, threadFunc6, (void *)2, 0, &threadid );
925     ok( thread != NULL, "CreateThread failed : (%d)\n", GetLastError() );
926     if (!thread)
927     {
928         trace("Thread creation failed, skipping rest of test\n");
929         return;
930     }
931     WaitForSingleObject( event, INFINITE );
932     SuspendThread( thread );
933     CloseHandle( event );
934
935     ctx.ContextFlags = CONTEXT_FULL;
936     SetLastError(0xdeadbeef);
937     ret = GetThreadContext( thread, &ctx );
938     ok( ret, "GetThreadContext failed : (%u)\n", GetLastError() );
939
940     if (ret)
941     {
942         /* simulate a call to set_test_val(10) */
943         stack = (int *)ctx.Esp;
944         stack[-1] = 10;
945         stack[-2] = ctx.Eip;
946         ctx.Esp -= 2 * sizeof(int *);
947         ctx.Eip = (DWORD)set_test_val;
948         SetLastError(0xdeadbeef);
949         ret = SetThreadContext( thread, &ctx );
950         ok( ret, "SetThreadContext failed : (%d)\n", GetLastError() );
951     }
952
953     SetLastError(0xdeadbeef);
954     prevcount = ResumeThread( thread );
955     ok ( prevcount == 1, "Previous suspend count (%d) instead of 1, last error : (%d)\n",
956                          prevcount, GetLastError() );
957
958     WaitForSingleObject( thread, INFINITE );
959     ok( test_value == 10, "test_value %d\n", test_value );
960
961     ctx.ContextFlags = CONTEXT_FULL;
962     SetLastError(0xdeadbeef);
963     ret = GetThreadContext( thread, &ctx );
964     ok( (!ret && (GetLastError() == ERROR_GEN_FAILURE)) ||
965         (!ret && broken(GetLastError() == ERROR_INVALID_HANDLE)) || /* win2k */
966         broken(ret),   /* 32bit application on NT 5.x 64bit */
967         "got %d with %u (expected FALSE with ERROR_GEN_FAILURE)\n",
968         ret, GetLastError() );
969
970     SetLastError(0xdeadbeef);
971     ret = SetThreadContext( thread, &ctx );
972     ok( (!ret && ((GetLastError() == ERROR_GEN_FAILURE) || (GetLastError() == ERROR_ACCESS_DENIED))) ||
973         (!ret && broken(GetLastError() == ERROR_INVALID_HANDLE)) || /* win2k */
974         broken(ret),   /* 32bit application on NT 5.x 64bit */
975         "got %d with %u (expected FALSE with ERROR_GEN_FAILURE or ERROR_ACCESS_DENIED)\n",
976         ret, GetLastError() );
977
978     CloseHandle( thread );
979 }
980
981 #endif  /* __i386__ */
982
983 static HANDLE finish_event;
984 static LONG times_executed;
985
986 static DWORD CALLBACK work_function(void *p)
987 {
988     LONG executed = InterlockedIncrement(&times_executed);
989
990     if (executed == 100)
991         SetEvent(finish_event);
992     return 0;
993 }
994
995 static void test_QueueUserWorkItem(void)
996 {
997     INT_PTR i;
998     DWORD wait_result;
999     DWORD before, after;
1000
1001     /* QueueUserWorkItem not present on win9x */
1002     if (!pQueueUserWorkItem) return;
1003
1004     finish_event = CreateEvent(NULL, TRUE, FALSE, NULL);
1005
1006     before = GetTickCount();
1007
1008     for (i = 0; i < 100; i++)
1009     {
1010         BOOL ret = pQueueUserWorkItem(work_function, (void *)i, WT_EXECUTEDEFAULT);
1011         ok(ret, "QueueUserWorkItem failed with error %d\n", GetLastError());
1012     }
1013
1014     wait_result = WaitForSingleObject(finish_event, 10000);
1015
1016     after = GetTickCount();
1017     trace("100 QueueUserWorkItem calls took %dms\n", after - before);
1018     ok(wait_result == WAIT_OBJECT_0, "wait failed with error 0x%x\n", wait_result);
1019
1020     ok(times_executed == 100, "didn't execute all of the work items\n");
1021 }
1022
1023 static void CALLBACK signaled_function(PVOID p, BOOLEAN TimerOrWaitFired)
1024 {
1025     HANDLE event = p;
1026     SetEvent(event);
1027     ok(!TimerOrWaitFired, "wait shouldn't have timed out\n");
1028 }
1029
1030 static void CALLBACK timeout_function(PVOID p, BOOLEAN TimerOrWaitFired)
1031 {
1032     HANDLE event = p;
1033     SetEvent(event);
1034     ok(TimerOrWaitFired, "wait should have timed out\n");
1035 }
1036
1037 static void test_RegisterWaitForSingleObject(void)
1038 {
1039     BOOL ret;
1040     HANDLE wait_handle;
1041     HANDLE handle;
1042     HANDLE complete_event;
1043
1044     if (!pRegisterWaitForSingleObject || !pUnregisterWait)
1045     {
1046         win_skip("RegisterWaitForSingleObject or UnregisterWait not implemented\n");
1047         return;
1048     }
1049
1050     /* test signaled case */
1051
1052     handle = CreateEvent(NULL, TRUE, TRUE, NULL);
1053     complete_event = CreateEvent(NULL, FALSE, FALSE, NULL);
1054
1055     ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1056     ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1057
1058     WaitForSingleObject(complete_event, INFINITE);
1059     /* give worker thread chance to complete */
1060     Sleep(100);
1061
1062     ret = pUnregisterWait(wait_handle);
1063     ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1064
1065     /* test cancel case */
1066
1067     ResetEvent(handle);
1068
1069     ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1070     ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1071
1072     ret = pUnregisterWait(wait_handle);
1073     ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1074
1075     /* test timeout case */
1076
1077     ret = pRegisterWaitForSingleObject(&wait_handle, handle, timeout_function, complete_event, 0, WT_EXECUTEONLYONCE);
1078     ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1079
1080     WaitForSingleObject(complete_event, INFINITE);
1081     /* give worker thread chance to complete */
1082     Sleep(100);
1083
1084     ret = pUnregisterWait(wait_handle);
1085     ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1086 }
1087
1088 static DWORD TLS_main;
1089 static DWORD TLS_index0, TLS_index1;
1090
1091 static DWORD WINAPI TLS_InheritanceProc(LPVOID p)
1092 {
1093   /* We should NOT inherit the TLS values from our parent or from the
1094      main thread.  */
1095   LPVOID val;
1096
1097   val = TlsGetValue(TLS_main);
1098   ok(val == NULL, "TLS inheritance failed\n");
1099
1100   val = TlsGetValue(TLS_index0);
1101   ok(val == NULL, "TLS inheritance failed\n");
1102
1103   val = TlsGetValue(TLS_index1);
1104   ok(val == NULL, "TLS inheritance failed\n");
1105
1106   return 0;
1107 }
1108
1109 /* Basic TLS usage test.  Make sure we can create slots and the values we
1110    store in them are separate among threads.  Also test TLS value
1111    inheritance with TLS_InheritanceProc.  */
1112 static DWORD WINAPI TLS_ThreadProc(LPVOID p)
1113 {
1114   LONG_PTR id = (LONG_PTR) p;
1115   LPVOID val;
1116   BOOL ret;
1117
1118   if (sync_threads_and_run_one(0, id))
1119   {
1120     TLS_index0 = TlsAlloc();
1121     ok(TLS_index0 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1122   }
1123   resync_after_run();
1124
1125   if (sync_threads_and_run_one(1, id))
1126   {
1127     TLS_index1 = TlsAlloc();
1128     ok(TLS_index1 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1129
1130     /* Slot indices should be different even if created in different
1131        threads.  */
1132     ok(TLS_index0 != TLS_index1, "TlsAlloc failed\n");
1133
1134     /* Both slots should be initialized to NULL */
1135     val = TlsGetValue(TLS_index0);
1136     ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1137     ok(val == NULL, "TLS slot not initialized correctly\n");
1138
1139     val = TlsGetValue(TLS_index1);
1140     ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1141     ok(val == NULL, "TLS slot not initialized correctly\n");
1142   }
1143   resync_after_run();
1144
1145   if (sync_threads_and_run_one(0, id))
1146   {
1147     val = TlsGetValue(TLS_index0);
1148     ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1149     ok(val == NULL, "TLS slot not initialized correctly\n");
1150
1151     val = TlsGetValue(TLS_index1);
1152     ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1153     ok(val == NULL, "TLS slot not initialized correctly\n");
1154
1155     ret = TlsSetValue(TLS_index0, (LPVOID) 1);
1156     ok(ret, "TlsSetValue failed\n");
1157
1158     ret = TlsSetValue(TLS_index1, (LPVOID) 2);
1159     ok(ret, "TlsSetValue failed\n");
1160
1161     val = TlsGetValue(TLS_index0);
1162     ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1163     ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1164
1165     val = TlsGetValue(TLS_index1);
1166     ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1167     ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1168   }
1169   resync_after_run();
1170
1171   if (sync_threads_and_run_one(1, id))
1172   {
1173     val = TlsGetValue(TLS_index0);
1174     ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1175     ok(val == NULL, "TLS slot not initialized correctly\n");
1176
1177     val = TlsGetValue(TLS_index1);
1178     ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1179     ok(val == NULL, "TLS slot not initialized correctly\n");
1180
1181     ret = TlsSetValue(TLS_index0, (LPVOID) 3);
1182     ok(ret, "TlsSetValue failed\n");
1183
1184     ret = TlsSetValue(TLS_index1, (LPVOID) 4);
1185     ok(ret, "TlsSetValue failed\n");
1186
1187     val = TlsGetValue(TLS_index0);
1188     ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1189     ok(val == (LPVOID) 3, "TLS slot not initialized correctly\n");
1190
1191     val = TlsGetValue(TLS_index1);
1192     ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1193     ok(val == (LPVOID) 4, "TLS slot not initialized correctly\n");
1194   }
1195   resync_after_run();
1196
1197   if (sync_threads_and_run_one(0, id))
1198   {
1199     HANDLE thread;
1200     DWORD waitret, tid;
1201
1202     val = TlsGetValue(TLS_index0);
1203     ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1204     ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1205
1206     val = TlsGetValue(TLS_index1);
1207     ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1208     ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1209
1210     thread = CreateThread(NULL, 0, TLS_InheritanceProc, 0, 0, &tid);
1211     ok(thread != NULL, "CreateThread failed\n");
1212     waitret = WaitForSingleObject(thread, 60000);
1213     ok(waitret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
1214     CloseHandle(thread);
1215
1216     ret = TlsFree(TLS_index0);
1217     ok(ret, "TlsFree failed\n");
1218   }
1219   resync_after_run();
1220
1221   if (sync_threads_and_run_one(1, id))
1222   {
1223     ret = TlsFree(TLS_index1);
1224     ok(ret, "TlsFree failed\n");
1225   }
1226   resync_after_run();
1227
1228   return 0;
1229 }
1230
1231 static void test_TLS(void)
1232 {
1233   HANDLE threads[2];
1234   LONG_PTR i;
1235   DWORD ret;
1236   BOOL suc;
1237
1238   init_thread_sync_helpers();
1239
1240   /* Allocate a TLS slot in the main thread to test for inheritance.  */
1241   TLS_main = TlsAlloc();
1242   ok(TLS_main != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1243   suc = TlsSetValue(TLS_main, (LPVOID) 4114);
1244   ok(suc, "TlsSetValue failed\n");
1245
1246   for (i = 0; i < 2; ++i)
1247   {
1248     DWORD tid;
1249
1250     threads[i] = CreateThread(NULL, 0, TLS_ThreadProc, (LPVOID) i, 0, &tid);
1251     ok(threads[i] != NULL, "CreateThread failed\n");
1252   }
1253
1254   ret = WaitForMultipleObjects(2, threads, TRUE, 60000);
1255   ok(ret == WAIT_OBJECT_0 || broken(ret == WAIT_OBJECT_0+1 /* nt4,w2k */), "WaitForAllObjects 2 threads %d\n",ret);
1256
1257   for (i = 0; i < 2; ++i)
1258     CloseHandle(threads[i]);
1259
1260   suc = TlsFree(TLS_main);
1261   ok(suc, "TlsFree failed\n");
1262   cleanup_thread_sync_helpers();
1263 }
1264
1265 static void test_ThreadErrorMode(void)
1266 {
1267     DWORD oldmode;
1268     DWORD mode;
1269     DWORD rtlmode;
1270     BOOL ret;
1271
1272     if (!pSetThreadErrorMode || !pGetThreadErrorMode)
1273     {
1274         win_skip("SetThreadErrorMode and/or GetThreadErrorMode unavailable (added in Windows 7)\n");
1275         return;
1276     }
1277
1278     if (!pRtlGetThreadErrorMode) {
1279         win_skip("RtlGetThreadErrorMode not available\n");
1280         return;
1281     }
1282
1283     oldmode = pGetThreadErrorMode();
1284
1285     ret = pSetThreadErrorMode(0, &mode);
1286     ok(ret, "SetThreadErrorMode failed\n");
1287     ok(mode == oldmode,
1288        "SetThreadErrorMode returned old mode 0x%x, expected 0x%x\n",
1289        mode, oldmode);
1290     mode = pGetThreadErrorMode();
1291     ok(mode == 0, "GetThreadErrorMode returned mode 0x%x, expected 0\n", mode);
1292     rtlmode = pRtlGetThreadErrorMode();
1293     ok(rtlmode == 0,
1294        "RtlGetThreadErrorMode returned mode 0x%x, expected 0\n", mode);
1295
1296     ret = pSetThreadErrorMode(SEM_FAILCRITICALERRORS, &mode);
1297     ok(ret, "SetThreadErrorMode failed\n");
1298     ok(mode == 0,
1299        "SetThreadErrorMode returned old mode 0x%x, expected 0\n", mode);
1300     mode = pGetThreadErrorMode();
1301     ok(mode == SEM_FAILCRITICALERRORS,
1302        "GetThreadErrorMode returned mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1303        mode);
1304     rtlmode = pRtlGetThreadErrorMode();
1305     ok(rtlmode == 0x10,
1306        "RtlGetThreadErrorMode returned mode 0x%x, expected 0x10\n", mode);
1307
1308     ret = pSetThreadErrorMode(SEM_NOGPFAULTERRORBOX, &mode);
1309     ok(ret, "SetThreadErrorMode failed\n");
1310     ok(mode == SEM_FAILCRITICALERRORS,
1311        "SetThreadErrorMode returned old mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1312        mode);
1313     mode = pGetThreadErrorMode();
1314     ok(mode == SEM_NOGPFAULTERRORBOX,
1315        "GetThreadErrorMode returned mode 0x%x, expected SEM_NOGPFAULTERRORBOX\n",
1316        mode);
1317     rtlmode = pRtlGetThreadErrorMode();
1318     ok(rtlmode == 0x20,
1319        "RtlGetThreadErrorMode returned mode 0x%x, expected 0x20\n", mode);
1320
1321     ret = pSetThreadErrorMode(SEM_NOOPENFILEERRORBOX, NULL);
1322     ok(ret, "SetThreadErrorMode failed\n");
1323     mode = pGetThreadErrorMode();
1324     ok(mode == SEM_NOOPENFILEERRORBOX,
1325        "GetThreadErrorMode returned mode 0x%x, expected SEM_NOOPENFILEERRORBOX\n",
1326        mode);
1327     rtlmode = pRtlGetThreadErrorMode();
1328     ok(rtlmode == 0x40,
1329        "RtlGetThreadErrorMode returned mode 0x%x, expected 0x40\n", rtlmode);
1330
1331     for (mode = 1; mode; mode <<= 1)
1332     {
1333         ret = pSetThreadErrorMode(mode, NULL);
1334         if (mode & (SEM_FAILCRITICALERRORS |
1335                     SEM_NOGPFAULTERRORBOX |
1336                     SEM_NOOPENFILEERRORBOX))
1337         {
1338             ok(ret,
1339                "SetThreadErrorMode(0x%x,NULL) failed with error %d\n",
1340                mode, GetLastError());
1341         }
1342         else
1343         {
1344             DWORD GLE = GetLastError();
1345             ok(!ret,
1346                "SetThreadErrorMode(0x%x,NULL) succeeded, expected failure\n",
1347                mode);
1348             ok(GLE == ERROR_INVALID_PARAMETER,
1349                "SetThreadErrorMode(0x%x,NULL) failed with %d, "
1350                "expected ERROR_INVALID_PARAMETER\n",
1351                mode, GLE);
1352         }
1353     }
1354
1355     pSetThreadErrorMode(oldmode, NULL);
1356 }
1357
1358 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
1359 static inline void set_fpu_cw(WORD cw)
1360 {
1361     __asm__ volatile ("fnclex; fldcw %0" : : "m" (cw));
1362 }
1363
1364 static inline WORD get_fpu_cw(void)
1365 {
1366     WORD cw = 0;
1367     __asm__ volatile ("fnstcw %0" : "=m" (cw));
1368     return cw;
1369 }
1370
1371 struct fpu_thread_ctx
1372 {
1373     WORD cw;
1374     HANDLE finished;
1375 };
1376
1377 static DWORD WINAPI fpu_thread(void *param)
1378 {
1379     struct fpu_thread_ctx *ctx = param;
1380     BOOL ret;
1381
1382     ctx->cw = get_fpu_cw();
1383
1384     ret = SetEvent(ctx->finished);
1385     ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
1386
1387     return 0;
1388 }
1389
1390 static WORD get_thread_fpu_cw(void)
1391 {
1392     struct fpu_thread_ctx ctx;
1393     DWORD tid, res;
1394     HANDLE thread;
1395
1396     ctx.finished = CreateEvent(NULL, FALSE, FALSE, NULL);
1397     ok(!!ctx.finished, "Failed to create event, last error %#x.\n", GetLastError());
1398
1399     thread = CreateThread(NULL, 0, fpu_thread, &ctx, 0, &tid);
1400     ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
1401
1402     res = WaitForSingleObject(ctx.finished, INFINITE);
1403     ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
1404
1405     res = CloseHandle(ctx.finished);
1406     ok(!!res, "Failed to close event handle, last error %#x.\n", GetLastError());
1407
1408     return ctx.cw;
1409 }
1410
1411 static void test_thread_fpu_cw(void)
1412 {
1413     WORD initial_cw, cw;
1414
1415     initial_cw = get_fpu_cw();
1416     ok(initial_cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", initial_cw);
1417
1418     cw = get_thread_fpu_cw();
1419     ok(cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", cw);
1420
1421     set_fpu_cw(0xf60);
1422     cw = get_fpu_cw();
1423     ok(cw == 0xf60, "Expected FPU control word 0xf60, got %#x.\n", cw);
1424
1425     cw = get_thread_fpu_cw();
1426     ok(cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", cw);
1427
1428     cw = get_fpu_cw();
1429     ok(cw == 0xf60, "Expected FPU control word 0xf60, got %#x.\n", cw);
1430
1431     set_fpu_cw(initial_cw);
1432     cw = get_fpu_cw();
1433     ok(cw == initial_cw, "Expected FPU control word %#x, got %#x.\n", initial_cw, cw);
1434 }
1435 #endif
1436
1437 START_TEST(thread)
1438 {
1439    HINSTANCE lib;
1440    HINSTANCE ntdll;
1441    int argc;
1442    char **argv;
1443    argc = winetest_get_mainargs( &argv );
1444 /* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
1445    so that the compile passes
1446 */
1447    lib=GetModuleHandleA("kernel32.dll");
1448    ok(lib!=NULL,"Couldn't get a handle for kernel32.dll\n");
1449    pGetThreadPriorityBoost=(void *)GetProcAddress(lib,"GetThreadPriorityBoost");
1450    pOpenThread=(void *)GetProcAddress(lib,"OpenThread");
1451    pQueueUserWorkItem=(void *)GetProcAddress(lib,"QueueUserWorkItem");
1452    pSetThreadIdealProcessor=(void *)GetProcAddress(lib,"SetThreadIdealProcessor");
1453    pSetThreadPriorityBoost=(void *)GetProcAddress(lib,"SetThreadPriorityBoost");
1454    pRegisterWaitForSingleObject=(void *)GetProcAddress(lib,"RegisterWaitForSingleObject");
1455    pUnregisterWait=(void *)GetProcAddress(lib,"UnregisterWait");
1456    pIsWow64Process=(void *)GetProcAddress(lib,"IsWow64Process");
1457    pSetThreadErrorMode=(void *)GetProcAddress(lib,"SetThreadErrorMode");
1458    pGetThreadErrorMode=(void *)GetProcAddress(lib,"GetThreadErrorMode");
1459
1460    ntdll=GetModuleHandleA("ntdll.dll");
1461    if (ntdll)
1462    {
1463        pRtlGetThreadErrorMode=(void *)GetProcAddress(ntdll,"RtlGetThreadErrorMode");
1464    }
1465
1466    if (argc >= 3)
1467    {
1468        if (!strcmp(argv[2], "sleep"))
1469        {
1470            HANDLE hAddrEvents[2];
1471            create_function_addr_events(hAddrEvents);
1472            SetEvent(hAddrEvents[0]);
1473            SetEvent(hAddrEvents[1]);
1474            Sleep(5000); /* spawned process runs for at most 5 seconds */
1475            return;
1476        }
1477        while (1)
1478        {
1479            HANDLE hThread;
1480            DWORD tid;
1481            hThread = CreateThread(NULL, 0, threadFunc2, NULL, 0, &tid);
1482            ok(hThread != NULL, "CreateThread failed, error %u\n",
1483               GetLastError());
1484            ok(WaitForSingleObject(hThread, 200) == WAIT_OBJECT_0,
1485               "Thread did not exit in time\n");
1486            if (hThread == NULL) break;
1487            CloseHandle(hThread);
1488        }
1489        return;
1490    }
1491
1492    test_CreateRemoteThread();
1493    test_CreateThread_basic();
1494    test_CreateThread_suspended();
1495    test_SuspendThread();
1496    test_TerminateThread();
1497    test_CreateThread_stack();
1498    test_thread_priority();
1499    test_GetThreadTimes();
1500    test_thread_processor();
1501    test_GetThreadExitCode();
1502 #ifdef __i386__
1503    test_SetThreadContext();
1504 #endif
1505    test_QueueUserWorkItem();
1506    test_RegisterWaitForSingleObject();
1507    test_TLS();
1508    test_ThreadErrorMode();
1509 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
1510    test_thread_fpu_cw();
1511 #endif
1512 }