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