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