windowscodecs: Silence fixme for IID_CMetaBitmapRenderTarget.
[wine.git] / dlls / kernel32 / tests / thread.c
blob9925da322225bea017337f7d7f323c265ef693e0
1 /*
2 * Unit test suite for thread functions.
4 * Copyright 2002 Geoffrey Hausheer
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <assert.h>
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <float.h>
25 #include <math.h>
27 /* the tests intentionally pass invalid pointers and need an exception handler */
28 #define WINE_NO_INLINE_STRING
30 #include <ntstatus.h>
31 #define WIN32_NO_STATUS
32 #include <windef.h>
33 #include <winbase.h>
34 #include <winnt.h>
35 #include <winerror.h>
36 #include <winnls.h>
37 #include <winternl.h>
38 #include "wine/test.h"
40 /* THREAD_ALL_ACCESS in Vista+ PSDKs is incompatible with older Windows versions */
41 #define THREAD_ALL_ACCESS_NT4 (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3ff)
43 /* Specify the number of simultaneous threads to test */
44 #define NUM_THREADS 4
45 /* Specify whether to test the extended priorities for Win2k/XP */
46 #define USE_EXTENDED_PRIORITIES 0
47 /* Specify whether to test the stack allocation in CreateThread */
48 #define CHECK_STACK 0
50 /* Set CHECK_STACK to 1 if you want to try to test the stack-limit from
51 CreateThread. So far I have been unable to make this work, and
52 I am in doubt as to how portable it is. Also, according to MSDN,
53 you shouldn't mix C-run-time-libraries (i.e. alloca) with CreateThread.
54 Anyhow, the check is currently commented out
56 #if CHECK_STACK
57 # ifdef __try
58 # define __TRY __try
59 # define __EXCEPT __except
60 # define __ENDTRY
61 # else
62 # include "wine/exception.h"
63 # endif
64 #endif
66 #ifdef __i386__
67 #define ARCH "x86"
68 #elif defined __x86_64__
69 #define ARCH "amd64"
70 #elif defined __arm__
71 #define ARCH "arm"
72 #elif defined __aarch64__
73 #define ARCH "arm64"
74 #else
75 #define ARCH "none"
76 #endif
78 static void (WINAPI *pGetCurrentThreadStackLimits)(PULONG_PTR,PULONG_PTR);
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 BOOL (WINAPI *pSetThreadPriorityBoost)(HANDLE,BOOL);
83 static BOOL (WINAPI *pSetThreadStackGuarantee)(ULONG*);
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 PTP_POOL (WINAPI *pCreateThreadpool)(PVOID);
91 static void (WINAPI *pCloseThreadpool)(PTP_POOL);
92 static PTP_WORK (WINAPI *pCreateThreadpoolWork)(PTP_WORK_CALLBACK,PVOID,PTP_CALLBACK_ENVIRON);
93 static void (WINAPI *pSubmitThreadpoolWork)(PTP_WORK);
94 static void (WINAPI *pWaitForThreadpoolWorkCallbacks)(PTP_WORK,BOOL);
95 static void (WINAPI *pCloseThreadpoolWork)(PTP_WORK);
96 static NTSTATUS (WINAPI *pNtQueryInformationThread)(HANDLE,THREADINFOCLASS,PVOID,ULONG,PULONG);
97 static BOOL (WINAPI *pGetThreadGroupAffinity)(HANDLE,GROUP_AFFINITY*);
98 static BOOL (WINAPI *pSetThreadGroupAffinity)(HANDLE,const GROUP_AFFINITY*,GROUP_AFFINITY*);
99 static NTSTATUS (WINAPI *pNtSetInformationThread)(HANDLE,THREADINFOCLASS,LPCVOID,ULONG);
100 static HRESULT (WINAPI *pSetThreadDescription)(HANDLE,const WCHAR *);
101 static HRESULT (WINAPI *pGetThreadDescription)(HANDLE,WCHAR **);
102 static PVOID (WINAPI *pRtlAddVectoredExceptionHandler)(ULONG,PVECTORED_EXCEPTION_HANDLER);
103 static ULONG (WINAPI *pRtlRemoveVectoredExceptionHandler)(PVOID);
105 static HANDLE create_target_process(const char *arg)
107 char **argv;
108 char cmdline[MAX_PATH];
109 PROCESS_INFORMATION pi;
110 BOOL ret;
111 STARTUPINFOA si = { 0 };
112 si.cb = sizeof(si);
114 winetest_get_mainargs( &argv );
115 sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
116 ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
117 ok(ret, "error: %lu\n", GetLastError());
118 ret = CloseHandle(pi.hThread);
119 ok(ret, "error %lu\n", GetLastError());
120 return pi.hProcess;
123 /* Functions not tested yet:
124 AttachThreadInput
125 SetThreadContext
126 SwitchToThread
128 In addition there are no checks that the inheritance works properly in
129 CreateThread
132 /* Functions to ensure that from a group of threads, only one executes
133 certain chunks of code at a time, and we know which one is executing
134 it. It basically makes multithreaded execution linear, which defeats
135 the purpose of multiple threads, but makes testing easy. */
136 static HANDLE start_event, stop_event;
137 static LONG num_synced;
139 static void init_thread_sync_helpers(void)
141 start_event = CreateEventW(NULL, TRUE, FALSE, NULL);
142 ok(start_event != NULL, "CreateEvent failed\n");
143 stop_event = CreateEventW(NULL, TRUE, FALSE, NULL);
144 ok(stop_event != NULL, "CreateEvent failed\n");
145 num_synced = -1;
148 static BOOL sync_threads_and_run_one(DWORD sync_id, DWORD my_id)
150 LONG num = InterlockedIncrement(&num_synced);
151 assert(-1 <= num && num <= 1);
152 if (num == 1)
154 ResetEvent( stop_event );
155 SetEvent( start_event );
157 else
159 DWORD ret = WaitForSingleObject(start_event, 10000);
160 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed %lx\n",ret);
162 return sync_id == my_id;
165 static void resync_after_run(void)
167 LONG num = InterlockedDecrement(&num_synced);
168 assert(-1 <= num && num <= 1);
169 if (num == -1)
171 ResetEvent( start_event );
172 SetEvent( stop_event );
174 else
176 DWORD ret = WaitForSingleObject(stop_event, 10000);
177 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
181 static void cleanup_thread_sync_helpers(void)
183 CloseHandle(start_event);
184 CloseHandle(stop_event);
187 static DWORD tlsIndex;
189 typedef struct {
190 int threadnum;
191 HANDLE *event;
192 DWORD *threadmem;
193 } t1Struct;
195 /* WinME supports OpenThread but doesn't know about access restrictions so
196 we require them to be either completely ignored or always obeyed.
198 static INT obeying_ars = 0; /* -1 == no, 0 == dunno yet, 1 == yes */
199 #define obey_ar(x) \
200 (obeying_ars == 0 \
201 ? ((x) \
202 ? (obeying_ars = +1) \
203 : ((obeying_ars = -1), \
204 trace("not restricted, assuming consistent behaviour\n"))) \
205 : (obeying_ars < 0) \
206 ? ok(!(x), "access restrictions obeyed\n") \
207 : ok( (x), "access restrictions not obeyed\n"))
209 /* Basic test that simultaneous threads can access shared memory,
210 that the thread local storage routines work correctly, and that
211 threads actually run concurrently
213 static DWORD WINAPI threadFunc1(LPVOID p)
215 t1Struct *tstruct = p;
216 int i;
217 /* write our thread # into shared memory */
218 tstruct->threadmem[tstruct->threadnum]=GetCurrentThreadId();
219 ok(TlsSetValue(tlsIndex,(LPVOID)(INT_PTR)(tstruct->threadnum+1))!=0,
220 "TlsSetValue failed\n");
221 /* The threads synchronize before terminating. This is done by
222 Signaling an event, and waiting for all events to occur
224 SetEvent(tstruct->event[tstruct->threadnum]);
225 WaitForMultipleObjects(NUM_THREADS,tstruct->event,TRUE,INFINITE);
226 /* Double check that all threads really did run by validating that
227 they have all written to the shared memory. There should be no race
228 here, since all threads were synchronized after the write.*/
229 for (i = 0; i < NUM_THREADS; i++)
230 ok(tstruct->threadmem[i] != 0, "expected threadmem[%d] != 0\n", i);
232 /* lstrlenA contains an exception handler so this makes sure exceptions work in threads */
233 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
235 /* Check that no one changed our tls memory */
236 ok((INT_PTR)TlsGetValue(tlsIndex)-1==tstruct->threadnum,
237 "TlsGetValue failed\n");
238 return NUM_THREADS+tstruct->threadnum;
241 static DWORD WINAPI threadFunc2(LPVOID p)
243 return 99;
246 static DWORD WINAPI threadFunc3(LPVOID p)
248 HANDLE thread;
249 thread=GetCurrentThread();
250 SuspendThread(thread);
251 return 99;
254 static DWORD WINAPI threadFunc4(LPVOID p)
256 HANDLE event = p;
257 if(event != NULL) {
258 SetEvent(event);
260 Sleep(99000);
261 return 0;
264 #if CHECK_STACK
265 static DWORD WINAPI threadFunc5(LPVOID p)
267 DWORD *exitCode = p;
268 SYSTEM_INFO sysInfo;
269 sysInfo.dwPageSize=0;
270 GetSystemInfo(&sysInfo);
271 *exitCode=0;
272 __TRY
274 alloca(2*sysInfo.dwPageSize);
276 __EXCEPT(1) {
277 *exitCode=1;
279 __ENDTRY
280 return 0;
282 #endif
284 static DWORD WINAPI threadFunc_SetEvent(LPVOID p)
286 SetEvent(p);
287 return 0;
290 static DWORD WINAPI threadFunc_CloseHandle(LPVOID p)
292 CloseHandle(p);
293 return 0;
296 struct thread_actctx_param
298 HANDLE thread_context;
299 HANDLE handle;
302 static DWORD WINAPI thread_actctx_func(void *p)
304 struct thread_actctx_param *param = (struct thread_actctx_param*)p;
305 HANDLE cur;
306 BOOL ret;
308 cur = (void*)0xdeadbeef;
309 ret = GetCurrentActCtx(&cur);
310 ok(ret, "thread GetCurrentActCtx failed, %lu\n", GetLastError());
311 ok(cur == param->handle, "got %p, expected %p\n", cur, param->handle);
312 param->thread_context = cur;
314 return 0;
317 static void create_function_addr_events(HANDLE events[2])
319 char buffer[256];
321 sprintf(buffer, "threadFunc_SetEvent %p", threadFunc_SetEvent);
322 events[0] = CreateEventA(NULL, FALSE, FALSE, buffer);
324 sprintf(buffer, "threadFunc_CloseHandle %p", threadFunc_CloseHandle);
325 events[1] = CreateEventA(NULL, FALSE, FALSE, buffer);
328 /* check CreateRemoteThread */
329 static VOID test_CreateRemoteThread(void)
331 HANDLE hProcess, hThread, hEvent, hRemoteEvent;
332 DWORD tid, ret, exitcode;
333 HANDLE hAddrEvents[2];
335 hProcess = create_target_process("sleep");
336 ok(hProcess != NULL, "Can't start process\n");
338 /* ensure threadFunc_SetEvent & threadFunc_CloseHandle are the same
339 * address as in the child process */
340 create_function_addr_events(hAddrEvents);
341 ret = WaitForMultipleObjects(2, hAddrEvents, TRUE, 5000);
342 if (ret == WAIT_TIMEOUT)
344 skip("child process wasn't mapped at same address, so can't do CreateRemoteThread tests.\n");
345 return;
347 ok(ret == WAIT_OBJECT_0 || broken(ret == WAIT_OBJECT_0+1 /* nt4,w2k */), "WaitForAllObjects 2 events %ld\n", ret);
349 hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
350 ok(hEvent != NULL, "Can't create event, err=%lu\n", GetLastError());
351 ret = DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &hRemoteEvent,
352 0, FALSE, DUPLICATE_SAME_ACCESS);
353 ok(ret != 0, "DuplicateHandle failed, err=%lu\n", GetLastError());
355 /* create suspended remote thread with entry point SetEvent() */
356 SetLastError(0xdeadbeef);
357 hThread = CreateRemoteThread(hProcess, NULL, 0, threadFunc_SetEvent,
358 hRemoteEvent, CREATE_SUSPENDED, &tid);
359 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
361 win_skip("CreateRemoteThread is not implemented\n");
362 goto cleanup;
364 ok(hThread != NULL, "CreateRemoteThread failed, err=%lu\n", GetLastError());
365 ok(tid != 0, "null tid\n");
366 ret = SuspendThread(hThread);
367 ok(ret == 1, "ret=%lu, err=%lu\n", ret, GetLastError());
368 ret = ResumeThread(hThread);
369 ok(ret == 2, "ret=%lu, err=%lu\n", ret, GetLastError());
371 /* thread still suspended, so wait times out */
372 ret = WaitForSingleObject(hEvent, 1000);
373 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%lu\n", ret);
375 ret = ResumeThread(hThread);
376 ok(ret == 1, "ret=%lu, err=%lu\n", ret, GetLastError());
378 /* wait that doesn't time out */
379 ret = WaitForSingleObject(hEvent, 1000);
380 ok(ret == WAIT_OBJECT_0, "object not signaled, ret=%lu\n", ret);
382 /* wait for thread end */
383 ret = WaitForSingleObject(hThread, 1000);
384 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%lu\n", ret);
385 CloseHandle(hThread);
387 /* create and wait for remote thread with entry point CloseHandle() */
388 hThread = CreateRemoteThread(hProcess, NULL, 0,
389 threadFunc_CloseHandle,
390 hRemoteEvent, 0, &tid);
391 ok(hThread != NULL, "CreateRemoteThread failed, err=%lu\n", GetLastError());
392 ret = WaitForSingleObject(hThread, 1000);
393 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%lu\n", ret);
394 CloseHandle(hThread);
396 /* create remote thread with entry point SetEvent() */
397 hThread = CreateRemoteThread(hProcess, NULL, 0,
398 threadFunc_SetEvent,
399 hRemoteEvent, 0, &tid);
400 ok(hThread != NULL, "CreateRemoteThread failed, err=%lu\n", GetLastError());
402 /* closed handle, so wait times out */
403 ret = WaitForSingleObject(hEvent, 1000);
404 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%lu\n", ret);
406 /* check that remote SetEvent() failed */
407 ret = GetExitCodeThread(hThread, &exitcode);
408 ok(ret != 0, "GetExitCodeThread failed, err=%lu\n", GetLastError());
409 if (ret) ok(exitcode == 0, "SetEvent succeeded, expected to fail\n");
410 CloseHandle(hThread);
412 cleanup:
413 TerminateProcess(hProcess, 0);
414 CloseHandle(hEvent);
415 CloseHandle(hProcess);
418 /* Check basic functionality of CreateThread and Tls* functions */
419 static VOID test_CreateThread_basic(void)
421 HANDLE thread[NUM_THREADS],event[NUM_THREADS];
422 DWORD threadid[NUM_THREADS],curthreadId;
423 DWORD threadmem[NUM_THREADS];
424 DWORD exitCode;
425 t1Struct tstruct[NUM_THREADS];
426 int error;
427 DWORD i,j;
428 DWORD GLE, ret;
429 DWORD tid;
430 BOOL bRet;
432 /* lstrlenA contains an exception handler so this makes sure exceptions work in the main thread */
433 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
435 /* Retrieve current Thread ID for later comparisons */
436 curthreadId=GetCurrentThreadId();
437 /* Allocate some local storage */
438 ok((tlsIndex=TlsAlloc())!=TLS_OUT_OF_INDEXES,"TlsAlloc failed\n");
439 /* Create events for thread synchronization */
440 for(i=0;i<NUM_THREADS;i++) {
441 threadmem[i]=0;
442 /* Note that it doesn't matter what type of event we choose here. This
443 test isn't trying to thoroughly test events
445 event[i]=CreateEventA(NULL,TRUE,FALSE,NULL);
446 tstruct[i].threadnum=i;
447 tstruct[i].threadmem=threadmem;
448 tstruct[i].event=event;
451 /* Test that passing arguments to threads works okay */
452 for(i=0;i<NUM_THREADS;i++) {
453 thread[i] = CreateThread(NULL,0,threadFunc1,
454 &tstruct[i],0,&threadid[i]);
455 ok(thread[i]!=NULL,"Create Thread failed\n");
457 /* Test that the threads actually complete */
458 for(i=0;i<NUM_THREADS;i++) {
459 error=WaitForSingleObject(thread[i],5000);
460 ok(error==WAIT_OBJECT_0, "Thread did not complete within timelimit\n");
461 if(error!=WAIT_OBJECT_0) {
462 TerminateThread(thread[i],i+NUM_THREADS);
464 ok(GetExitCodeThread(thread[i],&exitCode),"Could not retrieve ext code\n");
465 ok(exitCode==i+NUM_THREADS,"Thread returned an incorrect exit code\n");
467 /* Test that each thread executed in its parent's address space
468 (it was able to change threadmem and pass that change back to its parent)
469 and that each thread id was independent). Note that we prove that the
470 threads actually execute concurrently by having them block on each other
471 in threadFunc1
473 for(i=0;i<NUM_THREADS;i++) {
474 error=0;
475 for(j=i+1;j<NUM_THREADS;j++) {
476 if (threadmem[i]==threadmem[j]) {
477 error=1;
480 ok(!error && threadmem[i]==threadid[i] && threadmem[i]!=curthreadId,
481 "Thread did not execute successfully\n");
482 ok(CloseHandle(thread[i])!=0,"CloseHandle failed\n");
485 SetLastError(0xCAFEF00D);
486 bRet = TlsFree(tlsIndex);
487 ok(bRet, "TlsFree failed: %08lx\n", GetLastError());
488 ok(GetLastError()==0xCAFEF00D,
489 "GetLastError: expected 0xCAFEF00D, got %08lx\n", GetLastError());
491 /* Test freeing an already freed TLS index */
492 SetLastError(0xCAFEF00D);
493 ok(TlsFree(tlsIndex)==0,"TlsFree succeeded\n");
494 ok(GetLastError()==ERROR_INVALID_PARAMETER,
495 "GetLastError: expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
497 /* Test how passing NULL as a pointer to threadid works */
498 SetLastError(0xFACEaBAD);
499 thread[0] = CreateThread(NULL,0,threadFunc2,NULL,0,&tid);
500 GLE = GetLastError();
501 if (thread[0]) { /* NT */
502 ok(GLE==0xFACEaBAD, "CreateThread set last error to %ld, expected 4207848365\n", GLE);
503 ret = WaitForSingleObject(thread[0],100);
504 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
505 ret = GetExitCodeThread(thread[0],&exitCode);
506 ok(ret!=0, "GetExitCodeThread returned %ld (expected nonzero)\n", ret);
507 ok(exitCode==99, "threadFunc2 exited with code: %ld (expected 99)\n", exitCode);
508 ok(CloseHandle(thread[0])!=0,"Error closing thread handle\n");
510 else { /* 9x */
511 ok(GLE==ERROR_INVALID_PARAMETER, "CreateThread set last error to %ld, expected 87\n", GLE);
515 /* Check that using the CREATE_SUSPENDED flag works */
516 static VOID test_CreateThread_suspended(void)
518 HANDLE thread;
519 DWORD threadId;
520 DWORD suspend_count;
521 int error;
523 thread = CreateThread(NULL,0,threadFunc2,NULL,
524 CREATE_SUSPENDED,&threadId);
525 ok(thread!=NULL,"Create Thread failed\n");
526 /* Check that the thread is suspended */
527 ok(SuspendThread(thread)==1,"Thread did not start suspended\n");
528 ok(ResumeThread(thread)==2,"Resume thread returned an invalid value\n");
529 /* Check that resume thread didn't actually start the thread. I can't think
530 of a better way of checking this than just waiting. I am not sure if this
531 will work on slow computers.
533 ok(WaitForSingleObject(thread,1000)==WAIT_TIMEOUT,
534 "ResumeThread should not have actually started the thread\n");
535 /* Now actually resume the thread and make sure that it actually completes*/
536 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
537 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
538 "Thread did not resume\n");
539 if(error!=WAIT_OBJECT_0) {
540 TerminateThread(thread,1);
543 suspend_count = SuspendThread(thread);
544 ok(suspend_count == -1, "SuspendThread returned %ld, expected -1\n", suspend_count);
546 suspend_count = ResumeThread(thread);
547 ok(suspend_count == 0 ||
548 broken(suspend_count == -1), /* win9x */
549 "ResumeThread returned %ld, expected 0\n", suspend_count);
551 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
554 /* Check that SuspendThread and ResumeThread work */
555 static VOID test_SuspendThread(void)
557 HANDLE thread,access_thread;
558 DWORD threadId,exitCode,error;
559 int i;
561 thread = CreateThread(NULL,0,threadFunc3,NULL,
562 0,&threadId);
563 ok(thread!=NULL,"Create Thread failed\n");
564 /* Check that the thread is suspended */
565 /* Note that this is a polling method, and there is a race between
566 SuspendThread being called (in the child, and the loop below timing out,
567 so the test could fail on a heavily loaded or slow computer.
569 error=0;
570 for(i=0;error==0 && i<100;i++) {
571 error=SuspendThread(thread);
572 ResumeThread(thread);
573 if(error==0) {
574 Sleep(50);
575 i++;
578 ok(error==1,"SuspendThread did not work\n");
579 /* check that access restrictions are obeyed */
580 if (pOpenThread) {
581 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 & (~THREAD_SUSPEND_RESUME),
582 0,threadId);
583 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
584 if (access_thread!=NULL) {
585 obey_ar(SuspendThread(access_thread)==~0U);
586 obey_ar(ResumeThread(access_thread)==~0U);
587 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
590 /* Double check that the thread really is suspended */
591 ok((error=GetExitCodeThread(thread,&exitCode))!=0 && exitCode==STILL_ACTIVE,
592 "Thread did not really suspend\n");
593 /* Resume the thread, and make sure it actually completes */
594 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
595 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
596 "Thread did not resume\n");
597 if(error!=WAIT_OBJECT_0) {
598 TerminateThread(thread,1);
600 /* Trying to suspend a terminated thread should fail */
601 error=SuspendThread(thread);
602 ok(error==~0U, "wrong return code: %ld\n", error);
603 ok(GetLastError()==ERROR_ACCESS_DENIED || GetLastError()==ERROR_NO_MORE_ITEMS, "unexpected error code: %ld\n", GetLastError());
605 ok(CloseHandle(thread)!=0,"CloseHandle Failed\n");
608 /* Check that TerminateThread works properly
610 static VOID test_TerminateThread(void)
612 HANDLE thread,access_thread,event;
613 DWORD threadId,exitCode;
614 event=CreateEventA(NULL,TRUE,FALSE,NULL);
615 thread = CreateThread(NULL,0,threadFunc4,event,0,&threadId);
616 ok(thread!=NULL,"Create Thread failed\n");
617 /* TerminateThread has a race condition in Wine. If the thread is terminated
618 before it starts, it leaves a process behind. Therefore, we wait for the
619 thread to signal that it has started. There is no easy way to force the
620 race to occur, so we don't try to find it.
622 ok(WaitForSingleObject(event,5000)==WAIT_OBJECT_0,
623 "TerminateThread didn't work\n");
624 /* check that access restrictions are obeyed */
625 if (pOpenThread) {
626 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 & (~THREAD_TERMINATE),
627 0,threadId);
628 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
629 if (access_thread!=NULL) {
630 obey_ar(TerminateThread(access_thread,99)==0);
631 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
634 /* terminate a job and make sure it terminates */
635 ok(TerminateThread(thread,99)!=0,"TerminateThread failed\n");
636 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
637 "TerminateThread didn't work\n");
638 ok(GetExitCodeThread(thread,&exitCode)!=STILL_ACTIVE,
639 "TerminateThread should not leave the thread 'STILL_ACTIVE'\n");
640 ok(exitCode==99, "TerminateThread returned invalid exit code\n");
641 ok(CloseHandle(thread)!=0,"Error Closing thread handle\n");
644 /* Check if CreateThread obeys the specified stack size. This code does
645 not work properly, and is currently disabled
647 static VOID test_CreateThread_stack(void)
649 #if CHECK_STACK
650 /* The only way I know of to test the stack size is to use alloca
651 and __try/__except. However, this is probably not portable,
652 and I couldn't get it to work under Wine anyhow. However, here
653 is the code which should allow for testing that CreateThread
654 respects the stack-size limit
656 HANDLE thread;
657 DWORD threadId,exitCode;
659 SYSTEM_INFO sysInfo;
660 sysInfo.dwPageSize=0;
661 GetSystemInfo(&sysInfo);
662 ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
663 thread = CreateThread(NULL,sysInfo.dwPageSize,
664 threadFunc5,&exitCode,
665 0,&threadId);
666 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
667 "TerminateThread didn't work\n");
668 ok(exitCode==1,"CreateThread did not obey stack-size-limit\n");
669 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
670 #endif
673 /* Check whether setting/retrieving thread priorities works */
674 static VOID test_thread_priority(void)
676 HANDLE curthread,access_thread;
677 DWORD curthreadId,exitCode;
678 int min_priority=-2,max_priority=2;
679 BOOL disabled,rc;
680 int i;
682 curthread=GetCurrentThread();
683 curthreadId=GetCurrentThreadId();
684 /* Check thread priority */
685 /* NOTE: on Win2k/XP priority can be from -7 to 6. All other platforms it
686 is -2 to 2. However, even on a real Win2k system, using thread
687 priorities beyond the -2 to 2 range does not work. If you want to try
688 anyway, enable USE_EXTENDED_PRIORITIES
690 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_NORMAL,
691 "GetThreadPriority Failed\n");
693 if (pOpenThread) {
694 /* check that access control is obeyed */
695 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 &
696 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
697 0,curthreadId);
698 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
699 if (access_thread!=NULL) {
700 obey_ar(SetThreadPriority(access_thread,1)==0);
701 obey_ar(GetThreadPriority(access_thread)==THREAD_PRIORITY_ERROR_RETURN);
702 obey_ar(GetExitCodeThread(access_thread,&exitCode)==0);
703 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
706 #if USE_EXTENDED_PRIORITIES
707 min_priority=-7; max_priority=6;
708 #endif
709 for(i=min_priority;i<=max_priority;i++) {
710 ok(SetThreadPriority(curthread,i)!=0,
711 "SetThreadPriority Failed for priority: %d\n",i);
712 ok(GetThreadPriority(curthread)==i,
713 "GetThreadPriority Failed for priority: %d\n",i);
715 ok(SetThreadPriority(curthread,THREAD_PRIORITY_TIME_CRITICAL)!=0,
716 "SetThreadPriority Failed\n");
717 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_TIME_CRITICAL,
718 "GetThreadPriority Failed\n");
719 ok(SetThreadPriority(curthread,THREAD_PRIORITY_IDLE)!=0,
720 "SetThreadPriority Failed\n");
721 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_IDLE,
722 "GetThreadPriority Failed\n");
723 ok(SetThreadPriority(curthread,0)!=0,"SetThreadPriority Failed\n");
725 /* Check that the thread priority is not changed if SetThreadPriority
726 is called with a value outside of the max/min range */
727 SetThreadPriority(curthread,min_priority);
728 SetLastError(0xdeadbeef);
729 rc = SetThreadPriority(curthread,min_priority-1);
731 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
732 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
733 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
734 "SetThreadPriority error %ld, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
735 GetLastError());
736 ok(GetThreadPriority(curthread)==min_priority,
737 "GetThreadPriority didn't return min_priority\n");
739 SetThreadPriority(curthread,max_priority);
740 SetLastError(0xdeadbeef);
741 rc = SetThreadPriority(curthread,max_priority+1);
743 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
744 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
745 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
746 "SetThreadPriority error %ld, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
747 GetLastError());
748 ok(GetThreadPriority(curthread)==max_priority,
749 "GetThreadPriority didn't return max_priority\n");
751 /* Check thread priority boost */
752 if (!pGetThreadPriorityBoost || !pSetThreadPriorityBoost)
753 return; /* Win9x */
755 SetLastError(0xdeadbeef);
756 rc=pGetThreadPriorityBoost(curthread,&disabled);
757 if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
759 win_skip("GetThreadPriorityBoost is not implemented on WinME\n");
760 return;
763 ok(rc!=0,"error=%ld\n",GetLastError());
765 if (pOpenThread) {
766 /* check that access control is obeyed */
767 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 &
768 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
769 0,curthreadId);
770 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
771 if (access_thread!=NULL) {
772 todo_wine obey_ar(pSetThreadPriorityBoost(access_thread,1)==0);
773 todo_wine obey_ar(pGetThreadPriorityBoost(access_thread,&disabled)==0);
774 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
778 rc = pSetThreadPriorityBoost(curthread,1);
779 ok( rc != 0, "error=%ld\n",GetLastError());
780 todo_wine {
781 rc=pGetThreadPriorityBoost(curthread,&disabled);
782 ok(rc!=0 && disabled==1,
783 "rc=%d error=%ld disabled=%d\n",rc,GetLastError(),disabled);
786 rc = pSetThreadPriorityBoost(curthread,0);
787 ok( rc != 0, "error=%ld\n",GetLastError());
788 rc=pGetThreadPriorityBoost(curthread,&disabled);
789 ok(rc!=0 && disabled==0,
790 "rc=%d error=%ld disabled=%d\n",rc,GetLastError(),disabled);
793 /* check the GetThreadTimes function */
794 static VOID test_GetThreadTimes(void)
796 HANDLE thread,access_thread=NULL;
797 FILETIME creationTime,exitTime,kernelTime,userTime;
798 DWORD threadId;
799 int error;
801 thread = CreateThread(NULL,0,threadFunc2,NULL,
802 CREATE_SUSPENDED,&threadId);
804 ok(thread!=NULL,"Create Thread failed\n");
805 /* check that access control is obeyed */
806 if (pOpenThread) {
807 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 &
808 (~THREAD_QUERY_INFORMATION), 0,threadId);
809 ok(access_thread!=NULL,
810 "OpenThread returned an invalid handle\n");
812 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
813 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
814 "ResumeThread didn't work\n");
815 creationTime.dwLowDateTime=99; creationTime.dwHighDateTime=99;
816 exitTime.dwLowDateTime=99; exitTime.dwHighDateTime=99;
817 kernelTime.dwLowDateTime=99; kernelTime.dwHighDateTime=99;
818 userTime.dwLowDateTime=99; userTime.dwHighDateTime=99;
819 /* GetThreadTimes should set all of the parameters passed to it */
820 error=GetThreadTimes(thread,&creationTime,&exitTime,
821 &kernelTime,&userTime);
823 if (error == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
824 win_skip("GetThreadTimes is not implemented\n");
825 else {
826 ok(error!=0,"GetThreadTimes failed\n");
827 ok(creationTime.dwLowDateTime!=99 || creationTime.dwHighDateTime!=99,
828 "creationTime was invalid\n");
829 ok(exitTime.dwLowDateTime!=99 || exitTime.dwHighDateTime!=99,
830 "exitTime was invalid\n");
831 ok(kernelTime.dwLowDateTime!=99 || kernelTime.dwHighDateTime!=99,
832 "kernelTimewas invalid\n");
833 ok(userTime.dwLowDateTime!=99 || userTime.dwHighDateTime!=99,
834 "userTime was invalid\n");
835 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
836 if(access_thread!=NULL)
838 error=GetThreadTimes(access_thread,&creationTime,&exitTime,
839 &kernelTime,&userTime);
840 obey_ar(error==0);
843 if(access_thread!=NULL) {
844 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
848 /* Check the processor affinity functions */
849 /* NOTE: These functions should also be checked that they obey access control
851 static VOID test_thread_processor(void)
853 HANDLE curthread,curproc;
854 DWORD_PTR processMask,systemMask,retMask;
855 SYSTEM_INFO sysInfo;
856 BOOL is_wow64, old_wow64 = FALSE;
857 DWORD ret;
859 if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
861 if (is_wow64)
863 TEB64 *teb64 = ULongToPtr(NtCurrentTeb()->GdiBatchCount);
864 if (teb64)
866 PEB64 *peb64 = ULongToPtr(teb64->Peb);
867 old_wow64 = !peb64->LdrData;
871 sysInfo.dwNumberOfProcessors=0;
872 GetSystemInfo(&sysInfo);
873 ok(sysInfo.dwNumberOfProcessors>0,
874 "GetSystemInfo failed to return a valid # of processors\n");
875 /* Use the current Thread/process for all tests */
876 curthread=GetCurrentThread();
877 ok(curthread!=NULL,"GetCurrentThread failed\n");
878 curproc=GetCurrentProcess();
879 ok(curproc!=NULL,"GetCurrentProcess failed\n");
880 /* Check the Affinity Mask functions */
881 ok(GetProcessAffinityMask(curproc,&processMask,&systemMask)!=0,
882 "GetProcessAffinityMask failed\n");
883 ok(SetThreadAffinityMask(curthread,processMask)==processMask,
884 "SetThreadAffinityMask failed\n");
885 ok(SetThreadAffinityMask(curthread,processMask+1)==0,
886 "SetThreadAffinityMask passed for an illegal processor\n");
887 /* NOTE: Pre-Vista does not recognize the "all processors" flag (all bits set) */
888 retMask = SetThreadAffinityMask(curthread,~0);
889 ok(broken(retMask==0) || retMask==processMask,
890 "SetThreadAffinityMask(thread,-1) failed to request all processors.\n");
892 if (retMask == processMask)
894 /* Show that the "all processors" flag is handled in ntdll */
895 DWORD_PTR mask = ~0u;
896 NTSTATUS status = pNtSetInformationThread(curthread, ThreadAffinityMask, &mask, sizeof(mask));
897 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS in NtSetInformationThread, got %lx\n", status);
900 if (retMask == processMask && sizeof(ULONG_PTR) > sizeof(ULONG))
902 /* only the low 32-bits matter */
903 retMask = SetThreadAffinityMask(curthread,~(ULONG_PTR)0);
904 ok(retMask == processMask, "SetThreadAffinityMask failed\n");
905 retMask = SetThreadAffinityMask(curthread,~(ULONG_PTR)0 >> 3);
906 ok(retMask == processMask, "SetThreadAffinityMask failed\n");
909 SetLastError(0xdeadbeef);
910 ret = SetThreadIdealProcessor(GetCurrentThread(), 0);
911 ok(ret != ~0u, "Unexpected return value %lu.\n", ret);
913 if (is_wow64)
915 SetLastError(0xdeadbeef);
916 ret = SetThreadIdealProcessor(GetCurrentThread(), MAXIMUM_PROCESSORS + 1);
917 todo_wine_if(old_wow64)
918 ok(ret != ~0u, "Unexpected return value %lu.\n", ret);
920 SetLastError(0xdeadbeef);
921 ret = SetThreadIdealProcessor(GetCurrentThread(), 65);
922 ok(ret == ~0u, "Unexpected return value %lu.\n", ret);
923 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Unexpected error %ld.\n", GetLastError());
925 else
927 SetLastError(0xdeadbeef);
928 ret = SetThreadIdealProcessor(GetCurrentThread(), MAXIMUM_PROCESSORS+1);
929 ok(ret == ~0u, "Unexpected return value %lu.\n", ret);
930 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Unexpected error %ld.\n", GetLastError());
933 ret = SetThreadIdealProcessor(GetCurrentThread(), MAXIMUM_PROCESSORS);
934 ok(ret != ~0u, "Unexpected return value %lu.\n", ret);
936 if (pGetThreadGroupAffinity && pSetThreadGroupAffinity)
938 GROUP_AFFINITY affinity, affinity_new;
939 NTSTATUS status;
941 memset(&affinity, 0, sizeof(affinity));
942 ok(pGetThreadGroupAffinity(curthread, &affinity), "GetThreadGroupAffinity failed\n");
944 SetLastError(0xdeadbeef);
945 ok(!pGetThreadGroupAffinity(curthread, NULL), "GetThreadGroupAffinity succeeded\n");
946 ok(GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == ERROR_NOACCESS), /* Win 7 and 8 */
947 "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
948 ok(affinity.Group == 0, "Expected group 0 got %u\n", affinity.Group);
950 memset(&affinity_new, 0, sizeof(affinity_new));
951 affinity_new.Group = 0;
952 affinity_new.Mask = affinity.Mask;
953 ok(pSetThreadGroupAffinity(curthread, &affinity_new, &affinity), "SetThreadGroupAffinity failed\n");
954 ok(affinity_new.Mask == affinity.Mask, "Expected old affinity mask %Ix, got %Ix\n",
955 affinity_new.Mask, affinity.Mask);
957 /* show that the "all processors" flag is not supported for SetThreadGroupAffinity */
958 if (sysInfo.dwNumberOfProcessors < 8 * sizeof(DWORD_PTR))
960 affinity_new.Group = 0;
961 affinity_new.Mask = ~(DWORD_PTR)0;
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 %ld\n", GetLastError());
968 affinity_new.Group = 1; /* assumes that you have less than 64 logical processors */
969 affinity_new.Mask = 0x1;
970 SetLastError(0xdeadbeef);
971 ok(!pSetThreadGroupAffinity(curthread, &affinity_new, NULL), "SetThreadGroupAffinity succeeded\n");
972 ok(GetLastError() == ERROR_INVALID_PARAMETER,
973 "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
975 SetLastError(0xdeadbeef);
976 ok(!pSetThreadGroupAffinity(curthread, NULL, NULL), "SetThreadGroupAffinity succeeded\n");
977 ok(GetLastError() == ERROR_NOACCESS,
978 "Expected ERROR_NOACCESS, got %ld\n", GetLastError());
980 /* show that the access violation was detected in ntdll */
981 status = pNtSetInformationThread(curthread, ThreadGroupInformation, NULL, sizeof(affinity_new));
982 ok(status == STATUS_ACCESS_VIOLATION,
983 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", status);
985 /* restore original mask */
986 affinity_new.Group = 0;
987 affinity_new.Mask = affinity.Mask;
988 SetLastError(0xdeadbeef);
989 ok(pSetThreadGroupAffinity(curthread, &affinity_new, &affinity), "SetThreadGroupAffinity failed\n");
990 ok(affinity_new.Mask == affinity.Mask, "Expected old affinity mask %Ix, got %Ix\n",
991 affinity_new.Mask, affinity.Mask);
993 else
994 win_skip("Get/SetThreadGroupAffinity not available\n");
997 static VOID test_GetCurrentThreadStackLimits(void)
999 ULONG_PTR low = 0, high = 0;
1001 if (!pGetCurrentThreadStackLimits)
1003 win_skip("GetCurrentThreadStackLimits not available.\n");
1004 return;
1007 if (0)
1009 /* crashes on native */
1010 pGetCurrentThreadStackLimits(NULL, NULL);
1011 pGetCurrentThreadStackLimits(NULL, &high);
1012 pGetCurrentThreadStackLimits(&low, NULL);
1015 pGetCurrentThreadStackLimits(&low, &high);
1016 ok(low == (ULONG_PTR)NtCurrentTeb()->DeallocationStack, "expected %p, got %Ix\n", NtCurrentTeb()->DeallocationStack, low);
1017 ok(high == (ULONG_PTR)NtCurrentTeb()->Tib.StackBase, "expected %p, got %Ix\n", NtCurrentTeb()->Tib.StackBase, high);
1020 static void test_SetThreadStackGuarantee(void)
1022 ULONG size;
1023 BOOL ret;
1025 if (!pSetThreadStackGuarantee)
1027 win_skip("SetThreadStackGuarantee not available.\n");
1028 return;
1030 size = 0;
1031 ret = pSetThreadStackGuarantee( &size );
1032 ok( ret, "failed err %lu\n", GetLastError() );
1033 ok( size == 0, "wrong size %lu\n", size );
1034 ok( NtCurrentTeb()->GuaranteedStackBytes == 0, "wrong teb %lu\n",
1035 NtCurrentTeb()->GuaranteedStackBytes );
1036 size = 0xdeadbef;
1037 ret = pSetThreadStackGuarantee( &size );
1038 ok( !ret, "succeeded\n" );
1039 ok( GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_INVALID_ADDRESS,
1040 "wrong error %lu\n", GetLastError());
1041 ok( size == 0, "wrong size %lu\n", size );
1042 ok( NtCurrentTeb()->GuaranteedStackBytes == 0, "wrong teb %lu\n",
1043 NtCurrentTeb()->GuaranteedStackBytes );
1044 size = 200;
1045 ret = pSetThreadStackGuarantee( &size );
1046 ok( ret, "failed err %lu\n", GetLastError() );
1047 ok( size == 0, "wrong size %lu\n", size );
1048 ok( NtCurrentTeb()->GuaranteedStackBytes == 4096 * sizeof(void *) / 4, "wrong teb %lu\n",
1049 NtCurrentTeb()->GuaranteedStackBytes );
1050 size = 5000;
1051 ret = pSetThreadStackGuarantee( &size );
1052 ok( ret, "failed err %lu\n", GetLastError() );
1053 ok( size == 4096 * sizeof(void *) / 4, "wrong size %lu\n", size );
1054 ok( NtCurrentTeb()->GuaranteedStackBytes == 8192, "wrong teb %lu\n",
1055 NtCurrentTeb()->GuaranteedStackBytes );
1056 size = 2000;
1057 ret = pSetThreadStackGuarantee( &size );
1058 ok( ret, "failed err %lu\n", GetLastError() );
1059 ok( size == 8192, "wrong size %lu\n", size );
1060 ok( NtCurrentTeb()->GuaranteedStackBytes == 8192, "wrong teb %lu\n",
1061 NtCurrentTeb()->GuaranteedStackBytes );
1062 size = 10000;
1063 ret = pSetThreadStackGuarantee( &size );
1064 ok( ret, "failed err %lu\n", GetLastError() );
1065 ok( size == 8192, "wrong size %lu\n", size );
1066 ok( NtCurrentTeb()->GuaranteedStackBytes == 12288, "wrong teb %lu\n",
1067 NtCurrentTeb()->GuaranteedStackBytes );
1068 ret = pSetThreadStackGuarantee( &size );
1069 ok( ret, "failed err %lu\n", GetLastError() );
1070 ok( size == 12288, "wrong size %lu\n", size );
1071 ok( NtCurrentTeb()->GuaranteedStackBytes == 12288, "wrong teb %lu\n",
1072 NtCurrentTeb()->GuaranteedStackBytes );
1075 static VOID test_GetThreadExitCode(void)
1077 DWORD exitCode, threadid;
1078 DWORD GLE, ret;
1079 HANDLE thread;
1081 ret = GetExitCodeThread((HANDLE)0x2bad2bad,&exitCode);
1082 ok(ret==0, "GetExitCodeThread returned non zero value: %ld\n", ret);
1083 GLE = GetLastError();
1084 ok(GLE==ERROR_INVALID_HANDLE, "GetLastError returned %ld (expected 6)\n", GLE);
1086 thread = CreateThread(NULL,0,threadFunc2,NULL,0,&threadid);
1087 ret = WaitForSingleObject(thread,100);
1088 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
1089 ret = GetExitCodeThread(thread,&exitCode);
1090 ok(ret==exitCode || ret==1,
1091 "GetExitCodeThread returned %ld (expected 1 or %ld)\n", ret, exitCode);
1092 ok(exitCode==99, "threadFunc2 exited with code %ld (expected 99)\n", exitCode);
1093 ok(CloseHandle(thread)!=0,"Error closing thread handle\n");
1096 #ifdef __i386__
1098 static int test_value = 0;
1099 static HANDLE event;
1101 static void WINAPI set_test_val( int val )
1103 test_value += val;
1104 ExitThread(0);
1107 static DWORD WINAPI threadFunc6(LPVOID p)
1109 SetEvent( event );
1110 Sleep( 1000 );
1111 test_value *= (int)p;
1112 return 0;
1115 static void test_SetThreadContext(void)
1117 CONTEXT ctx;
1118 int *stack;
1119 HANDLE thread;
1120 DWORD threadid;
1121 DWORD prevcount;
1122 BOOL ret;
1124 SetLastError(0xdeadbeef);
1125 event = CreateEventW( NULL, TRUE, FALSE, NULL );
1126 thread = CreateThread( NULL, 0, threadFunc6, (void *)2, 0, &threadid );
1127 ok( thread != NULL, "CreateThread failed : (%ld)\n", GetLastError() );
1128 if (!thread)
1130 trace("Thread creation failed, skipping rest of test\n");
1131 return;
1133 WaitForSingleObject( event, INFINITE );
1134 SuspendThread( thread );
1135 CloseHandle( event );
1137 ctx.ContextFlags = CONTEXT_FULL;
1138 SetLastError(0xdeadbeef);
1139 ret = GetThreadContext( thread, &ctx );
1140 ok( ret, "GetThreadContext failed : (%lu)\n", GetLastError() );
1142 if (ret)
1144 /* simulate a call to set_test_val(10) */
1145 stack = (int *)ctx.Esp;
1146 stack[-1] = 10;
1147 stack[-2] = ctx.Eip;
1148 ctx.Esp -= 2 * sizeof(int *);
1149 ctx.Eip = (DWORD)set_test_val;
1150 SetLastError(0xdeadbeef);
1151 ret = SetThreadContext( thread, &ctx );
1152 ok( ret, "SetThreadContext failed : (%ld)\n", GetLastError() );
1155 SetLastError(0xdeadbeef);
1156 prevcount = ResumeThread( thread );
1157 ok ( prevcount == 1, "Previous suspend count (%ld) instead of 1, last error : (%ld)\n",
1158 prevcount, GetLastError() );
1160 WaitForSingleObject( thread, INFINITE );
1161 ok( test_value == 10, "test_value %d\n", test_value );
1163 ctx.ContextFlags = CONTEXT_FULL;
1164 SetLastError(0xdeadbeef);
1165 ret = GetThreadContext( thread, &ctx );
1166 ok( (!ret && ((GetLastError() == ERROR_GEN_FAILURE) || (GetLastError() == ERROR_ACCESS_DENIED))) ||
1167 (!ret && broken(GetLastError() == ERROR_INVALID_HANDLE)) || /* win2k */
1168 broken(ret), /* 32bit application on NT 5.x 64bit */
1169 "got %d with %lu (expected FALSE with ERROR_GEN_FAILURE or ERROR_ACCESS_DENIED)\n",
1170 ret, GetLastError() );
1172 SetLastError(0xdeadbeef);
1173 ret = SetThreadContext( thread, &ctx );
1174 ok( (!ret && ((GetLastError() == ERROR_GEN_FAILURE) || (GetLastError() == ERROR_ACCESS_DENIED))) ||
1175 (!ret && broken(GetLastError() == ERROR_INVALID_HANDLE)) || /* win2k */
1176 broken(ret), /* 32bit application on NT 5.x 64bit */
1177 "got %d with %lu (expected FALSE with ERROR_GEN_FAILURE or ERROR_ACCESS_DENIED)\n",
1178 ret, GetLastError() );
1180 CloseHandle( thread );
1183 static DWORD WINAPI test_stack( void *arg )
1185 DWORD *stack = (DWORD *)(((DWORD)&arg & ~0xfff) + 0x1000);
1187 ok( stack == NtCurrentTeb()->Tib.StackBase, "wrong stack %p/%p\n",
1188 stack, NtCurrentTeb()->Tib.StackBase );
1189 ok( !stack[-1], "wrong data %p = %08lx\n", stack - 1, stack[-1] );
1190 return 0;
1193 static void test_GetThreadContext(void)
1195 CONTEXT ctx;
1196 BOOL ret;
1197 HANDLE thread;
1199 memset(&ctx, 0xcc, sizeof(ctx));
1200 ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
1201 ret = GetThreadContext(GetCurrentThread(), &ctx);
1202 ok(ret, "GetThreadContext failed: %lu\n", GetLastError());
1203 ok(ctx.ContextFlags == CONTEXT_DEBUG_REGISTERS, "ContextFlags = %lx\n", ctx.ContextFlags);
1204 ok(!ctx.Dr0, "Dr0 = %lx\n", ctx.Dr0);
1205 ok(!ctx.Dr1, "Dr0 = %lx\n", ctx.Dr0);
1207 thread = CreateThread( NULL, 0, test_stack, (void *)0x1234, 0, NULL );
1208 WaitForSingleObject( thread, 1000 );
1209 CloseHandle( thread );
1212 static void test_GetThreadSelectorEntry(void)
1214 LDT_ENTRY entry;
1215 CONTEXT ctx;
1216 DWORD limit;
1217 void *base;
1218 BOOL ret;
1220 memset(&ctx, 0x11, sizeof(ctx));
1221 ctx.ContextFlags = CONTEXT_SEGMENTS | CONTEXT_CONTROL;
1222 ret = GetThreadContext(GetCurrentThread(), &ctx);
1223 ok(ret, "GetThreadContext error %lu\n", GetLastError());
1224 ok(!HIWORD(ctx.SegCs), "expected HIWORD(SegCs) == 0, got %lu\n", ctx.SegCs);
1225 ok(!HIWORD(ctx.SegDs), "expected HIWORD(SegDs) == 0, got %lu\n", ctx.SegDs);
1226 ok(!HIWORD(ctx.SegFs), "expected HIWORD(SegFs) == 0, got %lu\n", ctx.SegFs);
1228 ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegCs, &entry);
1229 ok(ret, "GetThreadSelectorEntry(SegCs) error %lu\n", GetLastError());
1230 ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegDs, &entry);
1231 ok(ret, "GetThreadSelectorEntry(SegDs) error %lu\n", GetLastError());
1232 ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegDs & ~3, &entry);
1233 ok(ret, "GetThreadSelectorEntry(SegDs) error %lu\n", GetLastError());
1234 ret = GetThreadSelectorEntry(GetCurrentThread(), 0, &entry);
1235 ok(ret, "GetThreadSelectorEntry(SegDs) error %lu\n", GetLastError());
1236 ret = GetThreadSelectorEntry(GetCurrentThread(), 3, &entry);
1237 ok(ret, "GetThreadSelectorEntry(SegDs) error %lu\n", GetLastError());
1238 SetLastError( 0xdeadbeef );
1239 ret = GetThreadSelectorEntry(GetCurrentThread(), 0xdeadbeef, &entry);
1240 ok(!ret, "GetThreadSelectorEntry(invalid) succeeded\n");
1241 ok( GetLastError() == ERROR_GEN_FAILURE
1242 || GetLastError() == ERROR_INVALID_THREAD_ID /* 32-bit */, "wrong error %lu\n", GetLastError() );
1243 ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegDs + 0x100, &entry);
1244 ok(!ret, "GetThreadSelectorEntry(invalid) succeeded\n");
1245 ok( GetLastError() == ERROR_GEN_FAILURE
1246 || GetLastError() == ERROR_NOACCESS /* 32-bit */, "wrong error %lu\n", GetLastError() );
1248 memset(&entry, 0x11, sizeof(entry));
1249 ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegFs, &entry);
1250 ok(ret, "GetThreadSelectorEntry(SegFs) error %lu\n", GetLastError());
1251 entry.HighWord.Bits.Type &= ~1; /* ignore accessed bit */
1253 base = (void *)((entry.HighWord.Bits.BaseHi << 24) | (entry.HighWord.Bits.BaseMid << 16) | entry.BaseLow);
1254 limit = (entry.HighWord.Bits.LimitHi << 16) | entry.LimitLow;
1256 ok(base == NtCurrentTeb(), "expected %p, got %p\n", NtCurrentTeb(), base);
1257 ok(limit == 0x0fff || limit == 0x4000, "expected 0x0fff or 0x4000, got %#lx\n", limit);
1258 ok(entry.HighWord.Bits.Type == 0x12, "expected 0x12, got %#x\n", entry.HighWord.Bits.Type);
1259 ok(entry.HighWord.Bits.Dpl == 3, "expected 3, got %u\n", entry.HighWord.Bits.Dpl);
1260 ok(entry.HighWord.Bits.Pres == 1, "expected 1, got %u\n", entry.HighWord.Bits.Pres);
1261 ok(entry.HighWord.Bits.Sys == 0, "expected 0, got %u\n", entry.HighWord.Bits.Sys);
1262 ok(entry.HighWord.Bits.Reserved_0 == 0, "expected 0, got %u\n", entry.HighWord.Bits.Reserved_0);
1263 ok(entry.HighWord.Bits.Default_Big == 1, "expected 1, got %u\n", entry.HighWord.Bits.Default_Big);
1264 ok(entry.HighWord.Bits.Granularity == 0, "expected 0, got %u\n", entry.HighWord.Bits.Granularity);
1266 memset(&entry, 0x11, sizeof(entry));
1267 ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegCs, &entry);
1268 ok(ret, "GetThreadSelectorEntry(SegDs) error %lu\n", GetLastError());
1269 entry.HighWord.Bits.Type &= ~1; /* ignore accessed bit */
1270 base = (void *)((entry.HighWord.Bits.BaseHi << 24) | (entry.HighWord.Bits.BaseMid << 16) | entry.BaseLow);
1271 limit = (entry.HighWord.Bits.LimitHi << 16) | entry.LimitLow;
1273 ok(base == 0, "got base %p\n", base);
1274 ok(limit == ~0u >> 12, "got limit %#lx\n", limit);
1275 ok(entry.HighWord.Bits.Type == 0x1a, "expected 0x12, got %#x\n", entry.HighWord.Bits.Type);
1276 ok(entry.HighWord.Bits.Dpl == 3, "expected 3, got %u\n", entry.HighWord.Bits.Dpl);
1277 ok(entry.HighWord.Bits.Pres == 1, "expected 1, got %u\n", entry.HighWord.Bits.Pres);
1278 ok(entry.HighWord.Bits.Sys == 0, "expected 0, got %u\n", entry.HighWord.Bits.Sys);
1279 ok(entry.HighWord.Bits.Reserved_0 == 0, "expected 0, got %u\n", entry.HighWord.Bits.Reserved_0);
1280 ok(entry.HighWord.Bits.Default_Big == 1, "expected 1, got %u\n", entry.HighWord.Bits.Default_Big);
1281 ok(entry.HighWord.Bits.Granularity == 1, "expected 1, got %u\n", entry.HighWord.Bits.Granularity);
1283 memset(&entry, 0x11, sizeof(entry));
1284 ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegDs, &entry);
1285 ok(ret, "GetThreadSelectorEntry(SegDs) error %lu\n", GetLastError());
1286 entry.HighWord.Bits.Type &= ~1; /* ignore accessed bit */
1287 base = (void *)((entry.HighWord.Bits.BaseHi << 24) | (entry.HighWord.Bits.BaseMid << 16) | entry.BaseLow);
1288 limit = (entry.HighWord.Bits.LimitHi << 16) | entry.LimitLow;
1290 ok(base == 0, "got base %p\n", base);
1291 ok(limit == ~0u >> 12, "got limit %#lx\n", limit);
1292 ok(entry.HighWord.Bits.Type == 0x12, "expected 0x12, got %#x\n", entry.HighWord.Bits.Type);
1293 ok(entry.HighWord.Bits.Dpl == 3, "expected 3, got %u\n", entry.HighWord.Bits.Dpl);
1294 ok(entry.HighWord.Bits.Pres == 1, "expected 1, got %u\n", entry.HighWord.Bits.Pres);
1295 ok(entry.HighWord.Bits.Sys == 0, "expected 0, got %u\n", entry.HighWord.Bits.Sys);
1296 ok(entry.HighWord.Bits.Reserved_0 == 0, "expected 0, got %u\n", entry.HighWord.Bits.Reserved_0);
1297 ok(entry.HighWord.Bits.Default_Big == 1, "expected 1, got %u\n", entry.HighWord.Bits.Default_Big);
1298 ok(entry.HighWord.Bits.Granularity == 1, "expected 1, got %u\n", entry.HighWord.Bits.Granularity);
1301 #endif /* __i386__ */
1303 static HANDLE finish_event;
1304 static LONG times_executed;
1306 static DWORD CALLBACK work_function(void *p)
1308 LONG executed = InterlockedIncrement(&times_executed);
1310 if (executed == 100)
1311 SetEvent(finish_event);
1312 return 0;
1315 static void test_QueueUserWorkItem(void)
1317 INT_PTR i;
1318 DWORD wait_result;
1319 DWORD before, after;
1321 /* QueueUserWorkItem not present on win9x */
1322 if (!pQueueUserWorkItem) return;
1324 finish_event = CreateEventW(NULL, TRUE, FALSE, NULL);
1326 before = GetTickCount();
1328 for (i = 0; i < 100; i++)
1330 BOOL ret = pQueueUserWorkItem(work_function, (void *)i, WT_EXECUTEDEFAULT);
1331 ok(ret, "QueueUserWorkItem failed with error %ld\n", GetLastError());
1334 wait_result = WaitForSingleObject(finish_event, 10000);
1336 after = GetTickCount();
1337 trace("100 QueueUserWorkItem calls took %ldms\n", after - before);
1338 ok(wait_result == WAIT_OBJECT_0, "wait failed with error 0x%lx\n", wait_result);
1340 ok(times_executed == 100, "didn't execute all of the work items\n");
1343 static void CALLBACK signaled_function(PVOID p, BOOLEAN TimerOrWaitFired)
1345 HANDLE event = p;
1346 SetEvent(event);
1347 ok(!TimerOrWaitFired, "wait shouldn't have timed out\n");
1350 static void CALLBACK wait_complete_function(PVOID p, BOOLEAN TimerOrWaitFired)
1352 HANDLE event = p;
1353 DWORD res;
1354 ok(!TimerOrWaitFired, "wait shouldn't have timed out\n");
1355 res = WaitForSingleObject(event, INFINITE);
1356 ok(res == WAIT_OBJECT_0, "WaitForSingleObject returned %lx\n", res);
1359 static void CALLBACK timeout_function(PVOID p, BOOLEAN TimerOrWaitFired)
1361 HANDLE event = p;
1362 SetEvent(event);
1363 ok(TimerOrWaitFired, "wait should have timed out\n");
1366 struct waitthread_test_param
1368 HANDLE trigger_event;
1369 HANDLE wait_event;
1370 HANDLE complete_event;
1373 static void CALLBACK waitthread_test_function(PVOID p, BOOLEAN TimerOrWaitFired)
1375 struct waitthread_test_param *param = p;
1376 DWORD ret;
1378 SetEvent(param->trigger_event);
1379 ret = WaitForSingleObject(param->wait_event, 100);
1380 ok(ret == WAIT_TIMEOUT, "wait should have timed out\n");
1381 SetEvent(param->complete_event);
1384 struct unregister_params
1386 HANDLE wait_handle;
1387 HANDLE complete_event;
1390 static void CALLBACK unregister_function(PVOID p, BOOLEAN TimerOrWaitFired)
1392 struct unregister_params *param = p;
1393 HANDLE wait_handle = param->wait_handle;
1394 BOOL ret;
1395 ok(wait_handle != INVALID_HANDLE_VALUE, "invalid wait handle\n");
1396 ret = pUnregisterWait(param->wait_handle);
1397 todo_wine ok(ret, "UnregisterWait failed with error %ld\n", GetLastError());
1398 SetEvent(param->complete_event);
1401 static void test_RegisterWaitForSingleObject(void)
1403 BOOL ret;
1404 HANDLE wait_handle, wait_handle2;
1405 HANDLE handle;
1406 HANDLE complete_event;
1407 HANDLE waitthread_trigger_event, waitthread_wait_event;
1408 struct waitthread_test_param param;
1409 struct unregister_params unregister_param;
1410 DWORD i;
1412 if (!pRegisterWaitForSingleObject || !pUnregisterWait)
1414 win_skip("RegisterWaitForSingleObject or UnregisterWait not implemented\n");
1415 return;
1418 /* test signaled case */
1420 handle = CreateEventW(NULL, TRUE, TRUE, NULL);
1421 complete_event = CreateEventW(NULL, FALSE, FALSE, NULL);
1423 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1424 ok(ret, "RegisterWaitForSingleObject failed with error %ld\n", GetLastError());
1426 WaitForSingleObject(complete_event, INFINITE);
1427 /* give worker thread chance to complete */
1428 Sleep(100);
1430 ret = pUnregisterWait(wait_handle);
1431 ok(ret, "UnregisterWait failed with error %ld\n", GetLastError());
1433 /* test cancel case */
1435 ResetEvent(handle);
1437 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1438 ok(ret, "RegisterWaitForSingleObject failed with error %ld\n", GetLastError());
1440 ret = pUnregisterWait(wait_handle);
1441 ok(ret, "UnregisterWait failed with error %ld\n", GetLastError());
1443 /* test unregister while running */
1445 SetEvent(handle);
1446 ret = pRegisterWaitForSingleObject(&wait_handle, handle, wait_complete_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1447 ok(ret, "RegisterWaitForSingleObject failed with error %ld\n", GetLastError());
1449 /* give worker thread chance to start */
1450 Sleep(50);
1451 ret = pUnregisterWait(wait_handle);
1452 ok(!ret, "UnregisterWait succeeded\n");
1453 ok(GetLastError() == ERROR_IO_PENDING, "UnregisterWait failed with error %ld\n", GetLastError());
1455 /* give worker thread chance to complete */
1456 SetEvent(complete_event);
1457 Sleep(50);
1459 /* test timeout case */
1461 ResetEvent(handle);
1463 ret = pRegisterWaitForSingleObject(&wait_handle, handle, timeout_function, complete_event, 0, WT_EXECUTEONLYONCE);
1464 ok(ret, "RegisterWaitForSingleObject failed with error %ld\n", GetLastError());
1466 WaitForSingleObject(complete_event, INFINITE);
1467 /* give worker thread chance to complete */
1468 Sleep(100);
1470 ret = pUnregisterWait(wait_handle);
1471 ok(ret, "UnregisterWait failed with error %ld\n", GetLastError());
1473 SetLastError(0xdeadbeef);
1474 ret = pUnregisterWait(NULL);
1475 ok(!ret, "Expected UnregisterWait to fail\n");
1476 ok(GetLastError() == ERROR_INVALID_HANDLE,
1477 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1479 /* test WT_EXECUTEINWAITTHREAD */
1481 SetEvent(handle);
1482 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE | WT_EXECUTEINWAITTHREAD);
1483 ok(ret, "RegisterWaitForSingleObject failed with error %ld\n", GetLastError());
1485 WaitForSingleObject(complete_event, INFINITE);
1486 /* give worker thread chance to complete */
1487 Sleep(100);
1489 ret = pUnregisterWait(wait_handle);
1490 ok(ret, "UnregisterWait failed with error %ld\n", GetLastError());
1492 /* the callback execution should be sequentially consistent with the wait handle return,
1493 even if the event is already set */
1495 for (i = 0; i < 100; ++i)
1497 SetEvent(handle);
1498 unregister_param.complete_event = complete_event;
1499 unregister_param.wait_handle = INVALID_HANDLE_VALUE;
1501 ret = pRegisterWaitForSingleObject(&unregister_param.wait_handle, handle, unregister_function, &unregister_param, INFINITE, WT_EXECUTEONLYONCE | WT_EXECUTEINWAITTHREAD);
1502 ok(ret, "RegisterWaitForSingleObject failed with error %ld\n", GetLastError());
1504 WaitForSingleObject(complete_event, INFINITE);
1507 /* test multiple waits with WT_EXECUTEINWAITTHREAD.
1508 * Windows puts multiple waits on the same wait thread, and using WT_EXECUTEINWAITTHREAD causes the callbacks to run serially.
1511 SetEvent(handle);
1512 waitthread_trigger_event = CreateEventW(NULL, FALSE, FALSE, NULL);
1513 waitthread_wait_event = CreateEventW(NULL, FALSE, FALSE, NULL);
1515 param.trigger_event = waitthread_trigger_event;
1516 param.wait_event = waitthread_wait_event;
1517 param.complete_event = complete_event;
1519 ret = pRegisterWaitForSingleObject(&wait_handle2, waitthread_trigger_event, signaled_function, waitthread_wait_event,
1520 INFINITE, WT_EXECUTEONLYONCE | WT_EXECUTEINWAITTHREAD);
1521 ok(ret, "RegisterWaitForSingleObject failed with error %ld\n", GetLastError());
1523 ret = pRegisterWaitForSingleObject(&wait_handle, handle, waitthread_test_function, &param, INFINITE, WT_EXECUTEONLYONCE | WT_EXECUTEINWAITTHREAD);
1524 ok(ret, "RegisterWaitForSingleObject failed with error %ld\n", GetLastError());
1526 WaitForSingleObject(complete_event, INFINITE);
1527 /* give worker thread chance to complete */
1528 Sleep(100);
1530 ret = pUnregisterWait(wait_handle);
1531 ok(ret, "UnregisterWait failed with error %ld\n", GetLastError());
1533 ret = pUnregisterWait(wait_handle2);
1534 ok(ret, "UnregisterWait failed with error %ld\n", GetLastError());
1536 CloseHandle(waitthread_wait_event);
1537 CloseHandle(waitthread_trigger_event);
1538 CloseHandle(complete_event);
1539 CloseHandle(handle);
1542 static DWORD LS_main;
1543 static DWORD LS_index0, LS_index1;
1544 static DWORD LS_OutOfIndexesValue;
1546 /* Function pointers to the FLS/TLS functions to test in LS_ThreadProc() */
1547 static DWORD (WINAPI *LS_AllocFunc)(void);
1548 static PVOID (WINAPI *LS_GetValueFunc)(DWORD);
1549 static BOOL (WINAPI *LS_SetValueFunc)(DWORD, PVOID);
1550 static BOOL (WINAPI *LS_FreeFunc)(DWORD);
1552 /* Names of the functions tested in LS_ThreadProc(), for error messages */
1553 static const char* LS_AllocFuncName = "";
1554 static const char* LS_GetValueFuncName = "";
1555 static const char* LS_SetValueFuncName = "";
1556 static const char* LS_FreeFuncName = "";
1558 /* FLS entry points, dynamically loaded in platforms that support them */
1559 static DWORD (WINAPI *pFlsAlloc)(PFLS_CALLBACK_FUNCTION);
1560 static BOOL (WINAPI *pFlsFree)(DWORD);
1561 static PVOID (WINAPI *pFlsGetValue)(DWORD);
1562 static BOOL (WINAPI *pFlsSetValue)(DWORD,PVOID);
1564 /* A thunk function to make FlsAlloc compatible with the signature of TlsAlloc */
1565 static DWORD WINAPI FLS_AllocFuncThunk(void)
1567 return pFlsAlloc(NULL);
1570 static DWORD WINAPI LS_InheritanceProc(LPVOID p)
1572 /* We should NOT inherit the FLS/TLS values from our parent or from the
1573 main thread. */
1574 LPVOID val;
1576 val = LS_GetValueFunc(LS_main);
1577 ok(val == NULL, "%s inheritance failed\n", LS_GetValueFuncName);
1579 val = LS_GetValueFunc(LS_index0);
1580 ok(val == NULL, "%s inheritance failed\n", LS_GetValueFuncName);
1582 val = LS_GetValueFunc(LS_index1);
1583 ok(val == NULL, "%s inheritance failed\n", LS_GetValueFuncName);
1585 return 0;
1588 /* Basic FLS/TLS usage test. Make sure we can create slots and the values we
1589 store in them are separate among threads. Also test FLS/TLS value
1590 inheritance with LS_InheritanceProc. */
1591 static DWORD WINAPI LS_ThreadProc(LPVOID p)
1593 LONG_PTR id = (LONG_PTR) p;
1594 LPVOID val;
1595 BOOL ret;
1597 if (sync_threads_and_run_one(0, id))
1599 LS_index0 = LS_AllocFunc();
1600 ok(LS_index0 != LS_OutOfIndexesValue, "%s failed\n", LS_AllocFuncName);
1602 resync_after_run();
1604 if (sync_threads_and_run_one(1, id))
1606 LS_index1 = LS_AllocFunc();
1607 ok(LS_index1 != LS_OutOfIndexesValue, "%s failed\n", LS_AllocFuncName);
1609 /* Slot indices should be different even if created in different
1610 threads. */
1611 ok(LS_index0 != LS_index1, "%s failed\n", LS_AllocFuncName);
1613 /* Both slots should be initialized to NULL */
1614 SetLastError(0xdeadbeef);
1615 val = LS_GetValueFunc(LS_index0);
1616 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1617 ok(val == NULL, "Slot not initialized correctly\n");
1619 SetLastError(0xdeadbeef);
1620 val = LS_GetValueFunc(LS_index1);
1621 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1622 ok(val == NULL, "Slot not initialized correctly\n");
1624 resync_after_run();
1626 if (sync_threads_and_run_one(0, id))
1628 SetLastError(0xdeadbeef);
1629 val = LS_GetValueFunc(LS_index0);
1630 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1631 ok(val == NULL, "Slot not initialized correctly\n");
1633 SetLastError(0xdeadbeef);
1634 val = LS_GetValueFunc(LS_index1);
1635 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1636 ok(val == NULL, "Slot not initialized correctly\n");
1638 ret = LS_SetValueFunc(LS_index0, (LPVOID) 1);
1639 ok(ret, "%s failed\n", LS_SetValueFuncName);
1641 ret = LS_SetValueFunc(LS_index1, (LPVOID) 2);
1642 ok(ret, "%s failed\n", LS_SetValueFuncName);
1644 SetLastError(0xdeadbeef);
1645 val = LS_GetValueFunc(LS_index0);
1646 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1647 ok(val == (LPVOID) 1, "Slot not initialized correctly\n");
1649 SetLastError(0xdeadbeef);
1650 val = LS_GetValueFunc(LS_index1);
1651 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1652 ok(val == (LPVOID) 2, "Slot not initialized correctly\n");
1654 resync_after_run();
1656 if (sync_threads_and_run_one(1, id))
1658 val = LS_GetValueFunc(LS_index0);
1659 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1660 ok(val == NULL, "Slot not initialized correctly\n");
1662 val = LS_GetValueFunc(LS_index1);
1663 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1664 ok(val == NULL, "Slot not initialized correctly\n");
1666 ret = LS_SetValueFunc(LS_index0, (LPVOID) 3);
1667 ok(ret, "%s failed\n", LS_SetValueFuncName);
1669 ret = LS_SetValueFunc(LS_index1, (LPVOID) 4);
1670 ok(ret, "%s failed\n", LS_SetValueFuncName);
1672 val = LS_GetValueFunc(LS_index0);
1673 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1674 ok(val == (LPVOID) 3, "Slot not initialized correctly\n");
1676 val = LS_GetValueFunc(LS_index1);
1677 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1678 ok(val == (LPVOID) 4, "Slot not initialized correctly\n");
1680 resync_after_run();
1682 if (sync_threads_and_run_one(0, id))
1684 HANDLE thread;
1685 DWORD waitret, tid;
1687 val = LS_GetValueFunc(LS_index0);
1688 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1689 ok(val == (LPVOID) 1, "Slot not initialized correctly\n");
1691 val = LS_GetValueFunc(LS_index1);
1692 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1693 ok(val == (LPVOID) 2, "Slot not initialized correctly\n");
1695 thread = CreateThread(NULL, 0, LS_InheritanceProc, 0, 0, &tid);
1696 ok(thread != NULL, "CreateThread failed\n");
1697 waitret = WaitForSingleObject(thread, 60000);
1698 ok(waitret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
1699 CloseHandle(thread);
1701 ret = LS_FreeFunc(LS_index0);
1702 ok(ret, "%s failed\n", LS_FreeFuncName);
1704 resync_after_run();
1706 if (sync_threads_and_run_one(1, id))
1708 ret = LS_FreeFunc(LS_index1);
1709 ok(ret, "%s failed\n", LS_FreeFuncName);
1711 resync_after_run();
1713 return 0;
1716 static void run_LS_tests(void)
1718 HANDLE threads[2];
1719 LONG_PTR i;
1720 DWORD ret;
1721 BOOL suc;
1723 init_thread_sync_helpers();
1725 /* Allocate a slot in the main thread to test for inheritance. */
1726 LS_main = LS_AllocFunc();
1727 ok(LS_main != LS_OutOfIndexesValue, "%s failed\n", LS_AllocFuncName);
1728 suc = LS_SetValueFunc(LS_main, (LPVOID) 4114);
1729 ok(suc, "%s failed\n", LS_SetValueFuncName);
1731 for (i = 0; i < 2; ++i)
1733 DWORD tid;
1735 threads[i] = CreateThread(NULL, 0, LS_ThreadProc, (LPVOID) i, 0, &tid);
1736 ok(threads[i] != NULL, "CreateThread failed\n");
1739 ret = WaitForMultipleObjects(2, threads, TRUE, 60000);
1740 ok(ret == WAIT_OBJECT_0 || broken(ret == WAIT_OBJECT_0+1 /* nt4,w2k */), "WaitForAllObjects 2 threads %ld\n",ret);
1742 for (i = 0; i < 2; ++i)
1743 CloseHandle(threads[i]);
1745 suc = LS_FreeFunc(LS_main);
1746 ok(suc, "%s failed\n", LS_FreeFuncName);
1747 cleanup_thread_sync_helpers();
1750 static void test_TLS(void)
1752 LS_OutOfIndexesValue = TLS_OUT_OF_INDEXES;
1754 LS_AllocFunc = &TlsAlloc;
1755 LS_GetValueFunc = &TlsGetValue;
1756 LS_SetValueFunc = &TlsSetValue;
1757 LS_FreeFunc = &TlsFree;
1759 LS_AllocFuncName = "TlsAlloc";
1760 LS_GetValueFuncName = "TlsGetValue";
1761 LS_SetValueFuncName = "TlsSetValue";
1762 LS_FreeFuncName = "TlsFree";
1764 run_LS_tests();
1767 static void test_FLS(void)
1769 if (!pFlsAlloc || !pFlsFree || !pFlsGetValue || !pFlsSetValue)
1771 win_skip("Fiber Local Storage not supported\n");
1772 return;
1775 LS_OutOfIndexesValue = FLS_OUT_OF_INDEXES;
1777 LS_AllocFunc = &FLS_AllocFuncThunk;
1778 LS_GetValueFunc = pFlsGetValue;
1779 LS_SetValueFunc = pFlsSetValue;
1780 LS_FreeFunc = pFlsFree;
1782 LS_AllocFuncName = "FlsAlloc";
1783 LS_GetValueFuncName = "FlsGetValue";
1784 LS_SetValueFuncName = "FlsSetValue";
1785 LS_FreeFuncName = "FlsFree";
1787 run_LS_tests();
1790 static void test_ThreadErrorMode(void)
1792 DWORD oldmode;
1793 DWORD mode;
1794 DWORD rtlmode;
1795 BOOL ret;
1797 if (!pSetThreadErrorMode || !pGetThreadErrorMode)
1799 win_skip("SetThreadErrorMode and/or GetThreadErrorMode unavailable (added in Windows 7)\n");
1800 return;
1803 if (!pRtlGetThreadErrorMode) {
1804 win_skip("RtlGetThreadErrorMode not available\n");
1805 return;
1808 oldmode = pGetThreadErrorMode();
1810 ret = pSetThreadErrorMode(0, &mode);
1811 ok(ret, "SetThreadErrorMode failed\n");
1812 ok(mode == oldmode,
1813 "SetThreadErrorMode returned old mode 0x%lx, expected 0x%lx\n",
1814 mode, oldmode);
1815 mode = pGetThreadErrorMode();
1816 ok(mode == 0, "GetThreadErrorMode returned mode 0x%lx, expected 0\n", mode);
1817 rtlmode = pRtlGetThreadErrorMode();
1818 ok(rtlmode == 0,
1819 "RtlGetThreadErrorMode returned mode 0x%lx, expected 0\n", mode);
1821 ret = pSetThreadErrorMode(SEM_FAILCRITICALERRORS, &mode);
1822 ok(ret, "SetThreadErrorMode failed\n");
1823 ok(mode == 0,
1824 "SetThreadErrorMode returned old mode 0x%lx, expected 0\n", mode);
1825 mode = pGetThreadErrorMode();
1826 ok(mode == SEM_FAILCRITICALERRORS,
1827 "GetThreadErrorMode returned mode 0x%lx, expected SEM_FAILCRITICALERRORS\n",
1828 mode);
1829 rtlmode = pRtlGetThreadErrorMode();
1830 ok(rtlmode == 0x10,
1831 "RtlGetThreadErrorMode returned mode 0x%lx, expected 0x10\n", mode);
1833 ret = pSetThreadErrorMode(SEM_NOGPFAULTERRORBOX, &mode);
1834 ok(ret, "SetThreadErrorMode failed\n");
1835 ok(mode == SEM_FAILCRITICALERRORS,
1836 "SetThreadErrorMode returned old mode 0x%lx, expected SEM_FAILCRITICALERRORS\n",
1837 mode);
1838 mode = pGetThreadErrorMode();
1839 ok(mode == SEM_NOGPFAULTERRORBOX,
1840 "GetThreadErrorMode returned mode 0x%lx, expected SEM_NOGPFAULTERRORBOX\n",
1841 mode);
1842 rtlmode = pRtlGetThreadErrorMode();
1843 ok(rtlmode == 0x20,
1844 "RtlGetThreadErrorMode returned mode 0x%lx, expected 0x20\n", mode);
1846 ret = pSetThreadErrorMode(SEM_NOOPENFILEERRORBOX, NULL);
1847 ok(ret, "SetThreadErrorMode failed\n");
1848 mode = pGetThreadErrorMode();
1849 ok(mode == SEM_NOOPENFILEERRORBOX,
1850 "GetThreadErrorMode returned mode 0x%lx, expected SEM_NOOPENFILEERRORBOX\n",
1851 mode);
1852 rtlmode = pRtlGetThreadErrorMode();
1853 ok(rtlmode == 0x40,
1854 "RtlGetThreadErrorMode returned mode 0x%lx, expected 0x40\n", rtlmode);
1856 for (mode = 1; mode; mode <<= 1)
1858 ret = pSetThreadErrorMode(mode, NULL);
1859 if (mode & (SEM_FAILCRITICALERRORS |
1860 SEM_NOGPFAULTERRORBOX |
1861 SEM_NOOPENFILEERRORBOX))
1863 ok(ret,
1864 "SetThreadErrorMode(0x%lx,NULL) failed with error %ld\n",
1865 mode, GetLastError());
1867 else
1869 DWORD GLE = GetLastError();
1870 ok(!ret,
1871 "SetThreadErrorMode(0x%lx,NULL) succeeded, expected failure\n",
1872 mode);
1873 ok(GLE == ERROR_INVALID_PARAMETER,
1874 "SetThreadErrorMode(0x%lx,NULL) failed with %ld, "
1875 "expected ERROR_INVALID_PARAMETER\n",
1876 mode, GLE);
1880 pSetThreadErrorMode(oldmode, NULL);
1883 struct fpu_thread_ctx
1885 unsigned int cw;
1886 unsigned long fpu_cw;
1887 HANDLE finished;
1890 static inline unsigned long get_fpu_cw(void)
1892 #if defined(__i386__) || defined(__x86_64__)
1893 WORD cw = 0;
1894 unsigned int sse = 0;
1895 #ifdef _MSC_VER
1896 __asm { fnstcw [cw] }
1897 __asm { stmxcsr [sse] }
1898 #else
1899 __asm__ volatile ("fnstcw %0" : "=m" (cw));
1900 __asm__ volatile ("stmxcsr %0" : "=m" (sse));
1901 #endif
1902 return MAKELONG( cw, sse );
1903 #elif defined(__aarch64__)
1904 ULONG_PTR cw;
1905 __asm__ __volatile__( "mrs %0, fpcr" : "=r" (cw) );
1906 return cw;
1907 #else
1908 return 0;
1909 #endif
1912 static inline void fpu_invalid_operation(void)
1914 double d;
1916 #if defined(__i386__)
1917 unsigned int sse;
1918 #ifdef _MSC_VER
1919 __asm { stmxcsr [sse] }
1920 sse |= 1; /* invalid operation flag */
1921 __asm { ldmxcsr [sse] }
1922 #else
1923 __asm__ volatile ("stmxcsr %0" : "=m" (sse));
1924 sse |= 1;
1925 __asm__ volatile ("ldmxcsr %0" : : "m" (sse));
1926 #endif
1927 #endif
1929 d = acos(2.0);
1930 ok(_isnan(d), "d = %lf\n", d);
1931 ok(_statusfp() == _SW_INVALID, "_statusfp() = %x\n", _statusfp());
1934 static DWORD WINAPI fpu_thread(void *param)
1936 struct fpu_thread_ctx *ctx = param;
1937 BOOL ret;
1939 ctx->cw = _control87( 0, 0 );
1940 ctx->fpu_cw = get_fpu_cw();
1942 ret = SetEvent(ctx->finished);
1943 ok(ret, "SetEvent failed, last error %#lx.\n", GetLastError());
1945 return 0;
1948 static unsigned int get_thread_fpu_cw( unsigned long *fpu_cw )
1950 struct fpu_thread_ctx ctx;
1951 DWORD tid, res;
1952 HANDLE thread;
1954 ctx.finished = CreateEventW(NULL, FALSE, FALSE, NULL);
1955 ok(!!ctx.finished, "Failed to create event, last error %#lx.\n", GetLastError());
1957 thread = CreateThread(NULL, 0, fpu_thread, &ctx, 0, &tid);
1958 ok(!!thread, "Failed to create thread, last error %#lx.\n", GetLastError());
1960 res = WaitForSingleObject(ctx.finished, INFINITE);
1961 ok(res == WAIT_OBJECT_0, "Wait failed (%#lx), last error %#lx.\n", res, GetLastError());
1963 res = CloseHandle(ctx.finished);
1964 ok(!!res, "Failed to close event handle, last error %#lx.\n", GetLastError());
1966 CloseHandle(thread);
1967 *fpu_cw = ctx.fpu_cw;
1968 return ctx.cw;
1971 static void test_thread_fpu_cw(void)
1973 static const struct {
1974 unsigned int cw; unsigned long fpu_cw; unsigned long fpu_cw_broken;
1975 } expected_cw[8] =
1977 #ifdef __i386__
1978 { _MCW_EM | _PC_53, MAKELONG( 0x27f, 0x1f80 ) },
1979 { _MCW_EM | _PC_53, MAKELONG( 0x27f, 0x1f80 ) },
1980 { _EM_INEXACT | _RC_CHOP | _PC_24, MAKELONG( 0xc60, 0x7000 ), MAKELONG( 0xc60, 0x1f80 ) },
1981 { _MCW_EM | _PC_53, MAKELONG( 0x27f, 0x1f80 ) },
1982 { _EM_INEXACT | _RC_CHOP | _PC_24, MAKELONG( 0xc60, 0x7000 ), MAKELONG( 0xc60, 0x1f80 ) },
1983 { _MCW_EM | _PC_53, MAKELONG( 0x27f, 0x1f80 ) },
1984 { _MCW_EM | _PC_53, MAKELONG( 0x27f, 0x1f81 ) },
1985 { _MCW_EM | _PC_53, MAKELONG( 0x27f, 0x1f81 ) }
1986 #elif defined(__x86_64__)
1987 { _MCW_EM | _PC_64, MAKELONG( 0x27f, 0x1f80 ) },
1988 { _MCW_EM | _PC_64, MAKELONG( 0x27f, 0x1f80 ) },
1989 { _EM_INEXACT | _RC_CHOP | _PC_64, MAKELONG( 0x27f, 0x7000 ) },
1990 { _MCW_EM | _PC_64, MAKELONG( 0x27f, 0x1f80 ) },
1991 { _EM_INEXACT | _RC_CHOP | _PC_64, MAKELONG( 0x27f, 0x7000 ) },
1992 { _MCW_EM | _PC_64, MAKELONG( 0x27f, 0x1f80 ) },
1993 { _MCW_EM | _PC_64, MAKELONG( 0x27f, 0x1f81 ) },
1994 { _MCW_EM | _PC_64, MAKELONG( 0x27f, 0x1f81 ) }
1995 #elif defined(__aarch64__)
1996 { _MCW_EM | _PC_64, 0 },
1997 { _MCW_EM | _PC_64, 0 },
1998 { _EM_INEXACT | _RC_CHOP | _PC_64, 0xc08f00 },
1999 { _MCW_EM | _PC_64, 0 },
2000 { _EM_INEXACT | _RC_CHOP | _PC_64, 0xc08f00 },
2001 { _MCW_EM | _PC_64, 0 },
2002 { _MCW_EM | _PC_64, 0 },
2003 { _MCW_EM | _PC_64, 0 }
2004 #else
2005 { 0xdeadbeef, 0xdeadbeef }
2006 #endif
2008 unsigned int initial_cw, cw;
2009 unsigned long fpu_cw;
2011 fpu_cw = get_fpu_cw();
2012 initial_cw = _control87( 0, 0 );
2013 ok(initial_cw == expected_cw[0].cw, "expected %#x got %#x\n", expected_cw[0].cw, initial_cw);
2014 ok(fpu_cw == expected_cw[0].fpu_cw, "expected %#lx got %#lx\n", expected_cw[0].fpu_cw, fpu_cw);
2016 cw = get_thread_fpu_cw( &fpu_cw );
2017 ok(cw == expected_cw[1].cw, "expected %#x got %#x\n", expected_cw[1].cw, cw);
2018 ok(fpu_cw == expected_cw[1].fpu_cw, "expected %#lx got %#lx\n", expected_cw[1].fpu_cw, fpu_cw);
2020 _control87( _EM_INEXACT | _RC_CHOP | _PC_24, _MCW_EM | _MCW_RC | _MCW_PC );
2021 cw = _control87( 0, 0 );
2022 fpu_cw = get_fpu_cw();
2023 ok(cw == expected_cw[2].cw, "expected %#x got %#x\n", expected_cw[2].cw, cw);
2024 ok(fpu_cw == expected_cw[2].fpu_cw ||
2025 broken(expected_cw[2].fpu_cw_broken && fpu_cw == expected_cw[2].fpu_cw_broken),
2026 "expected %#lx got %#lx\n", expected_cw[2].fpu_cw, fpu_cw);
2028 cw = get_thread_fpu_cw( &fpu_cw );
2029 ok(cw == expected_cw[3].cw, "expected %#x got %#x\n", expected_cw[3].cw, cw);
2030 ok(fpu_cw == expected_cw[3].fpu_cw, "expected %#lx got %#lx\n", expected_cw[3].fpu_cw, fpu_cw);
2032 cw = _control87( 0, 0 );
2033 fpu_cw = get_fpu_cw();
2034 ok(cw == expected_cw[4].cw, "expected %#x got %#x\n", expected_cw[4].cw, cw);
2035 ok(fpu_cw == expected_cw[4].fpu_cw ||
2036 broken(expected_cw[4].fpu_cw_broken && fpu_cw == expected_cw[4].fpu_cw_broken),
2037 "expected %#lx got %#lx\n", expected_cw[4].fpu_cw, fpu_cw);
2039 _control87( initial_cw, _MCW_EM | _MCW_RC | _MCW_PC );
2040 cw = _control87( 0, 0 );
2041 fpu_cw = get_fpu_cw();
2042 ok(cw == expected_cw[5].cw, "expected %#x got %#x\n", expected_cw[5].cw, cw);
2043 ok(fpu_cw == expected_cw[5].fpu_cw, "expected %#lx got %#lx\n", expected_cw[5].fpu_cw, fpu_cw);
2045 fpu_invalid_operation();
2046 cw = _control87( 0, 0 );
2047 fpu_cw = get_fpu_cw();
2048 ok(cw == expected_cw[6].cw, "expected %#x got %#x\n", expected_cw[6].cw, cw);
2049 ok(fpu_cw == expected_cw[6].fpu_cw, "expected %#lx got %#lx\n", expected_cw[6].fpu_cw, fpu_cw);
2051 cw = _control87( initial_cw, _MCW_EM | _MCW_RC | _MCW_PC );
2052 fpu_cw = get_fpu_cw();
2053 ok(cw == expected_cw[7].cw, "expected %#x got %#x\n", expected_cw[6].cw, cw);
2054 ok(fpu_cw == expected_cw[7].fpu_cw, "expected %#lx got %#lx\n", expected_cw[6].fpu_cw, fpu_cw);
2055 _clearfp();
2058 static const char manifest_dep[] =
2059 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
2060 "<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH "\"/>"
2061 " <file name=\"testdep.dll\" />"
2062 "</assembly>";
2064 static const char manifest_main[] =
2065 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
2066 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />"
2067 "<dependency>"
2068 " <dependentAssembly>"
2069 " <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH "\" />"
2070 " </dependentAssembly>"
2071 "</dependency>"
2072 "</assembly>";
2074 static void create_manifest_file(const char *filename, const char *manifest)
2076 WCHAR path[MAX_PATH];
2077 HANDLE file;
2078 DWORD size;
2080 MultiByteToWideChar( CP_ACP, 0, filename, -1, path, MAX_PATH );
2081 file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2082 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError());
2083 WriteFile(file, manifest, strlen(manifest), &size, NULL);
2084 CloseHandle(file);
2087 static HANDLE test_create(const char *file)
2089 WCHAR path[MAX_PATH];
2090 ACTCTXW actctx;
2091 HANDLE handle;
2093 MultiByteToWideChar(CP_ACP, 0, file, -1, path, MAX_PATH);
2094 memset(&actctx, 0, sizeof(ACTCTXW));
2095 actctx.cbSize = sizeof(ACTCTXW);
2096 actctx.lpSource = path;
2098 handle = CreateActCtxW(&actctx);
2099 ok(handle != INVALID_HANDLE_VALUE, "failed to create context, error %lu\n", GetLastError());
2101 ok(actctx.cbSize == sizeof(actctx), "cbSize=%ld\n", actctx.cbSize);
2102 ok(actctx.dwFlags == 0, "dwFlags=%ld\n", actctx.dwFlags);
2103 ok(actctx.lpSource == path, "lpSource=%p\n", actctx.lpSource);
2104 ok(actctx.wProcessorArchitecture == 0, "wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture);
2105 ok(actctx.wLangId == 0, "wLangId=%d\n", actctx.wLangId);
2106 ok(actctx.lpAssemblyDirectory == NULL, "lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory);
2107 ok(actctx.lpResourceName == NULL, "lpResourceName=%p\n", actctx.lpResourceName);
2108 ok(actctx.lpApplicationName == NULL, "lpApplicationName=%p\n", actctx.lpApplicationName);
2109 ok(actctx.hModule == NULL, "hModule=%p\n", actctx.hModule);
2111 return handle;
2114 static void test_thread_actctx(void)
2116 struct thread_actctx_param param;
2117 HANDLE thread, handle, context;
2118 ULONG_PTR cookie;
2119 DWORD tid, ret;
2120 BOOL b;
2122 create_manifest_file("testdep1.manifest", manifest_dep);
2123 create_manifest_file("main.manifest", manifest_main);
2125 context = test_create("main.manifest");
2126 DeleteFileA("testdep1.manifest");
2127 DeleteFileA("main.manifest");
2129 handle = (void*)0xdeadbeef;
2130 b = GetCurrentActCtx(&handle);
2131 ok(b, "GetCurrentActCtx failed: %lu\n", GetLastError());
2132 ok(handle == 0, "active context %p\n", handle);
2134 /* without active context */
2135 param.thread_context = (void*)0xdeadbeef;
2136 param.handle = NULL;
2137 thread = CreateThread(NULL, 0, thread_actctx_func, &param, 0, &tid);
2138 ok(thread != NULL, "failed, got %lu\n", GetLastError());
2140 ret = WaitForSingleObject(thread, 1000);
2141 ok(ret == WAIT_OBJECT_0, "wait timeout\n");
2142 ok(param.thread_context == NULL, "got wrong thread context %p\n", param.thread_context);
2143 CloseHandle(thread);
2145 b = ActivateActCtx(context, &cookie);
2146 ok(b, "activation failed: %lu\n", GetLastError());
2148 handle = 0;
2149 b = GetCurrentActCtx(&handle);
2150 ok(b, "GetCurrentActCtx failed: %lu\n", GetLastError());
2151 ok(handle != 0, "no active context\n");
2152 ReleaseActCtx(handle);
2154 param.handle = NULL;
2155 b = GetCurrentActCtx(&param.handle);
2156 ok(b && param.handle != NULL, "failed to get context, %lu\n", GetLastError());
2158 param.thread_context = (void*)0xdeadbeef;
2159 thread = CreateThread(NULL, 0, thread_actctx_func, &param, 0, &tid);
2160 ok(thread != NULL, "failed, got %lu\n", GetLastError());
2162 ret = WaitForSingleObject(thread, 1000);
2163 ok(ret == WAIT_OBJECT_0, "wait timeout\n");
2164 ok(param.thread_context == context, "got wrong thread context %p, %p\n", param.thread_context, context);
2165 ReleaseActCtx(param.thread_context);
2166 CloseHandle(thread);
2168 /* similar test for CreateRemoteThread() */
2169 param.thread_context = (void*)0xdeadbeef;
2170 thread = CreateRemoteThread(GetCurrentProcess(), NULL, 0, thread_actctx_func, &param, 0, &tid);
2171 ok(thread != NULL, "failed, got %lu\n", GetLastError());
2173 ret = WaitForSingleObject(thread, 1000);
2174 ok(ret == WAIT_OBJECT_0, "wait timeout\n");
2175 ok(param.thread_context == context, "got wrong thread context %p, %p\n", param.thread_context, context);
2176 ReleaseActCtx(param.thread_context);
2177 CloseHandle(thread);
2179 ReleaseActCtx(param.handle);
2181 b = DeactivateActCtx(0, cookie);
2182 ok(b, "DeactivateActCtx failed: %lu\n", GetLastError());
2183 ReleaseActCtx(context);
2186 static void WINAPI threadpool_workcallback(PTP_CALLBACK_INSTANCE instance, void *context, PTP_WORK work) {
2187 int *foo = (int*)context;
2189 (*foo)++;
2193 static void test_threadpool(void)
2195 PTP_POOL pool;
2196 PTP_WORK work;
2197 int workcalled = 0;
2199 if (!pCreateThreadpool) {
2200 win_skip("thread pool apis not supported.\n");
2201 return;
2204 work = pCreateThreadpoolWork(threadpool_workcallback, &workcalled, NULL);
2205 ok (work != NULL, "Error %ld in CreateThreadpoolWork\n", GetLastError());
2206 pSubmitThreadpoolWork(work);
2207 pWaitForThreadpoolWorkCallbacks(work, FALSE);
2208 pCloseThreadpoolWork(work);
2210 ok (workcalled == 1, "expected work to be called once, got %d\n", workcalled);
2212 pool = pCreateThreadpool(NULL);
2213 ok (pool != NULL, "CreateThreadpool failed\n");
2214 pCloseThreadpool(pool);
2217 static void test_reserved_tls(void)
2219 void *val;
2220 DWORD tls;
2221 BOOL ret;
2223 /* This seems to be a WinXP SP2+ feature. */
2224 if(!pIsWow64Process) {
2225 win_skip("Skipping reserved TLS slot on too old Windows.\n");
2226 return;
2229 val = TlsGetValue(0);
2230 ok(!val, "TlsGetValue(0) = %p\n", val);
2232 /* Also make sure that there is a TLS allocated. */
2233 tls = TlsAlloc();
2234 ok(tls && tls != TLS_OUT_OF_INDEXES, "tls = %lx\n", tls);
2235 TlsSetValue(tls, (void*)1);
2237 val = TlsGetValue(0);
2238 ok(!val, "TlsGetValue(0) = %p\n", val);
2240 TlsFree(tls);
2242 /* The following is too ugly to be run by default */
2243 if(0) {
2244 /* Set TLS index 0 value and see that this works and doesn't cause problems
2245 * for remaining tests. */
2246 ret = TlsSetValue(0, (void*)1);
2247 ok(ret, "TlsSetValue(0, 1) failed: %lu\n", GetLastError());
2249 val = TlsGetValue(0);
2250 ok(val == (void*)1, "TlsGetValue(0) = %p\n", val);
2254 static void test_thread_info(void)
2256 char buf[4096];
2257 static const ULONG info_size[] =
2259 sizeof(THREAD_BASIC_INFORMATION), /* ThreadBasicInformation */
2260 sizeof(KERNEL_USER_TIMES), /* ThreadTimes */
2261 sizeof(ULONG), /* ThreadPriority */
2262 sizeof(ULONG), /* ThreadBasePriority */
2263 sizeof(ULONG_PTR), /* ThreadAffinityMask */
2264 sizeof(HANDLE), /* ThreadImpersonationToken */
2265 sizeof(THREAD_DESCRIPTOR_INFORMATION), /* ThreadDescriptorTableEntry */
2266 sizeof(BOOLEAN), /* ThreadEnableAlignmentFaultFixup */
2267 0, /* ThreadEventPair_Reusable */
2268 sizeof(ULONG_PTR), /* ThreadQuerySetWin32StartAddress */
2269 sizeof(ULONG), /* ThreadZeroTlsCell */
2270 sizeof(LARGE_INTEGER), /* ThreadPerformanceCount */
2271 sizeof(ULONG), /* ThreadAmILastThread */
2272 sizeof(ULONG), /* ThreadIdealProcessor */
2273 sizeof(ULONG), /* ThreadPriorityBoost */
2274 sizeof(ULONG_PTR), /* ThreadSetTlsArrayAddress */
2275 sizeof(ULONG), /* ThreadIsIoPending */
2276 sizeof(BOOLEAN), /* ThreadHideFromDebugger */
2277 /* FIXME: Add remaining classes */
2279 HANDLE thread;
2280 ULONG i, status, ret_len;
2282 if (!pOpenThread)
2284 win_skip("OpenThread is not available on this platform\n");
2285 return;
2288 if (!pNtQueryInformationThread)
2290 win_skip("NtQueryInformationThread is not available on this platform\n");
2291 return;
2294 thread = pOpenThread(THREAD_QUERY_LIMITED_INFORMATION, FALSE, GetCurrentThreadId());
2295 if (!thread)
2297 win_skip("THREAD_QUERY_LIMITED_INFORMATION is not supported on this platform\n");
2298 return;
2301 for (i = 0; i < ARRAY_SIZE(info_size); i++)
2303 memset(buf, 0, sizeof(buf));
2305 #ifdef __i386__
2306 if (i == ThreadDescriptorTableEntry)
2308 CONTEXT ctx;
2309 THREAD_DESCRIPTOR_INFORMATION *tdi = (void *)buf;
2311 ctx.ContextFlags = CONTEXT_SEGMENTS;
2312 GetThreadContext(GetCurrentThread(), &ctx);
2313 tdi->Selector = ctx.SegDs;
2315 #endif
2316 ret_len = 0;
2317 status = pNtQueryInformationThread(thread, i, buf, info_size[i], &ret_len);
2318 if (status == STATUS_NOT_IMPLEMENTED) continue;
2319 if (status == STATUS_INVALID_INFO_CLASS) continue;
2320 if (status == STATUS_UNSUCCESSFUL) continue;
2322 switch (i)
2324 case ThreadBasicInformation:
2325 case ThreadAmILastThread:
2326 case ThreadPriorityBoost:
2327 ok(status == STATUS_SUCCESS, "for info %lu expected STATUS_SUCCESS, got %08lx (ret_len %lu)\n", i, status, ret_len);
2328 break;
2330 #ifdef __i386__
2331 case ThreadDescriptorTableEntry:
2332 ok(status == STATUS_SUCCESS || broken(status == STATUS_ACCESS_DENIED) /* testbot VM is broken */,
2333 "for info %lu expected STATUS_SUCCESS, got %08lx (ret_len %lu)\n", i, status, ret_len);
2334 break;
2335 #endif
2337 case ThreadTimes:
2338 ok(status == STATUS_SUCCESS, "for info %lu expected STATUS_SUCCESS, got %08lx (ret_len %lu)\n", i, status, ret_len);
2339 break;
2341 case ThreadIsIoPending:
2342 todo_wine
2343 ok(status == STATUS_ACCESS_DENIED, "for info %lu expected STATUS_ACCESS_DENIED, got %08lx (ret_len %lu)\n", i, status, ret_len);
2344 break;
2346 default:
2347 ok(status == STATUS_ACCESS_DENIED, "for info %lu expected STATUS_ACCESS_DENIED, got %08lx (ret_len %lu)\n", i, status, ret_len);
2348 break;
2352 CloseHandle(thread);
2355 typedef struct tagTHREADNAME_INFO
2357 DWORD dwType; /* Must be 0x1000. */
2358 LPCSTR szName; /* Pointer to name (in user addr space). */
2359 DWORD dwThreadID; /* Thread ID (-1 = caller thread). */
2360 DWORD dwFlags; /* Reserved for future use, must be zero. */
2361 } THREADNAME_INFO;
2363 static LONG CALLBACK msvc_threadname_vec_handler(EXCEPTION_POINTERS *ExceptionInfo)
2365 if (ExceptionInfo->ExceptionRecord != NULL &&
2366 ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_WINE_NAME_THREAD)
2367 return EXCEPTION_CONTINUE_EXECUTION;
2369 return EXCEPTION_CONTINUE_SEARCH;
2372 static void test_thread_description(void)
2374 THREAD_NAME_INFORMATION *thread_desc;
2375 static const WCHAR *desc = L"thread_desc";
2376 ULONG len, len2, desc_len;
2377 NTSTATUS status;
2378 char buff[128];
2379 WCHAR *ptr;
2380 HRESULT hr;
2381 HANDLE thread;
2382 PVOID vectored_handler;
2383 THREADNAME_INFO info;
2385 if (!pGetThreadDescription)
2387 win_skip("Thread description API is not supported.\n");
2388 return;
2391 desc_len = lstrlenW(desc) * sizeof(*desc);
2392 thread_desc = (THREAD_NAME_INFORMATION *)buff;
2394 /* Initial description. */
2395 ptr = NULL;
2396 hr = pGetThreadDescription(GetCurrentThread(), &ptr);
2397 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to get thread description, hr %#lx.\n", hr);
2398 ok(!lstrcmpW(ptr, L""), "Unexpected description %s.\n", wine_dbgstr_w(ptr));
2399 LocalFree(ptr);
2401 len = 0;
2402 status = pNtQueryInformationThread(GetCurrentThread(), ThreadNameInformation, NULL, 0, &len);
2403 ok(status == STATUS_BUFFER_TOO_SMALL, "Unexpected status %#lx.\n", status);
2404 ok(len == sizeof(*thread_desc), "Unexpected structure length %lu.\n", len);
2406 len2 = 0;
2407 thread_desc->ThreadName.Length = 1;
2408 thread_desc->ThreadName.MaximumLength = 0;
2409 thread_desc->ThreadName.Buffer = (WCHAR *)thread_desc;
2410 status = pNtQueryInformationThread(GetCurrentThread(), ThreadNameInformation, thread_desc, len, &len2);
2411 ok(!status, "Failed to get thread info, status %#lx.\n", status);
2412 ok(len2 == sizeof(*thread_desc), "Unexpected structure length %lu.\n", len);
2413 ok(!thread_desc->ThreadName.Length, "Unexpected description length %#x.\n", thread_desc->ThreadName.Length);
2414 ok(thread_desc->ThreadName.Buffer == (WCHAR *)(thread_desc + 1),
2415 "Unexpected description string pointer %p, %p.\n", thread_desc->ThreadName.Buffer, thread_desc);
2417 hr = pSetThreadDescription(GetCurrentThread(), NULL);
2418 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to set thread description, hr %#lx.\n", hr);
2420 hr = pSetThreadDescription(GetCurrentThread(), desc);
2421 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to set thread description, hr %#lx.\n", hr);
2423 ptr = NULL;
2424 hr = pGetThreadDescription(GetCurrentThread(), &ptr);
2425 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to get thread description, hr %#lx.\n", hr);
2426 ok(!lstrcmpW(ptr, desc), "Unexpected description %s.\n", wine_dbgstr_w(ptr));
2427 LocalFree(ptr);
2429 len = 0;
2430 status = pNtQueryInformationThread(GetCurrentThread(), ThreadNameInformation, NULL, 0, &len);
2431 ok(status == STATUS_BUFFER_TOO_SMALL, "Failed to get thread info, status %#lx.\n", status);
2432 ok(len == sizeof(*thread_desc) + desc_len, "Unexpected structure length %lu.\n", len);
2434 len = 0;
2435 status = pNtQueryInformationThread(GetCurrentThread(), ThreadNameInformation, buff, sizeof(buff), &len);
2436 ok(!status, "Failed to get thread info.\n");
2437 ok(len == sizeof(*thread_desc) + desc_len, "Unexpected structure length %lu.\n", len);
2439 ok(thread_desc->ThreadName.Length == desc_len && thread_desc->ThreadName.MaximumLength == desc_len,
2440 "Unexpected description length %u.\n", thread_desc->ThreadName.Length);
2441 ok(thread_desc->ThreadName.Buffer == (WCHAR *)(thread_desc + 1),
2442 "Unexpected description string pointer %p, %p.\n", thread_desc->ThreadName.Buffer, thread_desc);
2443 ok(!memcmp(thread_desc->ThreadName.Buffer, desc, desc_len), "Unexpected description string.\n");
2445 /* Partial results. */
2446 len = 0;
2447 status = pNtQueryInformationThread(GetCurrentThread(), ThreadNameInformation, NULL, 0, &len);
2448 ok(status == STATUS_BUFFER_TOO_SMALL, "Unexpected status %#lx.\n", status);
2449 ok(len == sizeof(*thread_desc) + desc_len, "Unexpected structure length %lu.\n", len);
2451 status = pNtQueryInformationThread(GetCurrentThread(), ThreadNameInformation, buff, len - sizeof(WCHAR), &len);
2452 ok(status == STATUS_BUFFER_TOO_SMALL, "Unexpected status %#lx.\n", status);
2453 ok(len == sizeof(*thread_desc) + desc_len, "Unexpected structure length %lu.\n", len);
2455 /* Change description. */
2456 thread_desc->ThreadName.Length = thread_desc->ThreadName.MaximumLength = 8;
2457 lstrcpyW((WCHAR *)(thread_desc + 1), L"desc");
2459 status = pNtSetInformationThread(GetCurrentThread(), ThreadNameInformation, thread_desc, sizeof(*thread_desc));
2460 ok(status == STATUS_SUCCESS, "Failed to set thread description, status %#lx.\n", status);
2462 ptr = NULL;
2463 hr = pGetThreadDescription(GetCurrentThread(), &ptr);
2464 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to get thread description, hr %#lx.\n", hr);
2465 ok(!lstrcmpW(ptr, L"desc"), "Unexpected description %s.\n", wine_dbgstr_w(ptr));
2466 LocalFree(ptr);
2468 status = pNtSetInformationThread(GetCurrentThread(), ThreadNameInformation, thread_desc, sizeof(*thread_desc) - 1);
2469 ok(status == STATUS_INFO_LENGTH_MISMATCH, "Unexpected status %#lx.\n", status);
2471 status = NtSetInformationThread(GetCurrentThread(), ThreadNameInformation, NULL, sizeof(*thread_desc));
2472 ok(status == STATUS_ACCESS_VIOLATION, "Unexpected status %#lx.\n", status);
2474 thread_desc->ThreadName.Buffer = NULL;
2475 status = pNtSetInformationThread(GetCurrentThread(), ThreadNameInformation, thread_desc, sizeof(*thread_desc));
2476 ok(status == STATUS_ACCESS_VIOLATION, "Unexpected status %#lx.\n", status);
2478 hr = pSetThreadDescription(GetCurrentThread(), NULL);
2479 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to set thread description, hr %#lx.\n", hr);
2481 ptr = NULL;
2482 hr = pGetThreadDescription(GetCurrentThread(), &ptr);
2483 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to get thread description, hr %#lx.\n", hr);
2484 ok(!lstrcmpW(ptr, L""), "Unexpected description %s.\n", wine_dbgstr_w(ptr));
2485 LocalFree(ptr);
2487 /* Set with a string from RtlInitUnicodeString. */
2488 hr = pSetThreadDescription(GetCurrentThread(), L"123");
2489 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to set thread description, hr %#lx.\n", hr);
2491 lstrcpyW((WCHAR *)(thread_desc + 1), L"desc");
2492 RtlInitUnicodeString(&thread_desc->ThreadName, (WCHAR *)(thread_desc + 1));
2494 status = pNtSetInformationThread(GetCurrentThread(), ThreadNameInformation, thread_desc, sizeof(*thread_desc));
2495 ok(status == STATUS_SUCCESS, "Failed to set thread description, status %#lx.\n", status);
2497 ptr = NULL;
2498 hr = pGetThreadDescription(GetCurrentThread(), &ptr);
2499 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to get thread description, hr %#lx.\n", hr);
2500 ok(!lstrcmpW(ptr, L"desc"), "Unexpected description %s.\n", wine_dbgstr_w(ptr));
2501 LocalFree(ptr);
2503 /* Set with 0 length/NULL pointer. */
2504 hr = pSetThreadDescription(GetCurrentThread(), L"123");
2505 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to set thread description, hr %#lx.\n", hr);
2507 memset(thread_desc, 0, sizeof(*thread_desc));
2508 status = pNtSetInformationThread(GetCurrentThread(), ThreadNameInformation, thread_desc, sizeof(*thread_desc));
2509 ok(!status, "Failed to set thread description, status %#lx.\n", status);
2511 ptr = NULL;
2512 hr = pGetThreadDescription(GetCurrentThread(), &ptr);
2513 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to get thread description, hr %#lx.\n", hr);
2514 ok(!lstrcmpW(ptr, L""), "Unexpected description %s.\n", wine_dbgstr_w(ptr));
2515 LocalFree(ptr);
2517 /* Get with only THREAD_QUERY_LIMITED_INFORMATION access. */
2518 thread = OpenThread(THREAD_QUERY_LIMITED_INFORMATION, FALSE, GetCurrentThreadId());
2520 ptr = NULL;
2521 hr = pGetThreadDescription(thread, &ptr);
2522 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to get thread description, hr %#lx.\n", hr);
2523 ok(!lstrcmpW(ptr, L""), "Unexpected description %s.\n", wine_dbgstr_w(ptr));
2524 LocalFree(ptr);
2526 len = 0;
2527 status = pNtQueryInformationThread(thread, ThreadNameInformation, NULL, 0, &len);
2528 ok(status == STATUS_BUFFER_TOO_SMALL, "Unexpected status %#lx.\n", status);
2529 ok(len == sizeof(*thread_desc), "Unexpected structure length %lu.\n", len);
2531 CloseHandle(thread);
2533 /* Set with only THREAD_SET_LIMITED_INFORMATION access. */
2534 thread = OpenThread(THREAD_SET_LIMITED_INFORMATION, FALSE, GetCurrentThreadId());
2536 hr = pSetThreadDescription(thread, desc);
2537 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to set thread description, hr %#lx.\n", hr);
2539 ptr = NULL;
2540 hr = pGetThreadDescription(GetCurrentThread(), &ptr);
2541 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to get thread description, hr %#lx.\n", hr);
2542 ok(!lstrcmpW(ptr, desc), "Unexpected description %s.\n", wine_dbgstr_w(ptr));
2543 LocalFree(ptr);
2545 CloseHandle(thread);
2547 /* The old exception-based thread name method should not affect GetThreadDescription. */
2548 hr = pSetThreadDescription(GetCurrentThread(), desc);
2549 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to set thread description, hr %#lx.\n", hr);
2551 vectored_handler = pRtlAddVectoredExceptionHandler(FALSE, &msvc_threadname_vec_handler);
2552 ok(vectored_handler != 0, "RtlAddVectoredExceptionHandler failed\n");
2554 info.dwType = 0x1000;
2555 info.szName = "123";
2556 info.dwThreadID = -1;
2557 info.dwFlags = 0;
2558 RaiseException(EXCEPTION_WINE_NAME_THREAD, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
2560 pRtlRemoveVectoredExceptionHandler(vectored_handler);
2562 ptr = NULL;
2563 hr = pGetThreadDescription(GetCurrentThread(), &ptr);
2564 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to get thread description, hr %#lx.\n", hr);
2565 ok(!lstrcmpW(ptr, desc), "Unexpected description %s.\n", wine_dbgstr_w(ptr));
2566 LocalFree(ptr);
2569 static void init_funcs(void)
2571 HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
2572 HMODULE ntdll = GetModuleHandleA("ntdll.dll");
2574 /* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
2575 so that the compile passes */
2577 #define X(f) p##f = (void*)GetProcAddress(hKernel32, #f)
2578 X(GetCurrentThreadStackLimits);
2579 X(GetThreadPriorityBoost);
2580 X(OpenThread);
2581 X(QueueUserWorkItem);
2582 X(SetThreadPriorityBoost);
2583 X(SetThreadStackGuarantee);
2584 X(RegisterWaitForSingleObject);
2585 X(UnregisterWait);
2586 X(IsWow64Process);
2587 X(SetThreadErrorMode);
2588 X(GetThreadErrorMode);
2590 X(CreateThreadpool);
2591 X(CloseThreadpool);
2592 X(CreateThreadpoolWork);
2593 X(SubmitThreadpoolWork);
2594 X(WaitForThreadpoolWorkCallbacks);
2595 X(CloseThreadpoolWork);
2597 X(GetThreadGroupAffinity);
2598 X(SetThreadGroupAffinity);
2599 X(SetThreadDescription);
2600 X(GetThreadDescription);
2602 X(FlsAlloc);
2603 X(FlsFree);
2604 X(FlsSetValue);
2605 X(FlsGetValue);
2606 #undef X
2608 #define X(f) p##f = (void*)GetProcAddress(ntdll, #f)
2609 if (ntdll)
2611 X(NtQueryInformationThread);
2612 X(RtlGetThreadErrorMode);
2613 X(NtSetInformationThread);
2614 X(RtlAddVectoredExceptionHandler);
2615 X(RtlRemoveVectoredExceptionHandler);
2617 #undef X
2620 START_TEST(thread)
2622 int argc;
2623 char **argv;
2624 argc = winetest_get_mainargs( &argv );
2626 init_funcs();
2628 if (argc >= 3)
2630 if (!strcmp(argv[2], "sleep"))
2632 HANDLE hAddrEvents[2];
2633 create_function_addr_events(hAddrEvents);
2634 SetEvent(hAddrEvents[0]);
2635 SetEvent(hAddrEvents[1]);
2636 Sleep(5000); /* spawned process runs for at most 5 seconds */
2637 return;
2639 while (1)
2641 HANDLE hThread;
2642 DWORD tid;
2643 hThread = CreateThread(NULL, 0, threadFunc2, NULL, 0, &tid);
2644 ok(hThread != NULL, "CreateThread failed, error %lu\n",
2645 GetLastError());
2646 ok(WaitForSingleObject(hThread, 200) == WAIT_OBJECT_0,
2647 "Thread did not exit in time\n");
2648 if (hThread == NULL) break;
2649 CloseHandle(hThread);
2651 return;
2654 test_thread_info();
2655 test_reserved_tls();
2656 test_CreateRemoteThread();
2657 test_CreateThread_basic();
2658 test_CreateThread_suspended();
2659 test_SuspendThread();
2660 test_TerminateThread();
2661 test_CreateThread_stack();
2662 test_thread_priority();
2663 test_GetCurrentThreadStackLimits();
2664 test_SetThreadStackGuarantee();
2665 test_GetThreadTimes();
2666 test_thread_processor();
2667 test_GetThreadExitCode();
2668 #ifdef __i386__
2669 test_SetThreadContext();
2670 test_GetThreadSelectorEntry();
2671 test_GetThreadContext();
2672 #endif
2673 test_QueueUserWorkItem();
2674 test_RegisterWaitForSingleObject();
2675 test_TLS();
2676 test_FLS();
2677 test_ThreadErrorMode();
2678 test_thread_fpu_cw();
2679 test_thread_actctx();
2680 test_thread_description();
2682 test_threadpool();