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
28 /* the tests intentionally pass invalid pointers and need an exception handler */
29 #define WINE_NO_INLINE_STRING
32 #define WIN32_NO_STATUS
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 */
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 */
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
60 # define __EXCEPT __except
63 # include "wine/exception.h"
69 #elif defined __x86_64__
73 #elif defined __aarch64__
79 static void (WINAPI
*pGetCurrentThreadStackLimits
)(PULONG_PTR
,PULONG_PTR
);
80 static BOOL (WINAPI
*pGetThreadPriorityBoost
)(HANDLE
,PBOOL
);
81 static HANDLE (WINAPI
*pOpenThread
)(DWORD
,BOOL
,DWORD
);
82 static BOOL (WINAPI
*pQueueUserWorkItem
)(LPTHREAD_START_ROUTINE
,PVOID
,ULONG
);
83 static DWORD (WINAPI
*pSetThreadIdealProcessor
)(HANDLE
,DWORD
);
84 static BOOL (WINAPI
*pSetThreadPriorityBoost
)(HANDLE
,BOOL
);
85 static BOOL (WINAPI
*pRegisterWaitForSingleObject
)(PHANDLE
,HANDLE
,WAITORTIMERCALLBACK
,PVOID
,ULONG
,ULONG
);
86 static BOOL (WINAPI
*pUnregisterWait
)(HANDLE
);
87 static BOOL (WINAPI
*pIsWow64Process
)(HANDLE
,PBOOL
);
88 static BOOL (WINAPI
*pSetThreadErrorMode
)(DWORD
,PDWORD
);
89 static DWORD (WINAPI
*pGetThreadErrorMode
)(void);
90 static DWORD (WINAPI
*pRtlGetThreadErrorMode
)(void);
91 static BOOL (WINAPI
*pActivateActCtx
)(HANDLE
,ULONG_PTR
*);
92 static HANDLE (WINAPI
*pCreateActCtxW
)(PCACTCTXW
);
93 static BOOL (WINAPI
*pDeactivateActCtx
)(DWORD
,ULONG_PTR
);
94 static BOOL (WINAPI
*pGetCurrentActCtx
)(HANDLE
*);
95 static void (WINAPI
*pReleaseActCtx
)(HANDLE
);
96 static PTP_POOL (WINAPI
*pCreateThreadpool
)(PVOID
);
97 static void (WINAPI
*pCloseThreadpool
)(PTP_POOL
);
98 static PTP_WORK (WINAPI
*pCreateThreadpoolWork
)(PTP_WORK_CALLBACK
,PVOID
,PTP_CALLBACK_ENVIRON
);
99 static void (WINAPI
*pSubmitThreadpoolWork
)(PTP_WORK
);
100 static void (WINAPI
*pWaitForThreadpoolWorkCallbacks
)(PTP_WORK
,BOOL
);
101 static void (WINAPI
*pCloseThreadpoolWork
)(PTP_WORK
);
102 static NTSTATUS (WINAPI
*pNtQueryInformationThread
)(HANDLE
,THREADINFOCLASS
,PVOID
,ULONG
,PULONG
);
103 static BOOL (WINAPI
*pGetThreadGroupAffinity
)(HANDLE
,GROUP_AFFINITY
*);
104 static BOOL (WINAPI
*pSetThreadGroupAffinity
)(HANDLE
,const GROUP_AFFINITY
*,GROUP_AFFINITY
*);
105 static NTSTATUS (WINAPI
*pNtSetInformationThread
)(HANDLE
,THREADINFOCLASS
,LPCVOID
,ULONG
);
107 static HANDLE
create_target_process(const char *arg
)
110 char cmdline
[MAX_PATH
];
111 PROCESS_INFORMATION pi
;
113 STARTUPINFOA si
= { 0 };
116 winetest_get_mainargs( &argv
);
117 sprintf(cmdline
, "%s %s %s", argv
[0], argv
[1], arg
);
118 ret
= CreateProcessA(NULL
, cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
119 ok(ret
, "error: %u\n", GetLastError());
120 ret
= CloseHandle(pi
.hThread
);
121 ok(ret
, "error %u\n", GetLastError());
125 /* Functions not tested yet:
130 In addition there are no checks that the inheritance works properly in
134 /* Functions to ensure that from a group of threads, only one executes
135 certain chunks of code at a time, and we know which one is executing
136 it. It basically makes multithreaded execution linear, which defeats
137 the purpose of multiple threads, but makes testing easy. */
138 static HANDLE start_event
, stop_event
;
139 static LONG num_synced
;
141 static void init_thread_sync_helpers(void)
143 start_event
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
144 ok(start_event
!= NULL
, "CreateEvent failed\n");
145 stop_event
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
146 ok(stop_event
!= NULL
, "CreateEvent failed\n");
150 static BOOL
sync_threads_and_run_one(DWORD sync_id
, DWORD my_id
)
152 LONG num
= InterlockedIncrement(&num_synced
);
153 assert(-1 <= num
&& num
<= 1);
156 ResetEvent( stop_event
);
157 SetEvent( start_event
);
161 DWORD ret
= WaitForSingleObject(start_event
, 10000);
162 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed %x\n",ret
);
164 return sync_id
== my_id
;
167 static void resync_after_run(void)
169 LONG num
= InterlockedDecrement(&num_synced
);
170 assert(-1 <= num
&& num
<= 1);
173 ResetEvent( start_event
);
174 SetEvent( stop_event
);
178 DWORD ret
= WaitForSingleObject(stop_event
, 10000);
179 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
183 static void cleanup_thread_sync_helpers(void)
185 CloseHandle(start_event
);
186 CloseHandle(stop_event
);
189 static DWORD tlsIndex
;
197 /* WinME supports OpenThread but doesn't know about access restrictions so
198 we require them to be either completely ignored or always obeyed.
200 static INT obeying_ars
= 0; /* -1 == no, 0 == dunno yet, 1 == yes */
204 ? (obeying_ars = +1) \
205 : ((obeying_ars = -1), \
206 trace("not restricted, assuming consistent behaviour\n"))) \
207 : (obeying_ars < 0) \
208 ? ok(!(x), "access restrictions obeyed\n") \
209 : ok( (x), "access restrictions not obeyed\n"))
211 /* Basic test that simultaneous threads can access shared memory,
212 that the thread local storage routines work correctly, and that
213 threads actually run concurrently
215 static DWORD WINAPI
threadFunc1(LPVOID p
)
217 t1Struct
*tstruct
= p
;
219 /* write our thread # into shared memory */
220 tstruct
->threadmem
[tstruct
->threadnum
]=GetCurrentThreadId();
221 ok(TlsSetValue(tlsIndex
,(LPVOID
)(INT_PTR
)(tstruct
->threadnum
+1))!=0,
222 "TlsSetValue failed\n");
223 /* The threads synchronize before terminating. This is done by
224 Signaling an event, and waiting for all events to occur
226 SetEvent(tstruct
->event
[tstruct
->threadnum
]);
227 WaitForMultipleObjects(NUM_THREADS
,tstruct
->event
,TRUE
,INFINITE
);
228 /* Double check that all threads really did run by validating that
229 they have all written to the shared memory. There should be no race
230 here, since all threads were synchronized after the write.*/
231 for (i
= 0; i
< NUM_THREADS
; i
++)
232 ok(tstruct
->threadmem
[i
] != 0, "expected threadmem[%d] != 0\n", i
);
234 /* lstrlenA contains an exception handler so this makes sure exceptions work in threads */
235 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
237 /* Check that no one changed our tls memory */
238 ok((INT_PTR
)TlsGetValue(tlsIndex
)-1==tstruct
->threadnum
,
239 "TlsGetValue failed\n");
240 return NUM_THREADS
+tstruct
->threadnum
;
243 static DWORD WINAPI
threadFunc2(LPVOID p
)
248 static DWORD WINAPI
threadFunc3(LPVOID p
)
251 thread
=GetCurrentThread();
252 SuspendThread(thread
);
256 static DWORD WINAPI
threadFunc4(LPVOID p
)
267 static DWORD WINAPI
threadFunc5(LPVOID p
)
271 sysInfo
.dwPageSize
=0;
272 GetSystemInfo(&sysInfo
);
276 alloca(2*sysInfo
.dwPageSize
);
286 static DWORD WINAPI
threadFunc_SetEvent(LPVOID p
)
292 static DWORD WINAPI
threadFunc_CloseHandle(LPVOID p
)
298 struct thread_actctx_param
300 HANDLE thread_context
;
304 static DWORD WINAPI
thread_actctx_func(void *p
)
306 struct thread_actctx_param
*param
= (struct thread_actctx_param
*)p
;
310 cur
= (void*)0xdeadbeef;
311 ret
= pGetCurrentActCtx(&cur
);
312 ok(ret
, "thread GetCurrentActCtx failed, %u\n", GetLastError());
313 ok(cur
== param
->handle
, "got %p, expected %p\n", cur
, param
->handle
);
314 param
->thread_context
= cur
;
319 static void create_function_addr_events(HANDLE events
[2])
323 sprintf(buffer
, "threadFunc_SetEvent %p", threadFunc_SetEvent
);
324 events
[0] = CreateEventA(NULL
, FALSE
, FALSE
, buffer
);
326 sprintf(buffer
, "threadFunc_CloseHandle %p", threadFunc_CloseHandle
);
327 events
[1] = CreateEventA(NULL
, FALSE
, FALSE
, buffer
);
330 /* check CreateRemoteThread */
331 static VOID
test_CreateRemoteThread(void)
333 HANDLE hProcess
, hThread
, hEvent
, hRemoteEvent
;
334 DWORD tid
, ret
, exitcode
;
335 HANDLE hAddrEvents
[2];
337 hProcess
= create_target_process("sleep");
338 ok(hProcess
!= NULL
, "Can't start process\n");
340 /* ensure threadFunc_SetEvent & threadFunc_CloseHandle are the same
341 * address as in the child process */
342 create_function_addr_events(hAddrEvents
);
343 ret
= WaitForMultipleObjects(2, hAddrEvents
, TRUE
, 5000);
344 if (ret
== WAIT_TIMEOUT
)
346 skip("child process wasn't mapped at same address, so can't do CreateRemoteThread tests.\n");
349 ok(ret
== WAIT_OBJECT_0
|| broken(ret
== WAIT_OBJECT_0
+1 /* nt4,w2k */), "WaitForAllObjects 2 events %d\n", ret
);
351 hEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
352 ok(hEvent
!= NULL
, "Can't create event, err=%u\n", GetLastError());
353 ret
= DuplicateHandle(GetCurrentProcess(), hEvent
, hProcess
, &hRemoteEvent
,
354 0, FALSE
, DUPLICATE_SAME_ACCESS
);
355 ok(ret
!= 0, "DuplicateHandle failed, err=%u\n", GetLastError());
357 /* create suspended remote thread with entry point SetEvent() */
358 SetLastError(0xdeadbeef);
359 hThread
= CreateRemoteThread(hProcess
, NULL
, 0, threadFunc_SetEvent
,
360 hRemoteEvent
, CREATE_SUSPENDED
, &tid
);
361 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
363 win_skip("CreateRemoteThread is not implemented\n");
366 ok(hThread
!= NULL
, "CreateRemoteThread failed, err=%u\n", GetLastError());
367 ok(tid
!= 0, "null tid\n");
368 ret
= SuspendThread(hThread
);
369 ok(ret
== 1, "ret=%u, err=%u\n", ret
, GetLastError());
370 ret
= ResumeThread(hThread
);
371 ok(ret
== 2, "ret=%u, err=%u\n", ret
, GetLastError());
373 /* thread still suspended, so wait times out */
374 ret
= WaitForSingleObject(hEvent
, 1000);
375 ok(ret
== WAIT_TIMEOUT
, "wait did not time out, ret=%u\n", ret
);
377 ret
= ResumeThread(hThread
);
378 ok(ret
== 1, "ret=%u, err=%u\n", ret
, GetLastError());
380 /* wait that doesn't time out */
381 ret
= WaitForSingleObject(hEvent
, 1000);
382 ok(ret
== WAIT_OBJECT_0
, "object not signaled, ret=%u\n", ret
);
384 /* wait for thread end */
385 ret
= WaitForSingleObject(hThread
, 1000);
386 ok(ret
== WAIT_OBJECT_0
, "waiting for thread failed, ret=%u\n", ret
);
387 CloseHandle(hThread
);
389 /* create and wait for remote thread with entry point CloseHandle() */
390 hThread
= CreateRemoteThread(hProcess
, NULL
, 0,
391 threadFunc_CloseHandle
,
392 hRemoteEvent
, 0, &tid
);
393 ok(hThread
!= NULL
, "CreateRemoteThread failed, err=%u\n", GetLastError());
394 ret
= WaitForSingleObject(hThread
, 1000);
395 ok(ret
== WAIT_OBJECT_0
, "waiting for thread failed, ret=%u\n", ret
);
396 CloseHandle(hThread
);
398 /* create remote thread with entry point SetEvent() */
399 hThread
= CreateRemoteThread(hProcess
, NULL
, 0,
401 hRemoteEvent
, 0, &tid
);
402 ok(hThread
!= NULL
, "CreateRemoteThread failed, err=%u\n", GetLastError());
404 /* closed handle, so wait times out */
405 ret
= WaitForSingleObject(hEvent
, 1000);
406 ok(ret
== WAIT_TIMEOUT
, "wait did not time out, ret=%u\n", ret
);
408 /* check that remote SetEvent() failed */
409 ret
= GetExitCodeThread(hThread
, &exitcode
);
410 ok(ret
!= 0, "GetExitCodeThread failed, err=%u\n", GetLastError());
411 if (ret
) ok(exitcode
== 0, "SetEvent succeeded, expected to fail\n");
412 CloseHandle(hThread
);
415 TerminateProcess(hProcess
, 0);
417 CloseHandle(hProcess
);
420 /* Check basic functionality of CreateThread and Tls* functions */
421 static VOID
test_CreateThread_basic(void)
423 HANDLE thread
[NUM_THREADS
],event
[NUM_THREADS
];
424 DWORD threadid
[NUM_THREADS
],curthreadId
;
425 DWORD threadmem
[NUM_THREADS
];
427 t1Struct tstruct
[NUM_THREADS
];
434 /* lstrlenA contains an exception handler so this makes sure exceptions work in the main thread */
435 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
437 /* Retrieve current Thread ID for later comparisons */
438 curthreadId
=GetCurrentThreadId();
439 /* Allocate some local storage */
440 ok((tlsIndex
=TlsAlloc())!=TLS_OUT_OF_INDEXES
,"TlsAlloc failed\n");
441 /* Create events for thread synchronization */
442 for(i
=0;i
<NUM_THREADS
;i
++) {
444 /* Note that it doesn't matter what type of event we choose here. This
445 test isn't trying to thoroughly test events
447 event
[i
]=CreateEventA(NULL
,TRUE
,FALSE
,NULL
);
448 tstruct
[i
].threadnum
=i
;
449 tstruct
[i
].threadmem
=threadmem
;
450 tstruct
[i
].event
=event
;
453 /* Test that passing arguments to threads works okay */
454 for(i
=0;i
<NUM_THREADS
;i
++) {
455 thread
[i
] = CreateThread(NULL
,0,threadFunc1
,
456 &tstruct
[i
],0,&threadid
[i
]);
457 ok(thread
[i
]!=NULL
,"Create Thread failed\n");
459 /* Test that the threads actually complete */
460 for(i
=0;i
<NUM_THREADS
;i
++) {
461 error
=WaitForSingleObject(thread
[i
],5000);
462 ok(error
==WAIT_OBJECT_0
, "Thread did not complete within timelimit\n");
463 if(error
!=WAIT_OBJECT_0
) {
464 TerminateThread(thread
[i
],i
+NUM_THREADS
);
466 ok(GetExitCodeThread(thread
[i
],&exitCode
),"Could not retrieve ext code\n");
467 ok(exitCode
==i
+NUM_THREADS
,"Thread returned an incorrect exit code\n");
469 /* Test that each thread executed in its parent's address space
470 (it was able to change threadmem and pass that change back to its parent)
471 and that each thread id was independent). Note that we prove that the
472 threads actually execute concurrently by having them block on each other
475 for(i
=0;i
<NUM_THREADS
;i
++) {
477 for(j
=i
+1;j
<NUM_THREADS
;j
++) {
478 if (threadmem
[i
]==threadmem
[j
]) {
482 ok(!error
&& threadmem
[i
]==threadid
[i
] && threadmem
[i
]!=curthreadId
,
483 "Thread did not execute successfully\n");
484 ok(CloseHandle(thread
[i
])!=0,"CloseHandle failed\n");
487 SetLastError(0xCAFEF00D);
488 bRet
= TlsFree(tlsIndex
);
489 ok(bRet
, "TlsFree failed: %08x\n", GetLastError());
490 ok(GetLastError()==0xCAFEF00D,
491 "GetLastError: expected 0xCAFEF00D, got %08x\n", GetLastError());
493 /* Test freeing an already freed TLS index */
494 SetLastError(0xCAFEF00D);
495 ok(TlsFree(tlsIndex
)==0,"TlsFree succeeded\n");
496 ok(GetLastError()==ERROR_INVALID_PARAMETER
,
497 "GetLastError: expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
499 /* Test how passing NULL as a pointer to threadid works */
500 SetLastError(0xFACEaBAD);
501 thread
[0] = CreateThread(NULL
,0,threadFunc2
,NULL
,0,&tid
);
502 GLE
= GetLastError();
503 if (thread
[0]) { /* NT */
504 ok(GLE
==0xFACEaBAD, "CreateThread set last error to %d, expected 4207848365\n", GLE
);
505 ret
= WaitForSingleObject(thread
[0],100);
506 ok(ret
==WAIT_OBJECT_0
, "threadFunc2 did not exit during 100 ms\n");
507 ret
= GetExitCodeThread(thread
[0],&exitCode
);
508 ok(ret
!=0, "GetExitCodeThread returned %d (expected nonzero)\n", ret
);
509 ok(exitCode
==99, "threadFunc2 exited with code: %d (expected 99)\n", exitCode
);
510 ok(CloseHandle(thread
[0])!=0,"Error closing thread handle\n");
513 ok(GLE
==ERROR_INVALID_PARAMETER
, "CreateThread set last error to %d, expected 87\n", GLE
);
517 /* Check that using the CREATE_SUSPENDED flag works */
518 static VOID
test_CreateThread_suspended(void)
525 thread
= CreateThread(NULL
,0,threadFunc2
,NULL
,
526 CREATE_SUSPENDED
,&threadId
);
527 ok(thread
!=NULL
,"Create Thread failed\n");
528 /* Check that the thread is suspended */
529 ok(SuspendThread(thread
)==1,"Thread did not start suspended\n");
530 ok(ResumeThread(thread
)==2,"Resume thread returned an invalid value\n");
531 /* Check that resume thread didn't actually start the thread. I can't think
532 of a better way of checking this than just waiting. I am not sure if this
533 will work on slow computers.
535 ok(WaitForSingleObject(thread
,1000)==WAIT_TIMEOUT
,
536 "ResumeThread should not have actually started the thread\n");
537 /* Now actually resume the thread and make sure that it actually completes*/
538 ok(ResumeThread(thread
)==1,"Resume thread returned an invalid value\n");
539 ok((error
=WaitForSingleObject(thread
,1000))==WAIT_OBJECT_0
,
540 "Thread did not resume\n");
541 if(error
!=WAIT_OBJECT_0
) {
542 TerminateThread(thread
,1);
545 suspend_count
= SuspendThread(thread
);
546 ok(suspend_count
== -1, "SuspendThread returned %d, expected -1\n", suspend_count
);
548 suspend_count
= ResumeThread(thread
);
549 ok(suspend_count
== 0 ||
550 broken(suspend_count
== -1), /* win9x */
551 "ResumeThread returned %d, expected 0\n", suspend_count
);
553 ok(CloseHandle(thread
)!=0,"CloseHandle failed\n");
556 /* Check that SuspendThread and ResumeThread work */
557 static VOID
test_SuspendThread(void)
559 HANDLE thread
,access_thread
;
560 DWORD threadId
,exitCode
,error
;
563 thread
= CreateThread(NULL
,0,threadFunc3
,NULL
,
565 ok(thread
!=NULL
,"Create Thread failed\n");
566 /* Check that the thread is suspended */
567 /* Note that this is a polling method, and there is a race between
568 SuspendThread being called (in the child, and the loop below timing out,
569 so the test could fail on a heavily loaded or slow computer.
572 for(i
=0;error
==0 && i
<100;i
++) {
573 error
=SuspendThread(thread
);
574 ResumeThread(thread
);
580 ok(error
==1,"SuspendThread did not work\n");
581 /* check that access restrictions are obeyed */
583 access_thread
=pOpenThread(THREAD_ALL_ACCESS_NT4
& (~THREAD_SUSPEND_RESUME
),
585 ok(access_thread
!=NULL
,"OpenThread returned an invalid handle\n");
586 if (access_thread
!=NULL
) {
587 obey_ar(SuspendThread(access_thread
)==~0U);
588 obey_ar(ResumeThread(access_thread
)==~0U);
589 ok(CloseHandle(access_thread
)!=0,"CloseHandle Failed\n");
592 /* Double check that the thread really is suspended */
593 ok((error
=GetExitCodeThread(thread
,&exitCode
))!=0 && exitCode
==STILL_ACTIVE
,
594 "Thread did not really suspend\n");
595 /* Resume the thread, and make sure it actually completes */
596 ok(ResumeThread(thread
)==1,"Resume thread returned an invalid value\n");
597 ok((error
=WaitForSingleObject(thread
,1000))==WAIT_OBJECT_0
,
598 "Thread did not resume\n");
599 if(error
!=WAIT_OBJECT_0
) {
600 TerminateThread(thread
,1);
602 /* Trying to suspend a terminated thread should fail */
603 error
=SuspendThread(thread
);
604 ok(error
==~0U, "wrong return code: %d\n", error
);
605 ok(GetLastError()==ERROR_ACCESS_DENIED
|| GetLastError()==ERROR_NO_MORE_ITEMS
, "unexpected error code: %d\n", GetLastError());
607 ok(CloseHandle(thread
)!=0,"CloseHandle Failed\n");
610 /* Check that TerminateThread works properly
612 static VOID
test_TerminateThread(void)
614 HANDLE thread
,access_thread
,event
;
615 DWORD threadId
,exitCode
;
616 event
=CreateEventA(NULL
,TRUE
,FALSE
,NULL
);
617 thread
= CreateThread(NULL
,0,threadFunc4
,event
,0,&threadId
);
618 ok(thread
!=NULL
,"Create Thread failed\n");
619 /* TerminateThread has a race condition in Wine. If the thread is terminated
620 before it starts, it leaves a process behind. Therefore, we wait for the
621 thread to signal that it has started. There is no easy way to force the
622 race to occur, so we don't try to find it.
624 ok(WaitForSingleObject(event
,5000)==WAIT_OBJECT_0
,
625 "TerminateThread didn't work\n");
626 /* check that access restrictions are obeyed */
628 access_thread
=pOpenThread(THREAD_ALL_ACCESS_NT4
& (~THREAD_TERMINATE
),
630 ok(access_thread
!=NULL
,"OpenThread returned an invalid handle\n");
631 if (access_thread
!=NULL
) {
632 obey_ar(TerminateThread(access_thread
,99)==0);
633 ok(CloseHandle(access_thread
)!=0,"CloseHandle Failed\n");
636 /* terminate a job and make sure it terminates */
637 ok(TerminateThread(thread
,99)!=0,"TerminateThread failed\n");
638 ok(WaitForSingleObject(thread
,5000)==WAIT_OBJECT_0
,
639 "TerminateThread didn't work\n");
640 ok(GetExitCodeThread(thread
,&exitCode
)!=STILL_ACTIVE
,
641 "TerminateThread should not leave the thread 'STILL_ACTIVE'\n");
642 ok(exitCode
==99, "TerminateThread returned invalid exit code\n");
643 ok(CloseHandle(thread
)!=0,"Error Closing thread handle\n");
646 /* Check if CreateThread obeys the specified stack size. This code does
647 not work properly, and is currently disabled
649 static VOID
test_CreateThread_stack(void)
652 /* The only way I know of to test the stack size is to use alloca
653 and __try/__except. However, this is probably not portable,
654 and I couldn't get it to work under Wine anyhow. However, here
655 is the code which should allow for testing that CreateThread
656 respects the stack-size limit
659 DWORD threadId
,exitCode
;
662 sysInfo
.dwPageSize
=0;
663 GetSystemInfo(&sysInfo
);
664 ok(sysInfo
.dwPageSize
>0,"GetSystemInfo should return a valid page size\n");
665 thread
= CreateThread(NULL
,sysInfo
.dwPageSize
,
666 threadFunc5
,&exitCode
,
668 ok(WaitForSingleObject(thread
,5000)==WAIT_OBJECT_0
,
669 "TerminateThread didn't work\n");
670 ok(exitCode
==1,"CreateThread did not obey stack-size-limit\n");
671 ok(CloseHandle(thread
)!=0,"CloseHandle failed\n");
675 /* Check whether setting/retrieving thread priorities works */
676 static VOID
test_thread_priority(void)
678 HANDLE curthread
,access_thread
;
679 DWORD curthreadId
,exitCode
;
680 int min_priority
=-2,max_priority
=2;
684 curthread
=GetCurrentThread();
685 curthreadId
=GetCurrentThreadId();
686 /* Check thread priority */
687 /* NOTE: on Win2k/XP priority can be from -7 to 6. All other platforms it
688 is -2 to 2. However, even on a real Win2k system, using thread
689 priorities beyond the -2 to 2 range does not work. If you want to try
690 anyway, enable USE_EXTENDED_PRIORITIES
692 ok(GetThreadPriority(curthread
)==THREAD_PRIORITY_NORMAL
,
693 "GetThreadPriority Failed\n");
696 /* check that access control is obeyed */
697 access_thread
=pOpenThread(THREAD_ALL_ACCESS_NT4
&
698 (~THREAD_QUERY_INFORMATION
) & (~THREAD_SET_INFORMATION
),
700 ok(access_thread
!=NULL
,"OpenThread returned an invalid handle\n");
701 if (access_thread
!=NULL
) {
702 obey_ar(SetThreadPriority(access_thread
,1)==0);
703 obey_ar(GetThreadPriority(access_thread
)==THREAD_PRIORITY_ERROR_RETURN
);
704 obey_ar(GetExitCodeThread(access_thread
,&exitCode
)==0);
705 ok(CloseHandle(access_thread
),"Error Closing thread handle\n");
708 #if USE_EXTENDED_PRIORITIES
709 min_priority
=-7; max_priority
=6;
711 for(i
=min_priority
;i
<=max_priority
;i
++) {
712 ok(SetThreadPriority(curthread
,i
)!=0,
713 "SetThreadPriority Failed for priority: %d\n",i
);
714 ok(GetThreadPriority(curthread
)==i
,
715 "GetThreadPriority Failed for priority: %d\n",i
);
717 ok(SetThreadPriority(curthread
,THREAD_PRIORITY_TIME_CRITICAL
)!=0,
718 "SetThreadPriority Failed\n");
719 ok(GetThreadPriority(curthread
)==THREAD_PRIORITY_TIME_CRITICAL
,
720 "GetThreadPriority Failed\n");
721 ok(SetThreadPriority(curthread
,THREAD_PRIORITY_IDLE
)!=0,
722 "SetThreadPriority Failed\n");
723 ok(GetThreadPriority(curthread
)==THREAD_PRIORITY_IDLE
,
724 "GetThreadPriority Failed\n");
725 ok(SetThreadPriority(curthread
,0)!=0,"SetThreadPriority Failed\n");
727 /* Check that the thread priority is not changed if SetThreadPriority
728 is called with a value outside of the max/min range */
729 SetThreadPriority(curthread
,min_priority
);
730 SetLastError(0xdeadbeef);
731 rc
= SetThreadPriority(curthread
,min_priority
-1);
733 ok(rc
== FALSE
, "SetThreadPriority passed with a bad argument\n");
734 ok(GetLastError() == ERROR_INVALID_PARAMETER
||
735 GetLastError() == ERROR_INVALID_PRIORITY
/* Win9x */,
736 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
738 ok(GetThreadPriority(curthread
)==min_priority
,
739 "GetThreadPriority didn't return min_priority\n");
741 SetThreadPriority(curthread
,max_priority
);
742 SetLastError(0xdeadbeef);
743 rc
= SetThreadPriority(curthread
,max_priority
+1);
745 ok(rc
== FALSE
, "SetThreadPriority passed with a bad argument\n");
746 ok(GetLastError() == ERROR_INVALID_PARAMETER
||
747 GetLastError() == ERROR_INVALID_PRIORITY
/* Win9x */,
748 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
750 ok(GetThreadPriority(curthread
)==max_priority
,
751 "GetThreadPriority didn't return max_priority\n");
753 /* Check thread priority boost */
754 if (!pGetThreadPriorityBoost
|| !pSetThreadPriorityBoost
)
757 SetLastError(0xdeadbeef);
758 rc
=pGetThreadPriorityBoost(curthread
,&disabled
);
759 if (rc
==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED
)
761 win_skip("GetThreadPriorityBoost is not implemented on WinME\n");
765 ok(rc
!=0,"error=%d\n",GetLastError());
768 /* check that access control is obeyed */
769 access_thread
=pOpenThread(THREAD_ALL_ACCESS_NT4
&
770 (~THREAD_QUERY_INFORMATION
) & (~THREAD_SET_INFORMATION
),
772 ok(access_thread
!=NULL
,"OpenThread returned an invalid handle\n");
773 if (access_thread
!=NULL
) {
774 todo_wine
obey_ar(pSetThreadPriorityBoost(access_thread
,1)==0);
775 todo_wine
obey_ar(pGetThreadPriorityBoost(access_thread
,&disabled
)==0);
776 ok(CloseHandle(access_thread
),"Error Closing thread handle\n");
780 rc
= pSetThreadPriorityBoost(curthread
,1);
781 ok( rc
!= 0, "error=%d\n",GetLastError());
783 rc
=pGetThreadPriorityBoost(curthread
,&disabled
);
784 ok(rc
!=0 && disabled
==1,
785 "rc=%d error=%d disabled=%d\n",rc
,GetLastError(),disabled
);
788 rc
= pSetThreadPriorityBoost(curthread
,0);
789 ok( rc
!= 0, "error=%d\n",GetLastError());
790 rc
=pGetThreadPriorityBoost(curthread
,&disabled
);
791 ok(rc
!=0 && disabled
==0,
792 "rc=%d error=%d disabled=%d\n",rc
,GetLastError(),disabled
);
795 /* check the GetThreadTimes function */
796 static VOID
test_GetThreadTimes(void)
798 HANDLE thread
,access_thread
=NULL
;
799 FILETIME creationTime
,exitTime
,kernelTime
,userTime
;
803 thread
= CreateThread(NULL
,0,threadFunc2
,NULL
,
804 CREATE_SUSPENDED
,&threadId
);
806 ok(thread
!=NULL
,"Create Thread failed\n");
807 /* check that access control is obeyed */
809 access_thread
=pOpenThread(THREAD_ALL_ACCESS_NT4
&
810 (~THREAD_QUERY_INFORMATION
), 0,threadId
);
811 ok(access_thread
!=NULL
,
812 "OpenThread returned an invalid handle\n");
814 ok(ResumeThread(thread
)==1,"Resume thread returned an invalid value\n");
815 ok(WaitForSingleObject(thread
,5000)==WAIT_OBJECT_0
,
816 "ResumeThread didn't work\n");
817 creationTime
.dwLowDateTime
=99; creationTime
.dwHighDateTime
=99;
818 exitTime
.dwLowDateTime
=99; exitTime
.dwHighDateTime
=99;
819 kernelTime
.dwLowDateTime
=99; kernelTime
.dwHighDateTime
=99;
820 userTime
.dwLowDateTime
=99; userTime
.dwHighDateTime
=99;
821 /* GetThreadTimes should set all of the parameters passed to it */
822 error
=GetThreadTimes(thread
,&creationTime
,&exitTime
,
823 &kernelTime
,&userTime
);
825 if (error
== 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
826 win_skip("GetThreadTimes is not implemented\n");
828 ok(error
!=0,"GetThreadTimes failed\n");
829 ok(creationTime
.dwLowDateTime
!=99 || creationTime
.dwHighDateTime
!=99,
830 "creationTime was invalid\n");
831 ok(exitTime
.dwLowDateTime
!=99 || exitTime
.dwHighDateTime
!=99,
832 "exitTime was invalid\n");
833 ok(kernelTime
.dwLowDateTime
!=99 || kernelTime
.dwHighDateTime
!=99,
834 "kernelTimewas invalid\n");
835 ok(userTime
.dwLowDateTime
!=99 || userTime
.dwHighDateTime
!=99,
836 "userTime was invalid\n");
837 ok(CloseHandle(thread
)!=0,"CloseHandle failed\n");
838 if(access_thread
!=NULL
)
840 error
=GetThreadTimes(access_thread
,&creationTime
,&exitTime
,
841 &kernelTime
,&userTime
);
845 if(access_thread
!=NULL
) {
846 ok(CloseHandle(access_thread
)!=0,"CloseHandle Failed\n");
850 /* Check the processor affinity functions */
851 /* NOTE: These functions should also be checked that they obey access control
853 static VOID
test_thread_processor(void)
855 HANDLE curthread
,curproc
;
856 DWORD_PTR processMask
,systemMask
,retMask
;
861 if (!pIsWow64Process
|| !pIsWow64Process( GetCurrentProcess(), &is_wow64
)) is_wow64
= FALSE
;
863 sysInfo
.dwNumberOfProcessors
=0;
864 GetSystemInfo(&sysInfo
);
865 ok(sysInfo
.dwNumberOfProcessors
>0,
866 "GetSystemInfo failed to return a valid # of processors\n");
867 /* Use the current Thread/process for all tests */
868 curthread
=GetCurrentThread();
869 ok(curthread
!=NULL
,"GetCurrentThread failed\n");
870 curproc
=GetCurrentProcess();
871 ok(curproc
!=NULL
,"GetCurrentProcess failed\n");
872 /* Check the Affinity Mask functions */
873 ok(GetProcessAffinityMask(curproc
,&processMask
,&systemMask
)!=0,
874 "GetProcessAffinityMask failed\n");
875 ok(SetThreadAffinityMask(curthread
,processMask
)==processMask
,
876 "SetThreadAffinityMask failed\n");
877 ok(SetThreadAffinityMask(curthread
,processMask
+1)==0,
878 "SetThreadAffinityMask passed for an illegal processor\n");
879 /* NOTE: Pre-Vista does not recognize the "all processors" flag (all bits set) */
880 retMask
= SetThreadAffinityMask(curthread
,~0);
881 ok(broken(retMask
==0) || retMask
==processMask
,
882 "SetThreadAffinityMask(thread,-1) failed to request all processors.\n");
884 if (retMask
== processMask
)
886 /* Show that the "all processors" flag is handled in ntdll */
887 DWORD_PTR mask
= ~0u;
888 NTSTATUS status
= pNtSetInformationThread(curthread
, ThreadAffinityMask
, &mask
, sizeof(mask
));
889 ok(status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS in NtSetInformationThread, got %x\n", status
);
892 if (retMask
== processMask
&& sizeof(ULONG_PTR
) > sizeof(ULONG
))
894 /* only the low 32-bits matter */
895 retMask
= SetThreadAffinityMask(curthread
,~(ULONG_PTR
)0);
896 ok(retMask
== processMask
, "SetThreadAffinityMask failed\n");
897 retMask
= SetThreadAffinityMask(curthread
,~(ULONG_PTR
)0 >> 3);
898 ok(retMask
== processMask
, "SetThreadAffinityMask failed\n");
900 /* NOTE: This only works on WinNT/2000/XP) */
901 if (pSetThreadIdealProcessor
)
903 SetLastError(0xdeadbeef);
904 error
=pSetThreadIdealProcessor(curthread
,0);
905 if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED
)
907 ok(error
!=-1, "SetThreadIdealProcessor failed\n");
911 SetLastError(0xdeadbeef);
912 error
=pSetThreadIdealProcessor(curthread
,MAXIMUM_PROCESSORS
+1);
914 ok(error
!=-1, "SetThreadIdealProcessor failed for %u on Wow64\n", MAXIMUM_PROCESSORS
+1);
916 SetLastError(0xdeadbeef);
917 error
=pSetThreadIdealProcessor(curthread
,65);
918 ok(error
==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
919 ok(GetLastError()==ERROR_INVALID_PARAMETER
,
920 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
924 SetLastError(0xdeadbeef);
925 error
=pSetThreadIdealProcessor(curthread
,MAXIMUM_PROCESSORS
+1);
926 ok(error
==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
927 ok(GetLastError()==ERROR_INVALID_PARAMETER
,
928 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
931 error
=pSetThreadIdealProcessor(curthread
,MAXIMUM_PROCESSORS
);
932 ok(error
!=-1, "SetThreadIdealProcessor failed\n");
935 win_skip("SetThreadIdealProcessor is not implemented\n");
938 if (pGetThreadGroupAffinity
&& pSetThreadGroupAffinity
)
940 GROUP_AFFINITY affinity
, affinity_new
;
943 memset(&affinity
, 0, sizeof(affinity
));
944 ok(pGetThreadGroupAffinity(curthread
, &affinity
), "GetThreadGroupAffinity failed\n");
946 SetLastError(0xdeadbeef);
947 ok(!pGetThreadGroupAffinity(curthread
, NULL
), "GetThreadGroupAffinity succeeded\n");
948 ok(GetLastError() == ERROR_INVALID_PARAMETER
|| broken(GetLastError() == ERROR_NOACCESS
), /* Win 7 and 8 */
949 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
950 ok(affinity
.Group
== 0, "Expected group 0 got %u\n", affinity
.Group
);
952 memset(&affinity_new
, 0, sizeof(affinity_new
));
953 affinity_new
.Group
= 0;
954 affinity_new
.Mask
= affinity
.Mask
;
955 ok(pSetThreadGroupAffinity(curthread
, &affinity_new
, &affinity
), "SetThreadGroupAffinity failed\n");
956 ok(affinity_new
.Mask
== affinity
.Mask
, "Expected old affinity mask %lx, got %lx\n",
957 affinity_new
.Mask
, affinity
.Mask
);
959 /* show that the "all processors" flag is not supported for SetThreadGroupAffinity */
960 affinity_new
.Group
= 0;
961 affinity_new
.Mask
= ~0u;
962 SetLastError(0xdeadbeef);
963 ok(!pSetThreadGroupAffinity(curthread
, &affinity_new
, NULL
), "SetThreadGroupAffinity succeeded\n");
964 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
965 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
967 affinity_new
.Group
= 1; /* assumes that you have less than 64 logical processors */
968 affinity_new
.Mask
= 0x1;
969 SetLastError(0xdeadbeef);
970 ok(!pSetThreadGroupAffinity(curthread
, &affinity_new
, NULL
), "SetThreadGroupAffinity succeeded\n");
971 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
972 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
974 SetLastError(0xdeadbeef);
975 ok(!pSetThreadGroupAffinity(curthread
, NULL
, NULL
), "SetThreadGroupAffinity succeeded\n");
976 ok(GetLastError() == ERROR_NOACCESS
,
977 "Expected ERROR_NOACCESS, got %d\n", GetLastError());
979 /* show that the access violation was detected in ntdll */
980 status
= pNtSetInformationThread(curthread
, ThreadGroupInformation
, NULL
, sizeof(affinity_new
));
981 ok(status
== STATUS_ACCESS_VIOLATION
,
982 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", status
);
984 /* restore original mask */
985 affinity_new
.Group
= 0;
986 affinity_new
.Mask
= affinity
.Mask
;
987 SetLastError(0xdeadbeef);
988 ok(pSetThreadGroupAffinity(curthread
, &affinity_new
, &affinity
), "SetThreadGroupAffinity failed\n");
989 ok(affinity_new
.Mask
== affinity
.Mask
, "Expected old affinity mask %lx, got %lx\n",
990 affinity_new
.Mask
, affinity
.Mask
);
993 win_skip("Get/SetThreadGroupAffinity not available\n");
996 static VOID
test_GetCurrentThreadStackLimits(void)
998 ULONG_PTR low
= 0, high
= 0;
1000 if (!pGetCurrentThreadStackLimits
)
1002 win_skip("GetCurrentThreadStackLimits not available.\n");
1008 /* crashes on native */
1009 pGetCurrentThreadStackLimits(NULL
, NULL
);
1010 pGetCurrentThreadStackLimits(NULL
, &high
);
1011 pGetCurrentThreadStackLimits(&low
, NULL
);
1014 pGetCurrentThreadStackLimits(&low
, &high
);
1015 ok(low
== (ULONG_PTR
)NtCurrentTeb()->DeallocationStack
, "exptected %p, got %lx\n", NtCurrentTeb()->DeallocationStack
, low
);
1016 ok(high
== (ULONG_PTR
)NtCurrentTeb()->Tib
.StackBase
, "exptected %p, got %lx\n", NtCurrentTeb()->Tib
.StackBase
, high
);
1019 static VOID
test_GetThreadExitCode(void)
1021 DWORD exitCode
, threadid
;
1025 ret
= GetExitCodeThread((HANDLE
)0x2bad2bad,&exitCode
);
1026 ok(ret
==0, "GetExitCodeThread returned non zero value: %d\n", ret
);
1027 GLE
= GetLastError();
1028 ok(GLE
==ERROR_INVALID_HANDLE
, "GetLastError returned %d (expected 6)\n", GLE
);
1030 thread
= CreateThread(NULL
,0,threadFunc2
,NULL
,0,&threadid
);
1031 ret
= WaitForSingleObject(thread
,100);
1032 ok(ret
==WAIT_OBJECT_0
, "threadFunc2 did not exit during 100 ms\n");
1033 ret
= GetExitCodeThread(thread
,&exitCode
);
1034 ok(ret
==exitCode
|| ret
==1,
1035 "GetExitCodeThread returned %d (expected 1 or %d)\n", ret
, exitCode
);
1036 ok(exitCode
==99, "threadFunc2 exited with code %d (expected 99)\n", exitCode
);
1037 ok(CloseHandle(thread
)!=0,"Error closing thread handle\n");
1042 static int test_value
= 0;
1043 static HANDLE event
;
1045 static void WINAPI
set_test_val( int val
)
1051 static DWORD WINAPI
threadFunc6(LPVOID p
)
1055 test_value
*= (int)p
;
1059 static void test_SetThreadContext(void)
1068 SetLastError(0xdeadbeef);
1069 event
= CreateEventW( NULL
, TRUE
, FALSE
, NULL
);
1070 thread
= CreateThread( NULL
, 0, threadFunc6
, (void *)2, 0, &threadid
);
1071 ok( thread
!= NULL
, "CreateThread failed : (%d)\n", GetLastError() );
1074 trace("Thread creation failed, skipping rest of test\n");
1077 WaitForSingleObject( event
, INFINITE
);
1078 SuspendThread( thread
);
1079 CloseHandle( event
);
1081 ctx
.ContextFlags
= CONTEXT_FULL
;
1082 SetLastError(0xdeadbeef);
1083 ret
= GetThreadContext( thread
, &ctx
);
1084 ok( ret
, "GetThreadContext failed : (%u)\n", GetLastError() );
1088 /* simulate a call to set_test_val(10) */
1089 stack
= (int *)ctx
.Esp
;
1091 stack
[-2] = ctx
.Eip
;
1092 ctx
.Esp
-= 2 * sizeof(int *);
1093 ctx
.Eip
= (DWORD
)set_test_val
;
1094 SetLastError(0xdeadbeef);
1095 ret
= SetThreadContext( thread
, &ctx
);
1096 ok( ret
, "SetThreadContext failed : (%d)\n", GetLastError() );
1099 SetLastError(0xdeadbeef);
1100 prevcount
= ResumeThread( thread
);
1101 ok ( prevcount
== 1, "Previous suspend count (%d) instead of 1, last error : (%d)\n",
1102 prevcount
, GetLastError() );
1104 WaitForSingleObject( thread
, INFINITE
);
1105 ok( test_value
== 10, "test_value %d\n", test_value
);
1107 ctx
.ContextFlags
= CONTEXT_FULL
;
1108 SetLastError(0xdeadbeef);
1109 ret
= GetThreadContext( thread
, &ctx
);
1110 ok( (!ret
&& ((GetLastError() == ERROR_GEN_FAILURE
) || (GetLastError() == ERROR_ACCESS_DENIED
))) ||
1111 (!ret
&& broken(GetLastError() == ERROR_INVALID_HANDLE
)) || /* win2k */
1112 broken(ret
), /* 32bit application on NT 5.x 64bit */
1113 "got %d with %u (expected FALSE with ERROR_GEN_FAILURE or ERROR_ACCESS_DENIED)\n",
1114 ret
, GetLastError() );
1116 SetLastError(0xdeadbeef);
1117 ret
= SetThreadContext( thread
, &ctx
);
1118 ok( (!ret
&& ((GetLastError() == ERROR_GEN_FAILURE
) || (GetLastError() == ERROR_ACCESS_DENIED
))) ||
1119 (!ret
&& broken(GetLastError() == ERROR_INVALID_HANDLE
)) || /* win2k */
1120 broken(ret
), /* 32bit application on NT 5.x 64bit */
1121 "got %d with %u (expected FALSE with ERROR_GEN_FAILURE or ERROR_ACCESS_DENIED)\n",
1122 ret
, GetLastError() );
1124 CloseHandle( thread
);
1127 static void test_GetThreadSelectorEntry(void)
1135 memset(&ctx
, 0x11, sizeof(ctx
));
1136 ctx
.ContextFlags
= CONTEXT_SEGMENTS
| CONTEXT_CONTROL
;
1137 ret
= GetThreadContext(GetCurrentThread(), &ctx
);
1138 ok(ret
, "GetThreadContext error %u\n", GetLastError());
1139 ok(!HIWORD(ctx
.SegCs
), "expected HIWORD(SegCs) == 0, got %u\n", ctx
.SegCs
);
1140 ok(!HIWORD(ctx
.SegDs
), "expected HIWORD(SegDs) == 0, got %u\n", ctx
.SegDs
);
1141 ok(!HIWORD(ctx
.SegFs
), "expected HIWORD(SegFs) == 0, got %u\n", ctx
.SegFs
);
1143 ret
= GetThreadSelectorEntry(GetCurrentThread(), ctx
.SegCs
, &entry
);
1144 ok(ret
, "GetThreadSelectorEntry(SegCs) error %u\n", GetLastError());
1145 ret
= GetThreadSelectorEntry(GetCurrentThread(), ctx
.SegDs
, &entry
);
1146 ok(ret
, "GetThreadSelectorEntry(SegDs) error %u\n", GetLastError());
1148 memset(&entry
, 0x11, sizeof(entry
));
1149 ret
= GetThreadSelectorEntry(GetCurrentThread(), ctx
.SegFs
, &entry
);
1150 ok(ret
, "GetThreadSelectorEntry(SegFs) error %u\n", GetLastError());
1151 entry
.HighWord
.Bits
.Type
&= ~1; /* ignore accessed bit */
1153 base
= (void *)((entry
.HighWord
.Bits
.BaseHi
<< 24) | (entry
.HighWord
.Bits
.BaseMid
<< 16) | entry
.BaseLow
);
1154 limit
= (entry
.HighWord
.Bits
.LimitHi
<< 16) | entry
.LimitLow
;
1156 ok(base
== NtCurrentTeb(), "expected %p, got %p\n", NtCurrentTeb(), base
);
1157 ok(limit
== 0x0fff || limit
== 0x4000, "expected 0x0fff or 0x4000, got %#x\n", limit
);
1158 ok(entry
.HighWord
.Bits
.Type
== 0x12, "expected 0x12, got %#x\n", entry
.HighWord
.Bits
.Type
);
1159 ok(entry
.HighWord
.Bits
.Dpl
== 3, "expected 3, got %u\n", entry
.HighWord
.Bits
.Dpl
);
1160 ok(entry
.HighWord
.Bits
.Pres
== 1, "expected 1, got %u\n", entry
.HighWord
.Bits
.Pres
);
1161 ok(entry
.HighWord
.Bits
.Sys
== 0, "expected 0, got %u\n", entry
.HighWord
.Bits
.Sys
);
1162 ok(entry
.HighWord
.Bits
.Reserved_0
== 0, "expected 0, got %u\n", entry
.HighWord
.Bits
.Reserved_0
);
1163 ok(entry
.HighWord
.Bits
.Default_Big
== 1, "expected 1, got %u\n", entry
.HighWord
.Bits
.Default_Big
);
1164 ok(entry
.HighWord
.Bits
.Granularity
== 0, "expected 0, got %u\n", entry
.HighWord
.Bits
.Granularity
);
1167 #endif /* __i386__ */
1169 static HANDLE finish_event
;
1170 static LONG times_executed
;
1172 static DWORD CALLBACK
work_function(void *p
)
1174 LONG executed
= InterlockedIncrement(×_executed
);
1176 if (executed
== 100)
1177 SetEvent(finish_event
);
1181 static void test_QueueUserWorkItem(void)
1185 DWORD before
, after
;
1187 /* QueueUserWorkItem not present on win9x */
1188 if (!pQueueUserWorkItem
) return;
1190 finish_event
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
1192 before
= GetTickCount();
1194 for (i
= 0; i
< 100; i
++)
1196 BOOL ret
= pQueueUserWorkItem(work_function
, (void *)i
, WT_EXECUTEDEFAULT
);
1197 ok(ret
, "QueueUserWorkItem failed with error %d\n", GetLastError());
1200 wait_result
= WaitForSingleObject(finish_event
, 10000);
1202 after
= GetTickCount();
1203 trace("100 QueueUserWorkItem calls took %dms\n", after
- before
);
1204 ok(wait_result
== WAIT_OBJECT_0
, "wait failed with error 0x%x\n", wait_result
);
1206 ok(times_executed
== 100, "didn't execute all of the work items\n");
1209 static void CALLBACK
signaled_function(PVOID p
, BOOLEAN TimerOrWaitFired
)
1213 ok(!TimerOrWaitFired
, "wait shouldn't have timed out\n");
1216 static void CALLBACK
timeout_function(PVOID p
, BOOLEAN TimerOrWaitFired
)
1220 ok(TimerOrWaitFired
, "wait should have timed out\n");
1223 static void test_RegisterWaitForSingleObject(void)
1228 HANDLE complete_event
;
1230 if (!pRegisterWaitForSingleObject
|| !pUnregisterWait
)
1232 win_skip("RegisterWaitForSingleObject or UnregisterWait not implemented\n");
1236 /* test signaled case */
1238 handle
= CreateEventW(NULL
, TRUE
, TRUE
, NULL
);
1239 complete_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1241 ret
= pRegisterWaitForSingleObject(&wait_handle
, handle
, signaled_function
, complete_event
, INFINITE
, WT_EXECUTEONLYONCE
);
1242 ok(ret
, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1244 WaitForSingleObject(complete_event
, INFINITE
);
1245 /* give worker thread chance to complete */
1248 ret
= pUnregisterWait(wait_handle
);
1249 ok(ret
, "UnregisterWait failed with error %d\n", GetLastError());
1251 /* test cancel case */
1255 ret
= pRegisterWaitForSingleObject(&wait_handle
, handle
, signaled_function
, complete_event
, INFINITE
, WT_EXECUTEONLYONCE
);
1256 ok(ret
, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1258 ret
= pUnregisterWait(wait_handle
);
1259 ok(ret
, "UnregisterWait failed with error %d\n", GetLastError());
1261 /* test timeout case */
1263 ret
= pRegisterWaitForSingleObject(&wait_handle
, handle
, timeout_function
, complete_event
, 0, WT_EXECUTEONLYONCE
);
1264 ok(ret
, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1266 WaitForSingleObject(complete_event
, INFINITE
);
1267 /* give worker thread chance to complete */
1270 ret
= pUnregisterWait(wait_handle
);
1271 ok(ret
, "UnregisterWait failed with error %d\n", GetLastError());
1273 SetLastError(0xdeadbeef);
1274 ret
= pUnregisterWait(NULL
);
1275 ok(!ret
, "Expected UnregisterWait to fail\n");
1276 ok(GetLastError() == ERROR_INVALID_HANDLE
,
1277 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1280 static DWORD LS_main
;
1281 static DWORD LS_index0
, LS_index1
;
1282 static DWORD LS_OutOfIndexesValue
;
1284 /* Function pointers to the FLS/TLS functions to test in LS_ThreadProc() */
1285 static DWORD (WINAPI
*LS_AllocFunc
)(void);
1286 static PVOID (WINAPI
*LS_GetValueFunc
)(DWORD
);
1287 static BOOL (WINAPI
*LS_SetValueFunc
)(DWORD
, PVOID
);
1288 static BOOL (WINAPI
*LS_FreeFunc
)(DWORD
);
1290 /* Names of the functions tested in LS_ThreadProc(), for error messages */
1291 static const char* LS_AllocFuncName
= "";
1292 static const char* LS_GetValueFuncName
= "";
1293 static const char* LS_SetValueFuncName
= "";
1294 static const char* LS_FreeFuncName
= "";
1296 /* FLS entry points, dynamically loaded in platforms that support them */
1297 static DWORD (WINAPI
*pFlsAlloc
)(PFLS_CALLBACK_FUNCTION
);
1298 static BOOL (WINAPI
*pFlsFree
)(DWORD
);
1299 static PVOID (WINAPI
*pFlsGetValue
)(DWORD
);
1300 static BOOL (WINAPI
*pFlsSetValue
)(DWORD
,PVOID
);
1302 /* A thunk function to make FlsAlloc compatible with the signature of TlsAlloc */
1303 static DWORD WINAPI
FLS_AllocFuncThunk(void)
1305 return pFlsAlloc(NULL
);
1308 static DWORD WINAPI
LS_InheritanceProc(LPVOID p
)
1310 /* We should NOT inherit the FLS/TLS values from our parent or from the
1314 val
= LS_GetValueFunc(LS_main
);
1315 ok(val
== NULL
, "%s inheritance failed\n", LS_GetValueFuncName
);
1317 val
= LS_GetValueFunc(LS_index0
);
1318 ok(val
== NULL
, "%s inheritance failed\n", LS_GetValueFuncName
);
1320 val
= LS_GetValueFunc(LS_index1
);
1321 ok(val
== NULL
, "%s inheritance failed\n", LS_GetValueFuncName
);
1326 /* Basic FLS/TLS usage test. Make sure we can create slots and the values we
1327 store in them are separate among threads. Also test FLS/TLS value
1328 inheritance with LS_InheritanceProc. */
1329 static DWORD WINAPI
LS_ThreadProc(LPVOID p
)
1331 LONG_PTR id
= (LONG_PTR
) p
;
1335 if (sync_threads_and_run_one(0, id
))
1337 LS_index0
= LS_AllocFunc();
1338 ok(LS_index0
!= LS_OutOfIndexesValue
, "%s failed\n", LS_AllocFuncName
);
1342 if (sync_threads_and_run_one(1, id
))
1344 LS_index1
= LS_AllocFunc();
1345 ok(LS_index1
!= LS_OutOfIndexesValue
, "%s failed\n", LS_AllocFuncName
);
1347 /* Slot indices should be different even if created in different
1349 ok(LS_index0
!= LS_index1
, "%s failed\n", LS_AllocFuncName
);
1351 /* Both slots should be initialized to NULL */
1352 SetLastError(0xdeadbeef);
1353 val
= LS_GetValueFunc(LS_index0
);
1354 ok(GetLastError() == ERROR_SUCCESS
, "%s failed\n", LS_GetValueFuncName
);
1355 ok(val
== NULL
, "Slot not initialized correctly\n");
1357 SetLastError(0xdeadbeef);
1358 val
= LS_GetValueFunc(LS_index1
);
1359 ok(GetLastError() == ERROR_SUCCESS
, "%s failed\n", LS_GetValueFuncName
);
1360 ok(val
== NULL
, "Slot not initialized correctly\n");
1364 if (sync_threads_and_run_one(0, id
))
1366 SetLastError(0xdeadbeef);
1367 val
= LS_GetValueFunc(LS_index0
);
1368 ok(GetLastError() == ERROR_SUCCESS
, "%s failed\n", LS_GetValueFuncName
);
1369 ok(val
== NULL
, "Slot not initialized correctly\n");
1371 SetLastError(0xdeadbeef);
1372 val
= LS_GetValueFunc(LS_index1
);
1373 ok(GetLastError() == ERROR_SUCCESS
, "%s failed\n", LS_GetValueFuncName
);
1374 ok(val
== NULL
, "Slot not initialized correctly\n");
1376 ret
= LS_SetValueFunc(LS_index0
, (LPVOID
) 1);
1377 ok(ret
, "%s failed\n", LS_SetValueFuncName
);
1379 ret
= LS_SetValueFunc(LS_index1
, (LPVOID
) 2);
1380 ok(ret
, "%s failed\n", LS_SetValueFuncName
);
1382 SetLastError(0xdeadbeef);
1383 val
= LS_GetValueFunc(LS_index0
);
1384 ok(GetLastError() == ERROR_SUCCESS
, "%s failed\n", LS_GetValueFuncName
);
1385 ok(val
== (LPVOID
) 1, "Slot not initialized correctly\n");
1387 SetLastError(0xdeadbeef);
1388 val
= LS_GetValueFunc(LS_index1
);
1389 ok(GetLastError() == ERROR_SUCCESS
, "%s failed\n", LS_GetValueFuncName
);
1390 ok(val
== (LPVOID
) 2, "Slot not initialized correctly\n");
1394 if (sync_threads_and_run_one(1, id
))
1396 val
= LS_GetValueFunc(LS_index0
);
1397 ok(GetLastError() == ERROR_SUCCESS
, "%s failed\n", LS_GetValueFuncName
);
1398 ok(val
== NULL
, "Slot not initialized correctly\n");
1400 val
= LS_GetValueFunc(LS_index1
);
1401 ok(GetLastError() == ERROR_SUCCESS
, "%s failed\n", LS_GetValueFuncName
);
1402 ok(val
== NULL
, "Slot not initialized correctly\n");
1404 ret
= LS_SetValueFunc(LS_index0
, (LPVOID
) 3);
1405 ok(ret
, "%s failed\n", LS_SetValueFuncName
);
1407 ret
= LS_SetValueFunc(LS_index1
, (LPVOID
) 4);
1408 ok(ret
, "%s failed\n", LS_SetValueFuncName
);
1410 val
= LS_GetValueFunc(LS_index0
);
1411 ok(GetLastError() == ERROR_SUCCESS
, "%s failed\n", LS_GetValueFuncName
);
1412 ok(val
== (LPVOID
) 3, "Slot not initialized correctly\n");
1414 val
= LS_GetValueFunc(LS_index1
);
1415 ok(GetLastError() == ERROR_SUCCESS
, "%s failed\n", LS_GetValueFuncName
);
1416 ok(val
== (LPVOID
) 4, "Slot not initialized correctly\n");
1420 if (sync_threads_and_run_one(0, id
))
1425 val
= LS_GetValueFunc(LS_index0
);
1426 ok(GetLastError() == ERROR_SUCCESS
, "%s failed\n", LS_GetValueFuncName
);
1427 ok(val
== (LPVOID
) 1, "Slot not initialized correctly\n");
1429 val
= LS_GetValueFunc(LS_index1
);
1430 ok(GetLastError() == ERROR_SUCCESS
, "%s failed\n", LS_GetValueFuncName
);
1431 ok(val
== (LPVOID
) 2, "Slot not initialized correctly\n");
1433 thread
= CreateThread(NULL
, 0, LS_InheritanceProc
, 0, 0, &tid
);
1434 ok(thread
!= NULL
, "CreateThread failed\n");
1435 waitret
= WaitForSingleObject(thread
, 60000);
1436 ok(waitret
== WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
1437 CloseHandle(thread
);
1439 ret
= LS_FreeFunc(LS_index0
);
1440 ok(ret
, "%s failed\n", LS_FreeFuncName
);
1444 if (sync_threads_and_run_one(1, id
))
1446 ret
= LS_FreeFunc(LS_index1
);
1447 ok(ret
, "%s failed\n", LS_FreeFuncName
);
1454 static void run_LS_tests(void)
1461 init_thread_sync_helpers();
1463 /* Allocate a slot in the main thread to test for inheritance. */
1464 LS_main
= LS_AllocFunc();
1465 ok(LS_main
!= LS_OutOfIndexesValue
, "%s failed\n", LS_AllocFuncName
);
1466 suc
= LS_SetValueFunc(LS_main
, (LPVOID
) 4114);
1467 ok(suc
, "%s failed\n", LS_SetValueFuncName
);
1469 for (i
= 0; i
< 2; ++i
)
1473 threads
[i
] = CreateThread(NULL
, 0, LS_ThreadProc
, (LPVOID
) i
, 0, &tid
);
1474 ok(threads
[i
] != NULL
, "CreateThread failed\n");
1477 ret
= WaitForMultipleObjects(2, threads
, TRUE
, 60000);
1478 ok(ret
== WAIT_OBJECT_0
|| broken(ret
== WAIT_OBJECT_0
+1 /* nt4,w2k */), "WaitForAllObjects 2 threads %d\n",ret
);
1480 for (i
= 0; i
< 2; ++i
)
1481 CloseHandle(threads
[i
]);
1483 suc
= LS_FreeFunc(LS_main
);
1484 ok(suc
, "%s failed\n", LS_FreeFuncName
);
1485 cleanup_thread_sync_helpers();
1488 static void test_TLS(void)
1490 LS_OutOfIndexesValue
= TLS_OUT_OF_INDEXES
;
1492 LS_AllocFunc
= &TlsAlloc
;
1493 LS_GetValueFunc
= &TlsGetValue
;
1494 LS_SetValueFunc
= &TlsSetValue
;
1495 LS_FreeFunc
= &TlsFree
;
1497 LS_AllocFuncName
= "TlsAlloc";
1498 LS_GetValueFuncName
= "TlsGetValue";
1499 LS_SetValueFuncName
= "TlsSetValue";
1500 LS_FreeFuncName
= "TlsFree";
1505 static void test_FLS(void)
1507 if (!pFlsAlloc
|| !pFlsFree
|| !pFlsGetValue
|| !pFlsSetValue
)
1509 win_skip("Fiber Local Storage not supported\n");
1513 LS_OutOfIndexesValue
= FLS_OUT_OF_INDEXES
;
1515 LS_AllocFunc
= &FLS_AllocFuncThunk
;
1516 LS_GetValueFunc
= pFlsGetValue
;
1517 LS_SetValueFunc
= pFlsSetValue
;
1518 LS_FreeFunc
= pFlsFree
;
1520 LS_AllocFuncName
= "FlsAlloc";
1521 LS_GetValueFuncName
= "FlsGetValue";
1522 LS_SetValueFuncName
= "FlsSetValue";
1523 LS_FreeFuncName
= "FlsFree";
1528 static void test_ThreadErrorMode(void)
1535 if (!pSetThreadErrorMode
|| !pGetThreadErrorMode
)
1537 win_skip("SetThreadErrorMode and/or GetThreadErrorMode unavailable (added in Windows 7)\n");
1541 if (!pRtlGetThreadErrorMode
) {
1542 win_skip("RtlGetThreadErrorMode not available\n");
1546 oldmode
= pGetThreadErrorMode();
1548 ret
= pSetThreadErrorMode(0, &mode
);
1549 ok(ret
, "SetThreadErrorMode failed\n");
1551 "SetThreadErrorMode returned old mode 0x%x, expected 0x%x\n",
1553 mode
= pGetThreadErrorMode();
1554 ok(mode
== 0, "GetThreadErrorMode returned mode 0x%x, expected 0\n", mode
);
1555 rtlmode
= pRtlGetThreadErrorMode();
1557 "RtlGetThreadErrorMode returned mode 0x%x, expected 0\n", mode
);
1559 ret
= pSetThreadErrorMode(SEM_FAILCRITICALERRORS
, &mode
);
1560 ok(ret
, "SetThreadErrorMode failed\n");
1562 "SetThreadErrorMode returned old mode 0x%x, expected 0\n", mode
);
1563 mode
= pGetThreadErrorMode();
1564 ok(mode
== SEM_FAILCRITICALERRORS
,
1565 "GetThreadErrorMode returned mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1567 rtlmode
= pRtlGetThreadErrorMode();
1569 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x10\n", mode
);
1571 ret
= pSetThreadErrorMode(SEM_NOGPFAULTERRORBOX
, &mode
);
1572 ok(ret
, "SetThreadErrorMode failed\n");
1573 ok(mode
== SEM_FAILCRITICALERRORS
,
1574 "SetThreadErrorMode returned old mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1576 mode
= pGetThreadErrorMode();
1577 ok(mode
== SEM_NOGPFAULTERRORBOX
,
1578 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOGPFAULTERRORBOX\n",
1580 rtlmode
= pRtlGetThreadErrorMode();
1582 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x20\n", mode
);
1584 ret
= pSetThreadErrorMode(SEM_NOOPENFILEERRORBOX
, NULL
);
1585 ok(ret
, "SetThreadErrorMode failed\n");
1586 mode
= pGetThreadErrorMode();
1587 ok(mode
== SEM_NOOPENFILEERRORBOX
,
1588 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOOPENFILEERRORBOX\n",
1590 rtlmode
= pRtlGetThreadErrorMode();
1592 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x40\n", rtlmode
);
1594 for (mode
= 1; mode
; mode
<<= 1)
1596 ret
= pSetThreadErrorMode(mode
, NULL
);
1597 if (mode
& (SEM_FAILCRITICALERRORS
|
1598 SEM_NOGPFAULTERRORBOX
|
1599 SEM_NOOPENFILEERRORBOX
))
1602 "SetThreadErrorMode(0x%x,NULL) failed with error %d\n",
1603 mode
, GetLastError());
1607 DWORD GLE
= GetLastError();
1609 "SetThreadErrorMode(0x%x,NULL) succeeded, expected failure\n",
1611 ok(GLE
== ERROR_INVALID_PARAMETER
,
1612 "SetThreadErrorMode(0x%x,NULL) failed with %d, "
1613 "expected ERROR_INVALID_PARAMETER\n",
1618 pSetThreadErrorMode(oldmode
, NULL
);
1621 #if (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) || (defined(_MSC_VER) && defined(__i386__))
1622 static inline void set_fpu_cw(WORD cw
)
1626 __asm
{ fldcw
[cw
] }
1628 __asm__
volatile ("fnclex; fldcw %0" : : "m" (cw
));
1632 static inline WORD
get_fpu_cw(void)
1636 __asm
{ fnstcw
[cw
] }
1638 __asm__
volatile ("fnstcw %0" : "=m" (cw
));
1643 struct fpu_thread_ctx
1649 static DWORD WINAPI
fpu_thread(void *param
)
1651 struct fpu_thread_ctx
*ctx
= param
;
1654 ctx
->cw
= get_fpu_cw();
1656 ret
= SetEvent(ctx
->finished
);
1657 ok(ret
, "SetEvent failed, last error %#x.\n", GetLastError());
1662 static WORD
get_thread_fpu_cw(void)
1664 struct fpu_thread_ctx ctx
;
1668 ctx
.finished
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1669 ok(!!ctx
.finished
, "Failed to create event, last error %#x.\n", GetLastError());
1671 thread
= CreateThread(NULL
, 0, fpu_thread
, &ctx
, 0, &tid
);
1672 ok(!!thread
, "Failed to create thread, last error %#x.\n", GetLastError());
1674 res
= WaitForSingleObject(ctx
.finished
, INFINITE
);
1675 ok(res
== WAIT_OBJECT_0
, "Wait failed (%#x), last error %#x.\n", res
, GetLastError());
1677 res
= CloseHandle(ctx
.finished
);
1678 ok(!!res
, "Failed to close event handle, last error %#x.\n", GetLastError());
1680 CloseHandle(thread
);
1684 static void test_thread_fpu_cw(void)
1686 WORD initial_cw
, cw
;
1688 initial_cw
= get_fpu_cw();
1689 ok(initial_cw
== 0x27f, "Expected FPU control word 0x27f, got %#x.\n", initial_cw
);
1691 cw
= get_thread_fpu_cw();
1692 ok(cw
== 0x27f, "Expected FPU control word 0x27f, got %#x.\n", cw
);
1696 ok(cw
== 0xf60, "Expected FPU control word 0xf60, got %#x.\n", cw
);
1698 cw
= get_thread_fpu_cw();
1699 ok(cw
== 0x27f, "Expected FPU control word 0x27f, got %#x.\n", cw
);
1702 ok(cw
== 0xf60, "Expected FPU control word 0xf60, got %#x.\n", cw
);
1704 set_fpu_cw(initial_cw
);
1706 ok(cw
== initial_cw
, "Expected FPU control word %#x, got %#x.\n", initial_cw
, cw
);
1710 static const char manifest_dep
[] =
1711 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
1712 "<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH
"\"/>"
1713 " <file name=\"testdep.dll\" />"
1716 static const char manifest_main
[] =
1717 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
1718 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />"
1720 " <dependentAssembly>"
1721 " <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH
"\" />"
1722 " </dependentAssembly>"
1726 static void create_manifest_file(const char *filename
, const char *manifest
)
1728 WCHAR path
[MAX_PATH
];
1732 MultiByteToWideChar( CP_ACP
, 0, filename
, -1, path
, MAX_PATH
);
1733 file
= CreateFileW(path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
1734 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %u\n", GetLastError());
1735 WriteFile(file
, manifest
, strlen(manifest
), &size
, NULL
);
1739 static HANDLE
test_create(const char *file
)
1741 WCHAR path
[MAX_PATH
];
1745 MultiByteToWideChar(CP_ACP
, 0, file
, -1, path
, MAX_PATH
);
1746 memset(&actctx
, 0, sizeof(ACTCTXW
));
1747 actctx
.cbSize
= sizeof(ACTCTXW
);
1748 actctx
.lpSource
= path
;
1750 handle
= pCreateActCtxW(&actctx
);
1751 ok(handle
!= INVALID_HANDLE_VALUE
, "failed to create context, error %u\n", GetLastError());
1753 ok(actctx
.cbSize
== sizeof(actctx
), "cbSize=%d\n", actctx
.cbSize
);
1754 ok(actctx
.dwFlags
== 0, "dwFlags=%d\n", actctx
.dwFlags
);
1755 ok(actctx
.lpSource
== path
, "lpSource=%p\n", actctx
.lpSource
);
1756 ok(actctx
.wProcessorArchitecture
== 0, "wProcessorArchitecture=%d\n", actctx
.wProcessorArchitecture
);
1757 ok(actctx
.wLangId
== 0, "wLangId=%d\n", actctx
.wLangId
);
1758 ok(actctx
.lpAssemblyDirectory
== NULL
, "lpAssemblyDirectory=%p\n", actctx
.lpAssemblyDirectory
);
1759 ok(actctx
.lpResourceName
== NULL
, "lpResourceName=%p\n", actctx
.lpResourceName
);
1760 ok(actctx
.lpApplicationName
== NULL
, "lpApplicationName=%p\n", actctx
.lpApplicationName
);
1761 ok(actctx
.hModule
== NULL
, "hModule=%p\n", actctx
.hModule
);
1766 static void test_thread_actctx(void)
1768 struct thread_actctx_param param
;
1769 HANDLE thread
, handle
, context
;
1774 if (!pActivateActCtx
)
1776 win_skip("skipping activation context tests\n");
1780 create_manifest_file("testdep1.manifest", manifest_dep
);
1781 create_manifest_file("main.manifest", manifest_main
);
1783 context
= test_create("main.manifest");
1784 DeleteFileA("testdep1.manifest");
1785 DeleteFileA("main.manifest");
1787 handle
= (void*)0xdeadbeef;
1788 b
= pGetCurrentActCtx(&handle
);
1789 ok(b
, "GetCurrentActCtx failed: %u\n", GetLastError());
1790 ok(handle
== 0, "active context %p\n", handle
);
1792 /* without active context */
1793 param
.thread_context
= (void*)0xdeadbeef;
1794 param
.handle
= NULL
;
1795 thread
= CreateThread(NULL
, 0, thread_actctx_func
, ¶m
, 0, &tid
);
1796 ok(thread
!= NULL
, "failed, got %u\n", GetLastError());
1798 ret
= WaitForSingleObject(thread
, 1000);
1799 ok(ret
== WAIT_OBJECT_0
, "wait timeout\n");
1800 ok(param
.thread_context
== NULL
, "got wrong thread context %p\n", param
.thread_context
);
1801 CloseHandle(thread
);
1803 b
= pActivateActCtx(context
, &cookie
);
1804 ok(b
, "activation failed: %u\n", GetLastError());
1807 b
= pGetCurrentActCtx(&handle
);
1808 ok(b
, "GetCurrentActCtx failed: %u\n", GetLastError());
1809 ok(handle
!= 0, "no active context\n");
1810 pReleaseActCtx(handle
);
1812 param
.handle
= NULL
;
1813 b
= pGetCurrentActCtx(¶m
.handle
);
1814 ok(b
&& param
.handle
!= NULL
, "failed to get context, %u\n", GetLastError());
1816 param
.thread_context
= (void*)0xdeadbeef;
1817 thread
= CreateThread(NULL
, 0, thread_actctx_func
, ¶m
, 0, &tid
);
1818 ok(thread
!= NULL
, "failed, got %u\n", GetLastError());
1820 ret
= WaitForSingleObject(thread
, 1000);
1821 ok(ret
== WAIT_OBJECT_0
, "wait timeout\n");
1822 ok(param
.thread_context
== context
, "got wrong thread context %p, %p\n", param
.thread_context
, context
);
1823 pReleaseActCtx(param
.thread_context
);
1824 CloseHandle(thread
);
1826 /* similar test for CreateRemoteThread() */
1827 param
.thread_context
= (void*)0xdeadbeef;
1828 thread
= CreateRemoteThread(GetCurrentProcess(), NULL
, 0, thread_actctx_func
, ¶m
, 0, &tid
);
1829 ok(thread
!= NULL
, "failed, got %u\n", GetLastError());
1831 ret
= WaitForSingleObject(thread
, 1000);
1832 ok(ret
== WAIT_OBJECT_0
, "wait timeout\n");
1833 ok(param
.thread_context
== context
, "got wrong thread context %p, %p\n", param
.thread_context
, context
);
1834 pReleaseActCtx(param
.thread_context
);
1835 CloseHandle(thread
);
1837 pReleaseActCtx(param
.handle
);
1839 b
= pDeactivateActCtx(0, cookie
);
1840 ok(b
, "DeactivateActCtx failed: %u\n", GetLastError());
1841 pReleaseActCtx(context
);
1845 static void WINAPI
threadpool_workcallback(PTP_CALLBACK_INSTANCE instance
, void *context
, PTP_WORK work
) {
1846 int *foo
= (int*)context
;
1852 static void test_threadpool(void)
1858 if (!pCreateThreadpool
) {
1859 win_skip("thread pool apis not supported.\n");
1863 work
= pCreateThreadpoolWork(threadpool_workcallback
, &workcalled
, NULL
);
1864 ok (work
!= NULL
, "Error %d in CreateThreadpoolWork\n", GetLastError());
1865 pSubmitThreadpoolWork(work
);
1866 pWaitForThreadpoolWorkCallbacks(work
, FALSE
);
1867 pCloseThreadpoolWork(work
);
1869 ok (workcalled
== 1, "expected work to be called once, got %d\n", workcalled
);
1871 pool
= pCreateThreadpool(NULL
);
1872 ok (pool
!= NULL
, "CreateThreadpool failed\n");
1873 pCloseThreadpool(pool
);
1876 static void test_reserved_tls(void)
1882 /* This seems to be a WinXP SP2+ feature. */
1883 if(!pIsWow64Process
) {
1884 win_skip("Skipping reserved TLS slot on too old Windows.\n");
1888 val
= TlsGetValue(0);
1889 ok(!val
, "TlsGetValue(0) = %p\n", val
);
1891 /* Also make sure that there is a TLS allocated. */
1893 ok(tls
&& tls
!= TLS_OUT_OF_INDEXES
, "tls = %x\n", tls
);
1894 TlsSetValue(tls
, (void*)1);
1896 val
= TlsGetValue(0);
1897 ok(!val
, "TlsGetValue(0) = %p\n", val
);
1901 /* The following is too ugly to be run by default */
1903 /* Set TLS index 0 value and see that this works and doesn't cause problems
1904 * for remaining tests. */
1905 ret
= TlsSetValue(0, (void*)1);
1906 ok(ret
, "TlsSetValue(0, 1) failed: %u\n", GetLastError());
1908 val
= TlsGetValue(0);
1909 ok(val
== (void*)1, "TlsGetValue(0) = %p\n", val
);
1913 static void test_thread_info(void)
1916 static const ULONG info_size
[] =
1918 sizeof(THREAD_BASIC_INFORMATION
), /* ThreadBasicInformation */
1919 sizeof(KERNEL_USER_TIMES
), /* ThreadTimes */
1920 sizeof(ULONG
), /* ThreadPriority */
1921 sizeof(ULONG
), /* ThreadBasePriority */
1922 sizeof(ULONG_PTR
), /* ThreadAffinityMask */
1923 sizeof(HANDLE
), /* ThreadImpersonationToken */
1924 sizeof(THREAD_DESCRIPTOR_INFORMATION
), /* ThreadDescriptorTableEntry */
1925 sizeof(BOOLEAN
), /* ThreadEnableAlignmentFaultFixup */
1926 0, /* ThreadEventPair_Reusable */
1927 sizeof(ULONG_PTR
), /* ThreadQuerySetWin32StartAddress */
1928 sizeof(ULONG
), /* ThreadZeroTlsCell */
1929 sizeof(LARGE_INTEGER
), /* ThreadPerformanceCount */
1930 sizeof(ULONG
), /* ThreadAmILastThread */
1931 sizeof(ULONG
), /* ThreadIdealProcessor */
1932 sizeof(ULONG
), /* ThreadPriorityBoost */
1933 sizeof(ULONG_PTR
), /* ThreadSetTlsArrayAddress */
1934 sizeof(ULONG
), /* ThreadIsIoPending */
1935 sizeof(BOOLEAN
), /* ThreadHideFromDebugger */
1936 /* FIXME: Add remaining classes */
1939 ULONG i
, status
, ret_len
;
1943 win_skip("OpenThread is not available on this platform\n");
1947 if (!pNtQueryInformationThread
)
1949 win_skip("NtQueryInformationThread is not available on this platform\n");
1953 thread
= pOpenThread(THREAD_QUERY_LIMITED_INFORMATION
, FALSE
, GetCurrentThreadId());
1956 win_skip("THREAD_QUERY_LIMITED_INFORMATION is not supported on this platform\n");
1960 for (i
= 0; i
< ARRAY_SIZE(info_size
); i
++)
1962 memset(buf
, 0, sizeof(buf
));
1965 if (i
== ThreadDescriptorTableEntry
)
1968 THREAD_DESCRIPTOR_INFORMATION
*tdi
= (void *)buf
;
1970 ctx
.ContextFlags
= CONTEXT_SEGMENTS
;
1971 GetThreadContext(GetCurrentThread(), &ctx
);
1972 tdi
->Selector
= ctx
.SegDs
;
1976 status
= pNtQueryInformationThread(thread
, i
, buf
, info_size
[i
], &ret_len
);
1977 if (status
== STATUS_NOT_IMPLEMENTED
) continue;
1978 if (status
== STATUS_INVALID_INFO_CLASS
) continue;
1979 if (status
== STATUS_UNSUCCESSFUL
) continue;
1983 case ThreadBasicInformation
:
1984 case ThreadAmILastThread
:
1985 case ThreadPriorityBoost
:
1986 ok(status
== STATUS_SUCCESS
, "for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i
, status
, ret_len
);
1990 case ThreadDescriptorTableEntry
:
1991 ok(status
== STATUS_SUCCESS
|| broken(status
== STATUS_ACCESS_DENIED
) /* testbot VM is broken */,
1992 "for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i
, status
, ret_len
);
1998 ok(status
== STATUS_SUCCESS
, "for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i
, status
, ret_len
);
2001 case ThreadAffinityMask
:
2002 case ThreadQuerySetWin32StartAddress
:
2003 case ThreadIsIoPending
:
2005 ok(status
== STATUS_ACCESS_DENIED
, "for info %u expected STATUS_ACCESS_DENIED, got %08x (ret_len %u)\n", i
, status
, ret_len
);
2009 ok(status
== STATUS_ACCESS_DENIED
, "for info %u expected STATUS_ACCESS_DENIED, got %08x (ret_len %u)\n", i
, status
, ret_len
);
2014 CloseHandle(thread
);
2017 static void init_funcs(void)
2019 HMODULE hKernel32
= GetModuleHandleA("kernel32.dll");
2020 HMODULE ntdll
= GetModuleHandleA("ntdll.dll");
2022 /* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
2023 so that the compile passes */
2025 #define X(f) p##f = (void*)GetProcAddress(hKernel32, #f)
2026 X(GetCurrentThreadStackLimits
);
2027 X(GetThreadPriorityBoost
);
2029 X(QueueUserWorkItem
);
2030 X(SetThreadIdealProcessor
);
2031 X(SetThreadPriorityBoost
);
2032 X(RegisterWaitForSingleObject
);
2035 X(SetThreadErrorMode
);
2036 X(GetThreadErrorMode
);
2039 X(DeactivateActCtx
);
2040 X(GetCurrentActCtx
);
2043 X(CreateThreadpool
);
2045 X(CreateThreadpoolWork
);
2046 X(SubmitThreadpoolWork
);
2047 X(WaitForThreadpoolWorkCallbacks
);
2048 X(CloseThreadpoolWork
);
2050 X(GetThreadGroupAffinity
);
2051 X(SetThreadGroupAffinity
);
2059 #define X(f) p##f = (void*)GetProcAddress(ntdll, #f)
2062 X(NtQueryInformationThread
);
2063 X(RtlGetThreadErrorMode
);
2064 X(NtSetInformationThread
);
2073 argc
= winetest_get_mainargs( &argv
);
2079 if (!strcmp(argv
[2], "sleep"))
2081 HANDLE hAddrEvents
[2];
2082 create_function_addr_events(hAddrEvents
);
2083 SetEvent(hAddrEvents
[0]);
2084 SetEvent(hAddrEvents
[1]);
2085 Sleep(5000); /* spawned process runs for at most 5 seconds */
2092 hThread
= CreateThread(NULL
, 0, threadFunc2
, NULL
, 0, &tid
);
2093 ok(hThread
!= NULL
, "CreateThread failed, error %u\n",
2095 ok(WaitForSingleObject(hThread
, 200) == WAIT_OBJECT_0
,
2096 "Thread did not exit in time\n");
2097 if (hThread
== NULL
) break;
2098 CloseHandle(hThread
);
2104 test_reserved_tls();
2105 test_CreateRemoteThread();
2106 test_CreateThread_basic();
2107 test_CreateThread_suspended();
2108 test_SuspendThread();
2109 test_TerminateThread();
2110 test_CreateThread_stack();
2111 test_thread_priority();
2112 test_GetCurrentThreadStackLimits();
2113 test_GetThreadTimes();
2114 test_thread_processor();
2115 test_GetThreadExitCode();
2117 test_SetThreadContext();
2118 test_GetThreadSelectorEntry();
2120 test_QueueUserWorkItem();
2121 test_RegisterWaitForSingleObject();
2124 test_ThreadErrorMode();
2125 #if (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) || (defined(_MSC_VER) && defined(__i386__))
2126 test_thread_fpu_cw();
2128 test_thread_actctx();