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