kernel32/tests: Initial threadpool test.
[wine/wine-gecko.git] / dlls / kernel32 / tests / thread.c
blob6cbf3834f21973106795a84dedee36b921aaa8c4
1 /*
2 * Unit test suite for thread functions.
4 * Copyright 2002 Geoffrey Hausheer
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.
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.
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
21 /* Define _WIN32_WINNT to get SetThreadIdealProcessor on Windows */
22 #define _WIN32_WINNT 0x0600
24 #include <assert.h>
25 #include <stdarg.h>
26 #include <stdio.h>
28 /* the tests intentionally pass invalid pointers and need an exception handler */
29 #define WINE_NO_INLINE_STRING
31 #include <windef.h>
32 #include <winbase.h>
33 #include <winnt.h>
34 #include <winerror.h>
35 #include <winnls.h>
36 #include "wine/test.h"
38 /* Specify the number of simultaneous threads to test */
39 #define NUM_THREADS 4
40 /* Specify whether to test the extended priorities for Win2k/XP */
41 #define USE_EXTENDED_PRIORITIES 0
42 /* Specify whether to test the stack allocation in CreateThread */
43 #define CHECK_STACK 0
45 /* Set CHECK_STACK to 1 if you want to try to test the stack-limit from
46 CreateThread. So far I have been unable to make this work, and
47 I am in doubt as to how portable it is. Also, according to MSDN,
48 you shouldn't mix C-run-time-libraries (i.e. alloca) with CreateThread.
49 Anyhow, the check is currently commented out
51 #if CHECK_STACK
52 # ifdef __try
53 # define __TRY __try
54 # define __EXCEPT __except
55 # define __ENDTRY
56 # else
57 # include "wine/exception.h"
58 # endif
59 #endif
61 #ifdef __i386__
62 #define ARCH "x86"
63 #elif defined __x86_64__
64 #define ARCH "amd64"
65 #else
66 #define ARCH "none"
67 #endif
69 static BOOL (WINAPI *pGetThreadPriorityBoost)(HANDLE,PBOOL);
70 static HANDLE (WINAPI *pOpenThread)(DWORD,BOOL,DWORD);
71 static BOOL (WINAPI *pQueueUserWorkItem)(LPTHREAD_START_ROUTINE,PVOID,ULONG);
72 static DWORD (WINAPI *pSetThreadIdealProcessor)(HANDLE,DWORD);
73 static BOOL (WINAPI *pSetThreadPriorityBoost)(HANDLE,BOOL);
74 static BOOL (WINAPI *pRegisterWaitForSingleObject)(PHANDLE,HANDLE,WAITORTIMERCALLBACK,PVOID,ULONG,ULONG);
75 static BOOL (WINAPI *pUnregisterWait)(HANDLE);
76 static BOOL (WINAPI *pIsWow64Process)(HANDLE,PBOOL);
77 static BOOL (WINAPI *pSetThreadErrorMode)(DWORD,PDWORD);
78 static DWORD (WINAPI *pGetThreadErrorMode)(void);
79 static DWORD (WINAPI *pRtlGetThreadErrorMode)(void);
80 static BOOL (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*);
81 static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW);
82 static BOOL (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR);
83 static BOOL (WINAPI *pGetCurrentActCtx)(HANDLE *);
84 static void (WINAPI *pReleaseActCtx)(HANDLE);
85 static PTP_POOL (WINAPI *pCreateThreadpool)(PVOID);
86 static PTP_WORK (WINAPI *pCreateThreadpoolWork)(PTP_WORK_CALLBACK,PVOID,PTP_CALLBACK_ENVIRON);
87 static void (WINAPI *pSubmitThreadpoolWork)(PTP_WORK);
88 static void (WINAPI *pWaitForThreadpoolWorkCallbacks)(PTP_WORK,BOOL);
89 static void (WINAPI *pCloseThreadpoolWork)(PTP_WORK);
91 static HANDLE create_target_process(const char *arg)
93 char **argv;
94 char cmdline[MAX_PATH];
95 PROCESS_INFORMATION pi;
96 BOOL ret;
97 STARTUPINFOA si = { 0 };
98 si.cb = sizeof(si);
100 winetest_get_mainargs( &argv );
101 sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
102 ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
103 ok(ret, "error: %u\n", GetLastError());
104 ret = CloseHandle(pi.hThread);
105 ok(ret, "error %u\n", GetLastError());
106 return pi.hProcess;
109 /* Functions not tested yet:
110 AttachThreadInput
111 SetThreadContext
112 SwitchToThread
114 In addition there are no checks that the inheritance works properly in
115 CreateThread
118 /* Functions to ensure that from a group of threads, only one executes
119 certain chunks of code at a time, and we know which one is executing
120 it. It basically makes multithreaded execution linear, which defeats
121 the purpose of multiple threads, but makes testing easy. */
122 static HANDLE start_event, stop_event;
123 static LONG num_synced;
125 static void init_thread_sync_helpers(void)
127 start_event = CreateEventW(NULL, TRUE, FALSE, NULL);
128 ok(start_event != NULL, "CreateEvent failed\n");
129 stop_event = CreateEventW(NULL, TRUE, FALSE, NULL);
130 ok(stop_event != NULL, "CreateEvent failed\n");
131 num_synced = -1;
134 static BOOL sync_threads_and_run_one(DWORD sync_id, DWORD my_id)
136 LONG num = InterlockedIncrement(&num_synced);
137 assert(-1 <= num && num <= 1);
138 if (num == 1)
140 ResetEvent( stop_event );
141 SetEvent( start_event );
143 else
145 DWORD ret = WaitForSingleObject(start_event, 10000);
146 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed %x\n",ret);
148 return sync_id == my_id;
151 static void resync_after_run(void)
153 LONG num = InterlockedDecrement(&num_synced);
154 assert(-1 <= num && num <= 1);
155 if (num == -1)
157 ResetEvent( start_event );
158 SetEvent( stop_event );
160 else
162 DWORD ret = WaitForSingleObject(stop_event, 10000);
163 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
167 static void cleanup_thread_sync_helpers(void)
169 CloseHandle(start_event);
170 CloseHandle(stop_event);
173 static DWORD tlsIndex;
175 typedef struct {
176 int threadnum;
177 HANDLE *event;
178 DWORD *threadmem;
179 } t1Struct;
181 /* WinME supports OpenThread but doesn't know about access restrictions so
182 we require them to be either completely ignored or always obeyed.
184 static INT obeying_ars = 0; /* -1 == no, 0 == dunno yet, 1 == yes */
185 #define obey_ar(x) \
186 (obeying_ars == 0 \
187 ? ((x) \
188 ? (obeying_ars = +1) \
189 : ((obeying_ars = -1), \
190 trace("not restricted, assuming consistent behaviour\n"))) \
191 : (obeying_ars < 0) \
192 ? ok(!(x), "access restrictions obeyed\n") \
193 : ok( (x), "access restrictions not obeyed\n"))
195 /* Basic test that simultaneous threads can access shared memory,
196 that the thread local storage routines work correctly, and that
197 threads actually run concurrently
199 static DWORD WINAPI threadFunc1(LPVOID p)
201 t1Struct *tstruct = p;
202 int i;
203 /* write our thread # into shared memory */
204 tstruct->threadmem[tstruct->threadnum]=GetCurrentThreadId();
205 ok(TlsSetValue(tlsIndex,(LPVOID)(INT_PTR)(tstruct->threadnum+1))!=0,
206 "TlsSetValue failed\n");
207 /* The threads synchronize before terminating. This is done by
208 Signaling an event, and waiting for all events to occur
210 SetEvent(tstruct->event[tstruct->threadnum]);
211 WaitForMultipleObjects(NUM_THREADS,tstruct->event,TRUE,INFINITE);
212 /* Double check that all threads really did run by validating that
213 they have all written to the shared memory. There should be no race
214 here, since all threads were synchronized after the write.*/
215 for(i=0;i<NUM_THREADS;i++) {
216 while(tstruct->threadmem[i]==0) ;
219 /* lstrlenA contains an exception handler so this makes sure exceptions work in threads */
220 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
222 /* Check that no one changed our tls memory */
223 ok((INT_PTR)TlsGetValue(tlsIndex)-1==tstruct->threadnum,
224 "TlsGetValue failed\n");
225 return NUM_THREADS+tstruct->threadnum;
228 static DWORD WINAPI threadFunc2(LPVOID p)
230 return 99;
233 static DWORD WINAPI threadFunc3(LPVOID p)
235 HANDLE thread;
236 thread=GetCurrentThread();
237 SuspendThread(thread);
238 return 99;
241 static DWORD WINAPI threadFunc4(LPVOID p)
243 HANDLE event = p;
244 if(event != NULL) {
245 SetEvent(event);
247 Sleep(99000);
248 return 0;
251 #if CHECK_STACK
252 static DWORD WINAPI threadFunc5(LPVOID p)
254 DWORD *exitCode = p;
255 SYSTEM_INFO sysInfo;
256 sysInfo.dwPageSize=0;
257 GetSystemInfo(&sysInfo);
258 *exitCode=0;
259 __TRY
261 alloca(2*sysInfo.dwPageSize);
263 __EXCEPT(1) {
264 *exitCode=1;
266 __ENDTRY
267 return 0;
269 #endif
271 static DWORD WINAPI threadFunc_SetEvent(LPVOID p)
273 SetEvent(p);
274 return 0;
277 static DWORD WINAPI threadFunc_CloseHandle(LPVOID p)
279 CloseHandle(p);
280 return 0;
283 struct thread_actctx_param
285 HANDLE thread_context;
286 HANDLE handle;
289 static DWORD WINAPI thread_actctx_func(void *p)
291 struct thread_actctx_param *param = (struct thread_actctx_param*)p;
292 HANDLE cur;
293 BOOL ret;
295 cur = (void*)0xdeadbeef;
296 ret = pGetCurrentActCtx(&cur);
297 ok(ret, "thread GetCurrentActCtx failed, %u\n", GetLastError());
298 ok(cur == param->handle, "got %p, expected %p\n", cur, param->handle);
299 param->thread_context = cur;
301 return 0;
304 static void create_function_addr_events(HANDLE events[2])
306 char buffer[256];
308 sprintf(buffer, "threadFunc_SetEvent %p", threadFunc_SetEvent);
309 events[0] = CreateEventA(NULL, FALSE, FALSE, buffer);
311 sprintf(buffer, "threadFunc_CloseHandle %p", threadFunc_CloseHandle);
312 events[1] = CreateEventA(NULL, FALSE, FALSE, buffer);
315 /* check CreateRemoteThread */
316 static VOID test_CreateRemoteThread(void)
318 HANDLE hProcess, hThread, hEvent, hRemoteEvent;
319 DWORD tid, ret, exitcode;
320 HANDLE hAddrEvents[2];
322 hProcess = create_target_process("sleep");
323 ok(hProcess != NULL, "Can't start process\n");
325 /* ensure threadFunc_SetEvent & threadFunc_CloseHandle are the same
326 * address as in the child process */
327 create_function_addr_events(hAddrEvents);
328 ret = WaitForMultipleObjects(2, hAddrEvents, TRUE, 5000);
329 if (ret == WAIT_TIMEOUT)
331 skip("child process wasn't mapped at same address, so can't do CreateRemoteThread tests.\n");
332 return;
334 ok(ret == WAIT_OBJECT_0 || broken(ret == WAIT_OBJECT_0+1 /* nt4,w2k */), "WaitForAllObjects 2 events %d\n", ret);
336 hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
337 ok(hEvent != NULL, "Can't create event, err=%u\n", GetLastError());
338 ret = DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &hRemoteEvent,
339 0, FALSE, DUPLICATE_SAME_ACCESS);
340 ok(ret != 0, "DuplicateHandle failed, err=%u\n", GetLastError());
342 /* create suspended remote thread with entry point SetEvent() */
343 SetLastError(0xdeadbeef);
344 hThread = CreateRemoteThread(hProcess, NULL, 0, threadFunc_SetEvent,
345 hRemoteEvent, CREATE_SUSPENDED, &tid);
346 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
348 win_skip("CreateRemoteThread is not implemented\n");
349 goto cleanup;
351 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
352 ok(tid != 0, "null tid\n");
353 ret = SuspendThread(hThread);
354 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
355 ret = ResumeThread(hThread);
356 ok(ret == 2, "ret=%u, err=%u\n", ret, GetLastError());
358 /* thread still suspended, so wait times out */
359 ret = WaitForSingleObject(hEvent, 1000);
360 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
362 ret = ResumeThread(hThread);
363 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
365 /* wait that doesn't time out */
366 ret = WaitForSingleObject(hEvent, 1000);
367 ok(ret == WAIT_OBJECT_0, "object not signaled, ret=%u\n", ret);
369 /* wait for thread end */
370 ret = WaitForSingleObject(hThread, 1000);
371 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
372 CloseHandle(hThread);
374 /* create and wait for remote thread with entry point CloseHandle() */
375 hThread = CreateRemoteThread(hProcess, NULL, 0,
376 threadFunc_CloseHandle,
377 hRemoteEvent, 0, &tid);
378 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
379 ret = WaitForSingleObject(hThread, 1000);
380 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
381 CloseHandle(hThread);
383 /* create remote thread with entry point SetEvent() */
384 hThread = CreateRemoteThread(hProcess, NULL, 0,
385 threadFunc_SetEvent,
386 hRemoteEvent, 0, &tid);
387 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
389 /* closed handle, so wait times out */
390 ret = WaitForSingleObject(hEvent, 1000);
391 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
393 /* check that remote SetEvent() failed */
394 ret = GetExitCodeThread(hThread, &exitcode);
395 ok(ret != 0, "GetExitCodeThread failed, err=%u\n", GetLastError());
396 if (ret) ok(exitcode == 0, "SetEvent succeeded, expected to fail\n");
397 CloseHandle(hThread);
399 cleanup:
400 TerminateProcess(hProcess, 0);
401 CloseHandle(hEvent);
402 CloseHandle(hProcess);
405 /* Check basic functionality of CreateThread and Tls* functions */
406 static VOID test_CreateThread_basic(void)
408 HANDLE thread[NUM_THREADS],event[NUM_THREADS];
409 DWORD threadid[NUM_THREADS],curthreadId;
410 DWORD threadmem[NUM_THREADS];
411 DWORD exitCode;
412 t1Struct tstruct[NUM_THREADS];
413 int error;
414 DWORD i,j;
415 DWORD GLE, ret;
416 DWORD tid;
417 BOOL bRet;
419 /* lstrlenA contains an exception handler so this makes sure exceptions work in the main thread */
420 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
422 /* Retrieve current Thread ID for later comparisons */
423 curthreadId=GetCurrentThreadId();
424 /* Allocate some local storage */
425 ok((tlsIndex=TlsAlloc())!=TLS_OUT_OF_INDEXES,"TlsAlloc failed\n");
426 /* Create events for thread synchronization */
427 for(i=0;i<NUM_THREADS;i++) {
428 threadmem[i]=0;
429 /* Note that it doesn't matter what type of event we choose here. This
430 test isn't trying to thoroughly test events
432 event[i]=CreateEventA(NULL,TRUE,FALSE,NULL);
433 tstruct[i].threadnum=i;
434 tstruct[i].threadmem=threadmem;
435 tstruct[i].event=event;
438 /* Test that passing arguments to threads works okay */
439 for(i=0;i<NUM_THREADS;i++) {
440 thread[i] = CreateThread(NULL,0,threadFunc1,
441 &tstruct[i],0,&threadid[i]);
442 ok(thread[i]!=NULL,"Create Thread failed\n");
444 /* Test that the threads actually complete */
445 for(i=0;i<NUM_THREADS;i++) {
446 error=WaitForSingleObject(thread[i],5000);
447 ok(error==WAIT_OBJECT_0, "Thread did not complete within timelimit\n");
448 if(error!=WAIT_OBJECT_0) {
449 TerminateThread(thread[i],i+NUM_THREADS);
451 ok(GetExitCodeThread(thread[i],&exitCode),"Could not retrieve ext code\n");
452 ok(exitCode==i+NUM_THREADS,"Thread returned an incorrect exit code\n");
454 /* Test that each thread executed in its parent's address space
455 (it was able to change threadmem and pass that change back to its parent)
456 and that each thread id was independent). Note that we prove that the
457 threads actually execute concurrently by having them block on each other
458 in threadFunc1
460 for(i=0;i<NUM_THREADS;i++) {
461 error=0;
462 for(j=i+1;j<NUM_THREADS;j++) {
463 if (threadmem[i]==threadmem[j]) {
464 error=1;
467 ok(!error && threadmem[i]==threadid[i] && threadmem[i]!=curthreadId,
468 "Thread did not execute successfully\n");
469 ok(CloseHandle(thread[i])!=0,"CloseHandle failed\n");
472 SetLastError(0xCAFEF00D);
473 bRet = TlsFree(tlsIndex);
474 ok(bRet, "TlsFree failed: %08x\n", GetLastError());
475 ok(GetLastError()==0xCAFEF00D,
476 "GetLastError: expected 0xCAFEF00D, got %08x\n", GetLastError());
478 /* Test freeing an already freed TLS index */
479 SetLastError(0xCAFEF00D);
480 ok(TlsFree(tlsIndex)==0,"TlsFree succeeded\n");
481 ok(GetLastError()==ERROR_INVALID_PARAMETER,
482 "GetLastError: expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
484 /* Test how passing NULL as a pointer to threadid works */
485 SetLastError(0xFACEaBAD);
486 thread[0] = CreateThread(NULL,0,threadFunc2,NULL,0,&tid);
487 GLE = GetLastError();
488 if (thread[0]) { /* NT */
489 ok(GLE==0xFACEaBAD, "CreateThread set last error to %d, expected 4207848365\n", GLE);
490 ret = WaitForSingleObject(thread[0],100);
491 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
492 ret = GetExitCodeThread(thread[0],&exitCode);
493 ok(ret!=0, "GetExitCodeThread returned %d (expected nonzero)\n", ret);
494 ok(exitCode==99, "threadFunc2 exited with code: %d (expected 99)\n", exitCode);
495 ok(CloseHandle(thread[0])!=0,"Error closing thread handle\n");
497 else { /* 9x */
498 ok(GLE==ERROR_INVALID_PARAMETER, "CreateThread set last error to %d, expected 87\n", GLE);
502 /* Check that using the CREATE_SUSPENDED flag works */
503 static VOID test_CreateThread_suspended(void)
505 HANDLE thread;
506 DWORD threadId;
507 DWORD suspend_count;
508 int error;
510 thread = CreateThread(NULL,0,threadFunc2,NULL,
511 CREATE_SUSPENDED,&threadId);
512 ok(thread!=NULL,"Create Thread failed\n");
513 /* Check that the thread is suspended */
514 ok(SuspendThread(thread)==1,"Thread did not start suspended\n");
515 ok(ResumeThread(thread)==2,"Resume thread returned an invalid value\n");
516 /* Check that resume thread didn't actually start the thread. I can't think
517 of a better way of checking this than just waiting. I am not sure if this
518 will work on slow computers.
520 ok(WaitForSingleObject(thread,1000)==WAIT_TIMEOUT,
521 "ResumeThread should not have actually started the thread\n");
522 /* Now actually resume the thread and make sure that 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);
530 suspend_count = SuspendThread(thread);
531 ok(suspend_count == -1, "SuspendThread returned %d, expected -1\n", suspend_count);
533 suspend_count = ResumeThread(thread);
534 ok(suspend_count == 0 ||
535 broken(suspend_count == -1), /* win9x */
536 "ResumeThread returned %d, expected 0\n", suspend_count);
538 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
541 /* Check that SuspendThread and ResumeThread work */
542 static VOID test_SuspendThread(void)
544 HANDLE thread,access_thread;
545 DWORD threadId,exitCode,error;
546 int i;
548 thread = CreateThread(NULL,0,threadFunc3,NULL,
549 0,&threadId);
550 ok(thread!=NULL,"Create Thread failed\n");
551 /* Check that the thread is suspended */
552 /* Note that this is a polling method, and there is a race between
553 SuspendThread being called (in the child, and the loop below timing out,
554 so the test could fail on a heavily loaded or slow computer.
556 error=0;
557 for(i=0;error==0 && i<100;i++) {
558 error=SuspendThread(thread);
559 ResumeThread(thread);
560 if(error==0) {
561 Sleep(50);
562 i++;
565 ok(error==1,"SuspendThread did not work\n");
566 /* check that access restrictions are obeyed */
567 if (pOpenThread) {
568 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_SUSPEND_RESUME),
569 0,threadId);
570 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
571 if (access_thread!=NULL) {
572 obey_ar(SuspendThread(access_thread)==~0U);
573 obey_ar(ResumeThread(access_thread)==~0U);
574 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
577 /* Double check that the thread really is suspended */
578 ok((error=GetExitCodeThread(thread,&exitCode))!=0 && exitCode==STILL_ACTIVE,
579 "Thread did not really suspend\n");
580 /* Resume the thread, and make sure it actually completes */
581 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
582 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
583 "Thread did not resume\n");
584 if(error!=WAIT_OBJECT_0) {
585 TerminateThread(thread,1);
587 /* Trying to suspend a terminated thread should fail */
588 error=SuspendThread(thread);
589 ok(error==~0U, "wrong return code: %d\n", error);
590 ok(GetLastError()==ERROR_ACCESS_DENIED || GetLastError()==ERROR_NO_MORE_ITEMS, "unexpected error code: %d\n", GetLastError());
592 ok(CloseHandle(thread)!=0,"CloseHandle Failed\n");
595 /* Check that TerminateThread works properly
597 static VOID test_TerminateThread(void)
599 HANDLE thread,access_thread,event;
600 DWORD threadId,exitCode;
601 event=CreateEventA(NULL,TRUE,FALSE,NULL);
602 thread = CreateThread(NULL,0,threadFunc4,event,0,&threadId);
603 ok(thread!=NULL,"Create Thread failed\n");
604 /* TerminateThread has a race condition in Wine. If the thread is terminated
605 before it starts, it leaves a process behind. Therefore, we wait for the
606 thread to signal that it has started. There is no easy way to force the
607 race to occur, so we don't try to find it.
609 ok(WaitForSingleObject(event,5000)==WAIT_OBJECT_0,
610 "TerminateThread didn't work\n");
611 /* check that access restrictions are obeyed */
612 if (pOpenThread) {
613 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_TERMINATE),
614 0,threadId);
615 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
616 if (access_thread!=NULL) {
617 obey_ar(TerminateThread(access_thread,99)==0);
618 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
621 /* terminate a job and make sure it terminates */
622 ok(TerminateThread(thread,99)!=0,"TerminateThread failed\n");
623 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
624 "TerminateThread didn't work\n");
625 ok(GetExitCodeThread(thread,&exitCode)!=STILL_ACTIVE,
626 "TerminateThread should not leave the thread 'STILL_ACTIVE'\n");
627 ok(exitCode==99, "TerminateThread returned invalid exit code\n");
628 ok(CloseHandle(thread)!=0,"Error Closing thread handle\n");
631 /* Check if CreateThread obeys the specified stack size. This code does
632 not work properly, and is currently disabled
634 static VOID test_CreateThread_stack(void)
636 #if CHECK_STACK
637 /* The only way I know of to test the stack size is to use alloca
638 and __try/__except. However, this is probably not portable,
639 and I couldn't get it to work under Wine anyhow. However, here
640 is the code which should allow for testing that CreateThread
641 respects the stack-size limit
643 HANDLE thread;
644 DWORD threadId,exitCode;
646 SYSTEM_INFO sysInfo;
647 sysInfo.dwPageSize=0;
648 GetSystemInfo(&sysInfo);
649 ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
650 thread = CreateThread(NULL,sysInfo.dwPageSize,
651 threadFunc5,&exitCode,
652 0,&threadId);
653 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
654 "TerminateThread didn't work\n");
655 ok(exitCode==1,"CreateThread did not obey stack-size-limit\n");
656 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
657 #endif
660 /* Check whether setting/retrieving thread priorities works */
661 static VOID test_thread_priority(void)
663 HANDLE curthread,access_thread;
664 DWORD curthreadId,exitCode;
665 int min_priority=-2,max_priority=2;
666 BOOL disabled,rc;
667 int i;
669 curthread=GetCurrentThread();
670 curthreadId=GetCurrentThreadId();
671 /* Check thread priority */
672 /* NOTE: on Win2k/XP priority can be from -7 to 6. All other platforms it
673 is -2 to 2. However, even on a real Win2k system, using thread
674 priorities beyond the -2 to 2 range does not work. If you want to try
675 anyway, enable USE_EXTENDED_PRIORITIES
677 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_NORMAL,
678 "GetThreadPriority Failed\n");
680 if (pOpenThread) {
681 /* check that access control is obeyed */
682 access_thread=pOpenThread(THREAD_ALL_ACCESS &
683 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
684 0,curthreadId);
685 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
686 if (access_thread!=NULL) {
687 obey_ar(SetThreadPriority(access_thread,1)==0);
688 obey_ar(GetThreadPriority(access_thread)==THREAD_PRIORITY_ERROR_RETURN);
689 obey_ar(GetExitCodeThread(access_thread,&exitCode)==0);
690 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
693 #if USE_EXTENDED_PRIORITIES
694 min_priority=-7; max_priority=6;
695 #endif
696 for(i=min_priority;i<=max_priority;i++) {
697 ok(SetThreadPriority(curthread,i)!=0,
698 "SetThreadPriority Failed for priority: %d\n",i);
699 ok(GetThreadPriority(curthread)==i,
700 "GetThreadPriority Failed for priority: %d\n",i);
702 ok(SetThreadPriority(curthread,THREAD_PRIORITY_TIME_CRITICAL)!=0,
703 "SetThreadPriority Failed\n");
704 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_TIME_CRITICAL,
705 "GetThreadPriority Failed\n");
706 ok(SetThreadPriority(curthread,THREAD_PRIORITY_IDLE)!=0,
707 "SetThreadPriority Failed\n");
708 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_IDLE,
709 "GetThreadPriority Failed\n");
710 ok(SetThreadPriority(curthread,0)!=0,"SetThreadPriority Failed\n");
712 /* Check that the thread priority is not changed if SetThreadPriority
713 is called with a value outside of the max/min range */
714 SetThreadPriority(curthread,min_priority);
715 SetLastError(0xdeadbeef);
716 rc = SetThreadPriority(curthread,min_priority-1);
718 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
719 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
720 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
721 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
722 GetLastError());
723 ok(GetThreadPriority(curthread)==min_priority,
724 "GetThreadPriority didn't return min_priority\n");
726 SetThreadPriority(curthread,max_priority);
727 SetLastError(0xdeadbeef);
728 rc = SetThreadPriority(curthread,max_priority+1);
730 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
731 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
732 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
733 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
734 GetLastError());
735 ok(GetThreadPriority(curthread)==max_priority,
736 "GetThreadPriority didn't return max_priority\n");
738 /* Check thread priority boost */
739 if (!pGetThreadPriorityBoost || !pSetThreadPriorityBoost)
740 return; /* Win9x */
742 SetLastError(0xdeadbeef);
743 rc=pGetThreadPriorityBoost(curthread,&disabled);
744 if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
746 win_skip("GetThreadPriorityBoost is not implemented on WinME\n");
747 return;
750 ok(rc!=0,"error=%d\n",GetLastError());
752 if (pOpenThread) {
753 /* check that access control is obeyed */
754 access_thread=pOpenThread(THREAD_ALL_ACCESS &
755 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
756 0,curthreadId);
757 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
758 if (access_thread!=NULL) {
759 todo_wine obey_ar(pSetThreadPriorityBoost(access_thread,1)==0);
760 todo_wine obey_ar(pGetThreadPriorityBoost(access_thread,&disabled)==0);
761 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
765 rc = pSetThreadPriorityBoost(curthread,1);
766 ok( rc != 0, "error=%d\n",GetLastError());
767 todo_wine {
768 rc=pGetThreadPriorityBoost(curthread,&disabled);
769 ok(rc!=0 && disabled==1,
770 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
773 rc = pSetThreadPriorityBoost(curthread,0);
774 ok( rc != 0, "error=%d\n",GetLastError());
775 rc=pGetThreadPriorityBoost(curthread,&disabled);
776 ok(rc!=0 && disabled==0,
777 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
780 /* check the GetThreadTimes function */
781 static VOID test_GetThreadTimes(void)
783 HANDLE thread,access_thread=NULL;
784 FILETIME creationTime,exitTime,kernelTime,userTime;
785 DWORD threadId;
786 int error;
788 thread = CreateThread(NULL,0,threadFunc2,NULL,
789 CREATE_SUSPENDED,&threadId);
791 ok(thread!=NULL,"Create Thread failed\n");
792 /* check that access control is obeyed */
793 if (pOpenThread) {
794 access_thread=pOpenThread(THREAD_ALL_ACCESS &
795 (~THREAD_QUERY_INFORMATION), 0,threadId);
796 ok(access_thread!=NULL,
797 "OpenThread returned an invalid handle\n");
799 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
800 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
801 "ResumeThread didn't work\n");
802 creationTime.dwLowDateTime=99; creationTime.dwHighDateTime=99;
803 exitTime.dwLowDateTime=99; exitTime.dwHighDateTime=99;
804 kernelTime.dwLowDateTime=99; kernelTime.dwHighDateTime=99;
805 userTime.dwLowDateTime=99; userTime.dwHighDateTime=99;
806 /* GetThreadTimes should set all of the parameters passed to it */
807 error=GetThreadTimes(thread,&creationTime,&exitTime,
808 &kernelTime,&userTime);
810 if (error == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
811 win_skip("GetThreadTimes is not implemented\n");
812 else {
813 ok(error!=0,"GetThreadTimes failed\n");
814 ok(creationTime.dwLowDateTime!=99 || creationTime.dwHighDateTime!=99,
815 "creationTime was invalid\n");
816 ok(exitTime.dwLowDateTime!=99 || exitTime.dwHighDateTime!=99,
817 "exitTime was invalid\n");
818 ok(kernelTime.dwLowDateTime!=99 || kernelTime.dwHighDateTime!=99,
819 "kernelTimewas invalid\n");
820 ok(userTime.dwLowDateTime!=99 || userTime.dwHighDateTime!=99,
821 "userTime was invalid\n");
822 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
823 if(access_thread!=NULL)
825 error=GetThreadTimes(access_thread,&creationTime,&exitTime,
826 &kernelTime,&userTime);
827 obey_ar(error==0);
830 if(access_thread!=NULL) {
831 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
835 /* Check the processor affinity functions */
836 /* NOTE: These functions should also be checked that they obey access control
838 static VOID test_thread_processor(void)
840 HANDLE curthread,curproc;
841 DWORD_PTR processMask,systemMask,retMask;
842 SYSTEM_INFO sysInfo;
843 int error=0;
844 BOOL is_wow64;
846 if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
848 sysInfo.dwNumberOfProcessors=0;
849 GetSystemInfo(&sysInfo);
850 ok(sysInfo.dwNumberOfProcessors>0,
851 "GetSystemInfo failed to return a valid # of processors\n");
852 /* Use the current Thread/process for all tests */
853 curthread=GetCurrentThread();
854 ok(curthread!=NULL,"GetCurrentThread failed\n");
855 curproc=GetCurrentProcess();
856 ok(curproc!=NULL,"GetCurrentProcess failed\n");
857 /* Check the Affinity Mask functions */
858 ok(GetProcessAffinityMask(curproc,&processMask,&systemMask)!=0,
859 "GetProcessAffinityMask failed\n");
860 ok(SetThreadAffinityMask(curthread,processMask)==processMask,
861 "SetThreadAffinityMask failed\n");
862 ok(SetThreadAffinityMask(curthread,processMask+1)==0,
863 "SetThreadAffinityMask passed for an illegal processor\n");
864 /* NOTE: Pre-Vista does not recognize the "all processors" flag (all bits set) */
865 retMask = SetThreadAffinityMask(curthread,~0);
866 ok(broken(retMask==0) || retMask==processMask,
867 "SetThreadAffinityMask(thread,-1) failed to request all processors.\n");
868 if (retMask == processMask && sizeof(ULONG_PTR) > sizeof(ULONG))
870 /* only the low 32-bits matter */
871 retMask = SetThreadAffinityMask(curthread,~(ULONG_PTR)0);
872 ok(retMask == processMask, "SetThreadAffinityMask failed\n");
873 retMask = SetThreadAffinityMask(curthread,~(ULONG_PTR)0 >> 3);
874 ok(retMask == processMask, "SetThreadAffinityMask failed\n");
876 /* NOTE: This only works on WinNT/2000/XP) */
877 if (pSetThreadIdealProcessor) {
878 SetLastError(0xdeadbeef);
879 error=pSetThreadIdealProcessor(curthread,0);
880 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
882 win_skip("SetThreadIdealProcessor is not implemented\n");
883 return;
885 ok(error!=-1, "SetThreadIdealProcessor failed\n");
887 if (is_wow64)
889 SetLastError(0xdeadbeef);
890 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
891 todo_wine
892 ok(error!=-1, "SetThreadIdealProcessor failed for %u on Wow64\n", MAXIMUM_PROCESSORS+1);
894 SetLastError(0xdeadbeef);
895 error=pSetThreadIdealProcessor(curthread,65);
896 ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
897 ok(GetLastError()==ERROR_INVALID_PARAMETER,
898 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
900 else
902 SetLastError(0xdeadbeef);
903 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
904 ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
905 ok(GetLastError()==ERROR_INVALID_PARAMETER,
906 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
909 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS);
910 ok(error!=-1, "SetThreadIdealProcessor failed\n");
914 static VOID test_GetThreadExitCode(void)
916 DWORD exitCode, threadid;
917 DWORD GLE, ret;
918 HANDLE thread;
920 ret = GetExitCodeThread((HANDLE)0x2bad2bad,&exitCode);
921 ok(ret==0, "GetExitCodeThread returned non zero value: %d\n", ret);
922 GLE = GetLastError();
923 ok(GLE==ERROR_INVALID_HANDLE, "GetLastError returned %d (expected 6)\n", GLE);
925 thread = CreateThread(NULL,0,threadFunc2,NULL,0,&threadid);
926 ret = WaitForSingleObject(thread,100);
927 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
928 ret = GetExitCodeThread(thread,&exitCode);
929 ok(ret==exitCode || ret==1,
930 "GetExitCodeThread returned %d (expected 1 or %d)\n", ret, exitCode);
931 ok(exitCode==99, "threadFunc2 exited with code %d (expected 99)\n", exitCode);
932 ok(CloseHandle(thread)!=0,"Error closing thread handle\n");
935 #ifdef __i386__
937 static int test_value = 0;
938 static HANDLE event;
940 static void WINAPI set_test_val( int val )
942 test_value += val;
943 ExitThread(0);
946 static DWORD WINAPI threadFunc6(LPVOID p)
948 SetEvent( event );
949 Sleep( 1000 );
950 test_value *= (int)p;
951 return 0;
954 static void test_SetThreadContext(void)
956 CONTEXT ctx;
957 int *stack;
958 HANDLE thread;
959 DWORD threadid;
960 DWORD prevcount;
961 BOOL ret;
963 SetLastError(0xdeadbeef);
964 event = CreateEventW( NULL, TRUE, FALSE, NULL );
965 thread = CreateThread( NULL, 0, threadFunc6, (void *)2, 0, &threadid );
966 ok( thread != NULL, "CreateThread failed : (%d)\n", GetLastError() );
967 if (!thread)
969 trace("Thread creation failed, skipping rest of test\n");
970 return;
972 WaitForSingleObject( event, INFINITE );
973 SuspendThread( thread );
974 CloseHandle( event );
976 ctx.ContextFlags = CONTEXT_FULL;
977 SetLastError(0xdeadbeef);
978 ret = GetThreadContext( thread, &ctx );
979 ok( ret, "GetThreadContext failed : (%u)\n", GetLastError() );
981 if (ret)
983 /* simulate a call to set_test_val(10) */
984 stack = (int *)ctx.Esp;
985 stack[-1] = 10;
986 stack[-2] = ctx.Eip;
987 ctx.Esp -= 2 * sizeof(int *);
988 ctx.Eip = (DWORD)set_test_val;
989 SetLastError(0xdeadbeef);
990 ret = SetThreadContext( thread, &ctx );
991 ok( ret, "SetThreadContext failed : (%d)\n", GetLastError() );
994 SetLastError(0xdeadbeef);
995 prevcount = ResumeThread( thread );
996 ok ( prevcount == 1, "Previous suspend count (%d) instead of 1, last error : (%d)\n",
997 prevcount, GetLastError() );
999 WaitForSingleObject( thread, INFINITE );
1000 ok( test_value == 10, "test_value %d\n", test_value );
1002 ctx.ContextFlags = CONTEXT_FULL;
1003 SetLastError(0xdeadbeef);
1004 ret = GetThreadContext( thread, &ctx );
1005 ok( (!ret && (GetLastError() == ERROR_GEN_FAILURE)) ||
1006 (!ret && broken(GetLastError() == ERROR_INVALID_HANDLE)) || /* win2k */
1007 broken(ret), /* 32bit application on NT 5.x 64bit */
1008 "got %d with %u (expected FALSE with ERROR_GEN_FAILURE)\n",
1009 ret, GetLastError() );
1011 SetLastError(0xdeadbeef);
1012 ret = SetThreadContext( thread, &ctx );
1013 ok( (!ret && ((GetLastError() == ERROR_GEN_FAILURE) || (GetLastError() == ERROR_ACCESS_DENIED))) ||
1014 (!ret && broken(GetLastError() == ERROR_INVALID_HANDLE)) || /* win2k */
1015 broken(ret), /* 32bit application on NT 5.x 64bit */
1016 "got %d with %u (expected FALSE with ERROR_GEN_FAILURE or ERROR_ACCESS_DENIED)\n",
1017 ret, GetLastError() );
1019 CloseHandle( thread );
1022 #endif /* __i386__ */
1024 static HANDLE finish_event;
1025 static LONG times_executed;
1027 static DWORD CALLBACK work_function(void *p)
1029 LONG executed = InterlockedIncrement(&times_executed);
1031 if (executed == 100)
1032 SetEvent(finish_event);
1033 return 0;
1036 static void test_QueueUserWorkItem(void)
1038 INT_PTR i;
1039 DWORD wait_result;
1040 DWORD before, after;
1042 /* QueueUserWorkItem not present on win9x */
1043 if (!pQueueUserWorkItem) return;
1045 finish_event = CreateEventW(NULL, TRUE, FALSE, NULL);
1047 before = GetTickCount();
1049 for (i = 0; i < 100; i++)
1051 BOOL ret = pQueueUserWorkItem(work_function, (void *)i, WT_EXECUTEDEFAULT);
1052 ok(ret, "QueueUserWorkItem failed with error %d\n", GetLastError());
1055 wait_result = WaitForSingleObject(finish_event, 10000);
1057 after = GetTickCount();
1058 trace("100 QueueUserWorkItem calls took %dms\n", after - before);
1059 ok(wait_result == WAIT_OBJECT_0, "wait failed with error 0x%x\n", wait_result);
1061 ok(times_executed == 100, "didn't execute all of the work items\n");
1064 static void CALLBACK signaled_function(PVOID p, BOOLEAN TimerOrWaitFired)
1066 HANDLE event = p;
1067 SetEvent(event);
1068 ok(!TimerOrWaitFired, "wait shouldn't have timed out\n");
1071 static void CALLBACK timeout_function(PVOID p, BOOLEAN TimerOrWaitFired)
1073 HANDLE event = p;
1074 SetEvent(event);
1075 ok(TimerOrWaitFired, "wait should have timed out\n");
1078 static void test_RegisterWaitForSingleObject(void)
1080 BOOL ret;
1081 HANDLE wait_handle;
1082 HANDLE handle;
1083 HANDLE complete_event;
1085 if (!pRegisterWaitForSingleObject || !pUnregisterWait)
1087 win_skip("RegisterWaitForSingleObject or UnregisterWait not implemented\n");
1088 return;
1091 /* test signaled case */
1093 handle = CreateEventW(NULL, TRUE, TRUE, NULL);
1094 complete_event = CreateEventW(NULL, FALSE, FALSE, NULL);
1096 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1097 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1099 WaitForSingleObject(complete_event, INFINITE);
1100 /* give worker thread chance to complete */
1101 Sleep(100);
1103 ret = pUnregisterWait(wait_handle);
1104 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1106 /* test cancel case */
1108 ResetEvent(handle);
1110 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1111 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1113 ret = pUnregisterWait(wait_handle);
1114 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1116 /* test timeout case */
1118 ret = pRegisterWaitForSingleObject(&wait_handle, handle, timeout_function, complete_event, 0, WT_EXECUTEONLYONCE);
1119 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1121 WaitForSingleObject(complete_event, INFINITE);
1122 /* give worker thread chance to complete */
1123 Sleep(100);
1125 ret = pUnregisterWait(wait_handle);
1126 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1129 static DWORD TLS_main;
1130 static DWORD TLS_index0, TLS_index1;
1132 static DWORD WINAPI TLS_InheritanceProc(LPVOID p)
1134 /* We should NOT inherit the TLS values from our parent or from the
1135 main thread. */
1136 LPVOID val;
1138 val = TlsGetValue(TLS_main);
1139 ok(val == NULL, "TLS inheritance failed\n");
1141 val = TlsGetValue(TLS_index0);
1142 ok(val == NULL, "TLS inheritance failed\n");
1144 val = TlsGetValue(TLS_index1);
1145 ok(val == NULL, "TLS inheritance failed\n");
1147 return 0;
1150 /* Basic TLS usage test. Make sure we can create slots and the values we
1151 store in them are separate among threads. Also test TLS value
1152 inheritance with TLS_InheritanceProc. */
1153 static DWORD WINAPI TLS_ThreadProc(LPVOID p)
1155 LONG_PTR id = (LONG_PTR) p;
1156 LPVOID val;
1157 BOOL ret;
1159 if (sync_threads_and_run_one(0, id))
1161 TLS_index0 = TlsAlloc();
1162 ok(TLS_index0 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1164 resync_after_run();
1166 if (sync_threads_and_run_one(1, id))
1168 TLS_index1 = TlsAlloc();
1169 ok(TLS_index1 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1171 /* Slot indices should be different even if created in different
1172 threads. */
1173 ok(TLS_index0 != TLS_index1, "TlsAlloc failed\n");
1175 /* Both slots should be initialized to NULL */
1176 val = TlsGetValue(TLS_index0);
1177 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1178 ok(val == NULL, "TLS slot not initialized correctly\n");
1180 val = TlsGetValue(TLS_index1);
1181 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1182 ok(val == NULL, "TLS slot not initialized correctly\n");
1184 resync_after_run();
1186 if (sync_threads_and_run_one(0, id))
1188 val = TlsGetValue(TLS_index0);
1189 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1190 ok(val == NULL, "TLS slot not initialized correctly\n");
1192 val = TlsGetValue(TLS_index1);
1193 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1194 ok(val == NULL, "TLS slot not initialized correctly\n");
1196 ret = TlsSetValue(TLS_index0, (LPVOID) 1);
1197 ok(ret, "TlsSetValue failed\n");
1199 ret = TlsSetValue(TLS_index1, (LPVOID) 2);
1200 ok(ret, "TlsSetValue failed\n");
1202 val = TlsGetValue(TLS_index0);
1203 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1204 ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1206 val = TlsGetValue(TLS_index1);
1207 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1208 ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1210 resync_after_run();
1212 if (sync_threads_and_run_one(1, id))
1214 val = TlsGetValue(TLS_index0);
1215 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1216 ok(val == NULL, "TLS slot not initialized correctly\n");
1218 val = TlsGetValue(TLS_index1);
1219 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1220 ok(val == NULL, "TLS slot not initialized correctly\n");
1222 ret = TlsSetValue(TLS_index0, (LPVOID) 3);
1223 ok(ret, "TlsSetValue failed\n");
1225 ret = TlsSetValue(TLS_index1, (LPVOID) 4);
1226 ok(ret, "TlsSetValue failed\n");
1228 val = TlsGetValue(TLS_index0);
1229 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1230 ok(val == (LPVOID) 3, "TLS slot not initialized correctly\n");
1232 val = TlsGetValue(TLS_index1);
1233 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1234 ok(val == (LPVOID) 4, "TLS slot not initialized correctly\n");
1236 resync_after_run();
1238 if (sync_threads_and_run_one(0, id))
1240 HANDLE thread;
1241 DWORD waitret, tid;
1243 val = TlsGetValue(TLS_index0);
1244 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1245 ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1247 val = TlsGetValue(TLS_index1);
1248 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1249 ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1251 thread = CreateThread(NULL, 0, TLS_InheritanceProc, 0, 0, &tid);
1252 ok(thread != NULL, "CreateThread failed\n");
1253 waitret = WaitForSingleObject(thread, 60000);
1254 ok(waitret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
1255 CloseHandle(thread);
1257 ret = TlsFree(TLS_index0);
1258 ok(ret, "TlsFree failed\n");
1260 resync_after_run();
1262 if (sync_threads_and_run_one(1, id))
1264 ret = TlsFree(TLS_index1);
1265 ok(ret, "TlsFree failed\n");
1267 resync_after_run();
1269 return 0;
1272 static void test_TLS(void)
1274 HANDLE threads[2];
1275 LONG_PTR i;
1276 DWORD ret;
1277 BOOL suc;
1279 init_thread_sync_helpers();
1281 /* Allocate a TLS slot in the main thread to test for inheritance. */
1282 TLS_main = TlsAlloc();
1283 ok(TLS_main != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1284 suc = TlsSetValue(TLS_main, (LPVOID) 4114);
1285 ok(suc, "TlsSetValue failed\n");
1287 for (i = 0; i < 2; ++i)
1289 DWORD tid;
1291 threads[i] = CreateThread(NULL, 0, TLS_ThreadProc, (LPVOID) i, 0, &tid);
1292 ok(threads[i] != NULL, "CreateThread failed\n");
1295 ret = WaitForMultipleObjects(2, threads, TRUE, 60000);
1296 ok(ret == WAIT_OBJECT_0 || broken(ret == WAIT_OBJECT_0+1 /* nt4,w2k */), "WaitForAllObjects 2 threads %d\n",ret);
1298 for (i = 0; i < 2; ++i)
1299 CloseHandle(threads[i]);
1301 suc = TlsFree(TLS_main);
1302 ok(suc, "TlsFree failed\n");
1303 cleanup_thread_sync_helpers();
1306 static void test_ThreadErrorMode(void)
1308 DWORD oldmode;
1309 DWORD mode;
1310 DWORD rtlmode;
1311 BOOL ret;
1313 if (!pSetThreadErrorMode || !pGetThreadErrorMode)
1315 win_skip("SetThreadErrorMode and/or GetThreadErrorMode unavailable (added in Windows 7)\n");
1316 return;
1319 if (!pRtlGetThreadErrorMode) {
1320 win_skip("RtlGetThreadErrorMode not available\n");
1321 return;
1324 oldmode = pGetThreadErrorMode();
1326 ret = pSetThreadErrorMode(0, &mode);
1327 ok(ret, "SetThreadErrorMode failed\n");
1328 ok(mode == oldmode,
1329 "SetThreadErrorMode returned old mode 0x%x, expected 0x%x\n",
1330 mode, oldmode);
1331 mode = pGetThreadErrorMode();
1332 ok(mode == 0, "GetThreadErrorMode returned mode 0x%x, expected 0\n", mode);
1333 rtlmode = pRtlGetThreadErrorMode();
1334 ok(rtlmode == 0,
1335 "RtlGetThreadErrorMode returned mode 0x%x, expected 0\n", mode);
1337 ret = pSetThreadErrorMode(SEM_FAILCRITICALERRORS, &mode);
1338 ok(ret, "SetThreadErrorMode failed\n");
1339 ok(mode == 0,
1340 "SetThreadErrorMode returned old mode 0x%x, expected 0\n", mode);
1341 mode = pGetThreadErrorMode();
1342 ok(mode == SEM_FAILCRITICALERRORS,
1343 "GetThreadErrorMode returned mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1344 mode);
1345 rtlmode = pRtlGetThreadErrorMode();
1346 ok(rtlmode == 0x10,
1347 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x10\n", mode);
1349 ret = pSetThreadErrorMode(SEM_NOGPFAULTERRORBOX, &mode);
1350 ok(ret, "SetThreadErrorMode failed\n");
1351 ok(mode == SEM_FAILCRITICALERRORS,
1352 "SetThreadErrorMode returned old mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1353 mode);
1354 mode = pGetThreadErrorMode();
1355 ok(mode == SEM_NOGPFAULTERRORBOX,
1356 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOGPFAULTERRORBOX\n",
1357 mode);
1358 rtlmode = pRtlGetThreadErrorMode();
1359 ok(rtlmode == 0x20,
1360 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x20\n", mode);
1362 ret = pSetThreadErrorMode(SEM_NOOPENFILEERRORBOX, NULL);
1363 ok(ret, "SetThreadErrorMode failed\n");
1364 mode = pGetThreadErrorMode();
1365 ok(mode == SEM_NOOPENFILEERRORBOX,
1366 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOOPENFILEERRORBOX\n",
1367 mode);
1368 rtlmode = pRtlGetThreadErrorMode();
1369 ok(rtlmode == 0x40,
1370 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x40\n", rtlmode);
1372 for (mode = 1; mode; mode <<= 1)
1374 ret = pSetThreadErrorMode(mode, NULL);
1375 if (mode & (SEM_FAILCRITICALERRORS |
1376 SEM_NOGPFAULTERRORBOX |
1377 SEM_NOOPENFILEERRORBOX))
1379 ok(ret,
1380 "SetThreadErrorMode(0x%x,NULL) failed with error %d\n",
1381 mode, GetLastError());
1383 else
1385 DWORD GLE = GetLastError();
1386 ok(!ret,
1387 "SetThreadErrorMode(0x%x,NULL) succeeded, expected failure\n",
1388 mode);
1389 ok(GLE == ERROR_INVALID_PARAMETER,
1390 "SetThreadErrorMode(0x%x,NULL) failed with %d, "
1391 "expected ERROR_INVALID_PARAMETER\n",
1392 mode, GLE);
1396 pSetThreadErrorMode(oldmode, NULL);
1399 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
1400 static inline void set_fpu_cw(WORD cw)
1402 __asm__ volatile ("fnclex; fldcw %0" : : "m" (cw));
1405 static inline WORD get_fpu_cw(void)
1407 WORD cw = 0;
1408 __asm__ volatile ("fnstcw %0" : "=m" (cw));
1409 return cw;
1412 struct fpu_thread_ctx
1414 WORD cw;
1415 HANDLE finished;
1418 static DWORD WINAPI fpu_thread(void *param)
1420 struct fpu_thread_ctx *ctx = param;
1421 BOOL ret;
1423 ctx->cw = get_fpu_cw();
1425 ret = SetEvent(ctx->finished);
1426 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
1428 return 0;
1431 static WORD get_thread_fpu_cw(void)
1433 struct fpu_thread_ctx ctx;
1434 DWORD tid, res;
1435 HANDLE thread;
1437 ctx.finished = CreateEventW(NULL, FALSE, FALSE, NULL);
1438 ok(!!ctx.finished, "Failed to create event, last error %#x.\n", GetLastError());
1440 thread = CreateThread(NULL, 0, fpu_thread, &ctx, 0, &tid);
1441 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
1443 res = WaitForSingleObject(ctx.finished, INFINITE);
1444 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
1446 res = CloseHandle(ctx.finished);
1447 ok(!!res, "Failed to close event handle, last error %#x.\n", GetLastError());
1449 return ctx.cw;
1452 static void test_thread_fpu_cw(void)
1454 WORD initial_cw, cw;
1456 initial_cw = get_fpu_cw();
1457 ok(initial_cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", initial_cw);
1459 cw = get_thread_fpu_cw();
1460 ok(cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", cw);
1462 set_fpu_cw(0xf60);
1463 cw = get_fpu_cw();
1464 ok(cw == 0xf60, "Expected FPU control word 0xf60, got %#x.\n", cw);
1466 cw = get_thread_fpu_cw();
1467 ok(cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", cw);
1469 cw = get_fpu_cw();
1470 ok(cw == 0xf60, "Expected FPU control word 0xf60, got %#x.\n", cw);
1472 set_fpu_cw(initial_cw);
1473 cw = get_fpu_cw();
1474 ok(cw == initial_cw, "Expected FPU control word %#x, got %#x.\n", initial_cw, cw);
1476 #endif
1478 static const char manifest_dep[] =
1479 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
1480 "<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH "\"/>"
1481 " <file name=\"testdep.dll\" />"
1482 "</assembly>";
1484 static const char manifest_main[] =
1485 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
1486 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />"
1487 "<dependency>"
1488 " <dependentAssembly>"
1489 " <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH "\" />"
1490 " </dependentAssembly>"
1491 "</dependency>"
1492 "</assembly>";
1494 static void create_manifest_file(const char *filename, const char *manifest)
1496 WCHAR path[MAX_PATH];
1497 HANDLE file;
1498 DWORD size;
1500 MultiByteToWideChar( CP_ACP, 0, filename, -1, path, MAX_PATH );
1501 file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1502 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
1503 WriteFile(file, manifest, strlen(manifest), &size, NULL);
1504 CloseHandle(file);
1507 static HANDLE test_create(const char *file)
1509 WCHAR path[MAX_PATH];
1510 ACTCTXW actctx;
1511 HANDLE handle;
1513 MultiByteToWideChar(CP_ACP, 0, file, -1, path, MAX_PATH);
1514 memset(&actctx, 0, sizeof(ACTCTXW));
1515 actctx.cbSize = sizeof(ACTCTXW);
1516 actctx.lpSource = path;
1518 handle = pCreateActCtxW(&actctx);
1519 ok(handle != INVALID_HANDLE_VALUE, "failed to create context, error %u\n", GetLastError());
1521 ok(actctx.cbSize == sizeof(actctx), "cbSize=%d\n", actctx.cbSize);
1522 ok(actctx.dwFlags == 0, "dwFlags=%d\n", actctx.dwFlags);
1523 ok(actctx.lpSource == path, "lpSource=%p\n", actctx.lpSource);
1524 ok(actctx.wProcessorArchitecture == 0, "wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture);
1525 ok(actctx.wLangId == 0, "wLangId=%d\n", actctx.wLangId);
1526 ok(actctx.lpAssemblyDirectory == NULL, "lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory);
1527 ok(actctx.lpResourceName == NULL, "lpResourceName=%p\n", actctx.lpResourceName);
1528 ok(actctx.lpApplicationName == NULL, "lpApplicationName=%p\n", actctx.lpApplicationName);
1529 ok(actctx.hModule == NULL, "hModule=%p\n", actctx.hModule);
1531 return handle;
1534 static void test_thread_actctx(void)
1536 struct thread_actctx_param param;
1537 HANDLE thread, handle, context;
1538 ULONG_PTR cookie;
1539 DWORD tid, ret;
1540 BOOL b;
1542 if (!pActivateActCtx)
1544 win_skip("skipping activation context tests\n");
1545 return;
1548 create_manifest_file("testdep1.manifest", manifest_dep);
1549 create_manifest_file("main.manifest", manifest_main);
1551 context = test_create("main.manifest");
1552 DeleteFileA("testdep1.manifest");
1553 DeleteFileA("main.manifest");
1555 handle = (void*)0xdeadbeef;
1556 b = pGetCurrentActCtx(&handle);
1557 ok(b, "GetCurentActCtx failed: %u\n", GetLastError());
1558 ok(handle == 0, "active context %p\n", handle);
1560 /* without active context */
1561 param.thread_context = (void*)0xdeadbeef;
1562 param.handle = NULL;
1563 thread = CreateThread(NULL, 0, thread_actctx_func, &param, 0, &tid);
1564 ok(thread != NULL, "failed, got %u\n", GetLastError());
1566 ret = WaitForSingleObject(thread, 1000);
1567 ok(ret == WAIT_OBJECT_0, "wait timeout\n");
1568 ok(param.thread_context == NULL, "got wrong thread context %p\n", param.thread_context);
1569 CloseHandle(thread);
1571 b = pActivateActCtx(context, &cookie);
1572 ok(b, "activation failed: %u\n", GetLastError());
1574 handle = 0;
1575 b = pGetCurrentActCtx(&handle);
1576 ok(b, "GetCurentActCtx failed: %u\n", GetLastError());
1577 ok(handle != 0, "no active context\n");
1579 param.handle = NULL;
1580 b = pGetCurrentActCtx(&param.handle);
1581 ok(b && param.handle != NULL, "failed to get context, %u\n", GetLastError());
1583 param.thread_context = (void*)0xdeadbeef;
1584 thread = CreateThread(NULL, 0, thread_actctx_func, &param, 0, &tid);
1585 ok(thread != NULL, "failed, got %u\n", GetLastError());
1587 ret = WaitForSingleObject(thread, 1000);
1588 ok(ret == WAIT_OBJECT_0, "wait timeout\n");
1589 ok(param.thread_context == context, "got wrong thread context %p, %p\n", param.thread_context, context);
1590 CloseHandle(thread);
1592 /* similar test for CreateRemoteThread() */
1593 param.thread_context = (void*)0xdeadbeef;
1594 thread = CreateRemoteThread(GetCurrentProcess(), NULL, 0, thread_actctx_func, &param, 0, &tid);
1595 ok(thread != NULL, "failed, got %u\n", GetLastError());
1597 ret = WaitForSingleObject(thread, 1000);
1598 ok(ret == WAIT_OBJECT_0, "wait timeout\n");
1599 ok(param.thread_context == context, "got wrong thread context %p, %p\n", param.thread_context, context);
1600 CloseHandle(thread);
1602 b = pDeactivateActCtx(0, cookie);
1603 ok(b, "DeactivateActCtx failed: %u\n", GetLastError());
1604 pReleaseActCtx(context);
1608 static void WINAPI threadpool_workcallback(PTP_CALLBACK_INSTANCE instance, void *context, PTP_WORK work) {
1609 int *foo = (int*)context;
1611 (*foo)++;
1615 static void test_threadpool(void)
1617 PTP_POOL pool;
1618 PTP_WORK work;
1619 int workcalled = 0;
1621 if (!pCreateThreadpool) {
1622 todo_wine win_skip("thread pool apis not supported.\n");
1623 return;
1626 work = pCreateThreadpoolWork(threadpool_workcallback, &workcalled, NULL);
1627 ok (work != NULL, "Error %d in CreateThreadpoolWork\n", GetLastError());
1628 pSubmitThreadpoolWork(work);
1629 pWaitForThreadpoolWorkCallbacks(work, FALSE);
1630 pCloseThreadpoolWork(work);
1632 ok (workcalled == 1, "expected work to be called once, got %d\n", workcalled);
1634 pool = pCreateThreadpool(NULL);
1635 todo_wine ok (pool != NULL, "CreateThreadpool failed\n");
1638 static void init_funcs(void)
1640 HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
1642 /* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
1643 so that the compile passes */
1645 #define X(f) p##f = (void*)GetProcAddress(hKernel32, #f)
1646 X(GetThreadPriorityBoost);
1647 X(OpenThread);
1648 X(QueueUserWorkItem);
1649 X(SetThreadIdealProcessor);
1650 X(SetThreadPriorityBoost);
1651 X(RegisterWaitForSingleObject);
1652 X(UnregisterWait);
1653 X(IsWow64Process);
1654 X(SetThreadErrorMode);
1655 X(GetThreadErrorMode);
1656 X(ActivateActCtx);
1657 X(CreateActCtxW);
1658 X(DeactivateActCtx);
1659 X(GetCurrentActCtx);
1660 X(ReleaseActCtx);
1662 X(CreateThreadpool);
1663 X(CreateThreadpoolWork);
1664 X(SubmitThreadpoolWork);
1665 X(WaitForThreadpoolWorkCallbacks);
1666 X(CloseThreadpoolWork);
1667 #undef X
1670 START_TEST(thread)
1672 HINSTANCE ntdll;
1673 int argc;
1674 char **argv;
1675 argc = winetest_get_mainargs( &argv );
1677 init_funcs();
1679 ntdll=GetModuleHandleA("ntdll.dll");
1680 if (ntdll)
1682 pRtlGetThreadErrorMode=(void *)GetProcAddress(ntdll,"RtlGetThreadErrorMode");
1685 if (argc >= 3)
1687 if (!strcmp(argv[2], "sleep"))
1689 HANDLE hAddrEvents[2];
1690 create_function_addr_events(hAddrEvents);
1691 SetEvent(hAddrEvents[0]);
1692 SetEvent(hAddrEvents[1]);
1693 Sleep(5000); /* spawned process runs for at most 5 seconds */
1694 return;
1696 while (1)
1698 HANDLE hThread;
1699 DWORD tid;
1700 hThread = CreateThread(NULL, 0, threadFunc2, NULL, 0, &tid);
1701 ok(hThread != NULL, "CreateThread failed, error %u\n",
1702 GetLastError());
1703 ok(WaitForSingleObject(hThread, 200) == WAIT_OBJECT_0,
1704 "Thread did not exit in time\n");
1705 if (hThread == NULL) break;
1706 CloseHandle(hThread);
1708 return;
1711 test_CreateRemoteThread();
1712 test_CreateThread_basic();
1713 test_CreateThread_suspended();
1714 test_SuspendThread();
1715 test_TerminateThread();
1716 test_CreateThread_stack();
1717 test_thread_priority();
1718 test_GetThreadTimes();
1719 test_thread_processor();
1720 test_GetThreadExitCode();
1721 #ifdef __i386__
1722 test_SetThreadContext();
1723 #endif
1724 test_QueueUserWorkItem();
1725 test_RegisterWaitForSingleObject();
1726 test_TLS();
1727 test_ThreadErrorMode();
1728 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
1729 test_thread_fpu_cw();
1730 #endif
1731 test_thread_actctx();
1733 test_threadpool();