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 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
)
109 char cmdline
[MAX_PATH
];
110 PROCESS_INFORMATION pi
;
112 STARTUPINFOA si
= { 0 };
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());
124 /* Functions not tested yet:
129 In addition there are no checks that the inheritance works properly in
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");
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);
155 ResetEvent( stop_event
);
156 SetEvent( start_event
);
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);
172 ResetEvent( start_event
);
173 SetEvent( stop_event
);
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
;
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 */
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
;
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
)
247 static DWORD WINAPI
threadFunc3(LPVOID p
)
250 thread
=GetCurrentThread();
251 SuspendThread(thread
);
255 static DWORD WINAPI
threadFunc4(LPVOID p
)
266 static DWORD WINAPI
threadFunc5(LPVOID p
)
270 sysInfo
.dwPageSize
=0;
271 GetSystemInfo(&sysInfo
);
275 alloca(2*sysInfo
.dwPageSize
);
285 static DWORD WINAPI
threadFunc_SetEvent(LPVOID p
)
291 static DWORD WINAPI
threadFunc_CloseHandle(LPVOID p
)
297 struct thread_actctx_param
299 HANDLE thread_context
;
303 static DWORD WINAPI
thread_actctx_func(void *p
)
305 struct thread_actctx_param
*param
= (struct thread_actctx_param
*)p
;
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
;
318 static void create_function_addr_events(HANDLE events
[2])
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");
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");
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,
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
);
414 TerminateProcess(hProcess
, 0);
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
];
426 t1Struct tstruct
[NUM_THREADS
];
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
++) {
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
474 for(i
=0;i
<NUM_THREADS
;i
++) {
476 for(j
=i
+1;j
<NUM_THREADS
;j
++) {
477 if (threadmem
[i
]==threadmem
[j
]) {
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");
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)
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
;
562 thread
= CreateThread(NULL
,0,threadFunc3
,NULL
,
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.
571 for(i
=0;error
==0 && i
<100;i
++) {
572 error
=SuspendThread(thread
);
573 ResumeThread(thread
);
579 ok(error
==1,"SuspendThread did not work\n");
580 /* check that access restrictions are obeyed */
582 access_thread
=pOpenThread(THREAD_ALL_ACCESS_NT4
& (~THREAD_SUSPEND_RESUME
),
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 */
627 access_thread
=pOpenThread(THREAD_ALL_ACCESS_NT4
& (~THREAD_TERMINATE
),
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)
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
658 DWORD threadId
,exitCode
;
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
,
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");
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;
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");
695 /* check that access control is obeyed */
696 access_thread
=pOpenThread(THREAD_ALL_ACCESS_NT4
&
697 (~THREAD_QUERY_INFORMATION
) & (~THREAD_SET_INFORMATION
),
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;
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",
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",
749 ok(GetThreadPriority(curthread
)==max_priority
,
750 "GetThreadPriority didn't return max_priority\n");
752 /* Check thread priority boost */
753 if (!pGetThreadPriorityBoost
|| !pSetThreadPriorityBoost
)
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");
764 ok(rc
!=0,"error=%d\n",GetLastError());
767 /* check that access control is obeyed */
768 access_thread
=pOpenThread(THREAD_ALL_ACCESS_NT4
&
769 (~THREAD_QUERY_INFORMATION
) & (~THREAD_SET_INFORMATION
),
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());
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
;
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 */
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");
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
);
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
;
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");
910 SetLastError(0xdeadbeef);
911 error
=pSetThreadIdealProcessor(curthread
,MAXIMUM_PROCESSORS
+1);
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());
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");
934 win_skip("SetThreadIdealProcessor is not implemented\n");
937 if (pGetThreadGroupAffinity
&& pSetThreadGroupAffinity
)
939 GROUP_AFFINITY affinity
, affinity_new
;
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
);
992 win_skip("Get/SetThreadGroupAffinity not available\n");
995 static VOID
test_GetThreadExitCode(void)
997 DWORD exitCode
, threadid
;
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");
1018 static int test_value
= 0;
1019 static HANDLE event
;
1021 static void WINAPI
set_test_val( int val
)
1027 static DWORD WINAPI
threadFunc6(LPVOID p
)
1031 test_value
*= (int)p
;
1035 static void test_SetThreadContext(void)
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() );
1050 trace("Thread creation failed, skipping rest of test\n");
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() );
1064 /* simulate a call to set_test_val(10) */
1065 stack
= (int *)ctx
.Esp
;
1067 stack
[-2] = ctx
.Eip
;
1068 ctx
.Esp
-= 2 * sizeof(int *);
1069 ctx
.Eip
= (DWORD
)set_test_val
;
1070 SetLastError(0xdeadbeef);
1071 ret
= SetThreadContext( thread
, &ctx
);
1072 ok( ret
, "SetThreadContext failed : (%d)\n", GetLastError() );
1075 SetLastError(0xdeadbeef);
1076 prevcount
= ResumeThread( thread
);
1077 ok ( prevcount
== 1, "Previous suspend count (%d) instead of 1, last error : (%d)\n",
1078 prevcount
, GetLastError() );
1080 WaitForSingleObject( thread
, INFINITE
);
1081 ok( test_value
== 10, "test_value %d\n", test_value
);
1083 ctx
.ContextFlags
= CONTEXT_FULL
;
1084 SetLastError(0xdeadbeef);
1085 ret
= GetThreadContext( thread
, &ctx
);
1086 ok( (!ret
&& (GetLastError() == ERROR_GEN_FAILURE
)) ||
1087 (!ret
&& broken(GetLastError() == ERROR_INVALID_HANDLE
)) || /* win2k */
1088 broken(ret
), /* 32bit application on NT 5.x 64bit */
1089 "got %d with %u (expected FALSE with ERROR_GEN_FAILURE)\n",
1090 ret
, GetLastError() );
1092 SetLastError(0xdeadbeef);
1093 ret
= SetThreadContext( thread
, &ctx
);
1094 ok( (!ret
&& ((GetLastError() == ERROR_GEN_FAILURE
) || (GetLastError() == ERROR_ACCESS_DENIED
))) ||
1095 (!ret
&& broken(GetLastError() == ERROR_INVALID_HANDLE
)) || /* win2k */
1096 broken(ret
), /* 32bit application on NT 5.x 64bit */
1097 "got %d with %u (expected FALSE with ERROR_GEN_FAILURE or ERROR_ACCESS_DENIED)\n",
1098 ret
, GetLastError() );
1100 CloseHandle( thread
);
1103 #endif /* __i386__ */
1105 static HANDLE finish_event
;
1106 static LONG times_executed
;
1108 static DWORD CALLBACK
work_function(void *p
)
1110 LONG executed
= InterlockedIncrement(×_executed
);
1112 if (executed
== 100)
1113 SetEvent(finish_event
);
1117 static void test_QueueUserWorkItem(void)
1121 DWORD before
, after
;
1123 /* QueueUserWorkItem not present on win9x */
1124 if (!pQueueUserWorkItem
) return;
1126 finish_event
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
1128 before
= GetTickCount();
1130 for (i
= 0; i
< 100; i
++)
1132 BOOL ret
= pQueueUserWorkItem(work_function
, (void *)i
, WT_EXECUTEDEFAULT
);
1133 ok(ret
, "QueueUserWorkItem failed with error %d\n", GetLastError());
1136 wait_result
= WaitForSingleObject(finish_event
, 10000);
1138 after
= GetTickCount();
1139 trace("100 QueueUserWorkItem calls took %dms\n", after
- before
);
1140 ok(wait_result
== WAIT_OBJECT_0
, "wait failed with error 0x%x\n", wait_result
);
1142 ok(times_executed
== 100, "didn't execute all of the work items\n");
1145 static void CALLBACK
signaled_function(PVOID p
, BOOLEAN TimerOrWaitFired
)
1149 ok(!TimerOrWaitFired
, "wait shouldn't have timed out\n");
1152 static void CALLBACK
timeout_function(PVOID p
, BOOLEAN TimerOrWaitFired
)
1156 ok(TimerOrWaitFired
, "wait should have timed out\n");
1159 static void test_RegisterWaitForSingleObject(void)
1164 HANDLE complete_event
;
1166 if (!pRegisterWaitForSingleObject
|| !pUnregisterWait
)
1168 win_skip("RegisterWaitForSingleObject or UnregisterWait not implemented\n");
1172 /* test signaled case */
1174 handle
= CreateEventW(NULL
, TRUE
, TRUE
, NULL
);
1175 complete_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1177 ret
= pRegisterWaitForSingleObject(&wait_handle
, handle
, signaled_function
, complete_event
, INFINITE
, WT_EXECUTEONLYONCE
);
1178 ok(ret
, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1180 WaitForSingleObject(complete_event
, INFINITE
);
1181 /* give worker thread chance to complete */
1184 ret
= pUnregisterWait(wait_handle
);
1185 ok(ret
, "UnregisterWait failed with error %d\n", GetLastError());
1187 /* test cancel case */
1191 ret
= pRegisterWaitForSingleObject(&wait_handle
, handle
, signaled_function
, complete_event
, INFINITE
, WT_EXECUTEONLYONCE
);
1192 ok(ret
, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1194 ret
= pUnregisterWait(wait_handle
);
1195 ok(ret
, "UnregisterWait failed with error %d\n", GetLastError());
1197 /* test timeout case */
1199 ret
= pRegisterWaitForSingleObject(&wait_handle
, handle
, timeout_function
, complete_event
, 0, WT_EXECUTEONLYONCE
);
1200 ok(ret
, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1202 WaitForSingleObject(complete_event
, INFINITE
);
1203 /* give worker thread chance to complete */
1206 ret
= pUnregisterWait(wait_handle
);
1207 ok(ret
, "UnregisterWait failed with error %d\n", GetLastError());
1210 static DWORD TLS_main
;
1211 static DWORD TLS_index0
, TLS_index1
;
1213 static DWORD WINAPI
TLS_InheritanceProc(LPVOID p
)
1215 /* We should NOT inherit the TLS values from our parent or from the
1219 val
= TlsGetValue(TLS_main
);
1220 ok(val
== NULL
, "TLS inheritance failed\n");
1222 val
= TlsGetValue(TLS_index0
);
1223 ok(val
== NULL
, "TLS inheritance failed\n");
1225 val
= TlsGetValue(TLS_index1
);
1226 ok(val
== NULL
, "TLS inheritance failed\n");
1231 /* Basic TLS usage test. Make sure we can create slots and the values we
1232 store in them are separate among threads. Also test TLS value
1233 inheritance with TLS_InheritanceProc. */
1234 static DWORD WINAPI
TLS_ThreadProc(LPVOID p
)
1236 LONG_PTR id
= (LONG_PTR
) p
;
1240 if (sync_threads_and_run_one(0, id
))
1242 TLS_index0
= TlsAlloc();
1243 ok(TLS_index0
!= TLS_OUT_OF_INDEXES
, "TlsAlloc failed\n");
1247 if (sync_threads_and_run_one(1, id
))
1249 TLS_index1
= TlsAlloc();
1250 ok(TLS_index1
!= TLS_OUT_OF_INDEXES
, "TlsAlloc failed\n");
1252 /* Slot indices should be different even if created in different
1254 ok(TLS_index0
!= TLS_index1
, "TlsAlloc failed\n");
1256 /* Both slots should be initialized to NULL */
1257 val
= TlsGetValue(TLS_index0
);
1258 ok(GetLastError() == ERROR_SUCCESS
, "TlsGetValue failed\n");
1259 ok(val
== NULL
, "TLS slot not initialized correctly\n");
1261 val
= TlsGetValue(TLS_index1
);
1262 ok(GetLastError() == ERROR_SUCCESS
, "TlsGetValue failed\n");
1263 ok(val
== NULL
, "TLS slot not initialized correctly\n");
1267 if (sync_threads_and_run_one(0, id
))
1269 val
= TlsGetValue(TLS_index0
);
1270 ok(GetLastError() == ERROR_SUCCESS
, "TlsGetValue failed\n");
1271 ok(val
== NULL
, "TLS slot not initialized correctly\n");
1273 val
= TlsGetValue(TLS_index1
);
1274 ok(GetLastError() == ERROR_SUCCESS
, "TlsGetValue failed\n");
1275 ok(val
== NULL
, "TLS slot not initialized correctly\n");
1277 ret
= TlsSetValue(TLS_index0
, (LPVOID
) 1);
1278 ok(ret
, "TlsSetValue failed\n");
1280 ret
= TlsSetValue(TLS_index1
, (LPVOID
) 2);
1281 ok(ret
, "TlsSetValue failed\n");
1283 val
= TlsGetValue(TLS_index0
);
1284 ok(GetLastError() == ERROR_SUCCESS
, "TlsGetValue failed\n");
1285 ok(val
== (LPVOID
) 1, "TLS slot not initialized correctly\n");
1287 val
= TlsGetValue(TLS_index1
);
1288 ok(GetLastError() == ERROR_SUCCESS
, "TlsGetValue failed\n");
1289 ok(val
== (LPVOID
) 2, "TLS slot not initialized correctly\n");
1293 if (sync_threads_and_run_one(1, id
))
1295 val
= TlsGetValue(TLS_index0
);
1296 ok(GetLastError() == ERROR_SUCCESS
, "TlsGetValue failed\n");
1297 ok(val
== NULL
, "TLS slot not initialized correctly\n");
1299 val
= TlsGetValue(TLS_index1
);
1300 ok(GetLastError() == ERROR_SUCCESS
, "TlsGetValue failed\n");
1301 ok(val
== NULL
, "TLS slot not initialized correctly\n");
1303 ret
= TlsSetValue(TLS_index0
, (LPVOID
) 3);
1304 ok(ret
, "TlsSetValue failed\n");
1306 ret
= TlsSetValue(TLS_index1
, (LPVOID
) 4);
1307 ok(ret
, "TlsSetValue failed\n");
1309 val
= TlsGetValue(TLS_index0
);
1310 ok(GetLastError() == ERROR_SUCCESS
, "TlsGetValue failed\n");
1311 ok(val
== (LPVOID
) 3, "TLS slot not initialized correctly\n");
1313 val
= TlsGetValue(TLS_index1
);
1314 ok(GetLastError() == ERROR_SUCCESS
, "TlsGetValue failed\n");
1315 ok(val
== (LPVOID
) 4, "TLS slot not initialized correctly\n");
1319 if (sync_threads_and_run_one(0, id
))
1324 val
= TlsGetValue(TLS_index0
);
1325 ok(GetLastError() == ERROR_SUCCESS
, "TlsGetValue failed\n");
1326 ok(val
== (LPVOID
) 1, "TLS slot not initialized correctly\n");
1328 val
= TlsGetValue(TLS_index1
);
1329 ok(GetLastError() == ERROR_SUCCESS
, "TlsGetValue failed\n");
1330 ok(val
== (LPVOID
) 2, "TLS slot not initialized correctly\n");
1332 thread
= CreateThread(NULL
, 0, TLS_InheritanceProc
, 0, 0, &tid
);
1333 ok(thread
!= NULL
, "CreateThread failed\n");
1334 waitret
= WaitForSingleObject(thread
, 60000);
1335 ok(waitret
== WAIT_OBJECT_0
, "WaitForSingleObject failed\n");
1336 CloseHandle(thread
);
1338 ret
= TlsFree(TLS_index0
);
1339 ok(ret
, "TlsFree failed\n");
1343 if (sync_threads_and_run_one(1, id
))
1345 ret
= TlsFree(TLS_index1
);
1346 ok(ret
, "TlsFree failed\n");
1353 static void test_TLS(void)
1360 init_thread_sync_helpers();
1362 /* Allocate a TLS slot in the main thread to test for inheritance. */
1363 TLS_main
= TlsAlloc();
1364 ok(TLS_main
!= TLS_OUT_OF_INDEXES
, "TlsAlloc failed\n");
1365 suc
= TlsSetValue(TLS_main
, (LPVOID
) 4114);
1366 ok(suc
, "TlsSetValue failed\n");
1368 for (i
= 0; i
< 2; ++i
)
1372 threads
[i
] = CreateThread(NULL
, 0, TLS_ThreadProc
, (LPVOID
) i
, 0, &tid
);
1373 ok(threads
[i
] != NULL
, "CreateThread failed\n");
1376 ret
= WaitForMultipleObjects(2, threads
, TRUE
, 60000);
1377 ok(ret
== WAIT_OBJECT_0
|| broken(ret
== WAIT_OBJECT_0
+1 /* nt4,w2k */), "WaitForAllObjects 2 threads %d\n",ret
);
1379 for (i
= 0; i
< 2; ++i
)
1380 CloseHandle(threads
[i
]);
1382 suc
= TlsFree(TLS_main
);
1383 ok(suc
, "TlsFree failed\n");
1384 cleanup_thread_sync_helpers();
1387 static void test_ThreadErrorMode(void)
1394 if (!pSetThreadErrorMode
|| !pGetThreadErrorMode
)
1396 win_skip("SetThreadErrorMode and/or GetThreadErrorMode unavailable (added in Windows 7)\n");
1400 if (!pRtlGetThreadErrorMode
) {
1401 win_skip("RtlGetThreadErrorMode not available\n");
1405 oldmode
= pGetThreadErrorMode();
1407 ret
= pSetThreadErrorMode(0, &mode
);
1408 ok(ret
, "SetThreadErrorMode failed\n");
1410 "SetThreadErrorMode returned old mode 0x%x, expected 0x%x\n",
1412 mode
= pGetThreadErrorMode();
1413 ok(mode
== 0, "GetThreadErrorMode returned mode 0x%x, expected 0\n", mode
);
1414 rtlmode
= pRtlGetThreadErrorMode();
1416 "RtlGetThreadErrorMode returned mode 0x%x, expected 0\n", mode
);
1418 ret
= pSetThreadErrorMode(SEM_FAILCRITICALERRORS
, &mode
);
1419 ok(ret
, "SetThreadErrorMode failed\n");
1421 "SetThreadErrorMode returned old mode 0x%x, expected 0\n", mode
);
1422 mode
= pGetThreadErrorMode();
1423 ok(mode
== SEM_FAILCRITICALERRORS
,
1424 "GetThreadErrorMode returned mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1426 rtlmode
= pRtlGetThreadErrorMode();
1428 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x10\n", mode
);
1430 ret
= pSetThreadErrorMode(SEM_NOGPFAULTERRORBOX
, &mode
);
1431 ok(ret
, "SetThreadErrorMode failed\n");
1432 ok(mode
== SEM_FAILCRITICALERRORS
,
1433 "SetThreadErrorMode returned old mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1435 mode
= pGetThreadErrorMode();
1436 ok(mode
== SEM_NOGPFAULTERRORBOX
,
1437 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOGPFAULTERRORBOX\n",
1439 rtlmode
= pRtlGetThreadErrorMode();
1441 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x20\n", mode
);
1443 ret
= pSetThreadErrorMode(SEM_NOOPENFILEERRORBOX
, NULL
);
1444 ok(ret
, "SetThreadErrorMode failed\n");
1445 mode
= pGetThreadErrorMode();
1446 ok(mode
== SEM_NOOPENFILEERRORBOX
,
1447 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOOPENFILEERRORBOX\n",
1449 rtlmode
= pRtlGetThreadErrorMode();
1451 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x40\n", rtlmode
);
1453 for (mode
= 1; mode
; mode
<<= 1)
1455 ret
= pSetThreadErrorMode(mode
, NULL
);
1456 if (mode
& (SEM_FAILCRITICALERRORS
|
1457 SEM_NOGPFAULTERRORBOX
|
1458 SEM_NOOPENFILEERRORBOX
))
1461 "SetThreadErrorMode(0x%x,NULL) failed with error %d\n",
1462 mode
, GetLastError());
1466 DWORD GLE
= GetLastError();
1468 "SetThreadErrorMode(0x%x,NULL) succeeded, expected failure\n",
1470 ok(GLE
== ERROR_INVALID_PARAMETER
,
1471 "SetThreadErrorMode(0x%x,NULL) failed with %d, "
1472 "expected ERROR_INVALID_PARAMETER\n",
1477 pSetThreadErrorMode(oldmode
, NULL
);
1480 #if (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) || (defined(_MSC_VER) && defined(__i386__))
1481 static inline void set_fpu_cw(WORD cw
)
1485 __asm
{ fldcw
[cw
] }
1487 __asm__
volatile ("fnclex; fldcw %0" : : "m" (cw
));
1491 static inline WORD
get_fpu_cw(void)
1495 __asm
{ fnstcw
[cw
] }
1497 __asm__
volatile ("fnstcw %0" : "=m" (cw
));
1502 struct fpu_thread_ctx
1508 static DWORD WINAPI
fpu_thread(void *param
)
1510 struct fpu_thread_ctx
*ctx
= param
;
1513 ctx
->cw
= get_fpu_cw();
1515 ret
= SetEvent(ctx
->finished
);
1516 ok(ret
, "SetEvent failed, last error %#x.\n", GetLastError());
1521 static WORD
get_thread_fpu_cw(void)
1523 struct fpu_thread_ctx ctx
;
1527 ctx
.finished
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1528 ok(!!ctx
.finished
, "Failed to create event, last error %#x.\n", GetLastError());
1530 thread
= CreateThread(NULL
, 0, fpu_thread
, &ctx
, 0, &tid
);
1531 ok(!!thread
, "Failed to create thread, last error %#x.\n", GetLastError());
1533 res
= WaitForSingleObject(ctx
.finished
, INFINITE
);
1534 ok(res
== WAIT_OBJECT_0
, "Wait failed (%#x), last error %#x.\n", res
, GetLastError());
1536 res
= CloseHandle(ctx
.finished
);
1537 ok(!!res
, "Failed to close event handle, last error %#x.\n", GetLastError());
1542 static void test_thread_fpu_cw(void)
1544 WORD initial_cw
, cw
;
1546 initial_cw
= get_fpu_cw();
1547 ok(initial_cw
== 0x27f, "Expected FPU control word 0x27f, got %#x.\n", initial_cw
);
1549 cw
= get_thread_fpu_cw();
1550 ok(cw
== 0x27f, "Expected FPU control word 0x27f, got %#x.\n", cw
);
1554 ok(cw
== 0xf60, "Expected FPU control word 0xf60, got %#x.\n", cw
);
1556 cw
= get_thread_fpu_cw();
1557 ok(cw
== 0x27f, "Expected FPU control word 0x27f, got %#x.\n", cw
);
1560 ok(cw
== 0xf60, "Expected FPU control word 0xf60, got %#x.\n", cw
);
1562 set_fpu_cw(initial_cw
);
1564 ok(cw
== initial_cw
, "Expected FPU control word %#x, got %#x.\n", initial_cw
, cw
);
1568 static const char manifest_dep
[] =
1569 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
1570 "<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH
"\"/>"
1571 " <file name=\"testdep.dll\" />"
1574 static const char manifest_main
[] =
1575 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
1576 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />"
1578 " <dependentAssembly>"
1579 " <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH
"\" />"
1580 " </dependentAssembly>"
1584 static void create_manifest_file(const char *filename
, const char *manifest
)
1586 WCHAR path
[MAX_PATH
];
1590 MultiByteToWideChar( CP_ACP
, 0, filename
, -1, path
, MAX_PATH
);
1591 file
= CreateFileW(path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
1592 ok(file
!= INVALID_HANDLE_VALUE
, "CreateFile failed: %u\n", GetLastError());
1593 WriteFile(file
, manifest
, strlen(manifest
), &size
, NULL
);
1597 static HANDLE
test_create(const char *file
)
1599 WCHAR path
[MAX_PATH
];
1603 MultiByteToWideChar(CP_ACP
, 0, file
, -1, path
, MAX_PATH
);
1604 memset(&actctx
, 0, sizeof(ACTCTXW
));
1605 actctx
.cbSize
= sizeof(ACTCTXW
);
1606 actctx
.lpSource
= path
;
1608 handle
= pCreateActCtxW(&actctx
);
1609 ok(handle
!= INVALID_HANDLE_VALUE
, "failed to create context, error %u\n", GetLastError());
1611 ok(actctx
.cbSize
== sizeof(actctx
), "cbSize=%d\n", actctx
.cbSize
);
1612 ok(actctx
.dwFlags
== 0, "dwFlags=%d\n", actctx
.dwFlags
);
1613 ok(actctx
.lpSource
== path
, "lpSource=%p\n", actctx
.lpSource
);
1614 ok(actctx
.wProcessorArchitecture
== 0, "wProcessorArchitecture=%d\n", actctx
.wProcessorArchitecture
);
1615 ok(actctx
.wLangId
== 0, "wLangId=%d\n", actctx
.wLangId
);
1616 ok(actctx
.lpAssemblyDirectory
== NULL
, "lpAssemblyDirectory=%p\n", actctx
.lpAssemblyDirectory
);
1617 ok(actctx
.lpResourceName
== NULL
, "lpResourceName=%p\n", actctx
.lpResourceName
);
1618 ok(actctx
.lpApplicationName
== NULL
, "lpApplicationName=%p\n", actctx
.lpApplicationName
);
1619 ok(actctx
.hModule
== NULL
, "hModule=%p\n", actctx
.hModule
);
1624 static void test_thread_actctx(void)
1626 struct thread_actctx_param param
;
1627 HANDLE thread
, handle
, context
;
1632 if (!pActivateActCtx
)
1634 win_skip("skipping activation context tests\n");
1638 create_manifest_file("testdep1.manifest", manifest_dep
);
1639 create_manifest_file("main.manifest", manifest_main
);
1641 context
= test_create("main.manifest");
1642 DeleteFileA("testdep1.manifest");
1643 DeleteFileA("main.manifest");
1645 handle
= (void*)0xdeadbeef;
1646 b
= pGetCurrentActCtx(&handle
);
1647 ok(b
, "GetCurentActCtx failed: %u\n", GetLastError());
1648 ok(handle
== 0, "active context %p\n", handle
);
1650 /* without active context */
1651 param
.thread_context
= (void*)0xdeadbeef;
1652 param
.handle
= NULL
;
1653 thread
= CreateThread(NULL
, 0, thread_actctx_func
, ¶m
, 0, &tid
);
1654 ok(thread
!= NULL
, "failed, got %u\n", GetLastError());
1656 ret
= WaitForSingleObject(thread
, 1000);
1657 ok(ret
== WAIT_OBJECT_0
, "wait timeout\n");
1658 ok(param
.thread_context
== NULL
, "got wrong thread context %p\n", param
.thread_context
);
1659 CloseHandle(thread
);
1661 b
= pActivateActCtx(context
, &cookie
);
1662 ok(b
, "activation failed: %u\n", GetLastError());
1665 b
= pGetCurrentActCtx(&handle
);
1666 ok(b
, "GetCurentActCtx failed: %u\n", GetLastError());
1667 ok(handle
!= 0, "no active context\n");
1668 pReleaseActCtx(handle
);
1670 param
.handle
= NULL
;
1671 b
= pGetCurrentActCtx(¶m
.handle
);
1672 ok(b
&& param
.handle
!= NULL
, "failed to get context, %u\n", GetLastError());
1674 param
.thread_context
= (void*)0xdeadbeef;
1675 thread
= CreateThread(NULL
, 0, thread_actctx_func
, ¶m
, 0, &tid
);
1676 ok(thread
!= NULL
, "failed, got %u\n", GetLastError());
1678 ret
= WaitForSingleObject(thread
, 1000);
1679 ok(ret
== WAIT_OBJECT_0
, "wait timeout\n");
1680 ok(param
.thread_context
== context
, "got wrong thread context %p, %p\n", param
.thread_context
, context
);
1681 pReleaseActCtx(param
.thread_context
);
1682 CloseHandle(thread
);
1684 /* similar test for CreateRemoteThread() */
1685 param
.thread_context
= (void*)0xdeadbeef;
1686 thread
= CreateRemoteThread(GetCurrentProcess(), NULL
, 0, thread_actctx_func
, ¶m
, 0, &tid
);
1687 ok(thread
!= NULL
, "failed, got %u\n", GetLastError());
1689 ret
= WaitForSingleObject(thread
, 1000);
1690 ok(ret
== WAIT_OBJECT_0
, "wait timeout\n");
1691 ok(param
.thread_context
== context
, "got wrong thread context %p, %p\n", param
.thread_context
, context
);
1692 pReleaseActCtx(param
.thread_context
);
1693 CloseHandle(thread
);
1695 pReleaseActCtx(param
.handle
);
1697 b
= pDeactivateActCtx(0, cookie
);
1698 ok(b
, "DeactivateActCtx failed: %u\n", GetLastError());
1699 pReleaseActCtx(context
);
1703 static void WINAPI
threadpool_workcallback(PTP_CALLBACK_INSTANCE instance
, void *context
, PTP_WORK work
) {
1704 int *foo
= (int*)context
;
1710 static void test_threadpool(void)
1716 if (!pCreateThreadpool
) {
1717 win_skip("thread pool apis not supported.\n");
1721 work
= pCreateThreadpoolWork(threadpool_workcallback
, &workcalled
, NULL
);
1722 ok (work
!= NULL
, "Error %d in CreateThreadpoolWork\n", GetLastError());
1723 pSubmitThreadpoolWork(work
);
1724 pWaitForThreadpoolWorkCallbacks(work
, FALSE
);
1725 pCloseThreadpoolWork(work
);
1727 ok (workcalled
== 1, "expected work to be called once, got %d\n", workcalled
);
1729 pool
= pCreateThreadpool(NULL
);
1730 ok (pool
!= NULL
, "CreateThreadpool failed\n");
1731 pCloseThreadpool(pool
);
1734 static void test_reserved_tls(void)
1740 /* This seems to be a WinXP SP2+ feature. */
1741 if(!pIsWow64Process
) {
1742 win_skip("Skipping reserved TLS slot on too old Windows.\n");
1746 val
= TlsGetValue(0);
1747 ok(!val
, "TlsGetValue(0) = %p\n", val
);
1749 /* Also make sure that there is a TLS allocated. */
1751 ok(tls
&& tls
!= TLS_OUT_OF_INDEXES
, "tls = %x\n", tls
);
1752 TlsSetValue(tls
, (void*)1);
1754 val
= TlsGetValue(0);
1755 ok(!val
, "TlsGetValue(0) = %p\n", val
);
1759 /* The following is too ugly to be run by default */
1761 /* Set TLS index 0 value and see that this works and doesn't cause problems
1762 * for remaining tests. */
1763 ret
= TlsSetValue(0, (void*)1);
1764 ok(ret
, "TlsSetValue(0, 1) failed: %u\n", GetLastError());
1766 val
= TlsGetValue(0);
1767 ok(val
== (void*)1, "TlsGetValue(0) = %p\n", val
);
1771 static void test_thread_info(void)
1774 static const ULONG info_size
[] =
1776 sizeof(THREAD_BASIC_INFORMATION
), /* ThreadBasicInformation */
1777 sizeof(KERNEL_USER_TIMES
), /* ThreadTimes */
1778 sizeof(ULONG
), /* ThreadPriority */
1779 sizeof(ULONG
), /* ThreadBasePriority */
1780 sizeof(ULONG_PTR
), /* ThreadAffinityMask */
1781 sizeof(HANDLE
), /* ThreadImpersonationToken */
1782 sizeof(THREAD_DESCRIPTOR_INFORMATION
), /* ThreadDescriptorTableEntry */
1783 sizeof(BOOLEAN
), /* ThreadEnableAlignmentFaultFixup */
1784 0, /* ThreadEventPair_Reusable */
1785 sizeof(ULONG_PTR
), /* ThreadQuerySetWin32StartAddress */
1786 sizeof(ULONG
), /* ThreadZeroTlsCell */
1787 sizeof(LARGE_INTEGER
), /* ThreadPerformanceCount */
1788 sizeof(ULONG
), /* ThreadAmILastThread */
1789 sizeof(ULONG
), /* ThreadIdealProcessor */
1790 sizeof(ULONG
), /* ThreadPriorityBoost */
1791 sizeof(ULONG_PTR
), /* ThreadSetTlsArrayAddress */
1792 sizeof(ULONG
), /* ThreadIsIoPending */
1793 sizeof(BOOLEAN
), /* ThreadHideFromDebugger */
1794 /* FIXME: Add remaining classes */
1797 ULONG i
, status
, ret_len
;
1801 win_skip("OpenThread is not available on this platform\n");
1805 if (!pNtQueryInformationThread
)
1807 win_skip("NtQueryInformationThread is not available on this platform\n");
1811 thread
= pOpenThread(THREAD_QUERY_LIMITED_INFORMATION
, FALSE
, GetCurrentThreadId());
1814 win_skip("THREAD_QUERY_LIMITED_INFORMATION is not supported on this platform\n");
1818 for (i
= 0; i
< sizeof(info_size
)/sizeof(info_size
[0]); i
++)
1820 memset(buf
, 0, sizeof(buf
));
1823 if (i
== ThreadDescriptorTableEntry
)
1826 THREAD_DESCRIPTOR_INFORMATION
*tdi
= (void *)buf
;
1828 ctx
.ContextFlags
= CONTEXT_SEGMENTS
;
1829 GetThreadContext(GetCurrentThread(), &ctx
);
1830 tdi
->Selector
= ctx
.SegDs
;
1834 status
= pNtQueryInformationThread(thread
, i
, buf
, info_size
[i
], &ret_len
);
1835 if (status
== STATUS_NOT_IMPLEMENTED
) continue;
1836 if (status
== STATUS_INVALID_INFO_CLASS
) continue;
1837 if (status
== STATUS_UNSUCCESSFUL
) continue;
1841 case ThreadBasicInformation
:
1842 case ThreadAmILastThread
:
1843 case ThreadPriorityBoost
:
1844 ok(status
== STATUS_SUCCESS
, "for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i
, status
, ret_len
);
1848 case ThreadDescriptorTableEntry
:
1849 ok(status
== STATUS_SUCCESS
|| broken(status
== STATUS_ACCESS_DENIED
) /* testbot VM is broken */,
1850 "for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i
, status
, ret_len
);
1856 ok(status
== STATUS_SUCCESS
, "for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i
, status
, ret_len
);
1859 case ThreadAffinityMask
:
1860 case ThreadQuerySetWin32StartAddress
:
1862 ok(status
== STATUS_ACCESS_DENIED
, "for info %u expected STATUS_ACCESS_DENIED, got %08x (ret_len %u)\n", i
, status
, ret_len
);
1866 ok(status
== STATUS_ACCESS_DENIED
, "for info %u expected STATUS_ACCESS_DENIED, got %08x (ret_len %u)\n", i
, status
, ret_len
);
1871 CloseHandle(thread
);
1874 static void init_funcs(void)
1876 HMODULE hKernel32
= GetModuleHandleA("kernel32.dll");
1877 HMODULE ntdll
= GetModuleHandleA("ntdll.dll");
1879 /* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
1880 so that the compile passes */
1882 #define X(f) p##f = (void*)GetProcAddress(hKernel32, #f)
1883 X(GetThreadPriorityBoost
);
1885 X(QueueUserWorkItem
);
1886 X(SetThreadIdealProcessor
);
1887 X(SetThreadPriorityBoost
);
1888 X(RegisterWaitForSingleObject
);
1891 X(SetThreadErrorMode
);
1892 X(GetThreadErrorMode
);
1895 X(DeactivateActCtx
);
1896 X(GetCurrentActCtx
);
1899 X(CreateThreadpool
);
1901 X(CreateThreadpoolWork
);
1902 X(SubmitThreadpoolWork
);
1903 X(WaitForThreadpoolWorkCallbacks
);
1904 X(CloseThreadpoolWork
);
1906 X(GetThreadGroupAffinity
);
1907 X(SetThreadGroupAffinity
);
1910 #define X(f) p##f = (void*)GetProcAddress(ntdll, #f)
1913 X(NtQueryInformationThread
);
1914 X(RtlGetThreadErrorMode
);
1915 X(NtSetInformationThread
);
1924 argc
= winetest_get_mainargs( &argv
);
1930 if (!strcmp(argv
[2], "sleep"))
1932 HANDLE hAddrEvents
[2];
1933 create_function_addr_events(hAddrEvents
);
1934 SetEvent(hAddrEvents
[0]);
1935 SetEvent(hAddrEvents
[1]);
1936 Sleep(5000); /* spawned process runs for at most 5 seconds */
1943 hThread
= CreateThread(NULL
, 0, threadFunc2
, NULL
, 0, &tid
);
1944 ok(hThread
!= NULL
, "CreateThread failed, error %u\n",
1946 ok(WaitForSingleObject(hThread
, 200) == WAIT_OBJECT_0
,
1947 "Thread did not exit in time\n");
1948 if (hThread
== NULL
) break;
1949 CloseHandle(hThread
);
1955 test_reserved_tls();
1956 test_CreateRemoteThread();
1957 test_CreateThread_basic();
1958 test_CreateThread_suspended();
1959 test_SuspendThread();
1960 test_TerminateThread();
1961 test_CreateThread_stack();
1962 test_thread_priority();
1963 test_GetThreadTimes();
1964 test_thread_processor();
1965 test_GetThreadExitCode();
1967 test_SetThreadContext();
1969 test_QueueUserWorkItem();
1970 test_RegisterWaitForSingleObject();
1972 test_ThreadErrorMode();
1973 #if (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) || (defined(_MSC_VER) && defined(__i386__))
1974 test_thread_fpu_cw();
1976 test_thread_actctx();