kernel32/tests: Allow ERROR_ACCESS_DENIED for GetThreadContext.
[wine.git] / dlls / kernel32 / tests / thread.c
blob001128b466f63a67528f295eeb9c7a806acb7ae0
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) || (GetLastError() == ERROR_ACCESS_DENIED))) ||
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 or ERROR_ACCESS_DENIED)\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 static void test_GetThreadSelectorEntry(void)
1105 LDT_ENTRY entry;
1106 CONTEXT ctx;
1107 DWORD limit;
1108 void *base;
1109 BOOL ret;
1111 memset(&ctx, 0x11, sizeof(ctx));
1112 ctx.ContextFlags = CONTEXT_SEGMENTS | CONTEXT_CONTROL;
1113 ret = GetThreadContext(GetCurrentThread(), &ctx);
1114 ok(ret, "GetThreadContext error %u\n", GetLastError());
1115 ok(!HIWORD(ctx.SegCs), "expected HIWORD(SegCs) == 0, got %u\n", ctx.SegCs);
1116 ok(!HIWORD(ctx.SegDs), "expected HIWORD(SegDs) == 0, got %u\n", ctx.SegDs);
1117 ok(!HIWORD(ctx.SegFs), "expected HIWORD(SegFs) == 0, got %u\n", ctx.SegFs);
1119 ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegCs, &entry);
1120 ok(ret, "GetThreadSelectorEntry(SegCs) error %u\n", GetLastError());
1121 ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegDs, &entry);
1122 ok(ret, "GetThreadSelectorEntry(SegDs) error %u\n", GetLastError());
1124 memset(&entry, 0x11, sizeof(entry));
1125 ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegFs, &entry);
1126 ok(ret, "GetThreadSelectorEntry(SegFs) error %u\n", GetLastError());
1127 entry.HighWord.Bits.Type &= ~1; /* ignore accessed bit */
1129 base = (void *)((entry.HighWord.Bits.BaseHi << 24) | (entry.HighWord.Bits.BaseMid << 16) | entry.BaseLow);
1130 limit = (entry.HighWord.Bits.LimitHi << 16) | entry.LimitLow;
1132 ok(base == NtCurrentTeb(), "expected %p, got %p\n", NtCurrentTeb(), base);
1133 ok(limit == 0x0fff || limit == 0x4000, "expected 0x0fff or 0x4000, got %#x\n", limit);
1134 ok(entry.HighWord.Bits.Type == 0x12, "expected 0x12, got %#x\n", entry.HighWord.Bits.Type);
1135 ok(entry.HighWord.Bits.Dpl == 3, "expected 3, got %u\n", entry.HighWord.Bits.Dpl);
1136 ok(entry.HighWord.Bits.Pres == 1, "expected 1, got %u\n", entry.HighWord.Bits.Pres);
1137 ok(entry.HighWord.Bits.Sys == 0, "expected 0, got %u\n", entry.HighWord.Bits.Sys);
1138 ok(entry.HighWord.Bits.Reserved_0 == 0, "expected 0, got %u\n", entry.HighWord.Bits.Reserved_0);
1139 ok(entry.HighWord.Bits.Default_Big == 1, "expected 1, got %u\n", entry.HighWord.Bits.Default_Big);
1140 ok(entry.HighWord.Bits.Granularity == 0, "expected 0, got %u\n", entry.HighWord.Bits.Granularity);
1143 #endif /* __i386__ */
1145 static HANDLE finish_event;
1146 static LONG times_executed;
1148 static DWORD CALLBACK work_function(void *p)
1150 LONG executed = InterlockedIncrement(&times_executed);
1152 if (executed == 100)
1153 SetEvent(finish_event);
1154 return 0;
1157 static void test_QueueUserWorkItem(void)
1159 INT_PTR i;
1160 DWORD wait_result;
1161 DWORD before, after;
1163 /* QueueUserWorkItem not present on win9x */
1164 if (!pQueueUserWorkItem) return;
1166 finish_event = CreateEventW(NULL, TRUE, FALSE, NULL);
1168 before = GetTickCount();
1170 for (i = 0; i < 100; i++)
1172 BOOL ret = pQueueUserWorkItem(work_function, (void *)i, WT_EXECUTEDEFAULT);
1173 ok(ret, "QueueUserWorkItem failed with error %d\n", GetLastError());
1176 wait_result = WaitForSingleObject(finish_event, 10000);
1178 after = GetTickCount();
1179 trace("100 QueueUserWorkItem calls took %dms\n", after - before);
1180 ok(wait_result == WAIT_OBJECT_0, "wait failed with error 0x%x\n", wait_result);
1182 ok(times_executed == 100, "didn't execute all of the work items\n");
1185 static void CALLBACK signaled_function(PVOID p, BOOLEAN TimerOrWaitFired)
1187 HANDLE event = p;
1188 SetEvent(event);
1189 ok(!TimerOrWaitFired, "wait shouldn't have timed out\n");
1192 static void CALLBACK timeout_function(PVOID p, BOOLEAN TimerOrWaitFired)
1194 HANDLE event = p;
1195 SetEvent(event);
1196 ok(TimerOrWaitFired, "wait should have timed out\n");
1199 static void test_RegisterWaitForSingleObject(void)
1201 BOOL ret;
1202 HANDLE wait_handle;
1203 HANDLE handle;
1204 HANDLE complete_event;
1206 if (!pRegisterWaitForSingleObject || !pUnregisterWait)
1208 win_skip("RegisterWaitForSingleObject or UnregisterWait not implemented\n");
1209 return;
1212 /* test signaled case */
1214 handle = CreateEventW(NULL, TRUE, TRUE, NULL);
1215 complete_event = CreateEventW(NULL, FALSE, FALSE, NULL);
1217 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1218 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1220 WaitForSingleObject(complete_event, INFINITE);
1221 /* give worker thread chance to complete */
1222 Sleep(100);
1224 ret = pUnregisterWait(wait_handle);
1225 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1227 /* test cancel case */
1229 ResetEvent(handle);
1231 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1232 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1234 ret = pUnregisterWait(wait_handle);
1235 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1237 /* test timeout case */
1239 ret = pRegisterWaitForSingleObject(&wait_handle, handle, timeout_function, complete_event, 0, WT_EXECUTEONLYONCE);
1240 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1242 WaitForSingleObject(complete_event, INFINITE);
1243 /* give worker thread chance to complete */
1244 Sleep(100);
1246 ret = pUnregisterWait(wait_handle);
1247 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1249 SetLastError(0xdeadbeef);
1250 ret = pUnregisterWait(NULL);
1251 ok(!ret, "Expected UnregisterWait to fail\n");
1252 ok(GetLastError() == ERROR_INVALID_HANDLE,
1253 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1256 static DWORD LS_main;
1257 static DWORD LS_index0, LS_index1;
1258 static DWORD LS_OutOfIndexesValue;
1260 /* Function pointers to the FLS/TLS functions to test in LS_ThreadProc() */
1261 static DWORD (WINAPI *LS_AllocFunc)(void);
1262 static PVOID (WINAPI *LS_GetValueFunc)(DWORD);
1263 static BOOL (WINAPI *LS_SetValueFunc)(DWORD, PVOID);
1264 static BOOL (WINAPI *LS_FreeFunc)(DWORD);
1266 /* Names of the functions tested in LS_ThreadProc(), for error messages */
1267 static const char* LS_AllocFuncName = "";
1268 static const char* LS_GetValueFuncName = "";
1269 static const char* LS_SetValueFuncName = "";
1270 static const char* LS_FreeFuncName = "";
1272 /* FLS entry points, dynamically loaded in platforms that support them */
1273 static DWORD (WINAPI *pFlsAlloc)(PFLS_CALLBACK_FUNCTION);
1274 static BOOL (WINAPI *pFlsFree)(DWORD);
1275 static PVOID (WINAPI *pFlsGetValue)(DWORD);
1276 static BOOL (WINAPI *pFlsSetValue)(DWORD,PVOID);
1278 /* A thunk function to make FlsAlloc compatible with the signature of TlsAlloc */
1279 static DWORD WINAPI FLS_AllocFuncThunk(void)
1281 return pFlsAlloc(NULL);
1284 static DWORD WINAPI LS_InheritanceProc(LPVOID p)
1286 /* We should NOT inherit the FLS/TLS values from our parent or from the
1287 main thread. */
1288 LPVOID val;
1290 val = LS_GetValueFunc(LS_main);
1291 ok(val == NULL, "%s inheritance failed\n", LS_GetValueFuncName);
1293 val = LS_GetValueFunc(LS_index0);
1294 ok(val == NULL, "%s inheritance failed\n", LS_GetValueFuncName);
1296 val = LS_GetValueFunc(LS_index1);
1297 ok(val == NULL, "%s inheritance failed\n", LS_GetValueFuncName);
1299 return 0;
1302 /* Basic FLS/TLS usage test. Make sure we can create slots and the values we
1303 store in them are separate among threads. Also test FLS/TLS value
1304 inheritance with LS_InheritanceProc. */
1305 static DWORD WINAPI LS_ThreadProc(LPVOID p)
1307 LONG_PTR id = (LONG_PTR) p;
1308 LPVOID val;
1309 BOOL ret;
1311 if (sync_threads_and_run_one(0, id))
1313 LS_index0 = LS_AllocFunc();
1314 ok(LS_index0 != LS_OutOfIndexesValue, "%s failed\n", LS_AllocFuncName);
1316 resync_after_run();
1318 if (sync_threads_and_run_one(1, id))
1320 LS_index1 = LS_AllocFunc();
1321 ok(LS_index1 != LS_OutOfIndexesValue, "%s failed\n", LS_AllocFuncName);
1323 /* Slot indices should be different even if created in different
1324 threads. */
1325 ok(LS_index0 != LS_index1, "%s failed\n", LS_AllocFuncName);
1327 /* Both slots should be initialized to NULL */
1328 val = LS_GetValueFunc(LS_index0);
1329 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1330 ok(val == NULL, "Slot not initialized correctly\n");
1332 val = LS_GetValueFunc(LS_index1);
1333 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1334 ok(val == NULL, "Slot not initialized correctly\n");
1336 resync_after_run();
1338 if (sync_threads_and_run_one(0, id))
1340 val = LS_GetValueFunc(LS_index0);
1341 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1342 ok(val == NULL, "Slot not initialized correctly\n");
1344 val = LS_GetValueFunc(LS_index1);
1345 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1346 ok(val == NULL, "Slot not initialized correctly\n");
1348 ret = LS_SetValueFunc(LS_index0, (LPVOID) 1);
1349 ok(ret, "%s failed\n", LS_SetValueFuncName);
1351 ret = LS_SetValueFunc(LS_index1, (LPVOID) 2);
1352 ok(ret, "%s failed\n", LS_SetValueFuncName);
1354 val = LS_GetValueFunc(LS_index0);
1355 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1356 ok(val == (LPVOID) 1, "Slot not initialized correctly\n");
1358 val = LS_GetValueFunc(LS_index1);
1359 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1360 ok(val == (LPVOID) 2, "Slot not initialized correctly\n");
1362 resync_after_run();
1364 if (sync_threads_and_run_one(1, id))
1366 val = LS_GetValueFunc(LS_index0);
1367 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1368 ok(val == NULL, "Slot not initialized correctly\n");
1370 val = LS_GetValueFunc(LS_index1);
1371 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1372 ok(val == NULL, "Slot not initialized correctly\n");
1374 ret = LS_SetValueFunc(LS_index0, (LPVOID) 3);
1375 ok(ret, "%s failed\n", LS_SetValueFuncName);
1377 ret = LS_SetValueFunc(LS_index1, (LPVOID) 4);
1378 ok(ret, "%s failed\n", LS_SetValueFuncName);
1380 val = LS_GetValueFunc(LS_index0);
1381 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1382 ok(val == (LPVOID) 3, "Slot not initialized correctly\n");
1384 val = LS_GetValueFunc(LS_index1);
1385 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1386 ok(val == (LPVOID) 4, "Slot not initialized correctly\n");
1388 resync_after_run();
1390 if (sync_threads_and_run_one(0, id))
1392 HANDLE thread;
1393 DWORD waitret, tid;
1395 val = LS_GetValueFunc(LS_index0);
1396 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1397 ok(val == (LPVOID) 1, "Slot not initialized correctly\n");
1399 val = LS_GetValueFunc(LS_index1);
1400 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1401 ok(val == (LPVOID) 2, "Slot not initialized correctly\n");
1403 thread = CreateThread(NULL, 0, LS_InheritanceProc, 0, 0, &tid);
1404 ok(thread != NULL, "CreateThread failed\n");
1405 waitret = WaitForSingleObject(thread, 60000);
1406 ok(waitret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
1407 CloseHandle(thread);
1409 ret = LS_FreeFunc(LS_index0);
1410 ok(ret, "%s failed\n", LS_FreeFuncName);
1412 resync_after_run();
1414 if (sync_threads_and_run_one(1, id))
1416 ret = LS_FreeFunc(LS_index1);
1417 ok(ret, "%s failed\n", LS_FreeFuncName);
1419 resync_after_run();
1421 return 0;
1424 static void run_LS_tests(void)
1426 HANDLE threads[2];
1427 LONG_PTR i;
1428 DWORD ret;
1429 BOOL suc;
1431 init_thread_sync_helpers();
1433 /* Allocate a slot in the main thread to test for inheritance. */
1434 LS_main = LS_AllocFunc();
1435 ok(LS_main != LS_OutOfIndexesValue, "%s failed\n", LS_AllocFuncName);
1436 suc = LS_SetValueFunc(LS_main, (LPVOID) 4114);
1437 ok(suc, "%s failed\n", LS_SetValueFuncName);
1439 for (i = 0; i < 2; ++i)
1441 DWORD tid;
1443 threads[i] = CreateThread(NULL, 0, LS_ThreadProc, (LPVOID) i, 0, &tid);
1444 ok(threads[i] != NULL, "CreateThread failed\n");
1447 ret = WaitForMultipleObjects(2, threads, TRUE, 60000);
1448 ok(ret == WAIT_OBJECT_0 || broken(ret == WAIT_OBJECT_0+1 /* nt4,w2k */), "WaitForAllObjects 2 threads %d\n",ret);
1450 for (i = 0; i < 2; ++i)
1451 CloseHandle(threads[i]);
1453 suc = LS_FreeFunc(LS_main);
1454 ok(suc, "%s failed\n", LS_FreeFuncName);
1455 cleanup_thread_sync_helpers();
1458 static void test_TLS(void)
1460 LS_OutOfIndexesValue = TLS_OUT_OF_INDEXES;
1462 LS_AllocFunc = &TlsAlloc;
1463 LS_GetValueFunc = &TlsGetValue;
1464 LS_SetValueFunc = &TlsSetValue;
1465 LS_FreeFunc = &TlsFree;
1467 LS_AllocFuncName = "TlsAlloc";
1468 LS_GetValueFuncName = "TlsGetValue";
1469 LS_SetValueFuncName = "TlsSetValue";
1470 LS_FreeFuncName = "TlsFree";
1472 run_LS_tests();
1475 static void test_FLS(void)
1477 if (!pFlsAlloc || !pFlsFree || !pFlsGetValue || !pFlsSetValue)
1479 win_skip("Fiber Local Storage not supported\n");
1480 return;
1483 LS_OutOfIndexesValue = FLS_OUT_OF_INDEXES;
1485 LS_AllocFunc = &FLS_AllocFuncThunk;
1486 LS_GetValueFunc = pFlsGetValue;
1487 LS_SetValueFunc = pFlsSetValue;
1488 LS_FreeFunc = pFlsFree;
1490 LS_AllocFuncName = "FlsAlloc";
1491 LS_GetValueFuncName = "FlsGetValue";
1492 LS_SetValueFuncName = "FlsSetValue";
1493 LS_FreeFuncName = "FlsFree";
1495 run_LS_tests();
1498 static void test_ThreadErrorMode(void)
1500 DWORD oldmode;
1501 DWORD mode;
1502 DWORD rtlmode;
1503 BOOL ret;
1505 if (!pSetThreadErrorMode || !pGetThreadErrorMode)
1507 win_skip("SetThreadErrorMode and/or GetThreadErrorMode unavailable (added in Windows 7)\n");
1508 return;
1511 if (!pRtlGetThreadErrorMode) {
1512 win_skip("RtlGetThreadErrorMode not available\n");
1513 return;
1516 oldmode = pGetThreadErrorMode();
1518 ret = pSetThreadErrorMode(0, &mode);
1519 ok(ret, "SetThreadErrorMode failed\n");
1520 ok(mode == oldmode,
1521 "SetThreadErrorMode returned old mode 0x%x, expected 0x%x\n",
1522 mode, oldmode);
1523 mode = pGetThreadErrorMode();
1524 ok(mode == 0, "GetThreadErrorMode returned mode 0x%x, expected 0\n", mode);
1525 rtlmode = pRtlGetThreadErrorMode();
1526 ok(rtlmode == 0,
1527 "RtlGetThreadErrorMode returned mode 0x%x, expected 0\n", mode);
1529 ret = pSetThreadErrorMode(SEM_FAILCRITICALERRORS, &mode);
1530 ok(ret, "SetThreadErrorMode failed\n");
1531 ok(mode == 0,
1532 "SetThreadErrorMode returned old mode 0x%x, expected 0\n", mode);
1533 mode = pGetThreadErrorMode();
1534 ok(mode == SEM_FAILCRITICALERRORS,
1535 "GetThreadErrorMode returned mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1536 mode);
1537 rtlmode = pRtlGetThreadErrorMode();
1538 ok(rtlmode == 0x10,
1539 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x10\n", mode);
1541 ret = pSetThreadErrorMode(SEM_NOGPFAULTERRORBOX, &mode);
1542 ok(ret, "SetThreadErrorMode failed\n");
1543 ok(mode == SEM_FAILCRITICALERRORS,
1544 "SetThreadErrorMode returned old mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1545 mode);
1546 mode = pGetThreadErrorMode();
1547 ok(mode == SEM_NOGPFAULTERRORBOX,
1548 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOGPFAULTERRORBOX\n",
1549 mode);
1550 rtlmode = pRtlGetThreadErrorMode();
1551 ok(rtlmode == 0x20,
1552 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x20\n", mode);
1554 ret = pSetThreadErrorMode(SEM_NOOPENFILEERRORBOX, NULL);
1555 ok(ret, "SetThreadErrorMode failed\n");
1556 mode = pGetThreadErrorMode();
1557 ok(mode == SEM_NOOPENFILEERRORBOX,
1558 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOOPENFILEERRORBOX\n",
1559 mode);
1560 rtlmode = pRtlGetThreadErrorMode();
1561 ok(rtlmode == 0x40,
1562 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x40\n", rtlmode);
1564 for (mode = 1; mode; mode <<= 1)
1566 ret = pSetThreadErrorMode(mode, NULL);
1567 if (mode & (SEM_FAILCRITICALERRORS |
1568 SEM_NOGPFAULTERRORBOX |
1569 SEM_NOOPENFILEERRORBOX))
1571 ok(ret,
1572 "SetThreadErrorMode(0x%x,NULL) failed with error %d\n",
1573 mode, GetLastError());
1575 else
1577 DWORD GLE = GetLastError();
1578 ok(!ret,
1579 "SetThreadErrorMode(0x%x,NULL) succeeded, expected failure\n",
1580 mode);
1581 ok(GLE == ERROR_INVALID_PARAMETER,
1582 "SetThreadErrorMode(0x%x,NULL) failed with %d, "
1583 "expected ERROR_INVALID_PARAMETER\n",
1584 mode, GLE);
1588 pSetThreadErrorMode(oldmode, NULL);
1591 #if (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) || (defined(_MSC_VER) && defined(__i386__))
1592 static inline void set_fpu_cw(WORD cw)
1594 #ifdef _MSC_VER
1595 __asm { fnclex }
1596 __asm { fldcw [cw] }
1597 #else
1598 __asm__ volatile ("fnclex; fldcw %0" : : "m" (cw));
1599 #endif
1602 static inline WORD get_fpu_cw(void)
1604 WORD cw = 0;
1605 #ifdef _MSC_VER
1606 __asm { fnstcw [cw] }
1607 #else
1608 __asm__ volatile ("fnstcw %0" : "=m" (cw));
1609 #endif
1610 return cw;
1613 struct fpu_thread_ctx
1615 WORD cw;
1616 HANDLE finished;
1619 static DWORD WINAPI fpu_thread(void *param)
1621 struct fpu_thread_ctx *ctx = param;
1622 BOOL ret;
1624 ctx->cw = get_fpu_cw();
1626 ret = SetEvent(ctx->finished);
1627 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
1629 return 0;
1632 static WORD get_thread_fpu_cw(void)
1634 struct fpu_thread_ctx ctx;
1635 DWORD tid, res;
1636 HANDLE thread;
1638 ctx.finished = CreateEventW(NULL, FALSE, FALSE, NULL);
1639 ok(!!ctx.finished, "Failed to create event, last error %#x.\n", GetLastError());
1641 thread = CreateThread(NULL, 0, fpu_thread, &ctx, 0, &tid);
1642 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
1644 res = WaitForSingleObject(ctx.finished, INFINITE);
1645 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
1647 res = CloseHandle(ctx.finished);
1648 ok(!!res, "Failed to close event handle, last error %#x.\n", GetLastError());
1650 return ctx.cw;
1653 static void test_thread_fpu_cw(void)
1655 WORD initial_cw, cw;
1657 initial_cw = get_fpu_cw();
1658 ok(initial_cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", initial_cw);
1660 cw = get_thread_fpu_cw();
1661 ok(cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", cw);
1663 set_fpu_cw(0xf60);
1664 cw = get_fpu_cw();
1665 ok(cw == 0xf60, "Expected FPU control word 0xf60, got %#x.\n", cw);
1667 cw = get_thread_fpu_cw();
1668 ok(cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", cw);
1670 cw = get_fpu_cw();
1671 ok(cw == 0xf60, "Expected FPU control word 0xf60, got %#x.\n", cw);
1673 set_fpu_cw(initial_cw);
1674 cw = get_fpu_cw();
1675 ok(cw == initial_cw, "Expected FPU control word %#x, got %#x.\n", initial_cw, cw);
1677 #endif
1679 static const char manifest_dep[] =
1680 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
1681 "<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH "\"/>"
1682 " <file name=\"testdep.dll\" />"
1683 "</assembly>";
1685 static const char manifest_main[] =
1686 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
1687 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />"
1688 "<dependency>"
1689 " <dependentAssembly>"
1690 " <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH "\" />"
1691 " </dependentAssembly>"
1692 "</dependency>"
1693 "</assembly>";
1695 static void create_manifest_file(const char *filename, const char *manifest)
1697 WCHAR path[MAX_PATH];
1698 HANDLE file;
1699 DWORD size;
1701 MultiByteToWideChar( CP_ACP, 0, filename, -1, path, MAX_PATH );
1702 file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1703 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
1704 WriteFile(file, manifest, strlen(manifest), &size, NULL);
1705 CloseHandle(file);
1708 static HANDLE test_create(const char *file)
1710 WCHAR path[MAX_PATH];
1711 ACTCTXW actctx;
1712 HANDLE handle;
1714 MultiByteToWideChar(CP_ACP, 0, file, -1, path, MAX_PATH);
1715 memset(&actctx, 0, sizeof(ACTCTXW));
1716 actctx.cbSize = sizeof(ACTCTXW);
1717 actctx.lpSource = path;
1719 handle = pCreateActCtxW(&actctx);
1720 ok(handle != INVALID_HANDLE_VALUE, "failed to create context, error %u\n", GetLastError());
1722 ok(actctx.cbSize == sizeof(actctx), "cbSize=%d\n", actctx.cbSize);
1723 ok(actctx.dwFlags == 0, "dwFlags=%d\n", actctx.dwFlags);
1724 ok(actctx.lpSource == path, "lpSource=%p\n", actctx.lpSource);
1725 ok(actctx.wProcessorArchitecture == 0, "wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture);
1726 ok(actctx.wLangId == 0, "wLangId=%d\n", actctx.wLangId);
1727 ok(actctx.lpAssemblyDirectory == NULL, "lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory);
1728 ok(actctx.lpResourceName == NULL, "lpResourceName=%p\n", actctx.lpResourceName);
1729 ok(actctx.lpApplicationName == NULL, "lpApplicationName=%p\n", actctx.lpApplicationName);
1730 ok(actctx.hModule == NULL, "hModule=%p\n", actctx.hModule);
1732 return handle;
1735 static void test_thread_actctx(void)
1737 struct thread_actctx_param param;
1738 HANDLE thread, handle, context;
1739 ULONG_PTR cookie;
1740 DWORD tid, ret;
1741 BOOL b;
1743 if (!pActivateActCtx)
1745 win_skip("skipping activation context tests\n");
1746 return;
1749 create_manifest_file("testdep1.manifest", manifest_dep);
1750 create_manifest_file("main.manifest", manifest_main);
1752 context = test_create("main.manifest");
1753 DeleteFileA("testdep1.manifest");
1754 DeleteFileA("main.manifest");
1756 handle = (void*)0xdeadbeef;
1757 b = pGetCurrentActCtx(&handle);
1758 ok(b, "GetCurrentActCtx failed: %u\n", GetLastError());
1759 ok(handle == 0, "active context %p\n", handle);
1761 /* without active context */
1762 param.thread_context = (void*)0xdeadbeef;
1763 param.handle = NULL;
1764 thread = CreateThread(NULL, 0, thread_actctx_func, &param, 0, &tid);
1765 ok(thread != NULL, "failed, got %u\n", GetLastError());
1767 ret = WaitForSingleObject(thread, 1000);
1768 ok(ret == WAIT_OBJECT_0, "wait timeout\n");
1769 ok(param.thread_context == NULL, "got wrong thread context %p\n", param.thread_context);
1770 CloseHandle(thread);
1772 b = pActivateActCtx(context, &cookie);
1773 ok(b, "activation failed: %u\n", GetLastError());
1775 handle = 0;
1776 b = pGetCurrentActCtx(&handle);
1777 ok(b, "GetCurrentActCtx failed: %u\n", GetLastError());
1778 ok(handle != 0, "no active context\n");
1779 pReleaseActCtx(handle);
1781 param.handle = NULL;
1782 b = pGetCurrentActCtx(&param.handle);
1783 ok(b && param.handle != NULL, "failed to get context, %u\n", GetLastError());
1785 param.thread_context = (void*)0xdeadbeef;
1786 thread = CreateThread(NULL, 0, thread_actctx_func, &param, 0, &tid);
1787 ok(thread != NULL, "failed, got %u\n", GetLastError());
1789 ret = WaitForSingleObject(thread, 1000);
1790 ok(ret == WAIT_OBJECT_0, "wait timeout\n");
1791 ok(param.thread_context == context, "got wrong thread context %p, %p\n", param.thread_context, context);
1792 pReleaseActCtx(param.thread_context);
1793 CloseHandle(thread);
1795 /* similar test for CreateRemoteThread() */
1796 param.thread_context = (void*)0xdeadbeef;
1797 thread = CreateRemoteThread(GetCurrentProcess(), NULL, 0, thread_actctx_func, &param, 0, &tid);
1798 ok(thread != NULL, "failed, got %u\n", GetLastError());
1800 ret = WaitForSingleObject(thread, 1000);
1801 ok(ret == WAIT_OBJECT_0, "wait timeout\n");
1802 ok(param.thread_context == context, "got wrong thread context %p, %p\n", param.thread_context, context);
1803 pReleaseActCtx(param.thread_context);
1804 CloseHandle(thread);
1806 pReleaseActCtx(param.handle);
1808 b = pDeactivateActCtx(0, cookie);
1809 ok(b, "DeactivateActCtx failed: %u\n", GetLastError());
1810 pReleaseActCtx(context);
1814 static void WINAPI threadpool_workcallback(PTP_CALLBACK_INSTANCE instance, void *context, PTP_WORK work) {
1815 int *foo = (int*)context;
1817 (*foo)++;
1821 static void test_threadpool(void)
1823 PTP_POOL pool;
1824 PTP_WORK work;
1825 int workcalled = 0;
1827 if (!pCreateThreadpool) {
1828 win_skip("thread pool apis not supported.\n");
1829 return;
1832 work = pCreateThreadpoolWork(threadpool_workcallback, &workcalled, NULL);
1833 ok (work != NULL, "Error %d in CreateThreadpoolWork\n", GetLastError());
1834 pSubmitThreadpoolWork(work);
1835 pWaitForThreadpoolWorkCallbacks(work, FALSE);
1836 pCloseThreadpoolWork(work);
1838 ok (workcalled == 1, "expected work to be called once, got %d\n", workcalled);
1840 pool = pCreateThreadpool(NULL);
1841 ok (pool != NULL, "CreateThreadpool failed\n");
1842 pCloseThreadpool(pool);
1845 static void test_reserved_tls(void)
1847 void *val;
1848 DWORD tls;
1849 BOOL ret;
1851 /* This seems to be a WinXP SP2+ feature. */
1852 if(!pIsWow64Process) {
1853 win_skip("Skipping reserved TLS slot on too old Windows.\n");
1854 return;
1857 val = TlsGetValue(0);
1858 ok(!val, "TlsGetValue(0) = %p\n", val);
1860 /* Also make sure that there is a TLS allocated. */
1861 tls = TlsAlloc();
1862 ok(tls && tls != TLS_OUT_OF_INDEXES, "tls = %x\n", tls);
1863 TlsSetValue(tls, (void*)1);
1865 val = TlsGetValue(0);
1866 ok(!val, "TlsGetValue(0) = %p\n", val);
1868 TlsFree(tls);
1870 /* The following is too ugly to be run by default */
1871 if(0) {
1872 /* Set TLS index 0 value and see that this works and doesn't cause problems
1873 * for remaining tests. */
1874 ret = TlsSetValue(0, (void*)1);
1875 ok(ret, "TlsSetValue(0, 1) failed: %u\n", GetLastError());
1877 val = TlsGetValue(0);
1878 ok(val == (void*)1, "TlsGetValue(0) = %p\n", val);
1882 static void test_thread_info(void)
1884 char buf[4096];
1885 static const ULONG info_size[] =
1887 sizeof(THREAD_BASIC_INFORMATION), /* ThreadBasicInformation */
1888 sizeof(KERNEL_USER_TIMES), /* ThreadTimes */
1889 sizeof(ULONG), /* ThreadPriority */
1890 sizeof(ULONG), /* ThreadBasePriority */
1891 sizeof(ULONG_PTR), /* ThreadAffinityMask */
1892 sizeof(HANDLE), /* ThreadImpersonationToken */
1893 sizeof(THREAD_DESCRIPTOR_INFORMATION), /* ThreadDescriptorTableEntry */
1894 sizeof(BOOLEAN), /* ThreadEnableAlignmentFaultFixup */
1895 0, /* ThreadEventPair_Reusable */
1896 sizeof(ULONG_PTR), /* ThreadQuerySetWin32StartAddress */
1897 sizeof(ULONG), /* ThreadZeroTlsCell */
1898 sizeof(LARGE_INTEGER), /* ThreadPerformanceCount */
1899 sizeof(ULONG), /* ThreadAmILastThread */
1900 sizeof(ULONG), /* ThreadIdealProcessor */
1901 sizeof(ULONG), /* ThreadPriorityBoost */
1902 sizeof(ULONG_PTR), /* ThreadSetTlsArrayAddress */
1903 sizeof(ULONG), /* ThreadIsIoPending */
1904 sizeof(BOOLEAN), /* ThreadHideFromDebugger */
1905 /* FIXME: Add remaining classes */
1907 HANDLE thread;
1908 ULONG i, status, ret_len;
1910 if (!pOpenThread)
1912 win_skip("OpenThread is not available on this platform\n");
1913 return;
1916 if (!pNtQueryInformationThread)
1918 win_skip("NtQueryInformationThread is not available on this platform\n");
1919 return;
1922 thread = pOpenThread(THREAD_QUERY_LIMITED_INFORMATION, FALSE, GetCurrentThreadId());
1923 if (!thread)
1925 win_skip("THREAD_QUERY_LIMITED_INFORMATION is not supported on this platform\n");
1926 return;
1929 for (i = 0; i < sizeof(info_size)/sizeof(info_size[0]); i++)
1931 memset(buf, 0, sizeof(buf));
1933 #ifdef __i386__
1934 if (i == ThreadDescriptorTableEntry)
1936 CONTEXT ctx;
1937 THREAD_DESCRIPTOR_INFORMATION *tdi = (void *)buf;
1939 ctx.ContextFlags = CONTEXT_SEGMENTS;
1940 GetThreadContext(GetCurrentThread(), &ctx);
1941 tdi->Selector = ctx.SegDs;
1943 #endif
1944 ret_len = 0;
1945 status = pNtQueryInformationThread(thread, i, buf, info_size[i], &ret_len);
1946 if (status == STATUS_NOT_IMPLEMENTED) continue;
1947 if (status == STATUS_INVALID_INFO_CLASS) continue;
1948 if (status == STATUS_UNSUCCESSFUL) continue;
1950 switch (i)
1952 case ThreadBasicInformation:
1953 case ThreadAmILastThread:
1954 case ThreadPriorityBoost:
1955 ok(status == STATUS_SUCCESS, "for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i, status, ret_len);
1956 break;
1958 #ifdef __i386__
1959 case ThreadDescriptorTableEntry:
1960 ok(status == STATUS_SUCCESS || broken(status == STATUS_ACCESS_DENIED) /* testbot VM is broken */,
1961 "for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i, status, ret_len);
1962 break;
1963 #endif
1965 case ThreadTimes:
1966 todo_wine
1967 ok(status == STATUS_SUCCESS, "for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i, status, ret_len);
1968 break;
1970 case ThreadAffinityMask:
1971 case ThreadQuerySetWin32StartAddress:
1972 todo_wine
1973 ok(status == STATUS_ACCESS_DENIED, "for info %u expected STATUS_ACCESS_DENIED, got %08x (ret_len %u)\n", i, status, ret_len);
1974 break;
1976 default:
1977 ok(status == STATUS_ACCESS_DENIED, "for info %u expected STATUS_ACCESS_DENIED, got %08x (ret_len %u)\n", i, status, ret_len);
1978 break;
1982 CloseHandle(thread);
1985 static void init_funcs(void)
1987 HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
1988 HMODULE ntdll = GetModuleHandleA("ntdll.dll");
1990 /* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
1991 so that the compile passes */
1993 #define X(f) p##f = (void*)GetProcAddress(hKernel32, #f)
1994 X(GetThreadPriorityBoost);
1995 X(OpenThread);
1996 X(QueueUserWorkItem);
1997 X(SetThreadIdealProcessor);
1998 X(SetThreadPriorityBoost);
1999 X(RegisterWaitForSingleObject);
2000 X(UnregisterWait);
2001 X(IsWow64Process);
2002 X(SetThreadErrorMode);
2003 X(GetThreadErrorMode);
2004 X(ActivateActCtx);
2005 X(CreateActCtxW);
2006 X(DeactivateActCtx);
2007 X(GetCurrentActCtx);
2008 X(ReleaseActCtx);
2010 X(CreateThreadpool);
2011 X(CloseThreadpool);
2012 X(CreateThreadpoolWork);
2013 X(SubmitThreadpoolWork);
2014 X(WaitForThreadpoolWorkCallbacks);
2015 X(CloseThreadpoolWork);
2017 X(GetThreadGroupAffinity);
2018 X(SetThreadGroupAffinity);
2020 X(FlsAlloc);
2021 X(FlsFree);
2022 X(FlsSetValue);
2023 X(FlsGetValue);
2024 #undef X
2026 #define X(f) p##f = (void*)GetProcAddress(ntdll, #f)
2027 if (ntdll)
2029 X(NtQueryInformationThread);
2030 X(RtlGetThreadErrorMode);
2031 X(NtSetInformationThread);
2033 #undef X
2036 START_TEST(thread)
2038 int argc;
2039 char **argv;
2040 argc = winetest_get_mainargs( &argv );
2042 init_funcs();
2044 if (argc >= 3)
2046 if (!strcmp(argv[2], "sleep"))
2048 HANDLE hAddrEvents[2];
2049 create_function_addr_events(hAddrEvents);
2050 SetEvent(hAddrEvents[0]);
2051 SetEvent(hAddrEvents[1]);
2052 Sleep(5000); /* spawned process runs for at most 5 seconds */
2053 return;
2055 while (1)
2057 HANDLE hThread;
2058 DWORD tid;
2059 hThread = CreateThread(NULL, 0, threadFunc2, NULL, 0, &tid);
2060 ok(hThread != NULL, "CreateThread failed, error %u\n",
2061 GetLastError());
2062 ok(WaitForSingleObject(hThread, 200) == WAIT_OBJECT_0,
2063 "Thread did not exit in time\n");
2064 if (hThread == NULL) break;
2065 CloseHandle(hThread);
2067 return;
2070 test_thread_info();
2071 test_reserved_tls();
2072 test_CreateRemoteThread();
2073 test_CreateThread_basic();
2074 test_CreateThread_suspended();
2075 test_SuspendThread();
2076 test_TerminateThread();
2077 test_CreateThread_stack();
2078 test_thread_priority();
2079 test_GetThreadTimes();
2080 test_thread_processor();
2081 test_GetThreadExitCode();
2082 #ifdef __i386__
2083 test_SetThreadContext();
2084 test_GetThreadSelectorEntry();
2085 #endif
2086 test_QueueUserWorkItem();
2087 test_RegisterWaitForSingleObject();
2088 test_TLS();
2089 test_FLS();
2090 test_ThreadErrorMode();
2091 #if (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) || (defined(_MSC_VER) && defined(__i386__))
2092 test_thread_fpu_cw();
2093 #endif
2094 test_thread_actctx();
2096 test_threadpool();