kernel32: Return a dummy value in GetSystemPreferredUILanguages.
[wine.git] / dlls / kernel32 / tests / thread.c
blobe0de3f9fca1e0b1b0035fe95897cb8faf8baec7f
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 <ntstatus.h>
32 #define WIN32_NO_STATUS
33 #include <windef.h>
34 #include <winbase.h>
35 #include <winnt.h>
36 #include <winerror.h>
37 #include <winnls.h>
38 #include <winternl.h>
39 #include "wine/test.h"
41 /* THREAD_ALL_ACCESS in Vista+ PSDKs is incompatible with older Windows versions */
42 #define THREAD_ALL_ACCESS_NT4 (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3ff)
44 /* Specify the number of simultaneous threads to test */
45 #define NUM_THREADS 4
46 /* Specify whether to test the extended priorities for Win2k/XP */
47 #define USE_EXTENDED_PRIORITIES 0
48 /* Specify whether to test the stack allocation in CreateThread */
49 #define CHECK_STACK 0
51 /* Set CHECK_STACK to 1 if you want to try to test the stack-limit from
52 CreateThread. So far I have been unable to make this work, and
53 I am in doubt as to how portable it is. Also, according to MSDN,
54 you shouldn't mix C-run-time-libraries (i.e. alloca) with CreateThread.
55 Anyhow, the check is currently commented out
57 #if CHECK_STACK
58 # ifdef __try
59 # define __TRY __try
60 # define __EXCEPT __except
61 # define __ENDTRY
62 # else
63 # include "wine/exception.h"
64 # endif
65 #endif
67 #ifdef __i386__
68 #define ARCH "x86"
69 #elif defined __x86_64__
70 #define ARCH "amd64"
71 #elif defined __arm__
72 #define ARCH "arm"
73 #elif defined __aarch64__
74 #define ARCH "arm64"
75 #else
76 #define ARCH "none"
77 #endif
79 static BOOL (WINAPI *pGetThreadPriorityBoost)(HANDLE,PBOOL);
80 static HANDLE (WINAPI *pOpenThread)(DWORD,BOOL,DWORD);
81 static BOOL (WINAPI *pQueueUserWorkItem)(LPTHREAD_START_ROUTINE,PVOID,ULONG);
82 static DWORD (WINAPI *pSetThreadIdealProcessor)(HANDLE,DWORD);
83 static BOOL (WINAPI *pSetThreadPriorityBoost)(HANDLE,BOOL);
84 static BOOL (WINAPI *pRegisterWaitForSingleObject)(PHANDLE,HANDLE,WAITORTIMERCALLBACK,PVOID,ULONG,ULONG);
85 static BOOL (WINAPI *pUnregisterWait)(HANDLE);
86 static BOOL (WINAPI *pIsWow64Process)(HANDLE,PBOOL);
87 static BOOL (WINAPI *pSetThreadErrorMode)(DWORD,PDWORD);
88 static DWORD (WINAPI *pGetThreadErrorMode)(void);
89 static DWORD (WINAPI *pRtlGetThreadErrorMode)(void);
90 static BOOL (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*);
91 static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW);
92 static BOOL (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR);
93 static BOOL (WINAPI *pGetCurrentActCtx)(HANDLE *);
94 static void (WINAPI *pReleaseActCtx)(HANDLE);
95 static PTP_POOL (WINAPI *pCreateThreadpool)(PVOID);
96 static void (WINAPI *pCloseThreadpool)(PTP_POOL);
97 static PTP_WORK (WINAPI *pCreateThreadpoolWork)(PTP_WORK_CALLBACK,PVOID,PTP_CALLBACK_ENVIRON);
98 static void (WINAPI *pSubmitThreadpoolWork)(PTP_WORK);
99 static void (WINAPI *pWaitForThreadpoolWorkCallbacks)(PTP_WORK,BOOL);
100 static void (WINAPI *pCloseThreadpoolWork)(PTP_WORK);
101 static NTSTATUS (WINAPI *pNtQueryInformationThread)(HANDLE,THREADINFOCLASS,PVOID,ULONG,PULONG);
102 static BOOL (WINAPI *pGetThreadGroupAffinity)(HANDLE,GROUP_AFFINITY*);
103 static BOOL (WINAPI *pSetThreadGroupAffinity)(HANDLE,const GROUP_AFFINITY*,GROUP_AFFINITY*);
104 static NTSTATUS (WINAPI *pNtSetInformationThread)(HANDLE,THREADINFOCLASS,LPCVOID,ULONG);
106 static HANDLE create_target_process(const char *arg)
108 char **argv;
109 char cmdline[MAX_PATH];
110 PROCESS_INFORMATION pi;
111 BOOL ret;
112 STARTUPINFOA si = { 0 };
113 si.cb = sizeof(si);
115 winetest_get_mainargs( &argv );
116 sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
117 ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
118 ok(ret, "error: %u\n", GetLastError());
119 ret = CloseHandle(pi.hThread);
120 ok(ret, "error %u\n", GetLastError());
121 return pi.hProcess;
124 /* Functions not tested yet:
125 AttachThreadInput
126 SetThreadContext
127 SwitchToThread
129 In addition there are no checks that the inheritance works properly in
130 CreateThread
133 /* Functions to ensure that from a group of threads, only one executes
134 certain chunks of code at a time, and we know which one is executing
135 it. It basically makes multithreaded execution linear, which defeats
136 the purpose of multiple threads, but makes testing easy. */
137 static HANDLE start_event, stop_event;
138 static LONG num_synced;
140 static void init_thread_sync_helpers(void)
142 start_event = CreateEventW(NULL, TRUE, FALSE, NULL);
143 ok(start_event != NULL, "CreateEvent failed\n");
144 stop_event = CreateEventW(NULL, TRUE, FALSE, NULL);
145 ok(stop_event != NULL, "CreateEvent failed\n");
146 num_synced = -1;
149 static BOOL sync_threads_and_run_one(DWORD sync_id, DWORD my_id)
151 LONG num = InterlockedIncrement(&num_synced);
152 assert(-1 <= num && num <= 1);
153 if (num == 1)
155 ResetEvent( stop_event );
156 SetEvent( start_event );
158 else
160 DWORD ret = WaitForSingleObject(start_event, 10000);
161 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed %x\n",ret);
163 return sync_id == my_id;
166 static void resync_after_run(void)
168 LONG num = InterlockedDecrement(&num_synced);
169 assert(-1 <= num && num <= 1);
170 if (num == -1)
172 ResetEvent( start_event );
173 SetEvent( stop_event );
175 else
177 DWORD ret = WaitForSingleObject(stop_event, 10000);
178 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
182 static void cleanup_thread_sync_helpers(void)
184 CloseHandle(start_event);
185 CloseHandle(stop_event);
188 static DWORD tlsIndex;
190 typedef struct {
191 int threadnum;
192 HANDLE *event;
193 DWORD *threadmem;
194 } t1Struct;
196 /* WinME supports OpenThread but doesn't know about access restrictions so
197 we require them to be either completely ignored or always obeyed.
199 static INT obeying_ars = 0; /* -1 == no, 0 == dunno yet, 1 == yes */
200 #define obey_ar(x) \
201 (obeying_ars == 0 \
202 ? ((x) \
203 ? (obeying_ars = +1) \
204 : ((obeying_ars = -1), \
205 trace("not restricted, assuming consistent behaviour\n"))) \
206 : (obeying_ars < 0) \
207 ? ok(!(x), "access restrictions obeyed\n") \
208 : ok( (x), "access restrictions not obeyed\n"))
210 /* Basic test that simultaneous threads can access shared memory,
211 that the thread local storage routines work correctly, and that
212 threads actually run concurrently
214 static DWORD WINAPI threadFunc1(LPVOID p)
216 t1Struct *tstruct = p;
217 int i;
218 /* write our thread # into shared memory */
219 tstruct->threadmem[tstruct->threadnum]=GetCurrentThreadId();
220 ok(TlsSetValue(tlsIndex,(LPVOID)(INT_PTR)(tstruct->threadnum+1))!=0,
221 "TlsSetValue failed\n");
222 /* The threads synchronize before terminating. This is done by
223 Signaling an event, and waiting for all events to occur
225 SetEvent(tstruct->event[tstruct->threadnum]);
226 WaitForMultipleObjects(NUM_THREADS,tstruct->event,TRUE,INFINITE);
227 /* Double check that all threads really did run by validating that
228 they have all written to the shared memory. There should be no race
229 here, since all threads were synchronized after the write.*/
230 for (i = 0; i < NUM_THREADS; i++)
231 ok(tstruct->threadmem[i] != 0, "expected threadmem[%d] != 0\n", i);
233 /* lstrlenA contains an exception handler so this makes sure exceptions work in threads */
234 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
236 /* Check that no one changed our tls memory */
237 ok((INT_PTR)TlsGetValue(tlsIndex)-1==tstruct->threadnum,
238 "TlsGetValue failed\n");
239 return NUM_THREADS+tstruct->threadnum;
242 static DWORD WINAPI threadFunc2(LPVOID p)
244 return 99;
247 static DWORD WINAPI threadFunc3(LPVOID p)
249 HANDLE thread;
250 thread=GetCurrentThread();
251 SuspendThread(thread);
252 return 99;
255 static DWORD WINAPI threadFunc4(LPVOID p)
257 HANDLE event = p;
258 if(event != NULL) {
259 SetEvent(event);
261 Sleep(99000);
262 return 0;
265 #if CHECK_STACK
266 static DWORD WINAPI threadFunc5(LPVOID p)
268 DWORD *exitCode = p;
269 SYSTEM_INFO sysInfo;
270 sysInfo.dwPageSize=0;
271 GetSystemInfo(&sysInfo);
272 *exitCode=0;
273 __TRY
275 alloca(2*sysInfo.dwPageSize);
277 __EXCEPT(1) {
278 *exitCode=1;
280 __ENDTRY
281 return 0;
283 #endif
285 static DWORD WINAPI threadFunc_SetEvent(LPVOID p)
287 SetEvent(p);
288 return 0;
291 static DWORD WINAPI threadFunc_CloseHandle(LPVOID p)
293 CloseHandle(p);
294 return 0;
297 struct thread_actctx_param
299 HANDLE thread_context;
300 HANDLE handle;
303 static DWORD WINAPI thread_actctx_func(void *p)
305 struct thread_actctx_param *param = (struct thread_actctx_param*)p;
306 HANDLE cur;
307 BOOL ret;
309 cur = (void*)0xdeadbeef;
310 ret = pGetCurrentActCtx(&cur);
311 ok(ret, "thread GetCurrentActCtx failed, %u\n", GetLastError());
312 ok(cur == param->handle, "got %p, expected %p\n", cur, param->handle);
313 param->thread_context = cur;
315 return 0;
318 static void create_function_addr_events(HANDLE events[2])
320 char buffer[256];
322 sprintf(buffer, "threadFunc_SetEvent %p", threadFunc_SetEvent);
323 events[0] = CreateEventA(NULL, FALSE, FALSE, buffer);
325 sprintf(buffer, "threadFunc_CloseHandle %p", threadFunc_CloseHandle);
326 events[1] = CreateEventA(NULL, FALSE, FALSE, buffer);
329 /* check CreateRemoteThread */
330 static VOID test_CreateRemoteThread(void)
332 HANDLE hProcess, hThread, hEvent, hRemoteEvent;
333 DWORD tid, ret, exitcode;
334 HANDLE hAddrEvents[2];
336 hProcess = create_target_process("sleep");
337 ok(hProcess != NULL, "Can't start process\n");
339 /* ensure threadFunc_SetEvent & threadFunc_CloseHandle are the same
340 * address as in the child process */
341 create_function_addr_events(hAddrEvents);
342 ret = WaitForMultipleObjects(2, hAddrEvents, TRUE, 5000);
343 if (ret == WAIT_TIMEOUT)
345 skip("child process wasn't mapped at same address, so can't do CreateRemoteThread tests.\n");
346 return;
348 ok(ret == WAIT_OBJECT_0 || broken(ret == WAIT_OBJECT_0+1 /* nt4,w2k */), "WaitForAllObjects 2 events %d\n", ret);
350 hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
351 ok(hEvent != NULL, "Can't create event, err=%u\n", GetLastError());
352 ret = DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &hRemoteEvent,
353 0, FALSE, DUPLICATE_SAME_ACCESS);
354 ok(ret != 0, "DuplicateHandle failed, err=%u\n", GetLastError());
356 /* create suspended remote thread with entry point SetEvent() */
357 SetLastError(0xdeadbeef);
358 hThread = CreateRemoteThread(hProcess, NULL, 0, threadFunc_SetEvent,
359 hRemoteEvent, CREATE_SUSPENDED, &tid);
360 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
362 win_skip("CreateRemoteThread is not implemented\n");
363 goto cleanup;
365 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
366 ok(tid != 0, "null tid\n");
367 ret = SuspendThread(hThread);
368 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
369 ret = ResumeThread(hThread);
370 ok(ret == 2, "ret=%u, err=%u\n", ret, GetLastError());
372 /* thread still suspended, so wait times out */
373 ret = WaitForSingleObject(hEvent, 1000);
374 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
376 ret = ResumeThread(hThread);
377 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
379 /* wait that doesn't time out */
380 ret = WaitForSingleObject(hEvent, 1000);
381 ok(ret == WAIT_OBJECT_0, "object not signaled, ret=%u\n", ret);
383 /* wait for thread end */
384 ret = WaitForSingleObject(hThread, 1000);
385 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
386 CloseHandle(hThread);
388 /* create and wait for remote thread with entry point CloseHandle() */
389 hThread = CreateRemoteThread(hProcess, NULL, 0,
390 threadFunc_CloseHandle,
391 hRemoteEvent, 0, &tid);
392 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
393 ret = WaitForSingleObject(hThread, 1000);
394 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
395 CloseHandle(hThread);
397 /* create remote thread with entry point SetEvent() */
398 hThread = CreateRemoteThread(hProcess, NULL, 0,
399 threadFunc_SetEvent,
400 hRemoteEvent, 0, &tid);
401 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
403 /* closed handle, so wait times out */
404 ret = WaitForSingleObject(hEvent, 1000);
405 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
407 /* check that remote SetEvent() failed */
408 ret = GetExitCodeThread(hThread, &exitcode);
409 ok(ret != 0, "GetExitCodeThread failed, err=%u\n", GetLastError());
410 if (ret) ok(exitcode == 0, "SetEvent succeeded, expected to fail\n");
411 CloseHandle(hThread);
413 cleanup:
414 TerminateProcess(hProcess, 0);
415 CloseHandle(hEvent);
416 CloseHandle(hProcess);
419 /* Check basic functionality of CreateThread and Tls* functions */
420 static VOID test_CreateThread_basic(void)
422 HANDLE thread[NUM_THREADS],event[NUM_THREADS];
423 DWORD threadid[NUM_THREADS],curthreadId;
424 DWORD threadmem[NUM_THREADS];
425 DWORD exitCode;
426 t1Struct tstruct[NUM_THREADS];
427 int error;
428 DWORD i,j;
429 DWORD GLE, ret;
430 DWORD tid;
431 BOOL bRet;
433 /* lstrlenA contains an exception handler so this makes sure exceptions work in the main thread */
434 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
436 /* Retrieve current Thread ID for later comparisons */
437 curthreadId=GetCurrentThreadId();
438 /* Allocate some local storage */
439 ok((tlsIndex=TlsAlloc())!=TLS_OUT_OF_INDEXES,"TlsAlloc failed\n");
440 /* Create events for thread synchronization */
441 for(i=0;i<NUM_THREADS;i++) {
442 threadmem[i]=0;
443 /* Note that it doesn't matter what type of event we choose here. This
444 test isn't trying to thoroughly test events
446 event[i]=CreateEventA(NULL,TRUE,FALSE,NULL);
447 tstruct[i].threadnum=i;
448 tstruct[i].threadmem=threadmem;
449 tstruct[i].event=event;
452 /* Test that passing arguments to threads works okay */
453 for(i=0;i<NUM_THREADS;i++) {
454 thread[i] = CreateThread(NULL,0,threadFunc1,
455 &tstruct[i],0,&threadid[i]);
456 ok(thread[i]!=NULL,"Create Thread failed\n");
458 /* Test that the threads actually complete */
459 for(i=0;i<NUM_THREADS;i++) {
460 error=WaitForSingleObject(thread[i],5000);
461 ok(error==WAIT_OBJECT_0, "Thread did not complete within timelimit\n");
462 if(error!=WAIT_OBJECT_0) {
463 TerminateThread(thread[i],i+NUM_THREADS);
465 ok(GetExitCodeThread(thread[i],&exitCode),"Could not retrieve ext code\n");
466 ok(exitCode==i+NUM_THREADS,"Thread returned an incorrect exit code\n");
468 /* Test that each thread executed in its parent's address space
469 (it was able to change threadmem and pass that change back to its parent)
470 and that each thread id was independent). Note that we prove that the
471 threads actually execute concurrently by having them block on each other
472 in threadFunc1
474 for(i=0;i<NUM_THREADS;i++) {
475 error=0;
476 for(j=i+1;j<NUM_THREADS;j++) {
477 if (threadmem[i]==threadmem[j]) {
478 error=1;
481 ok(!error && threadmem[i]==threadid[i] && threadmem[i]!=curthreadId,
482 "Thread did not execute successfully\n");
483 ok(CloseHandle(thread[i])!=0,"CloseHandle failed\n");
486 SetLastError(0xCAFEF00D);
487 bRet = TlsFree(tlsIndex);
488 ok(bRet, "TlsFree failed: %08x\n", GetLastError());
489 ok(GetLastError()==0xCAFEF00D,
490 "GetLastError: expected 0xCAFEF00D, got %08x\n", GetLastError());
492 /* Test freeing an already freed TLS index */
493 SetLastError(0xCAFEF00D);
494 ok(TlsFree(tlsIndex)==0,"TlsFree succeeded\n");
495 ok(GetLastError()==ERROR_INVALID_PARAMETER,
496 "GetLastError: expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
498 /* Test how passing NULL as a pointer to threadid works */
499 SetLastError(0xFACEaBAD);
500 thread[0] = CreateThread(NULL,0,threadFunc2,NULL,0,&tid);
501 GLE = GetLastError();
502 if (thread[0]) { /* NT */
503 ok(GLE==0xFACEaBAD, "CreateThread set last error to %d, expected 4207848365\n", GLE);
504 ret = WaitForSingleObject(thread[0],100);
505 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
506 ret = GetExitCodeThread(thread[0],&exitCode);
507 ok(ret!=0, "GetExitCodeThread returned %d (expected nonzero)\n", ret);
508 ok(exitCode==99, "threadFunc2 exited with code: %d (expected 99)\n", exitCode);
509 ok(CloseHandle(thread[0])!=0,"Error closing thread handle\n");
511 else { /* 9x */
512 ok(GLE==ERROR_INVALID_PARAMETER, "CreateThread set last error to %d, expected 87\n", GLE);
516 /* Check that using the CREATE_SUSPENDED flag works */
517 static VOID test_CreateThread_suspended(void)
519 HANDLE thread;
520 DWORD threadId;
521 DWORD suspend_count;
522 int error;
524 thread = CreateThread(NULL,0,threadFunc2,NULL,
525 CREATE_SUSPENDED,&threadId);
526 ok(thread!=NULL,"Create Thread failed\n");
527 /* Check that the thread is suspended */
528 ok(SuspendThread(thread)==1,"Thread did not start suspended\n");
529 ok(ResumeThread(thread)==2,"Resume thread returned an invalid value\n");
530 /* Check that resume thread didn't actually start the thread. I can't think
531 of a better way of checking this than just waiting. I am not sure if this
532 will work on slow computers.
534 ok(WaitForSingleObject(thread,1000)==WAIT_TIMEOUT,
535 "ResumeThread should not have actually started the thread\n");
536 /* Now actually resume the thread and make sure that it actually completes*/
537 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
538 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
539 "Thread did not resume\n");
540 if(error!=WAIT_OBJECT_0) {
541 TerminateThread(thread,1);
544 suspend_count = SuspendThread(thread);
545 ok(suspend_count == -1, "SuspendThread returned %d, expected -1\n", suspend_count);
547 suspend_count = ResumeThread(thread);
548 ok(suspend_count == 0 ||
549 broken(suspend_count == -1), /* win9x */
550 "ResumeThread returned %d, expected 0\n", suspend_count);
552 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
555 /* Check that SuspendThread and ResumeThread work */
556 static VOID test_SuspendThread(void)
558 HANDLE thread,access_thread;
559 DWORD threadId,exitCode,error;
560 int i;
562 thread = CreateThread(NULL,0,threadFunc3,NULL,
563 0,&threadId);
564 ok(thread!=NULL,"Create Thread failed\n");
565 /* Check that the thread is suspended */
566 /* Note that this is a polling method, and there is a race between
567 SuspendThread being called (in the child, and the loop below timing out,
568 so the test could fail on a heavily loaded or slow computer.
570 error=0;
571 for(i=0;error==0 && i<100;i++) {
572 error=SuspendThread(thread);
573 ResumeThread(thread);
574 if(error==0) {
575 Sleep(50);
576 i++;
579 ok(error==1,"SuspendThread did not work\n");
580 /* check that access restrictions are obeyed */
581 if (pOpenThread) {
582 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 & (~THREAD_SUSPEND_RESUME),
583 0,threadId);
584 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
585 if (access_thread!=NULL) {
586 obey_ar(SuspendThread(access_thread)==~0U);
587 obey_ar(ResumeThread(access_thread)==~0U);
588 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
591 /* Double check that the thread really is suspended */
592 ok((error=GetExitCodeThread(thread,&exitCode))!=0 && exitCode==STILL_ACTIVE,
593 "Thread did not really suspend\n");
594 /* Resume the thread, and make sure it actually completes */
595 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
596 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
597 "Thread did not resume\n");
598 if(error!=WAIT_OBJECT_0) {
599 TerminateThread(thread,1);
601 /* Trying to suspend a terminated thread should fail */
602 error=SuspendThread(thread);
603 ok(error==~0U, "wrong return code: %d\n", error);
604 ok(GetLastError()==ERROR_ACCESS_DENIED || GetLastError()==ERROR_NO_MORE_ITEMS, "unexpected error code: %d\n", GetLastError());
606 ok(CloseHandle(thread)!=0,"CloseHandle Failed\n");
609 /* Check that TerminateThread works properly
611 static VOID test_TerminateThread(void)
613 HANDLE thread,access_thread,event;
614 DWORD threadId,exitCode;
615 event=CreateEventA(NULL,TRUE,FALSE,NULL);
616 thread = CreateThread(NULL,0,threadFunc4,event,0,&threadId);
617 ok(thread!=NULL,"Create Thread failed\n");
618 /* TerminateThread has a race condition in Wine. If the thread is terminated
619 before it starts, it leaves a process behind. Therefore, we wait for the
620 thread to signal that it has started. There is no easy way to force the
621 race to occur, so we don't try to find it.
623 ok(WaitForSingleObject(event,5000)==WAIT_OBJECT_0,
624 "TerminateThread didn't work\n");
625 /* check that access restrictions are obeyed */
626 if (pOpenThread) {
627 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 & (~THREAD_TERMINATE),
628 0,threadId);
629 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
630 if (access_thread!=NULL) {
631 obey_ar(TerminateThread(access_thread,99)==0);
632 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
635 /* terminate a job and make sure it terminates */
636 ok(TerminateThread(thread,99)!=0,"TerminateThread failed\n");
637 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
638 "TerminateThread didn't work\n");
639 ok(GetExitCodeThread(thread,&exitCode)!=STILL_ACTIVE,
640 "TerminateThread should not leave the thread 'STILL_ACTIVE'\n");
641 ok(exitCode==99, "TerminateThread returned invalid exit code\n");
642 ok(CloseHandle(thread)!=0,"Error Closing thread handle\n");
645 /* Check if CreateThread obeys the specified stack size. This code does
646 not work properly, and is currently disabled
648 static VOID test_CreateThread_stack(void)
650 #if CHECK_STACK
651 /* The only way I know of to test the stack size is to use alloca
652 and __try/__except. However, this is probably not portable,
653 and I couldn't get it to work under Wine anyhow. However, here
654 is the code which should allow for testing that CreateThread
655 respects the stack-size limit
657 HANDLE thread;
658 DWORD threadId,exitCode;
660 SYSTEM_INFO sysInfo;
661 sysInfo.dwPageSize=0;
662 GetSystemInfo(&sysInfo);
663 ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
664 thread = CreateThread(NULL,sysInfo.dwPageSize,
665 threadFunc5,&exitCode,
666 0,&threadId);
667 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
668 "TerminateThread didn't work\n");
669 ok(exitCode==1,"CreateThread did not obey stack-size-limit\n");
670 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
671 #endif
674 /* Check whether setting/retrieving thread priorities works */
675 static VOID test_thread_priority(void)
677 HANDLE curthread,access_thread;
678 DWORD curthreadId,exitCode;
679 int min_priority=-2,max_priority=2;
680 BOOL disabled,rc;
681 int i;
683 curthread=GetCurrentThread();
684 curthreadId=GetCurrentThreadId();
685 /* Check thread priority */
686 /* NOTE: on Win2k/XP priority can be from -7 to 6. All other platforms it
687 is -2 to 2. However, even on a real Win2k system, using thread
688 priorities beyond the -2 to 2 range does not work. If you want to try
689 anyway, enable USE_EXTENDED_PRIORITIES
691 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_NORMAL,
692 "GetThreadPriority Failed\n");
694 if (pOpenThread) {
695 /* check that access control is obeyed */
696 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 &
697 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
698 0,curthreadId);
699 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
700 if (access_thread!=NULL) {
701 obey_ar(SetThreadPriority(access_thread,1)==0);
702 obey_ar(GetThreadPriority(access_thread)==THREAD_PRIORITY_ERROR_RETURN);
703 obey_ar(GetExitCodeThread(access_thread,&exitCode)==0);
704 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
707 #if USE_EXTENDED_PRIORITIES
708 min_priority=-7; max_priority=6;
709 #endif
710 for(i=min_priority;i<=max_priority;i++) {
711 ok(SetThreadPriority(curthread,i)!=0,
712 "SetThreadPriority Failed for priority: %d\n",i);
713 ok(GetThreadPriority(curthread)==i,
714 "GetThreadPriority Failed for priority: %d\n",i);
716 ok(SetThreadPriority(curthread,THREAD_PRIORITY_TIME_CRITICAL)!=0,
717 "SetThreadPriority Failed\n");
718 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_TIME_CRITICAL,
719 "GetThreadPriority Failed\n");
720 ok(SetThreadPriority(curthread,THREAD_PRIORITY_IDLE)!=0,
721 "SetThreadPriority Failed\n");
722 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_IDLE,
723 "GetThreadPriority Failed\n");
724 ok(SetThreadPriority(curthread,0)!=0,"SetThreadPriority Failed\n");
726 /* Check that the thread priority is not changed if SetThreadPriority
727 is called with a value outside of the max/min range */
728 SetThreadPriority(curthread,min_priority);
729 SetLastError(0xdeadbeef);
730 rc = SetThreadPriority(curthread,min_priority-1);
732 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
733 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
734 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
735 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
736 GetLastError());
737 ok(GetThreadPriority(curthread)==min_priority,
738 "GetThreadPriority didn't return min_priority\n");
740 SetThreadPriority(curthread,max_priority);
741 SetLastError(0xdeadbeef);
742 rc = SetThreadPriority(curthread,max_priority+1);
744 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
745 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
746 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
747 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
748 GetLastError());
749 ok(GetThreadPriority(curthread)==max_priority,
750 "GetThreadPriority didn't return max_priority\n");
752 /* Check thread priority boost */
753 if (!pGetThreadPriorityBoost || !pSetThreadPriorityBoost)
754 return; /* Win9x */
756 SetLastError(0xdeadbeef);
757 rc=pGetThreadPriorityBoost(curthread,&disabled);
758 if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
760 win_skip("GetThreadPriorityBoost is not implemented on WinME\n");
761 return;
764 ok(rc!=0,"error=%d\n",GetLastError());
766 if (pOpenThread) {
767 /* check that access control is obeyed */
768 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 &
769 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
770 0,curthreadId);
771 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
772 if (access_thread!=NULL) {
773 todo_wine obey_ar(pSetThreadPriorityBoost(access_thread,1)==0);
774 todo_wine obey_ar(pGetThreadPriorityBoost(access_thread,&disabled)==0);
775 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
779 rc = pSetThreadPriorityBoost(curthread,1);
780 ok( rc != 0, "error=%d\n",GetLastError());
781 todo_wine {
782 rc=pGetThreadPriorityBoost(curthread,&disabled);
783 ok(rc!=0 && disabled==1,
784 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
787 rc = pSetThreadPriorityBoost(curthread,0);
788 ok( rc != 0, "error=%d\n",GetLastError());
789 rc=pGetThreadPriorityBoost(curthread,&disabled);
790 ok(rc!=0 && disabled==0,
791 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
794 /* check the GetThreadTimes function */
795 static VOID test_GetThreadTimes(void)
797 HANDLE thread,access_thread=NULL;
798 FILETIME creationTime,exitTime,kernelTime,userTime;
799 DWORD threadId;
800 int error;
802 thread = CreateThread(NULL,0,threadFunc2,NULL,
803 CREATE_SUSPENDED,&threadId);
805 ok(thread!=NULL,"Create Thread failed\n");
806 /* check that access control is obeyed */
807 if (pOpenThread) {
808 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 &
809 (~THREAD_QUERY_INFORMATION), 0,threadId);
810 ok(access_thread!=NULL,
811 "OpenThread returned an invalid handle\n");
813 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
814 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
815 "ResumeThread didn't work\n");
816 creationTime.dwLowDateTime=99; creationTime.dwHighDateTime=99;
817 exitTime.dwLowDateTime=99; exitTime.dwHighDateTime=99;
818 kernelTime.dwLowDateTime=99; kernelTime.dwHighDateTime=99;
819 userTime.dwLowDateTime=99; userTime.dwHighDateTime=99;
820 /* GetThreadTimes should set all of the parameters passed to it */
821 error=GetThreadTimes(thread,&creationTime,&exitTime,
822 &kernelTime,&userTime);
824 if (error == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
825 win_skip("GetThreadTimes is not implemented\n");
826 else {
827 ok(error!=0,"GetThreadTimes failed\n");
828 ok(creationTime.dwLowDateTime!=99 || creationTime.dwHighDateTime!=99,
829 "creationTime was invalid\n");
830 ok(exitTime.dwLowDateTime!=99 || exitTime.dwHighDateTime!=99,
831 "exitTime was invalid\n");
832 ok(kernelTime.dwLowDateTime!=99 || kernelTime.dwHighDateTime!=99,
833 "kernelTimewas invalid\n");
834 ok(userTime.dwLowDateTime!=99 || userTime.dwHighDateTime!=99,
835 "userTime was invalid\n");
836 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
837 if(access_thread!=NULL)
839 error=GetThreadTimes(access_thread,&creationTime,&exitTime,
840 &kernelTime,&userTime);
841 obey_ar(error==0);
844 if(access_thread!=NULL) {
845 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
849 /* Check the processor affinity functions */
850 /* NOTE: These functions should also be checked that they obey access control
852 static VOID test_thread_processor(void)
854 HANDLE curthread,curproc;
855 DWORD_PTR processMask,systemMask,retMask;
856 SYSTEM_INFO sysInfo;
857 int error=0;
858 BOOL is_wow64;
860 if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
862 sysInfo.dwNumberOfProcessors=0;
863 GetSystemInfo(&sysInfo);
864 ok(sysInfo.dwNumberOfProcessors>0,
865 "GetSystemInfo failed to return a valid # of processors\n");
866 /* Use the current Thread/process for all tests */
867 curthread=GetCurrentThread();
868 ok(curthread!=NULL,"GetCurrentThread failed\n");
869 curproc=GetCurrentProcess();
870 ok(curproc!=NULL,"GetCurrentProcess failed\n");
871 /* Check the Affinity Mask functions */
872 ok(GetProcessAffinityMask(curproc,&processMask,&systemMask)!=0,
873 "GetProcessAffinityMask failed\n");
874 ok(SetThreadAffinityMask(curthread,processMask)==processMask,
875 "SetThreadAffinityMask failed\n");
876 ok(SetThreadAffinityMask(curthread,processMask+1)==0,
877 "SetThreadAffinityMask passed for an illegal processor\n");
878 /* NOTE: Pre-Vista does not recognize the "all processors" flag (all bits set) */
879 retMask = SetThreadAffinityMask(curthread,~0);
880 ok(broken(retMask==0) || retMask==processMask,
881 "SetThreadAffinityMask(thread,-1) failed to request all processors.\n");
883 if (retMask == processMask)
885 /* Show that the "all processors" flag is handled in ntdll */
886 DWORD_PTR mask = ~0u;
887 NTSTATUS status = pNtSetInformationThread(curthread, ThreadAffinityMask, &mask, sizeof(mask));
888 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS in NtSetInformationThread, got %x\n", status);
891 if (retMask == processMask && sizeof(ULONG_PTR) > sizeof(ULONG))
893 /* only the low 32-bits matter */
894 retMask = SetThreadAffinityMask(curthread,~(ULONG_PTR)0);
895 ok(retMask == processMask, "SetThreadAffinityMask failed\n");
896 retMask = SetThreadAffinityMask(curthread,~(ULONG_PTR)0 >> 3);
897 ok(retMask == processMask, "SetThreadAffinityMask failed\n");
899 /* NOTE: This only works on WinNT/2000/XP) */
900 if (pSetThreadIdealProcessor)
902 SetLastError(0xdeadbeef);
903 error=pSetThreadIdealProcessor(curthread,0);
904 if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
906 ok(error!=-1, "SetThreadIdealProcessor failed\n");
908 if (is_wow64)
910 SetLastError(0xdeadbeef);
911 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
912 todo_wine
913 ok(error!=-1, "SetThreadIdealProcessor failed for %u on Wow64\n", MAXIMUM_PROCESSORS+1);
915 SetLastError(0xdeadbeef);
916 error=pSetThreadIdealProcessor(curthread,65);
917 ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
918 ok(GetLastError()==ERROR_INVALID_PARAMETER,
919 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
921 else
923 SetLastError(0xdeadbeef);
924 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
925 ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
926 ok(GetLastError()==ERROR_INVALID_PARAMETER,
927 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
930 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS);
931 ok(error!=-1, "SetThreadIdealProcessor failed\n");
933 else
934 win_skip("SetThreadIdealProcessor is not implemented\n");
937 if (pGetThreadGroupAffinity && pSetThreadGroupAffinity)
939 GROUP_AFFINITY affinity, affinity_new;
940 NTSTATUS status;
942 memset(&affinity, 0, sizeof(affinity));
943 ok(pGetThreadGroupAffinity(curthread, &affinity), "GetThreadGroupAffinity failed\n");
945 SetLastError(0xdeadbeef);
946 ok(!pGetThreadGroupAffinity(curthread, NULL), "GetThreadGroupAffinity succeeded\n");
947 ok(GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == ERROR_NOACCESS), /* Win 7 and 8 */
948 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
949 ok(affinity.Group == 0, "Expected group 0 got %u\n", affinity.Group);
951 memset(&affinity_new, 0, sizeof(affinity_new));
952 affinity_new.Group = 0;
953 affinity_new.Mask = affinity.Mask;
954 ok(pSetThreadGroupAffinity(curthread, &affinity_new, &affinity), "SetThreadGroupAffinity failed\n");
955 ok(affinity_new.Mask == affinity.Mask, "Expected old affinity mask %lx, got %lx\n",
956 affinity_new.Mask, affinity.Mask);
958 /* show that the "all processors" flag is not supported for SetThreadGroupAffinity */
959 affinity_new.Group = 0;
960 affinity_new.Mask = ~0u;
961 SetLastError(0xdeadbeef);
962 ok(!pSetThreadGroupAffinity(curthread, &affinity_new, NULL), "SetThreadGroupAffinity succeeded\n");
963 ok(GetLastError() == ERROR_INVALID_PARAMETER,
964 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
966 affinity_new.Group = 1; /* assumes that you have less than 64 logical processors */
967 affinity_new.Mask = 0x1;
968 SetLastError(0xdeadbeef);
969 ok(!pSetThreadGroupAffinity(curthread, &affinity_new, NULL), "SetThreadGroupAffinity succeeded\n");
970 ok(GetLastError() == ERROR_INVALID_PARAMETER,
971 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
973 SetLastError(0xdeadbeef);
974 ok(!pSetThreadGroupAffinity(curthread, NULL, NULL), "SetThreadGroupAffinity succeeded\n");
975 ok(GetLastError() == ERROR_NOACCESS,
976 "Expected ERROR_NOACCESS, got %d\n", GetLastError());
978 /* show that the access violation was detected in ntdll */
979 status = pNtSetInformationThread(curthread, ThreadGroupInformation, NULL, sizeof(affinity_new));
980 ok(status == STATUS_ACCESS_VIOLATION,
981 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
983 /* restore original mask */
984 affinity_new.Group = 0;
985 affinity_new.Mask = affinity.Mask;
986 SetLastError(0xdeadbeef);
987 ok(pSetThreadGroupAffinity(curthread, &affinity_new, &affinity), "SetThreadGroupAffinity failed\n");
988 ok(affinity_new.Mask == affinity.Mask, "Expected old affinity mask %lx, got %lx\n",
989 affinity_new.Mask, affinity.Mask);
991 else
992 win_skip("Get/SetThreadGroupAffinity not available\n");
995 static VOID test_GetThreadExitCode(void)
997 DWORD exitCode, threadid;
998 DWORD GLE, ret;
999 HANDLE thread;
1001 ret = GetExitCodeThread((HANDLE)0x2bad2bad,&exitCode);
1002 ok(ret==0, "GetExitCodeThread returned non zero value: %d\n", ret);
1003 GLE = GetLastError();
1004 ok(GLE==ERROR_INVALID_HANDLE, "GetLastError returned %d (expected 6)\n", GLE);
1006 thread = CreateThread(NULL,0,threadFunc2,NULL,0,&threadid);
1007 ret = WaitForSingleObject(thread,100);
1008 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
1009 ret = GetExitCodeThread(thread,&exitCode);
1010 ok(ret==exitCode || ret==1,
1011 "GetExitCodeThread returned %d (expected 1 or %d)\n", ret, exitCode);
1012 ok(exitCode==99, "threadFunc2 exited with code %d (expected 99)\n", exitCode);
1013 ok(CloseHandle(thread)!=0,"Error closing thread handle\n");
1016 #ifdef __i386__
1018 static int test_value = 0;
1019 static HANDLE event;
1021 static void WINAPI set_test_val( int val )
1023 test_value += val;
1024 ExitThread(0);
1027 static DWORD WINAPI threadFunc6(LPVOID p)
1029 SetEvent( event );
1030 Sleep( 1000 );
1031 test_value *= (int)p;
1032 return 0;
1035 static void test_SetThreadContext(void)
1037 CONTEXT ctx;
1038 int *stack;
1039 HANDLE thread;
1040 DWORD threadid;
1041 DWORD prevcount;
1042 BOOL ret;
1044 SetLastError(0xdeadbeef);
1045 event = CreateEventW( NULL, TRUE, FALSE, NULL );
1046 thread = CreateThread( NULL, 0, threadFunc6, (void *)2, 0, &threadid );
1047 ok( thread != NULL, "CreateThread failed : (%d)\n", GetLastError() );
1048 if (!thread)
1050 trace("Thread creation failed, skipping rest of test\n");
1051 return;
1053 WaitForSingleObject( event, INFINITE );
1054 SuspendThread( thread );
1055 CloseHandle( event );
1057 ctx.ContextFlags = CONTEXT_FULL;
1058 SetLastError(0xdeadbeef);
1059 ret = GetThreadContext( thread, &ctx );
1060 ok( ret, "GetThreadContext failed : (%u)\n", GetLastError() );
1062 if (ret)
1064 /* simulate a call to set_test_val(10) */
1065 stack = (int *)ctx.Esp;
1066 stack[-1] = 10;
1067 stack[-2] = ctx.Eip;
1068 ctx.Esp -= 2 * sizeof(int *);
1069 ctx.Eip = (DWORD)set_test_val;
1070 SetLastError(0xdeadbeef);
1071 ret = SetThreadContext( thread, &ctx );
1072 ok( ret, "SetThreadContext failed : (%d)\n", GetLastError() );
1075 SetLastError(0xdeadbeef);
1076 prevcount = ResumeThread( thread );
1077 ok ( prevcount == 1, "Previous suspend count (%d) instead of 1, last error : (%d)\n",
1078 prevcount, GetLastError() );
1080 WaitForSingleObject( thread, INFINITE );
1081 ok( test_value == 10, "test_value %d\n", test_value );
1083 ctx.ContextFlags = CONTEXT_FULL;
1084 SetLastError(0xdeadbeef);
1085 ret = GetThreadContext( thread, &ctx );
1086 ok( (!ret && (GetLastError() == ERROR_GEN_FAILURE)) ||
1087 (!ret && broken(GetLastError() == ERROR_INVALID_HANDLE)) || /* win2k */
1088 broken(ret), /* 32bit application on NT 5.x 64bit */
1089 "got %d with %u (expected FALSE with ERROR_GEN_FAILURE)\n",
1090 ret, GetLastError() );
1092 SetLastError(0xdeadbeef);
1093 ret = SetThreadContext( thread, &ctx );
1094 ok( (!ret && ((GetLastError() == ERROR_GEN_FAILURE) || (GetLastError() == ERROR_ACCESS_DENIED))) ||
1095 (!ret && broken(GetLastError() == ERROR_INVALID_HANDLE)) || /* win2k */
1096 broken(ret), /* 32bit application on NT 5.x 64bit */
1097 "got %d with %u (expected FALSE with ERROR_GEN_FAILURE or ERROR_ACCESS_DENIED)\n",
1098 ret, GetLastError() );
1100 CloseHandle( thread );
1103 #endif /* __i386__ */
1105 static HANDLE finish_event;
1106 static LONG times_executed;
1108 static DWORD CALLBACK work_function(void *p)
1110 LONG executed = InterlockedIncrement(&times_executed);
1112 if (executed == 100)
1113 SetEvent(finish_event);
1114 return 0;
1117 static void test_QueueUserWorkItem(void)
1119 INT_PTR i;
1120 DWORD wait_result;
1121 DWORD before, after;
1123 /* QueueUserWorkItem not present on win9x */
1124 if (!pQueueUserWorkItem) return;
1126 finish_event = CreateEventW(NULL, TRUE, FALSE, NULL);
1128 before = GetTickCount();
1130 for (i = 0; i < 100; i++)
1132 BOOL ret = pQueueUserWorkItem(work_function, (void *)i, WT_EXECUTEDEFAULT);
1133 ok(ret, "QueueUserWorkItem failed with error %d\n", GetLastError());
1136 wait_result = WaitForSingleObject(finish_event, 10000);
1138 after = GetTickCount();
1139 trace("100 QueueUserWorkItem calls took %dms\n", after - before);
1140 ok(wait_result == WAIT_OBJECT_0, "wait failed with error 0x%x\n", wait_result);
1142 ok(times_executed == 100, "didn't execute all of the work items\n");
1145 static void CALLBACK signaled_function(PVOID p, BOOLEAN TimerOrWaitFired)
1147 HANDLE event = p;
1148 SetEvent(event);
1149 ok(!TimerOrWaitFired, "wait shouldn't have timed out\n");
1152 static void CALLBACK timeout_function(PVOID p, BOOLEAN TimerOrWaitFired)
1154 HANDLE event = p;
1155 SetEvent(event);
1156 ok(TimerOrWaitFired, "wait should have timed out\n");
1159 static void test_RegisterWaitForSingleObject(void)
1161 BOOL ret;
1162 HANDLE wait_handle;
1163 HANDLE handle;
1164 HANDLE complete_event;
1166 if (!pRegisterWaitForSingleObject || !pUnregisterWait)
1168 win_skip("RegisterWaitForSingleObject or UnregisterWait not implemented\n");
1169 return;
1172 /* test signaled case */
1174 handle = CreateEventW(NULL, TRUE, TRUE, NULL);
1175 complete_event = CreateEventW(NULL, FALSE, FALSE, NULL);
1177 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1178 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1180 WaitForSingleObject(complete_event, INFINITE);
1181 /* give worker thread chance to complete */
1182 Sleep(100);
1184 ret = pUnregisterWait(wait_handle);
1185 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1187 /* test cancel case */
1189 ResetEvent(handle);
1191 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1192 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1194 ret = pUnregisterWait(wait_handle);
1195 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1197 /* test timeout case */
1199 ret = pRegisterWaitForSingleObject(&wait_handle, handle, timeout_function, complete_event, 0, WT_EXECUTEONLYONCE);
1200 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1202 WaitForSingleObject(complete_event, INFINITE);
1203 /* give worker thread chance to complete */
1204 Sleep(100);
1206 ret = pUnregisterWait(wait_handle);
1207 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1210 static DWORD TLS_main;
1211 static DWORD TLS_index0, TLS_index1;
1213 static DWORD WINAPI TLS_InheritanceProc(LPVOID p)
1215 /* We should NOT inherit the TLS values from our parent or from the
1216 main thread. */
1217 LPVOID val;
1219 val = TlsGetValue(TLS_main);
1220 ok(val == NULL, "TLS inheritance failed\n");
1222 val = TlsGetValue(TLS_index0);
1223 ok(val == NULL, "TLS inheritance failed\n");
1225 val = TlsGetValue(TLS_index1);
1226 ok(val == NULL, "TLS inheritance failed\n");
1228 return 0;
1231 /* Basic TLS usage test. Make sure we can create slots and the values we
1232 store in them are separate among threads. Also test TLS value
1233 inheritance with TLS_InheritanceProc. */
1234 static DWORD WINAPI TLS_ThreadProc(LPVOID p)
1236 LONG_PTR id = (LONG_PTR) p;
1237 LPVOID val;
1238 BOOL ret;
1240 if (sync_threads_and_run_one(0, id))
1242 TLS_index0 = TlsAlloc();
1243 ok(TLS_index0 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1245 resync_after_run();
1247 if (sync_threads_and_run_one(1, id))
1249 TLS_index1 = TlsAlloc();
1250 ok(TLS_index1 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1252 /* Slot indices should be different even if created in different
1253 threads. */
1254 ok(TLS_index0 != TLS_index1, "TlsAlloc failed\n");
1256 /* Both slots should be initialized to NULL */
1257 val = TlsGetValue(TLS_index0);
1258 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1259 ok(val == NULL, "TLS slot not initialized correctly\n");
1261 val = TlsGetValue(TLS_index1);
1262 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1263 ok(val == NULL, "TLS slot not initialized correctly\n");
1265 resync_after_run();
1267 if (sync_threads_and_run_one(0, id))
1269 val = TlsGetValue(TLS_index0);
1270 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1271 ok(val == NULL, "TLS slot not initialized correctly\n");
1273 val = TlsGetValue(TLS_index1);
1274 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1275 ok(val == NULL, "TLS slot not initialized correctly\n");
1277 ret = TlsSetValue(TLS_index0, (LPVOID) 1);
1278 ok(ret, "TlsSetValue failed\n");
1280 ret = TlsSetValue(TLS_index1, (LPVOID) 2);
1281 ok(ret, "TlsSetValue failed\n");
1283 val = TlsGetValue(TLS_index0);
1284 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1285 ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1287 val = TlsGetValue(TLS_index1);
1288 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1289 ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1291 resync_after_run();
1293 if (sync_threads_and_run_one(1, id))
1295 val = TlsGetValue(TLS_index0);
1296 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1297 ok(val == NULL, "TLS slot not initialized correctly\n");
1299 val = TlsGetValue(TLS_index1);
1300 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1301 ok(val == NULL, "TLS slot not initialized correctly\n");
1303 ret = TlsSetValue(TLS_index0, (LPVOID) 3);
1304 ok(ret, "TlsSetValue failed\n");
1306 ret = TlsSetValue(TLS_index1, (LPVOID) 4);
1307 ok(ret, "TlsSetValue failed\n");
1309 val = TlsGetValue(TLS_index0);
1310 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1311 ok(val == (LPVOID) 3, "TLS slot not initialized correctly\n");
1313 val = TlsGetValue(TLS_index1);
1314 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1315 ok(val == (LPVOID) 4, "TLS slot not initialized correctly\n");
1317 resync_after_run();
1319 if (sync_threads_and_run_one(0, id))
1321 HANDLE thread;
1322 DWORD waitret, tid;
1324 val = TlsGetValue(TLS_index0);
1325 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1326 ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1328 val = TlsGetValue(TLS_index1);
1329 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1330 ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1332 thread = CreateThread(NULL, 0, TLS_InheritanceProc, 0, 0, &tid);
1333 ok(thread != NULL, "CreateThread failed\n");
1334 waitret = WaitForSingleObject(thread, 60000);
1335 ok(waitret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
1336 CloseHandle(thread);
1338 ret = TlsFree(TLS_index0);
1339 ok(ret, "TlsFree failed\n");
1341 resync_after_run();
1343 if (sync_threads_and_run_one(1, id))
1345 ret = TlsFree(TLS_index1);
1346 ok(ret, "TlsFree failed\n");
1348 resync_after_run();
1350 return 0;
1353 static void test_TLS(void)
1355 HANDLE threads[2];
1356 LONG_PTR i;
1357 DWORD ret;
1358 BOOL suc;
1360 init_thread_sync_helpers();
1362 /* Allocate a TLS slot in the main thread to test for inheritance. */
1363 TLS_main = TlsAlloc();
1364 ok(TLS_main != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1365 suc = TlsSetValue(TLS_main, (LPVOID) 4114);
1366 ok(suc, "TlsSetValue failed\n");
1368 for (i = 0; i < 2; ++i)
1370 DWORD tid;
1372 threads[i] = CreateThread(NULL, 0, TLS_ThreadProc, (LPVOID) i, 0, &tid);
1373 ok(threads[i] != NULL, "CreateThread failed\n");
1376 ret = WaitForMultipleObjects(2, threads, TRUE, 60000);
1377 ok(ret == WAIT_OBJECT_0 || broken(ret == WAIT_OBJECT_0+1 /* nt4,w2k */), "WaitForAllObjects 2 threads %d\n",ret);
1379 for (i = 0; i < 2; ++i)
1380 CloseHandle(threads[i]);
1382 suc = TlsFree(TLS_main);
1383 ok(suc, "TlsFree failed\n");
1384 cleanup_thread_sync_helpers();
1387 static void test_ThreadErrorMode(void)
1389 DWORD oldmode;
1390 DWORD mode;
1391 DWORD rtlmode;
1392 BOOL ret;
1394 if (!pSetThreadErrorMode || !pGetThreadErrorMode)
1396 win_skip("SetThreadErrorMode and/or GetThreadErrorMode unavailable (added in Windows 7)\n");
1397 return;
1400 if (!pRtlGetThreadErrorMode) {
1401 win_skip("RtlGetThreadErrorMode not available\n");
1402 return;
1405 oldmode = pGetThreadErrorMode();
1407 ret = pSetThreadErrorMode(0, &mode);
1408 ok(ret, "SetThreadErrorMode failed\n");
1409 ok(mode == oldmode,
1410 "SetThreadErrorMode returned old mode 0x%x, expected 0x%x\n",
1411 mode, oldmode);
1412 mode = pGetThreadErrorMode();
1413 ok(mode == 0, "GetThreadErrorMode returned mode 0x%x, expected 0\n", mode);
1414 rtlmode = pRtlGetThreadErrorMode();
1415 ok(rtlmode == 0,
1416 "RtlGetThreadErrorMode returned mode 0x%x, expected 0\n", mode);
1418 ret = pSetThreadErrorMode(SEM_FAILCRITICALERRORS, &mode);
1419 ok(ret, "SetThreadErrorMode failed\n");
1420 ok(mode == 0,
1421 "SetThreadErrorMode returned old mode 0x%x, expected 0\n", mode);
1422 mode = pGetThreadErrorMode();
1423 ok(mode == SEM_FAILCRITICALERRORS,
1424 "GetThreadErrorMode returned mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1425 mode);
1426 rtlmode = pRtlGetThreadErrorMode();
1427 ok(rtlmode == 0x10,
1428 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x10\n", mode);
1430 ret = pSetThreadErrorMode(SEM_NOGPFAULTERRORBOX, &mode);
1431 ok(ret, "SetThreadErrorMode failed\n");
1432 ok(mode == SEM_FAILCRITICALERRORS,
1433 "SetThreadErrorMode returned old mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1434 mode);
1435 mode = pGetThreadErrorMode();
1436 ok(mode == SEM_NOGPFAULTERRORBOX,
1437 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOGPFAULTERRORBOX\n",
1438 mode);
1439 rtlmode = pRtlGetThreadErrorMode();
1440 ok(rtlmode == 0x20,
1441 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x20\n", mode);
1443 ret = pSetThreadErrorMode(SEM_NOOPENFILEERRORBOX, NULL);
1444 ok(ret, "SetThreadErrorMode failed\n");
1445 mode = pGetThreadErrorMode();
1446 ok(mode == SEM_NOOPENFILEERRORBOX,
1447 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOOPENFILEERRORBOX\n",
1448 mode);
1449 rtlmode = pRtlGetThreadErrorMode();
1450 ok(rtlmode == 0x40,
1451 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x40\n", rtlmode);
1453 for (mode = 1; mode; mode <<= 1)
1455 ret = pSetThreadErrorMode(mode, NULL);
1456 if (mode & (SEM_FAILCRITICALERRORS |
1457 SEM_NOGPFAULTERRORBOX |
1458 SEM_NOOPENFILEERRORBOX))
1460 ok(ret,
1461 "SetThreadErrorMode(0x%x,NULL) failed with error %d\n",
1462 mode, GetLastError());
1464 else
1466 DWORD GLE = GetLastError();
1467 ok(!ret,
1468 "SetThreadErrorMode(0x%x,NULL) succeeded, expected failure\n",
1469 mode);
1470 ok(GLE == ERROR_INVALID_PARAMETER,
1471 "SetThreadErrorMode(0x%x,NULL) failed with %d, "
1472 "expected ERROR_INVALID_PARAMETER\n",
1473 mode, GLE);
1477 pSetThreadErrorMode(oldmode, NULL);
1480 #if (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) || (defined(_MSC_VER) && defined(__i386__))
1481 static inline void set_fpu_cw(WORD cw)
1483 #ifdef _MSC_VER
1484 __asm { fnclex }
1485 __asm { fldcw [cw] }
1486 #else
1487 __asm__ volatile ("fnclex; fldcw %0" : : "m" (cw));
1488 #endif
1491 static inline WORD get_fpu_cw(void)
1493 WORD cw = 0;
1494 #ifdef _MSC_VER
1495 __asm { fnstcw [cw] }
1496 #else
1497 __asm__ volatile ("fnstcw %0" : "=m" (cw));
1498 #endif
1499 return cw;
1502 struct fpu_thread_ctx
1504 WORD cw;
1505 HANDLE finished;
1508 static DWORD WINAPI fpu_thread(void *param)
1510 struct fpu_thread_ctx *ctx = param;
1511 BOOL ret;
1513 ctx->cw = get_fpu_cw();
1515 ret = SetEvent(ctx->finished);
1516 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
1518 return 0;
1521 static WORD get_thread_fpu_cw(void)
1523 struct fpu_thread_ctx ctx;
1524 DWORD tid, res;
1525 HANDLE thread;
1527 ctx.finished = CreateEventW(NULL, FALSE, FALSE, NULL);
1528 ok(!!ctx.finished, "Failed to create event, last error %#x.\n", GetLastError());
1530 thread = CreateThread(NULL, 0, fpu_thread, &ctx, 0, &tid);
1531 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
1533 res = WaitForSingleObject(ctx.finished, INFINITE);
1534 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
1536 res = CloseHandle(ctx.finished);
1537 ok(!!res, "Failed to close event handle, last error %#x.\n", GetLastError());
1539 return ctx.cw;
1542 static void test_thread_fpu_cw(void)
1544 WORD initial_cw, cw;
1546 initial_cw = get_fpu_cw();
1547 ok(initial_cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", initial_cw);
1549 cw = get_thread_fpu_cw();
1550 ok(cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", cw);
1552 set_fpu_cw(0xf60);
1553 cw = get_fpu_cw();
1554 ok(cw == 0xf60, "Expected FPU control word 0xf60, got %#x.\n", cw);
1556 cw = get_thread_fpu_cw();
1557 ok(cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", cw);
1559 cw = get_fpu_cw();
1560 ok(cw == 0xf60, "Expected FPU control word 0xf60, got %#x.\n", cw);
1562 set_fpu_cw(initial_cw);
1563 cw = get_fpu_cw();
1564 ok(cw == initial_cw, "Expected FPU control word %#x, got %#x.\n", initial_cw, cw);
1566 #endif
1568 static const char manifest_dep[] =
1569 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
1570 "<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH "\"/>"
1571 " <file name=\"testdep.dll\" />"
1572 "</assembly>";
1574 static const char manifest_main[] =
1575 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
1576 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />"
1577 "<dependency>"
1578 " <dependentAssembly>"
1579 " <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH "\" />"
1580 " </dependentAssembly>"
1581 "</dependency>"
1582 "</assembly>";
1584 static void create_manifest_file(const char *filename, const char *manifest)
1586 WCHAR path[MAX_PATH];
1587 HANDLE file;
1588 DWORD size;
1590 MultiByteToWideChar( CP_ACP, 0, filename, -1, path, MAX_PATH );
1591 file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1592 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
1593 WriteFile(file, manifest, strlen(manifest), &size, NULL);
1594 CloseHandle(file);
1597 static HANDLE test_create(const char *file)
1599 WCHAR path[MAX_PATH];
1600 ACTCTXW actctx;
1601 HANDLE handle;
1603 MultiByteToWideChar(CP_ACP, 0, file, -1, path, MAX_PATH);
1604 memset(&actctx, 0, sizeof(ACTCTXW));
1605 actctx.cbSize = sizeof(ACTCTXW);
1606 actctx.lpSource = path;
1608 handle = pCreateActCtxW(&actctx);
1609 ok(handle != INVALID_HANDLE_VALUE, "failed to create context, error %u\n", GetLastError());
1611 ok(actctx.cbSize == sizeof(actctx), "cbSize=%d\n", actctx.cbSize);
1612 ok(actctx.dwFlags == 0, "dwFlags=%d\n", actctx.dwFlags);
1613 ok(actctx.lpSource == path, "lpSource=%p\n", actctx.lpSource);
1614 ok(actctx.wProcessorArchitecture == 0, "wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture);
1615 ok(actctx.wLangId == 0, "wLangId=%d\n", actctx.wLangId);
1616 ok(actctx.lpAssemblyDirectory == NULL, "lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory);
1617 ok(actctx.lpResourceName == NULL, "lpResourceName=%p\n", actctx.lpResourceName);
1618 ok(actctx.lpApplicationName == NULL, "lpApplicationName=%p\n", actctx.lpApplicationName);
1619 ok(actctx.hModule == NULL, "hModule=%p\n", actctx.hModule);
1621 return handle;
1624 static void test_thread_actctx(void)
1626 struct thread_actctx_param param;
1627 HANDLE thread, handle, context;
1628 ULONG_PTR cookie;
1629 DWORD tid, ret;
1630 BOOL b;
1632 if (!pActivateActCtx)
1634 win_skip("skipping activation context tests\n");
1635 return;
1638 create_manifest_file("testdep1.manifest", manifest_dep);
1639 create_manifest_file("main.manifest", manifest_main);
1641 context = test_create("main.manifest");
1642 DeleteFileA("testdep1.manifest");
1643 DeleteFileA("main.manifest");
1645 handle = (void*)0xdeadbeef;
1646 b = pGetCurrentActCtx(&handle);
1647 ok(b, "GetCurentActCtx failed: %u\n", GetLastError());
1648 ok(handle == 0, "active context %p\n", handle);
1650 /* without active context */
1651 param.thread_context = (void*)0xdeadbeef;
1652 param.handle = NULL;
1653 thread = CreateThread(NULL, 0, thread_actctx_func, &param, 0, &tid);
1654 ok(thread != NULL, "failed, got %u\n", GetLastError());
1656 ret = WaitForSingleObject(thread, 1000);
1657 ok(ret == WAIT_OBJECT_0, "wait timeout\n");
1658 ok(param.thread_context == NULL, "got wrong thread context %p\n", param.thread_context);
1659 CloseHandle(thread);
1661 b = pActivateActCtx(context, &cookie);
1662 ok(b, "activation failed: %u\n", GetLastError());
1664 handle = 0;
1665 b = pGetCurrentActCtx(&handle);
1666 ok(b, "GetCurentActCtx failed: %u\n", GetLastError());
1667 ok(handle != 0, "no active context\n");
1668 pReleaseActCtx(handle);
1670 param.handle = NULL;
1671 b = pGetCurrentActCtx(&param.handle);
1672 ok(b && param.handle != NULL, "failed to get context, %u\n", GetLastError());
1674 param.thread_context = (void*)0xdeadbeef;
1675 thread = CreateThread(NULL, 0, thread_actctx_func, &param, 0, &tid);
1676 ok(thread != NULL, "failed, got %u\n", GetLastError());
1678 ret = WaitForSingleObject(thread, 1000);
1679 ok(ret == WAIT_OBJECT_0, "wait timeout\n");
1680 ok(param.thread_context == context, "got wrong thread context %p, %p\n", param.thread_context, context);
1681 pReleaseActCtx(param.thread_context);
1682 CloseHandle(thread);
1684 /* similar test for CreateRemoteThread() */
1685 param.thread_context = (void*)0xdeadbeef;
1686 thread = CreateRemoteThread(GetCurrentProcess(), NULL, 0, thread_actctx_func, &param, 0, &tid);
1687 ok(thread != NULL, "failed, got %u\n", GetLastError());
1689 ret = WaitForSingleObject(thread, 1000);
1690 ok(ret == WAIT_OBJECT_0, "wait timeout\n");
1691 ok(param.thread_context == context, "got wrong thread context %p, %p\n", param.thread_context, context);
1692 pReleaseActCtx(param.thread_context);
1693 CloseHandle(thread);
1695 pReleaseActCtx(param.handle);
1697 b = pDeactivateActCtx(0, cookie);
1698 ok(b, "DeactivateActCtx failed: %u\n", GetLastError());
1699 pReleaseActCtx(context);
1703 static void WINAPI threadpool_workcallback(PTP_CALLBACK_INSTANCE instance, void *context, PTP_WORK work) {
1704 int *foo = (int*)context;
1706 (*foo)++;
1710 static void test_threadpool(void)
1712 PTP_POOL pool;
1713 PTP_WORK work;
1714 int workcalled = 0;
1716 if (!pCreateThreadpool) {
1717 win_skip("thread pool apis not supported.\n");
1718 return;
1721 work = pCreateThreadpoolWork(threadpool_workcallback, &workcalled, NULL);
1722 ok (work != NULL, "Error %d in CreateThreadpoolWork\n", GetLastError());
1723 pSubmitThreadpoolWork(work);
1724 pWaitForThreadpoolWorkCallbacks(work, FALSE);
1725 pCloseThreadpoolWork(work);
1727 ok (workcalled == 1, "expected work to be called once, got %d\n", workcalled);
1729 pool = pCreateThreadpool(NULL);
1730 ok (pool != NULL, "CreateThreadpool failed\n");
1731 pCloseThreadpool(pool);
1734 static void test_reserved_tls(void)
1736 void *val;
1737 DWORD tls;
1738 BOOL ret;
1740 /* This seems to be a WinXP SP2+ feature. */
1741 if(!pIsWow64Process) {
1742 win_skip("Skipping reserved TLS slot on too old Windows.\n");
1743 return;
1746 val = TlsGetValue(0);
1747 ok(!val, "TlsGetValue(0) = %p\n", val);
1749 /* Also make sure that there is a TLS allocated. */
1750 tls = TlsAlloc();
1751 ok(tls && tls != TLS_OUT_OF_INDEXES, "tls = %x\n", tls);
1752 TlsSetValue(tls, (void*)1);
1754 val = TlsGetValue(0);
1755 ok(!val, "TlsGetValue(0) = %p\n", val);
1757 TlsFree(tls);
1759 /* The following is too ugly to be run by default */
1760 if(0) {
1761 /* Set TLS index 0 value and see that this works and doesn't cause problems
1762 * for remaining tests. */
1763 ret = TlsSetValue(0, (void*)1);
1764 ok(ret, "TlsSetValue(0, 1) failed: %u\n", GetLastError());
1766 val = TlsGetValue(0);
1767 ok(val == (void*)1, "TlsGetValue(0) = %p\n", val);
1771 static void test_thread_info(void)
1773 char buf[4096];
1774 static const ULONG info_size[] =
1776 sizeof(THREAD_BASIC_INFORMATION), /* ThreadBasicInformation */
1777 sizeof(KERNEL_USER_TIMES), /* ThreadTimes */
1778 sizeof(ULONG), /* ThreadPriority */
1779 sizeof(ULONG), /* ThreadBasePriority */
1780 sizeof(ULONG_PTR), /* ThreadAffinityMask */
1781 sizeof(HANDLE), /* ThreadImpersonationToken */
1782 sizeof(THREAD_DESCRIPTOR_INFORMATION), /* ThreadDescriptorTableEntry */
1783 sizeof(BOOLEAN), /* ThreadEnableAlignmentFaultFixup */
1784 0, /* ThreadEventPair_Reusable */
1785 sizeof(ULONG_PTR), /* ThreadQuerySetWin32StartAddress */
1786 sizeof(ULONG), /* ThreadZeroTlsCell */
1787 sizeof(LARGE_INTEGER), /* ThreadPerformanceCount */
1788 sizeof(ULONG), /* ThreadAmILastThread */
1789 sizeof(ULONG), /* ThreadIdealProcessor */
1790 sizeof(ULONG), /* ThreadPriorityBoost */
1791 sizeof(ULONG_PTR), /* ThreadSetTlsArrayAddress */
1792 sizeof(ULONG), /* ThreadIsIoPending */
1793 sizeof(BOOLEAN), /* ThreadHideFromDebugger */
1794 /* FIXME: Add remaining classes */
1796 HANDLE thread;
1797 ULONG i, status, ret_len;
1799 if (!pOpenThread)
1801 win_skip("OpenThread is not available on this platform\n");
1802 return;
1805 if (!pNtQueryInformationThread)
1807 win_skip("NtQueryInformationThread is not available on this platform\n");
1808 return;
1811 thread = pOpenThread(THREAD_QUERY_LIMITED_INFORMATION, FALSE, GetCurrentThreadId());
1812 if (!thread)
1814 win_skip("THREAD_QUERY_LIMITED_INFORMATION is not supported on this platform\n");
1815 return;
1818 for (i = 0; i < sizeof(info_size)/sizeof(info_size[0]); i++)
1820 memset(buf, 0, sizeof(buf));
1822 #ifdef __i386__
1823 if (i == ThreadDescriptorTableEntry)
1825 CONTEXT ctx;
1826 THREAD_DESCRIPTOR_INFORMATION *tdi = (void *)buf;
1828 ctx.ContextFlags = CONTEXT_SEGMENTS;
1829 GetThreadContext(GetCurrentThread(), &ctx);
1830 tdi->Selector = ctx.SegDs;
1832 #endif
1833 ret_len = 0;
1834 status = pNtQueryInformationThread(thread, i, buf, info_size[i], &ret_len);
1835 if (status == STATUS_NOT_IMPLEMENTED) continue;
1836 if (status == STATUS_INVALID_INFO_CLASS) continue;
1837 if (status == STATUS_UNSUCCESSFUL) continue;
1839 switch (i)
1841 case ThreadBasicInformation:
1842 case ThreadAmILastThread:
1843 case ThreadPriorityBoost:
1844 ok(status == STATUS_SUCCESS, "for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i, status, ret_len);
1845 break;
1847 #ifdef __i386__
1848 case ThreadDescriptorTableEntry:
1849 ok(status == STATUS_SUCCESS || broken(status == STATUS_ACCESS_DENIED) /* testbot VM is broken */,
1850 "for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i, status, ret_len);
1851 break;
1852 #endif
1854 case ThreadTimes:
1855 todo_wine
1856 ok(status == STATUS_SUCCESS, "for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i, status, ret_len);
1857 break;
1859 case ThreadAffinityMask:
1860 case ThreadQuerySetWin32StartAddress:
1861 todo_wine
1862 ok(status == STATUS_ACCESS_DENIED, "for info %u expected STATUS_ACCESS_DENIED, got %08x (ret_len %u)\n", i, status, ret_len);
1863 break;
1865 default:
1866 ok(status == STATUS_ACCESS_DENIED, "for info %u expected STATUS_ACCESS_DENIED, got %08x (ret_len %u)\n", i, status, ret_len);
1867 break;
1871 CloseHandle(thread);
1874 static void init_funcs(void)
1876 HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
1877 HMODULE ntdll = GetModuleHandleA("ntdll.dll");
1879 /* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
1880 so that the compile passes */
1882 #define X(f) p##f = (void*)GetProcAddress(hKernel32, #f)
1883 X(GetThreadPriorityBoost);
1884 X(OpenThread);
1885 X(QueueUserWorkItem);
1886 X(SetThreadIdealProcessor);
1887 X(SetThreadPriorityBoost);
1888 X(RegisterWaitForSingleObject);
1889 X(UnregisterWait);
1890 X(IsWow64Process);
1891 X(SetThreadErrorMode);
1892 X(GetThreadErrorMode);
1893 X(ActivateActCtx);
1894 X(CreateActCtxW);
1895 X(DeactivateActCtx);
1896 X(GetCurrentActCtx);
1897 X(ReleaseActCtx);
1899 X(CreateThreadpool);
1900 X(CloseThreadpool);
1901 X(CreateThreadpoolWork);
1902 X(SubmitThreadpoolWork);
1903 X(WaitForThreadpoolWorkCallbacks);
1904 X(CloseThreadpoolWork);
1906 X(GetThreadGroupAffinity);
1907 X(SetThreadGroupAffinity);
1908 #undef X
1910 #define X(f) p##f = (void*)GetProcAddress(ntdll, #f)
1911 if (ntdll)
1913 X(NtQueryInformationThread);
1914 X(RtlGetThreadErrorMode);
1915 X(NtSetInformationThread);
1917 #undef X
1920 START_TEST(thread)
1922 int argc;
1923 char **argv;
1924 argc = winetest_get_mainargs( &argv );
1926 init_funcs();
1928 if (argc >= 3)
1930 if (!strcmp(argv[2], "sleep"))
1932 HANDLE hAddrEvents[2];
1933 create_function_addr_events(hAddrEvents);
1934 SetEvent(hAddrEvents[0]);
1935 SetEvent(hAddrEvents[1]);
1936 Sleep(5000); /* spawned process runs for at most 5 seconds */
1937 return;
1939 while (1)
1941 HANDLE hThread;
1942 DWORD tid;
1943 hThread = CreateThread(NULL, 0, threadFunc2, NULL, 0, &tid);
1944 ok(hThread != NULL, "CreateThread failed, error %u\n",
1945 GetLastError());
1946 ok(WaitForSingleObject(hThread, 200) == WAIT_OBJECT_0,
1947 "Thread did not exit in time\n");
1948 if (hThread == NULL) break;
1949 CloseHandle(hThread);
1951 return;
1954 test_thread_info();
1955 test_reserved_tls();
1956 test_CreateRemoteThread();
1957 test_CreateThread_basic();
1958 test_CreateThread_suspended();
1959 test_SuspendThread();
1960 test_TerminateThread();
1961 test_CreateThread_stack();
1962 test_thread_priority();
1963 test_GetThreadTimes();
1964 test_thread_processor();
1965 test_GetThreadExitCode();
1966 #ifdef __i386__
1967 test_SetThreadContext();
1968 #endif
1969 test_QueueUserWorkItem();
1970 test_RegisterWaitForSingleObject();
1971 test_TLS();
1972 test_ThreadErrorMode();
1973 #if (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) || (defined(_MSC_VER) && defined(__i386__))
1974 test_thread_fpu_cw();
1975 #endif
1976 test_thread_actctx();
1978 test_threadpool();