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