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