wined3d: Pack hardcoded local constants in ARB.
[wine] / dlls / kernel32 / tests / thread.c
1 /*
2  * Unit test suite for directory 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 typedef BOOL (WINAPI *GetThreadPriorityBoost_t)(HANDLE,PBOOL);
58 static GetThreadPriorityBoost_t pGetThreadPriorityBoost=NULL;
59
60 typedef HANDLE (WINAPI *OpenThread_t)(DWORD,BOOL,DWORD);
61 static OpenThread_t pOpenThread=NULL;
62
63 typedef BOOL (WINAPI *QueueUserWorkItem_t)(LPTHREAD_START_ROUTINE,PVOID,ULONG);
64 static QueueUserWorkItem_t pQueueUserWorkItem=NULL;
65
66 typedef DWORD (WINAPI *SetThreadIdealProcessor_t)(HANDLE,DWORD);
67 static SetThreadIdealProcessor_t pSetThreadIdealProcessor=NULL;
68
69 typedef BOOL (WINAPI *SetThreadPriorityBoost_t)(HANDLE,BOOL);
70 static SetThreadPriorityBoost_t pSetThreadPriorityBoost=NULL;
71
72 typedef BOOL (WINAPI *RegisterWaitForSingleObject_t)(PHANDLE,HANDLE,WAITORTIMERCALLBACK,PVOID,ULONG,ULONG);
73 static RegisterWaitForSingleObject_t pRegisterWaitForSingleObject=NULL;
74
75 typedef BOOL (WINAPI *UnregisterWait_t)(HANDLE);
76 static UnregisterWait_t pUnregisterWait=NULL;
77
78 static HANDLE create_target_process(const char *arg)
79 {
80     char **argv;
81     char cmdline[MAX_PATH];
82     PROCESS_INFORMATION pi;
83     STARTUPINFO si = { 0 };
84     si.cb = sizeof(si);
85
86     winetest_get_mainargs( &argv );
87     sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
88     ok(CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL,
89                      &si, &pi) != 0, "error: %u\n", GetLastError());
90     ok(CloseHandle(pi.hThread) != 0, "error %u\n", GetLastError());
91     return pi.hProcess;
92 }
93
94 /* Functions not tested yet:
95   AttachThreadInput
96   SetThreadContext
97   SwitchToThread
98
99 In addition there are no checks that the inheritance works properly in
100 CreateThread
101 */
102
103 /* Functions to ensure that from a group of threads, only one executes
104    certain chunks of code at a time, and we know which one is executing
105    it.  It basically makes multithreaded execution linear, which defeats
106    the purpose of multiple threads, but makes testing easy.  */
107 static HANDLE start_event, stop_event;
108 static LONG num_synced;
109
110 static void init_thread_sync_helpers(void)
111 {
112   start_event = CreateEvent(NULL, TRUE, FALSE, NULL);
113   ok(start_event != NULL, "CreateEvent failed\n");
114   stop_event = CreateEvent(NULL, TRUE, FALSE, NULL);
115   ok(stop_event != NULL, "CreateEvent failed\n");
116   num_synced = -1;
117 }
118
119 static BOOL sync_threads_and_run_one(DWORD sync_id, DWORD my_id)
120 {
121   LONG num = InterlockedIncrement(&num_synced);
122   assert(-1 <= num && num <= 1);
123   if (num == 1)
124   {
125       ResetEvent( stop_event );
126       SetEvent( start_event );
127   }
128   else
129   {
130     DWORD ret = WaitForSingleObject(start_event, 10000);
131     ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed %x\n",ret);
132   }
133   return sync_id == my_id;
134 }
135
136 static void resync_after_run(void)
137 {
138   LONG num = InterlockedDecrement(&num_synced);
139   assert(-1 <= num && num <= 1);
140   if (num == -1)
141   {
142       ResetEvent( start_event );
143       SetEvent( stop_event );
144   }
145   else
146   {
147     DWORD ret = WaitForSingleObject(stop_event, 10000);
148     ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
149   }
150 }
151
152 static void cleanup_thread_sync_helpers(void)
153 {
154   CloseHandle(start_event);
155   CloseHandle(stop_event);
156 }
157
158 DWORD tlsIndex;
159
160 typedef struct {
161   int threadnum;
162   HANDLE *event;
163   DWORD *threadmem;
164 } t1Struct;
165
166 /* WinME supports OpenThread but doesn't know about access restrictions so
167    we require them to be either completely ignored or always obeyed.
168 */
169 INT obeying_ars = 0; /* -1 == no, 0 == dunno yet, 1 == yes */
170 #define obey_ar(x) \
171   (obeying_ars == 0 \
172     ? ((x) \
173       ? (obeying_ars = +1) \
174       : ((obeying_ars = -1), \
175          trace("not restricted, assuming consistent behaviour\n"))) \
176     : (obeying_ars < 0) \
177       ? ok(!(x), "access restrictions obeyed\n") \
178       : ok( (x), "access restrictions not obeyed\n"))
179
180 /* Basic test that simultaneous threads can access shared memory,
181    that the thread local storage routines work correctly, and that
182    threads actually run concurrently
183 */
184 static DWORD WINAPI threadFunc1(LPVOID p)
185 {
186    t1Struct *tstruct = p;
187    int i;
188 /* write our thread # into shared memory */
189    tstruct->threadmem[tstruct->threadnum]=GetCurrentThreadId();
190    ok(TlsSetValue(tlsIndex,(LPVOID)(INT_PTR)(tstruct->threadnum+1))!=0,
191       "TlsSetValue failed\n");
192 /* The threads synchronize before terminating.  This is done by
193    Signaling an event, and waiting for all events to occur
194 */
195    SetEvent(tstruct->event[tstruct->threadnum]);
196    WaitForMultipleObjects(NUM_THREADS,tstruct->event,TRUE,INFINITE);
197 /* Double check that all threads really did run by validating that
198    they have all written to the shared memory. There should be no race
199    here, since all threads were synchronized after the write.*/
200    for(i=0;i<NUM_THREADS;i++) {
201      while(tstruct->threadmem[i]==0) ;
202    }
203
204    /* lstrlenA contains an exception handler so this makes sure exceptions work in threads */
205    ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
206
207 /* Check that no one changed our tls memory */
208    ok((INT_PTR)TlsGetValue(tlsIndex)-1==tstruct->threadnum,
209       "TlsGetValue failed\n");
210    return NUM_THREADS+tstruct->threadnum;
211 }
212
213 static DWORD WINAPI threadFunc2(LPVOID p)
214 {
215    return 99;
216 }
217
218 static DWORD WINAPI threadFunc3(LPVOID p)
219 {
220    HANDLE thread;
221    thread=GetCurrentThread();
222    SuspendThread(thread);
223    return 99;
224 }
225
226 static DWORD WINAPI threadFunc4(LPVOID p)
227 {
228    HANDLE event = p;
229    if(event != NULL) {
230      SetEvent(event);
231    }
232    Sleep(99000);
233    return 0;
234 }
235
236 #if CHECK_STACK
237 static DWORD WINAPI threadFunc5(LPVOID p)
238 {
239   DWORD *exitCode = p;
240   SYSTEM_INFO sysInfo;
241   sysInfo.dwPageSize=0;
242   GetSystemInfo(&sysInfo);
243   *exitCode=0;
244    __TRY
245    {
246      alloca(2*sysInfo.dwPageSize);
247    }
248     __EXCEPT(1) {
249      *exitCode=1;
250    }
251    __ENDTRY
252    return 0;
253 }
254 #endif
255
256 static DWORD WINAPI threadFunc_SetEvent(LPVOID p)
257 {
258     SetEvent(p);
259     return 0;
260 }
261
262 static DWORD WINAPI threadFunc_CloseHandle(LPVOID p)
263 {
264     CloseHandle(p);
265     return 0;
266 }
267
268 static void create_function_addr_events(HANDLE events[2])
269 {
270     char buffer[256];
271
272     sprintf(buffer, "threadFunc_SetEvent %p", threadFunc_SetEvent);
273     events[0] = CreateEvent(NULL, FALSE, FALSE, buffer);
274
275     sprintf(buffer, "threadFunc_CloseHandle %p", threadFunc_CloseHandle);
276     events[1] = CreateEvent(NULL, FALSE, FALSE, buffer);
277 }
278
279 /* check CreateRemoteThread */
280 static VOID test_CreateRemoteThread(void)
281 {
282     HANDLE hProcess, hThread, hEvent, hRemoteEvent;
283     DWORD tid, ret, exitcode;
284     HANDLE hAddrEvents[2];
285
286     hProcess = create_target_process("sleep");
287     ok(hProcess != NULL, "Can't start process\n");
288
289     /* ensure threadFunc_SetEvent & threadFunc_CloseHandle are the same
290      * address as in the child process */
291     create_function_addr_events(hAddrEvents);
292     ret = WaitForMultipleObjects(2, hAddrEvents, TRUE, 5000);
293     if (ret == WAIT_TIMEOUT)
294     {
295         skip("child process wasn't mapped at same address, so can't do CreateRemoteThread tests.\n");
296         return;
297     }
298
299     hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
300     ok(hEvent != NULL, "Can't create event, err=%u\n", GetLastError());
301     ret = DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &hRemoteEvent,
302                           0, FALSE, DUPLICATE_SAME_ACCESS);
303     ok(ret != 0, "DuplicateHandle failed, err=%u\n", GetLastError());
304
305     /* create suspended remote thread with entry point SetEvent() */
306     SetLastError(0xdeadbeef);
307     hThread = CreateRemoteThread(hProcess, NULL, 0, threadFunc_SetEvent,
308                                  hRemoteEvent, CREATE_SUSPENDED, &tid);
309     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
310     {
311         win_skip("CreateRemoteThread is not implemented\n");
312         goto cleanup;
313     }
314     ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
315     ok(tid != 0, "null tid\n");
316     ret = SuspendThread(hThread);
317     ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
318     ret = ResumeThread(hThread);
319     ok(ret == 2, "ret=%u, err=%u\n", ret, GetLastError());
320
321     /* thread still suspended, so wait times out */
322     ret = WaitForSingleObject(hEvent, 100);
323     ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
324
325     ret = ResumeThread(hThread);
326     ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
327
328     /* wait that doesn't time out */
329     ret = WaitForSingleObject(hEvent, 100);
330     ok(ret == WAIT_OBJECT_0, "object not signaled, ret=%u\n", ret);
331
332     /* wait for thread end */
333     ret = WaitForSingleObject(hThread, 100);
334     ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
335     CloseHandle(hThread);
336
337     /* create and wait for remote thread with entry point CloseHandle() */
338     hThread = CreateRemoteThread(hProcess, NULL, 0,
339                                  threadFunc_CloseHandle,
340                                  hRemoteEvent, 0, &tid);
341     ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
342     ret = WaitForSingleObject(hThread, 100);
343     ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
344     CloseHandle(hThread);
345
346     /* create remote thread with entry point SetEvent() */
347     hThread = CreateRemoteThread(hProcess, NULL, 0,
348                                  threadFunc_SetEvent,
349                                  hRemoteEvent, 0, &tid);
350     ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
351
352     /* closed handle, so wait times out */
353     ret = WaitForSingleObject(hEvent, 100);
354     ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
355
356     /* check that remote SetEvent() failed */
357     ret = GetExitCodeThread(hThread, &exitcode);
358     ok(ret != 0, "GetExitCodeThread failed, err=%u\n", GetLastError());
359     if (ret) ok(exitcode == 0, "SetEvent succeeded, expected to fail\n");
360     CloseHandle(hThread);
361
362 cleanup:
363     TerminateProcess(hProcess, 0);
364     CloseHandle(hEvent);
365     CloseHandle(hProcess);
366 }
367
368 /* Check basic functionality of CreateThread and Tls* functions */
369 static VOID test_CreateThread_basic(void)
370 {
371    HANDLE thread[NUM_THREADS],event[NUM_THREADS];
372    DWORD threadid[NUM_THREADS],curthreadId;
373    DWORD threadmem[NUM_THREADS];
374    DWORD exitCode;
375    t1Struct tstruct[NUM_THREADS];
376    int error;
377    DWORD i,j;
378    DWORD GLE, ret;
379    DWORD tid;
380
381    /* lstrlenA contains an exception handler so this makes sure exceptions work in the main thread */
382    ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
383
384 /* Retrieve current Thread ID for later comparisons */
385   curthreadId=GetCurrentThreadId();
386 /* Allocate some local storage */
387   ok((tlsIndex=TlsAlloc())!=TLS_OUT_OF_INDEXES,"TlsAlloc failed\n");
388 /* Create events for thread synchronization */
389   for(i=0;i<NUM_THREADS;i++) {
390     threadmem[i]=0;
391 /* Note that it doesn't matter what type of event we choose here.  This
392    test isn't trying to thoroughly test events
393 */
394     event[i]=CreateEventA(NULL,TRUE,FALSE,NULL);
395     tstruct[i].threadnum=i;
396     tstruct[i].threadmem=threadmem;
397     tstruct[i].event=event;
398   }
399
400 /* Test that passing arguments to threads works okay */
401   for(i=0;i<NUM_THREADS;i++) {
402     thread[i] = CreateThread(NULL,0,threadFunc1,
403                              &tstruct[i],0,&threadid[i]);
404     ok(thread[i]!=NULL,"Create Thread failed\n");
405   }
406 /* Test that the threads actually complete */
407   for(i=0;i<NUM_THREADS;i++) {
408     error=WaitForSingleObject(thread[i],5000);
409     ok(error==WAIT_OBJECT_0, "Thread did not complete within timelimit\n");
410     if(error!=WAIT_OBJECT_0) {
411       TerminateThread(thread[i],i+NUM_THREADS);
412     }
413     ok(GetExitCodeThread(thread[i],&exitCode),"Could not retrieve ext code\n");
414     ok(exitCode==i+NUM_THREADS,"Thread returned an incorrect exit code\n");
415   }
416 /* Test that each thread executed in its parent's address space
417    (it was able to change threadmem and pass that change back to its parent)
418    and that each thread id was independent).  Note that we prove that the
419    threads actually execute concurrently by having them block on each other
420    in threadFunc1
421 */
422   for(i=0;i<NUM_THREADS;i++) {
423     error=0;
424     for(j=i+1;j<NUM_THREADS;j++) {
425       if (threadmem[i]==threadmem[j]) {
426         error=1;
427       }
428     }
429     ok(!error && threadmem[i]==threadid[i] && threadmem[i]!=curthreadId,
430          "Thread did not execute successfully\n");
431     ok(CloseHandle(thread[i])!=0,"CloseHandle failed\n");
432   }
433   ok(TlsFree(tlsIndex)!=0,"TlsFree failed\n");
434
435   /* Test how passing NULL as a pointer to threadid works */
436   SetLastError(0xFACEaBAD);
437   thread[0] = CreateThread(NULL,0,threadFunc2,NULL,0,&tid);
438   GLE = GetLastError();
439   if (thread[0]) { /* NT */
440     ok(GLE==0xFACEaBAD, "CreateThread set last error to %d, expected 4207848365\n", GLE);
441     ret = WaitForSingleObject(thread[0],100);
442     ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
443     ret = GetExitCodeThread(thread[0],&exitCode);
444     ok(ret!=0, "GetExitCodeThread returned %d (expected nonzero)\n", ret);
445     ok(exitCode==99, "threadFunc2 exited with code: %d (expected 99)\n", exitCode);
446     ok(CloseHandle(thread[0])!=0,"Error closing thread handle\n");
447   }
448   else { /* 9x */
449     ok(GLE==ERROR_INVALID_PARAMETER, "CreateThread set last error to %d, expected 87\n", GLE);
450   }
451 }
452
453 /* Check that using the CREATE_SUSPENDED flag works */
454 static VOID test_CreateThread_suspended(void)
455 {
456   HANDLE thread;
457   DWORD threadId;
458   DWORD suspend_count;
459   int error;
460
461   thread = CreateThread(NULL,0,threadFunc2,NULL,
462                         CREATE_SUSPENDED,&threadId);
463   ok(thread!=NULL,"Create Thread failed\n");
464 /* Check that the thread is suspended */
465   ok(SuspendThread(thread)==1,"Thread did not start suspended\n");
466   ok(ResumeThread(thread)==2,"Resume thread returned an invalid value\n");
467 /* Check that resume thread didn't actually start the thread.  I can't think
468    of a better way of checking this than just waiting.  I am not sure if this
469    will work on slow computers.
470 */
471   ok(WaitForSingleObject(thread,1000)==WAIT_TIMEOUT,
472      "ResumeThread should not have actually started the thread\n");
473 /* Now actually resume the thread and make sure that it actually completes*/
474   ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
475   ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
476      "Thread did not resume\n");
477   if(error!=WAIT_OBJECT_0) {
478     TerminateThread(thread,1);
479   }
480
481   suspend_count = SuspendThread(thread);
482   ok(suspend_count == -1, "SuspendThread returned %d, expected -1\n", suspend_count);
483
484   suspend_count = ResumeThread(thread);
485   ok(suspend_count == 0 ||
486      broken(suspend_count == -1), /* win9x */
487      "ResumeThread returned %d, expected 0\n", suspend_count);
488
489   ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
490 }
491
492 /* Check that SuspendThread and ResumeThread work */
493 static VOID test_SuspendThread(void)
494 {
495   HANDLE thread,access_thread;
496   DWORD threadId,exitCode,error;
497   int i;
498
499   thread = CreateThread(NULL,0,threadFunc3,NULL,
500                         0,&threadId);
501   ok(thread!=NULL,"Create Thread failed\n");
502 /* Check that the thread is suspended */
503 /* Note that this is a polling method, and there is a race between
504    SuspendThread being called (in the child, and the loop below timing out,
505    so the test could fail on a heavily loaded or slow computer.
506 */
507   error=0;
508   for(i=0;error==0 && i<100;i++) {
509     error=SuspendThread(thread);
510     ResumeThread(thread);
511     if(error==0) {
512       Sleep(50);
513       i++;
514     }
515   }
516   ok(error==1,"SuspendThread did not work\n");
517 /* check that access restrictions are obeyed */
518   if (pOpenThread) {
519     access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_SUSPEND_RESUME),
520                            0,threadId);
521     ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
522     if (access_thread!=NULL) {
523       obey_ar(SuspendThread(access_thread)==~0U);
524       obey_ar(ResumeThread(access_thread)==~0U);
525       ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
526     }
527   }
528 /* Double check that the thread really is suspended */
529   ok((error=GetExitCodeThread(thread,&exitCode))!=0 && exitCode==STILL_ACTIVE,
530      "Thread did not really suspend\n");
531 /* Resume the thread, and make sure it actually completes */
532   ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
533   ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
534      "Thread did not resume\n");
535   if(error!=WAIT_OBJECT_0) {
536     TerminateThread(thread,1);
537   }
538   /* Trying to suspend a terminated thread should fail */
539   error=SuspendThread(thread);
540   ok(error==~0U, "wrong return code: %d\n", error);
541   ok(GetLastError()==ERROR_ACCESS_DENIED || GetLastError()==ERROR_NO_MORE_ITEMS, "unexpected error code: %d\n", GetLastError());
542
543   ok(CloseHandle(thread)!=0,"CloseHandle Failed\n");
544 }
545
546 /* Check that TerminateThread works properly
547 */
548 static VOID test_TerminateThread(void)
549 {
550   HANDLE thread,access_thread,event;
551   DWORD threadId,exitCode;
552   event=CreateEventA(NULL,TRUE,FALSE,NULL);
553   thread = CreateThread(NULL,0,threadFunc4,event,0,&threadId);
554   ok(thread!=NULL,"Create Thread failed\n");
555 /* TerminateThread has a race condition in Wine.  If the thread is terminated
556    before it starts, it leaves a process behind.  Therefore, we wait for the
557    thread to signal that it has started.  There is no easy way to force the
558    race to occur, so we don't try to find it.
559 */
560   ok(WaitForSingleObject(event,5000)==WAIT_OBJECT_0,
561      "TerminateThread didn't work\n");
562 /* check that access restrictions are obeyed */
563   if (pOpenThread) {
564     access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_TERMINATE),
565                              0,threadId);
566     ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
567     if (access_thread!=NULL) {
568       obey_ar(TerminateThread(access_thread,99)==0);
569       ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
570     }
571   }
572 /* terminate a job and make sure it terminates */
573   ok(TerminateThread(thread,99)!=0,"TerminateThread failed\n");
574   ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
575      "TerminateThread didn't work\n");
576   ok(GetExitCodeThread(thread,&exitCode)!=STILL_ACTIVE,
577      "TerminateThread should not leave the thread 'STILL_ACTIVE'\n");
578   ok(exitCode==99, "TerminateThread returned invalid exit code\n");
579   ok(CloseHandle(thread)!=0,"Error Closing thread handle\n");
580 }
581
582 /* Check if CreateThread obeys the specified stack size.  This code does
583    not work properly, and is currently disabled
584 */
585 static VOID test_CreateThread_stack(void)
586 {
587 #if CHECK_STACK
588 /* The only way I know of to test the stack size is to use alloca
589    and __try/__except.  However, this is probably not portable,
590    and I couldn't get it to work under Wine anyhow.  However, here
591    is the code which should allow for testing that CreateThread
592    respects the stack-size limit
593 */
594      HANDLE thread;
595      DWORD threadId,exitCode;
596
597      SYSTEM_INFO sysInfo;
598      sysInfo.dwPageSize=0;
599      GetSystemInfo(&sysInfo);
600      ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
601      thread = CreateThread(NULL,sysInfo.dwPageSize,
602                            threadFunc5,&exitCode,
603                            0,&threadId);
604      ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
605         "TerminateThread didn't work\n");
606      ok(exitCode==1,"CreateThread did not obey stack-size-limit\n");
607      ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
608 #endif
609 }
610
611 /* Check whether setting/retrieving thread priorities works */
612 static VOID test_thread_priority(void)
613 {
614    HANDLE curthread,access_thread;
615    DWORD curthreadId,exitCode;
616    int min_priority=-2,max_priority=2;
617    BOOL disabled,rc;
618    int i;
619
620    curthread=GetCurrentThread();
621    curthreadId=GetCurrentThreadId();
622 /* Check thread priority */
623 /* NOTE: on Win2k/XP priority can be from -7 to 6.  All other platforms it
624          is -2 to 2.  However, even on a real Win2k system, using thread
625          priorities beyond the -2 to 2 range does not work.  If you want to try
626          anyway, enable USE_EXTENDED_PRIORITIES
627 */
628    ok(GetThreadPriority(curthread)==THREAD_PRIORITY_NORMAL,
629       "GetThreadPriority Failed\n");
630
631    if (pOpenThread) {
632 /* check that access control is obeyed */
633      access_thread=pOpenThread(THREAD_ALL_ACCESS &
634                        (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
635                        0,curthreadId);
636      ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
637      if (access_thread!=NULL) {
638        obey_ar(SetThreadPriority(access_thread,1)==0);
639        obey_ar(GetThreadPriority(access_thread)==THREAD_PRIORITY_ERROR_RETURN);
640        obey_ar(GetExitCodeThread(access_thread,&exitCode)==0);
641        ok(CloseHandle(access_thread),"Error Closing thread handle\n");
642      }
643    }
644 #if USE_EXTENDED_PRIORITIES
645    min_priority=-7; max_priority=6;
646 #endif
647    for(i=min_priority;i<=max_priority;i++) {
648      ok(SetThreadPriority(curthread,i)!=0,
649         "SetThreadPriority Failed for priority: %d\n",i);
650      ok(GetThreadPriority(curthread)==i,
651         "GetThreadPriority Failed for priority: %d\n",i);
652    }
653    ok(SetThreadPriority(curthread,THREAD_PRIORITY_TIME_CRITICAL)!=0,
654       "SetThreadPriority Failed\n");
655    ok(GetThreadPriority(curthread)==THREAD_PRIORITY_TIME_CRITICAL,
656       "GetThreadPriority Failed\n");
657    ok(SetThreadPriority(curthread,THREAD_PRIORITY_IDLE)!=0,
658        "SetThreadPriority Failed\n");
659    ok(GetThreadPriority(curthread)==THREAD_PRIORITY_IDLE,
660        "GetThreadPriority Failed\n");
661    ok(SetThreadPriority(curthread,0)!=0,"SetThreadPriority Failed\n");
662
663 /* Check that the thread priority is not changed if SetThreadPriority
664    is called with a value outside of the max/min range */
665    SetThreadPriority(curthread,min_priority);
666    SetLastError(0xdeadbeef);
667    rc = SetThreadPriority(curthread,min_priority-1);
668
669    ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
670    ok(GetLastError() == ERROR_INVALID_PARAMETER ||
671       GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
672       "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
673       GetLastError());
674    ok(GetThreadPriority(curthread)==min_priority,
675       "GetThreadPriority didn't return min_priority\n");
676
677    SetThreadPriority(curthread,max_priority);
678    SetLastError(0xdeadbeef);
679    rc = SetThreadPriority(curthread,max_priority+1);
680
681    ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
682    ok(GetLastError() == ERROR_INVALID_PARAMETER ||
683       GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
684       "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
685       GetLastError());
686    ok(GetThreadPriority(curthread)==max_priority,
687       "GetThreadPriority didn't return max_priority\n");
688
689 /* Check thread priority boost */
690    if (!pGetThreadPriorityBoost || !pSetThreadPriorityBoost) 
691      return; /* Win9x */
692
693    SetLastError(0xdeadbeef);
694    rc=pGetThreadPriorityBoost(curthread,&disabled);
695    if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
696      return; /* WinME */
697
698    todo_wine
699      ok(rc!=0,"error=%d\n",GetLastError());
700
701    if (pOpenThread) {
702 /* check that access control is obeyed */
703      access_thread=pOpenThread(THREAD_ALL_ACCESS &
704                        (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
705                        0,curthreadId);
706      ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
707      if (access_thread!=NULL) {
708        obey_ar(pSetThreadPriorityBoost(access_thread,1)==0);
709        obey_ar(pGetThreadPriorityBoost(access_thread,&disabled)==0);
710        ok(CloseHandle(access_thread),"Error Closing thread handle\n");
711      }
712    }
713
714    todo_wine {
715      rc = pSetThreadPriorityBoost(curthread,1);
716      ok( rc != 0, "error=%d\n",GetLastError());
717      rc=pGetThreadPriorityBoost(curthread,&disabled);
718      ok(rc!=0 && disabled==1,
719         "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
720
721      rc = pSetThreadPriorityBoost(curthread,0);
722      ok( rc != 0, "error=%d\n",GetLastError());
723      rc=pGetThreadPriorityBoost(curthread,&disabled);
724      ok(rc!=0 && disabled==0,
725         "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
726    }
727 }
728
729 /* check the GetThreadTimes function */
730 static VOID test_GetThreadTimes(void)
731 {
732      HANDLE thread,access_thread=NULL;
733      FILETIME creationTime,exitTime,kernelTime,userTime;
734      DWORD threadId;
735      int error;
736
737      thread = CreateThread(NULL,0,threadFunc2,NULL,
738                            CREATE_SUSPENDED,&threadId);
739
740      ok(thread!=NULL,"Create Thread failed\n");
741 /* check that access control is obeyed */
742      if (pOpenThread) {
743        access_thread=pOpenThread(THREAD_ALL_ACCESS &
744                                    (~THREAD_QUERY_INFORMATION), 0,threadId);
745        ok(access_thread!=NULL,
746           "OpenThread returned an invalid handle\n");
747      }
748      ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
749      ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
750         "ResumeThread didn't work\n");
751      creationTime.dwLowDateTime=99; creationTime.dwHighDateTime=99;
752      exitTime.dwLowDateTime=99;     exitTime.dwHighDateTime=99;
753      kernelTime.dwLowDateTime=99;   kernelTime.dwHighDateTime=99;
754      userTime.dwLowDateTime=99;     userTime.dwHighDateTime=99;
755 /* GetThreadTimes should set all of the parameters passed to it */
756      error=GetThreadTimes(thread,&creationTime,&exitTime,
757                           &kernelTime,&userTime);
758      if (error!=0 || GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
759        ok(error!=0,"GetThreadTimes failed\n");
760        ok(creationTime.dwLowDateTime!=99 || creationTime.dwHighDateTime!=99,
761           "creationTime was invalid\n");
762        ok(exitTime.dwLowDateTime!=99 || exitTime.dwHighDateTime!=99,
763           "exitTime was invalid\n");
764        ok(kernelTime.dwLowDateTime!=99 || kernelTime.dwHighDateTime!=99,
765           "kernelTimewas invalid\n");
766        ok(userTime.dwLowDateTime!=99 || userTime.dwHighDateTime!=99,
767           "userTime was invalid\n");
768        ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
769        if(access_thread!=NULL)
770        {
771          error=GetThreadTimes(access_thread,&creationTime,&exitTime,
772                               &kernelTime,&userTime);
773          obey_ar(error==0);
774        }
775      }
776      if(access_thread!=NULL) {
777        ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
778      }
779 }
780
781 /* Check the processor affinity functions */
782 /* NOTE: These functions should also be checked that they obey access control
783 */
784 static VOID test_thread_processor(void)
785 {
786    HANDLE curthread,curproc;
787    DWORD_PTR processMask,systemMask;
788    SYSTEM_INFO sysInfo;
789    int error=0;
790
791    sysInfo.dwNumberOfProcessors=0;
792    GetSystemInfo(&sysInfo);
793    ok(sysInfo.dwNumberOfProcessors>0,
794       "GetSystemInfo failed to return a valid # of processors\n");
795 /* Use the current Thread/process for all tests */
796    curthread=GetCurrentThread();
797    ok(curthread!=NULL,"GetCurrentThread failed\n");
798    curproc=GetCurrentProcess();
799    ok(curproc!=NULL,"GetCurrentProcess failed\n");
800 /* Check the Affinity Mask functions */
801    ok(GetProcessAffinityMask(curproc,&processMask,&systemMask)!=0,
802       "GetProcessAffinityMask failed\n");
803    ok(SetThreadAffinityMask(curthread,processMask)==processMask,
804       "SetThreadAffinityMask failed\n");
805    ok(SetThreadAffinityMask(curthread,processMask+1)==0,
806       "SetThreadAffinityMask passed for an illegal processor\n");
807 /* NOTE: This only works on WinNT/2000/XP) */
808    if (pSetThreadIdealProcessor) {
809      todo_wine {
810        SetLastError(0);
811        error=pSetThreadIdealProcessor(curthread,0);
812        if (GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
813          ok(error!=-1, "SetThreadIdealProcessor failed\n");
814        }
815      }
816      if (GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
817        error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
818        ok(error==-1,
819           "SetThreadIdealProcessor succeeded with an illegal processor #\n");
820        todo_wine {
821          error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS);
822          ok(error==0, "SetThreadIdealProcessor returned an incorrect value\n");
823        }
824      }
825    }
826 }
827
828 static VOID test_GetThreadExitCode(void)
829 {
830     DWORD exitCode, threadid;
831     DWORD GLE, ret;
832     HANDLE thread;
833
834     ret = GetExitCodeThread((HANDLE)0x2bad2bad,&exitCode);
835     ok(ret==0, "GetExitCodeThread returned non zero value: %d\n", ret);
836     GLE = GetLastError();
837     ok(GLE==ERROR_INVALID_HANDLE, "GetLastError returned %d (expected 6)\n", GLE);
838
839     thread = CreateThread(NULL,0,threadFunc2,NULL,0,&threadid);
840     ret = WaitForSingleObject(thread,100);
841     ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
842     ret = GetExitCodeThread(thread,&exitCode);
843     ok(ret==exitCode || ret==1, 
844        "GetExitCodeThread returned %d (expected 1 or %d)\n", ret, exitCode);
845     ok(exitCode==99, "threadFunc2 exited with code %d (expected 99)\n", exitCode);
846     ok(CloseHandle(thread)!=0,"Error closing thread handle\n");
847 }
848
849 #ifdef __i386__
850
851 static int test_value = 0;
852 static HANDLE event;
853
854 static void WINAPI set_test_val( int val )
855 {
856     test_value += val;
857 }
858
859 static DWORD WINAPI threadFunc6(LPVOID p)
860 {
861     SetEvent( event );
862     Sleep( 1000 );
863     test_value *= (int)p;
864     return 0;
865 }
866
867 static void test_SetThreadContext(void)
868 {
869     CONTEXT ctx;
870     int *stack;
871     HANDLE thread;
872     DWORD threadid;
873     DWORD prevcount;
874     BOOL ret;
875
876     SetLastError(0xdeadbeef);
877     event = CreateEvent( NULL, TRUE, FALSE, NULL );
878     thread = CreateThread( NULL, 0, threadFunc6, (void *)2, 0, &threadid );
879     ok( thread != NULL, "CreateThread failed : (%d)\n", GetLastError() );
880     if (!thread)
881     {
882         trace("Thread creation failed, skipping rest of test\n");
883         return;
884     }
885     WaitForSingleObject( event, INFINITE );
886     SuspendThread( thread );
887     CloseHandle( event );
888
889     ctx.ContextFlags = CONTEXT_FULL;
890     SetLastError(0xdeadbeef);
891     ret = GetThreadContext( thread, &ctx );
892     ok( ret, "GetThreadContext failed : (%u)\n", GetLastError() );
893
894     if (ret)
895     {
896         /* simulate a call to set_test_val(10) */
897         stack = (int *)ctx.Esp;
898         stack[-1] = 10;
899         stack[-2] = ctx.Eip;
900         ctx.Esp -= 2 * sizeof(int *);
901         ctx.Eip = (DWORD)set_test_val;
902         SetLastError(0xdeadbeef);
903         ok( SetThreadContext( thread, &ctx ), "SetThreadContext failed : (%d)\n", GetLastError() );
904     }
905
906     SetLastError(0xdeadbeef);
907     prevcount = ResumeThread( thread );
908     ok ( prevcount == 1, "Previous suspend count (%d) instead of 1, last error : (%d)\n",
909                          prevcount, GetLastError() );
910
911     WaitForSingleObject( thread, INFINITE );
912     ok( test_value == 20, "test_value %d instead of 20\n", test_value );
913 }
914
915 #endif  /* __i386__ */
916
917 static HANDLE finish_event;
918 static LONG times_executed;
919
920 static DWORD CALLBACK work_function(void *p)
921 {
922     LONG executed = InterlockedIncrement(&times_executed);
923
924     if (executed == 100)
925         SetEvent(finish_event);
926     return 0;
927 }
928
929 static void test_QueueUserWorkItem(void)
930 {
931     INT_PTR i;
932     DWORD wait_result;
933     DWORD before, after;
934
935     /* QueueUserWorkItem not present on win9x */
936     if (!pQueueUserWorkItem) return;
937
938     finish_event = CreateEvent(NULL, TRUE, FALSE, NULL);
939
940     before = GetTickCount();
941
942     for (i = 0; i < 100; i++)
943     {
944         BOOL ret = pQueueUserWorkItem(work_function, (void *)i, WT_EXECUTEDEFAULT);
945         ok(ret, "QueueUserWorkItem failed with error %d\n", GetLastError());
946     }
947
948     wait_result = WaitForSingleObject(finish_event, 10000);
949
950     after = GetTickCount();
951     trace("100 QueueUserWorkItem calls took %dms\n", after - before);
952     ok(wait_result == WAIT_OBJECT_0, "wait failed with error 0x%x\n", wait_result);
953
954     ok(times_executed == 100, "didn't execute all of the work items\n");
955 }
956
957 static void CALLBACK signaled_function(PVOID p, BOOLEAN TimerOrWaitFired)
958 {
959     HANDLE event = p;
960     SetEvent(event);
961     ok(!TimerOrWaitFired, "wait shouldn't have timed out\n");
962 }
963
964 static void CALLBACK timeout_function(PVOID p, BOOLEAN TimerOrWaitFired)
965 {
966     HANDLE event = p;
967     SetEvent(event);
968     ok(TimerOrWaitFired, "wait should have timed out\n");
969 }
970
971 static void test_RegisterWaitForSingleObject(void)
972 {
973     BOOL ret;
974     HANDLE wait_handle;
975     HANDLE handle;
976     HANDLE complete_event;
977
978     if (!pRegisterWaitForSingleObject || !pUnregisterWait)
979     {
980         win_skip("RegisterWaitForSingleObject or UnregisterWait not implemented\n");
981         return;
982     }
983
984     /* test signaled case */
985
986     handle = CreateEvent(NULL, TRUE, TRUE, NULL);
987     complete_event = CreateEvent(NULL, FALSE, FALSE, NULL);
988
989     ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
990     ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
991
992     WaitForSingleObject(complete_event, INFINITE);
993     /* give worker thread chance to complete */
994     Sleep(100);
995
996     ret = pUnregisterWait(wait_handle);
997     ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
998
999     /* test cancel case */
1000
1001     ResetEvent(handle);
1002
1003     ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1004     ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1005
1006     ret = pUnregisterWait(wait_handle);
1007     ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1008
1009     /* test timeout case */
1010
1011     ret = pRegisterWaitForSingleObject(&wait_handle, handle, timeout_function, complete_event, 0, WT_EXECUTEONLYONCE);
1012     ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1013
1014     WaitForSingleObject(complete_event, INFINITE);
1015     /* give worker thread chance to complete */
1016     Sleep(100);
1017
1018     ret = pUnregisterWait(wait_handle);
1019     ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1020 }
1021
1022 static DWORD TLS_main;
1023 static DWORD TLS_index0, TLS_index1;
1024
1025 static DWORD WINAPI TLS_InheritanceProc(LPVOID p)
1026 {
1027   /* We should NOT inherit the TLS values from our parent or from the
1028      main thread.  */
1029   LPVOID val;
1030
1031   val = TlsGetValue(TLS_main);
1032   ok(val == NULL, "TLS inheritance failed\n");
1033
1034   val = TlsGetValue(TLS_index0);
1035   ok(val == NULL, "TLS inheritance failed\n");
1036
1037   val = TlsGetValue(TLS_index1);
1038   ok(val == NULL, "TLS inheritance failed\n");
1039
1040   return 0;
1041 }
1042
1043 /* Basic TLS usage test.  Make sure we can create slots and the values we
1044    store in them are separate among threads.  Also test TLS value
1045    inheritance with TLS_InheritanceProc.  */
1046 static DWORD WINAPI TLS_ThreadProc(LPVOID p)
1047 {
1048   LONG_PTR id = (LONG_PTR) p;
1049   LPVOID val;
1050   BOOL ret;
1051
1052   if (sync_threads_and_run_one(0, id))
1053   {
1054     TLS_index0 = TlsAlloc();
1055     ok(TLS_index0 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1056   }
1057   resync_after_run();
1058
1059   if (sync_threads_and_run_one(1, id))
1060   {
1061     TLS_index1 = TlsAlloc();
1062     ok(TLS_index1 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1063
1064     /* Slot indices should be different even if created in different
1065        threads.  */
1066     ok(TLS_index0 != TLS_index1, "TlsAlloc failed\n");
1067
1068     /* Both slots should be initialized to NULL */
1069     val = TlsGetValue(TLS_index0);
1070     ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1071     ok(val == NULL, "TLS slot not initialized correctly\n");
1072
1073     val = TlsGetValue(TLS_index1);
1074     ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1075     ok(val == NULL, "TLS slot not initialized correctly\n");
1076   }
1077   resync_after_run();
1078
1079   if (sync_threads_and_run_one(0, id))
1080   {
1081     val = TlsGetValue(TLS_index0);
1082     ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1083     ok(val == NULL, "TLS slot not initialized correctly\n");
1084
1085     val = TlsGetValue(TLS_index1);
1086     ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1087     ok(val == NULL, "TLS slot not initialized correctly\n");
1088
1089     ret = TlsSetValue(TLS_index0, (LPVOID) 1);
1090     ok(ret, "TlsSetValue failed\n");
1091
1092     ret = TlsSetValue(TLS_index1, (LPVOID) 2);
1093     ok(ret, "TlsSetValue failed\n");
1094
1095     val = TlsGetValue(TLS_index0);
1096     ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1097     ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1098
1099     val = TlsGetValue(TLS_index1);
1100     ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1101     ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1102   }
1103   resync_after_run();
1104
1105   if (sync_threads_and_run_one(1, id))
1106   {
1107     val = TlsGetValue(TLS_index0);
1108     ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1109     ok(val == NULL, "TLS slot not initialized correctly\n");
1110
1111     val = TlsGetValue(TLS_index1);
1112     ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1113     ok(val == NULL, "TLS slot not initialized correctly\n");
1114
1115     ret = TlsSetValue(TLS_index0, (LPVOID) 3);
1116     ok(ret, "TlsSetValue failed\n");
1117
1118     ret = TlsSetValue(TLS_index1, (LPVOID) 4);
1119     ok(ret, "TlsSetValue failed\n");
1120
1121     val = TlsGetValue(TLS_index0);
1122     ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1123     ok(val == (LPVOID) 3, "TLS slot not initialized correctly\n");
1124
1125     val = TlsGetValue(TLS_index1);
1126     ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1127     ok(val == (LPVOID) 4, "TLS slot not initialized correctly\n");
1128   }
1129   resync_after_run();
1130
1131   if (sync_threads_and_run_one(0, id))
1132   {
1133     HANDLE thread;
1134     DWORD waitret, tid;
1135
1136     val = TlsGetValue(TLS_index0);
1137     ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1138     ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1139
1140     val = TlsGetValue(TLS_index1);
1141     ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1142     ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1143
1144     thread = CreateThread(NULL, 0, TLS_InheritanceProc, 0, 0, &tid);
1145     ok(thread != NULL, "CreateThread failed\n");
1146     waitret = WaitForSingleObject(thread, 60000);
1147     ok(waitret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
1148     CloseHandle(thread);
1149
1150     ret = TlsFree(TLS_index0);
1151     ok(ret, "TlsFree failed\n");
1152   }
1153   resync_after_run();
1154
1155   if (sync_threads_and_run_one(1, id))
1156   {
1157     ret = TlsFree(TLS_index1);
1158     ok(ret, "TlsFree failed\n");
1159   }
1160   resync_after_run();
1161
1162   return 0;
1163 }
1164
1165 static void test_TLS(void)
1166 {
1167   HANDLE threads[2];
1168   LONG_PTR i;
1169   DWORD ret;
1170   BOOL suc;
1171
1172   init_thread_sync_helpers();
1173
1174   /* Allocate a TLS slot in the main thread to test for inheritance.  */
1175   TLS_main = TlsAlloc();
1176   ok(TLS_main != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1177   suc = TlsSetValue(TLS_main, (LPVOID) 4114);
1178   ok(suc, "TlsSetValue failed\n");
1179
1180   for (i = 0; i < 2; ++i)
1181   {
1182     DWORD tid;
1183
1184     threads[i] = CreateThread(NULL, 0, TLS_ThreadProc, (LPVOID) i, 0, &tid);
1185     ok(threads[i] != NULL, "CreateThread failed\n");
1186   }
1187
1188   ret = WaitForMultipleObjects(2, threads, TRUE, 60000);
1189   ok(ret == WAIT_OBJECT_0 || ret == WAIT_OBJECT_0+1 /* nt4 */, "WaitForMultipleObjects failed %u\n",ret);
1190
1191   for (i = 0; i < 2; ++i)
1192     CloseHandle(threads[i]);
1193
1194   suc = TlsFree(TLS_main);
1195   ok(suc, "TlsFree failed\n");
1196   cleanup_thread_sync_helpers();
1197 }
1198
1199 START_TEST(thread)
1200 {
1201    HINSTANCE lib;
1202    int argc;
1203    char **argv;
1204    argc = winetest_get_mainargs( &argv );
1205 /* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
1206    so that the compile passes
1207 */
1208    lib=GetModuleHandleA("kernel32.dll");
1209    ok(lib!=NULL,"Couldn't get a handle for kernel32.dll\n");
1210    pGetThreadPriorityBoost=(GetThreadPriorityBoost_t)GetProcAddress(lib,"GetThreadPriorityBoost");
1211    pOpenThread=(OpenThread_t)GetProcAddress(lib,"OpenThread");
1212    pQueueUserWorkItem=(QueueUserWorkItem_t)GetProcAddress(lib,"QueueUserWorkItem");
1213    pSetThreadIdealProcessor=(SetThreadIdealProcessor_t)GetProcAddress(lib,"SetThreadIdealProcessor");
1214    pSetThreadPriorityBoost=(SetThreadPriorityBoost_t)GetProcAddress(lib,"SetThreadPriorityBoost");
1215    pRegisterWaitForSingleObject=(RegisterWaitForSingleObject_t)GetProcAddress(lib,"RegisterWaitForSingleObject");
1216    pUnregisterWait=(UnregisterWait_t)GetProcAddress(lib,"UnregisterWait");
1217
1218    if (argc >= 3)
1219    {
1220        if (!strcmp(argv[2], "sleep"))
1221        {
1222            HANDLE hAddrEvents[2];
1223            create_function_addr_events(hAddrEvents);
1224            SetEvent(hAddrEvents[0]);
1225            SetEvent(hAddrEvents[1]);
1226            Sleep(5000); /* spawned process runs for at most 5 seconds */
1227            return;
1228        }
1229        while (1)
1230        {
1231            HANDLE hThread;
1232            DWORD tid;
1233            hThread = CreateThread(NULL, 0, threadFunc2, NULL, 0, &tid);
1234            ok(hThread != NULL, "CreateThread failed, error %u\n",
1235               GetLastError());
1236            ok(WaitForSingleObject(hThread, 200) == WAIT_OBJECT_0,
1237               "Thread did not exit in time\n");
1238            if (hThread == NULL) break;
1239            CloseHandle(hThread);
1240        }
1241        return;
1242    }
1243
1244    test_CreateRemoteThread();
1245    test_CreateThread_basic();
1246    test_CreateThread_suspended();
1247    test_SuspendThread();
1248    test_TerminateThread();
1249    test_CreateThread_stack();
1250    test_thread_priority();
1251    test_GetThreadTimes();
1252    test_thread_processor();
1253    test_GetThreadExitCode();
1254 #ifdef __i386__
1255    test_SetThreadContext();
1256 #endif
1257    test_QueueUserWorkItem();
1258    test_RegisterWaitForSingleObject();
1259    test_TLS();
1260 }