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