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