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