Remove unnecessary executable bits
[reactos.git] / modules / rostests / winetests / kernel32 / thread.c
1 /*
2 * Unit test suite for thread functions.
3 *
4 * Copyright 2002 Geoffrey Hausheer
5 *
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.
10 *
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.
15 *
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
19 */
20
21 /* Define _WIN32_WINNT to get SetThreadIdealProcessor on Windows */
22 #ifndef __REACTOS__
23 #define _WIN32_WINNT 0x0600
24 #endif
25
26 #include <assert.h>
27 #include <stdarg.h>
28 #include <stdio.h>
29
30 /* the tests intentionally pass invalid pointers and need an exception handler */
31 #define WINE_NO_INLINE_STRING
32
33 #include <ntstatus.h>
34 #define WIN32_NO_STATUS
35 #include <windef.h>
36 #include <winbase.h>
37 #include <winnt.h>
38 #include <winerror.h>
39 #include <winnls.h>
40 #include <winternl.h>
41 #include "wine/test.h"
42
43 /* THREAD_ALL_ACCESS in Vista+ PSDKs is incompatible with older Windows versions */
44 #define THREAD_ALL_ACCESS_NT4 (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3ff)
45
46 /* Specify the number of simultaneous threads to test */
47 #define NUM_THREADS 4
48 /* Specify whether to test the extended priorities for Win2k/XP */
49 #define USE_EXTENDED_PRIORITIES 0
50 /* Specify whether to test the stack allocation in CreateThread */
51 #define CHECK_STACK 0
52
53 /* Set CHECK_STACK to 1 if you want to try to test the stack-limit from
54 CreateThread. So far I have been unable to make this work, and
55 I am in doubt as to how portable it is. Also, according to MSDN,
56 you shouldn't mix C-run-time-libraries (i.e. alloca) with CreateThread.
57 Anyhow, the check is currently commented out
58 */
59 #if CHECK_STACK
60 # ifdef __try
61 # define __TRY __try
62 # define __EXCEPT __except
63 # define __ENDTRY
64 # else
65 # include "wine/exception.h"
66 # endif
67 #endif
68
69 #ifdef __i386__
70 #define ARCH "x86"
71 #elif defined __x86_64__
72 #define ARCH "amd64"
73 #elif defined __arm__
74 #define ARCH "arm"
75 #elif defined __aarch64__
76 #define ARCH "arm64"
77 #else
78 #define ARCH "none"
79 #endif
80
81 static BOOL (WINAPI *pGetThreadPriorityBoost)(HANDLE,PBOOL);
82 static HANDLE (WINAPI *pOpenThread)(DWORD,BOOL,DWORD);
83 static BOOL (WINAPI *pQueueUserWorkItem)(LPTHREAD_START_ROUTINE,PVOID,ULONG);
84 static DWORD (WINAPI *pSetThreadIdealProcessor)(HANDLE,DWORD);
85 static BOOL (WINAPI *pSetThreadPriorityBoost)(HANDLE,BOOL);
86 static BOOL (WINAPI *pRegisterWaitForSingleObject)(PHANDLE,HANDLE,WAITORTIMERCALLBACK,PVOID,ULONG,ULONG);
87 static BOOL (WINAPI *pUnregisterWait)(HANDLE);
88 static BOOL (WINAPI *pIsWow64Process)(HANDLE,PBOOL);
89 static BOOL (WINAPI *pSetThreadErrorMode)(DWORD,PDWORD);
90 static DWORD (WINAPI *pGetThreadErrorMode)(void);
91 static DWORD (WINAPI *pRtlGetThreadErrorMode)(void);
92 static BOOL (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*);
93 static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW);
94 static BOOL (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR);
95 static BOOL (WINAPI *pGetCurrentActCtx)(HANDLE *);
96 static void (WINAPI *pReleaseActCtx)(HANDLE);
97 static PTP_POOL (WINAPI *pCreateThreadpool)(PVOID);
98 static void (WINAPI *pCloseThreadpool)(PTP_POOL);
99 static PTP_WORK (WINAPI *pCreateThreadpoolWork)(PTP_WORK_CALLBACK,PVOID,PTP_CALLBACK_ENVIRON);
100 static void (WINAPI *pSubmitThreadpoolWork)(PTP_WORK);
101 static void (WINAPI *pWaitForThreadpoolWorkCallbacks)(PTP_WORK,BOOL);
102 static void (WINAPI *pCloseThreadpoolWork)(PTP_WORK);
103 static NTSTATUS (WINAPI *pNtQueryInformationThread)(HANDLE,THREADINFOCLASS,PVOID,ULONG,PULONG);
104 static BOOL (WINAPI *pGetThreadGroupAffinity)(HANDLE,GROUP_AFFINITY*);
105 static BOOL (WINAPI *pSetThreadGroupAffinity)(HANDLE,const GROUP_AFFINITY*,GROUP_AFFINITY*);
106 static NTSTATUS (WINAPI *pNtSetInformationThread)(HANDLE,THREADINFOCLASS,LPCVOID,ULONG);
107 static NTSTATUS (WINAPI *pNtSetLdtEntries)(ULONG,ULONG,ULONG,ULONG,ULONG,ULONG);
108
109 static HANDLE create_target_process(const char *arg)
110 {
111 char **argv;
112 char cmdline[MAX_PATH];
113 PROCESS_INFORMATION pi;
114 BOOL ret;
115 STARTUPINFOA si = { 0 };
116 si.cb = sizeof(si);
117
118 winetest_get_mainargs( &argv );
119 sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
120 ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
121 ok(ret, "error: %u\n", GetLastError());
122 ret = CloseHandle(pi.hThread);
123 ok(ret, "error %u\n", GetLastError());
124 return pi.hProcess;
125 }
126
127 /* Functions not tested yet:
128 AttachThreadInput
129 SetThreadContext
130 SwitchToThread
131
132 In addition there are no checks that the inheritance works properly in
133 CreateThread
134 */
135
136 /* Functions to ensure that from a group of threads, only one executes
137 certain chunks of code at a time, and we know which one is executing
138 it. It basically makes multithreaded execution linear, which defeats
139 the purpose of multiple threads, but makes testing easy. */
140 static HANDLE start_event, stop_event;
141 static LONG num_synced;
142
143 static void init_thread_sync_helpers(void)
144 {
145 start_event = CreateEventW(NULL, TRUE, FALSE, NULL);
146 ok(start_event != NULL, "CreateEvent failed\n");
147 stop_event = CreateEventW(NULL, TRUE, FALSE, NULL);
148 ok(stop_event != NULL, "CreateEvent failed\n");
149 num_synced = -1;
150 }
151
152 static BOOL sync_threads_and_run_one(DWORD sync_id, DWORD my_id)
153 {
154 LONG num = InterlockedIncrement(&num_synced);
155 assert(-1 <= num && num <= 1);
156 if (num == 1)
157 {
158 ResetEvent( stop_event );
159 SetEvent( start_event );
160 }
161 else
162 {
163 DWORD ret = WaitForSingleObject(start_event, 10000);
164 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed %x\n",ret);
165 }
166 return sync_id == my_id;
167 }
168
169 static void resync_after_run(void)
170 {
171 LONG num = InterlockedDecrement(&num_synced);
172 assert(-1 <= num && num <= 1);
173 if (num == -1)
174 {
175 ResetEvent( start_event );
176 SetEvent( stop_event );
177 }
178 else
179 {
180 DWORD ret = WaitForSingleObject(stop_event, 10000);
181 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
182 }
183 }
184
185 static void cleanup_thread_sync_helpers(void)
186 {
187 CloseHandle(start_event);
188 CloseHandle(stop_event);
189 }
190
191 static DWORD tlsIndex;
192
193 typedef struct {
194 int threadnum;
195 HANDLE *event;
196 DWORD *threadmem;
197 } t1Struct;
198
199 /* WinME supports OpenThread but doesn't know about access restrictions so
200 we require them to be either completely ignored or always obeyed.
201 */
202 static INT obeying_ars = 0; /* -1 == no, 0 == dunno yet, 1 == yes */
203 #define obey_ar(x) \
204 (obeying_ars == 0 \
205 ? ((x) \
206 ? (obeying_ars = +1) \
207 : ((obeying_ars = -1), \
208 trace("not restricted, assuming consistent behaviour\n"))) \
209 : (obeying_ars < 0) \
210 ? ok(!(x), "access restrictions obeyed\n") \
211 : ok( (x), "access restrictions not obeyed\n"))
212
213 /* Basic test that simultaneous threads can access shared memory,
214 that the thread local storage routines work correctly, and that
215 threads actually run concurrently
216 */
217 static DWORD WINAPI threadFunc1(LPVOID p)
218 {
219 t1Struct *tstruct = p;
220 int i;
221 /* write our thread # into shared memory */
222 tstruct->threadmem[tstruct->threadnum]=GetCurrentThreadId();
223 ok(TlsSetValue(tlsIndex,(LPVOID)(INT_PTR)(tstruct->threadnum+1))!=0,
224 "TlsSetValue failed\n");
225 /* The threads synchronize before terminating. This is done by
226 Signaling an event, and waiting for all events to occur
227 */
228 SetEvent(tstruct->event[tstruct->threadnum]);
229 WaitForMultipleObjects(NUM_THREADS,tstruct->event,TRUE,INFINITE);
230 /* Double check that all threads really did run by validating that
231 they have all written to the shared memory. There should be no race
232 here, since all threads were synchronized after the write.*/
233 for (i = 0; i < NUM_THREADS; i++)
234 ok(tstruct->threadmem[i] != 0, "expected threadmem[%d] != 0\n", i);
235
236 /* lstrlenA contains an exception handler so this makes sure exceptions work in threads */
237 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
238
239 /* Check that no one changed our tls memory */
240 ok((INT_PTR)TlsGetValue(tlsIndex)-1==tstruct->threadnum,
241 "TlsGetValue failed\n");
242 return NUM_THREADS+tstruct->threadnum;
243 }
244
245 static DWORD WINAPI threadFunc2(LPVOID p)
246 {
247 return 99;
248 }
249
250 static DWORD WINAPI threadFunc3(LPVOID p)
251 {
252 HANDLE thread;
253 thread=GetCurrentThread();
254 SuspendThread(thread);
255 return 99;
256 }
257
258 static DWORD WINAPI threadFunc4(LPVOID p)
259 {
260 HANDLE event = p;
261 if(event != NULL) {
262 SetEvent(event);
263 }
264 Sleep(99000);
265 return 0;
266 }
267
268 #if CHECK_STACK
269 static DWORD WINAPI threadFunc5(LPVOID p)
270 {
271 DWORD *exitCode = p;
272 SYSTEM_INFO sysInfo;
273 sysInfo.dwPageSize=0;
274 GetSystemInfo(&sysInfo);
275 *exitCode=0;
276 __TRY
277 {
278 alloca(2*sysInfo.dwPageSize);
279 }
280 __EXCEPT(1) {
281 *exitCode=1;
282 }
283 __ENDTRY
284 return 0;
285 }
286 #endif
287
288 static DWORD WINAPI threadFunc_SetEvent(LPVOID p)
289 {
290 SetEvent(p);
291 return 0;
292 }
293
294 static DWORD WINAPI threadFunc_CloseHandle(LPVOID p)
295 {
296 CloseHandle(p);
297 return 0;
298 }
299
300 struct thread_actctx_param
301 {
302 HANDLE thread_context;
303 HANDLE handle;
304 };
305
306 static DWORD WINAPI thread_actctx_func(void *p)
307 {
308 struct thread_actctx_param *param = (struct thread_actctx_param*)p;
309 HANDLE cur;
310 BOOL ret;
311
312 cur = (void*)0xdeadbeef;
313 ret = pGetCurrentActCtx(&cur);
314 ok(ret, "thread GetCurrentActCtx failed, %u\n", GetLastError());
315 ok(cur == param->handle, "got %p, expected %p\n", cur, param->handle);
316 param->thread_context = cur;
317
318 return 0;
319 }
320
321 static void create_function_addr_events(HANDLE events[2])
322 {
323 char buffer[256];
324
325 sprintf(buffer, "threadFunc_SetEvent %p", threadFunc_SetEvent);
326 events[0] = CreateEventA(NULL, FALSE, FALSE, buffer);
327
328 sprintf(buffer, "threadFunc_CloseHandle %p", threadFunc_CloseHandle);
329 events[1] = CreateEventA(NULL, FALSE, FALSE, buffer);
330 }
331
332 /* check CreateRemoteThread */
333 static VOID test_CreateRemoteThread(void)
334 {
335 HANDLE hProcess, hThread, hEvent, hRemoteEvent;
336 DWORD tid, ret, exitcode;
337 HANDLE hAddrEvents[2];
338
339 hProcess = create_target_process("sleep");
340 ok(hProcess != NULL, "Can't start process\n");
341
342 /* ensure threadFunc_SetEvent & threadFunc_CloseHandle are the same
343 * address as in the child process */
344 create_function_addr_events(hAddrEvents);
345 ret = WaitForMultipleObjects(2, hAddrEvents, TRUE, 5000);
346 if (ret == WAIT_TIMEOUT)
347 {
348 skip("child process wasn't mapped at same address, so can't do CreateRemoteThread tests.\n");
349 return;
350 }
351 ok(ret == WAIT_OBJECT_0 || broken(ret == WAIT_OBJECT_0+1 /* nt4,w2k */), "WaitForAllObjects 2 events %d\n", ret);
352
353 hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
354 ok(hEvent != NULL, "Can't create event, err=%u\n", GetLastError());
355 ret = DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &hRemoteEvent,
356 0, FALSE, DUPLICATE_SAME_ACCESS);
357 ok(ret != 0, "DuplicateHandle failed, err=%u\n", GetLastError());
358
359 /* create suspended remote thread with entry point SetEvent() */
360 SetLastError(0xdeadbeef);
361 hThread = CreateRemoteThread(hProcess, NULL, 0, threadFunc_SetEvent,
362 hRemoteEvent, CREATE_SUSPENDED, &tid);
363 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
364 {
365 win_skip("CreateRemoteThread is not implemented\n");
366 goto cleanup;
367 }
368 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
369 ok(tid != 0, "null tid\n");
370 ret = SuspendThread(hThread);
371 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
372 ret = ResumeThread(hThread);
373 ok(ret == 2, "ret=%u, err=%u\n", ret, GetLastError());
374
375 /* thread still suspended, so wait times out */
376 ret = WaitForSingleObject(hEvent, 1000);
377 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
378
379 ret = ResumeThread(hThread);
380 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
381
382 /* wait that doesn't time out */
383 ret = WaitForSingleObject(hEvent, 1000);
384 ok(ret == WAIT_OBJECT_0, "object not signaled, ret=%u\n", ret);
385
386 /* wait for thread end */
387 ret = WaitForSingleObject(hThread, 1000);
388 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
389 CloseHandle(hThread);
390
391 /* create and wait for remote thread with entry point CloseHandle() */
392 hThread = CreateRemoteThread(hProcess, NULL, 0,
393 threadFunc_CloseHandle,
394 hRemoteEvent, 0, &tid);
395 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
396 ret = WaitForSingleObject(hThread, 1000);
397 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
398 CloseHandle(hThread);
399
400 /* create remote thread with entry point SetEvent() */
401 hThread = CreateRemoteThread(hProcess, NULL, 0,
402 threadFunc_SetEvent,
403 hRemoteEvent, 0, &tid);
404 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
405
406 /* closed handle, so wait times out */
407 ret = WaitForSingleObject(hEvent, 1000);
408 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
409
410 /* check that remote SetEvent() failed */
411 ret = GetExitCodeThread(hThread, &exitcode);
412 ok(ret != 0, "GetExitCodeThread failed, err=%u\n", GetLastError());
413 if (ret) ok(exitcode == 0, "SetEvent succeeded, expected to fail\n");
414 CloseHandle(hThread);
415
416 cleanup:
417 TerminateProcess(hProcess, 0);
418 CloseHandle(hEvent);
419 CloseHandle(hProcess);
420 }
421
422 /* Check basic functionality of CreateThread and Tls* functions */
423 static VOID test_CreateThread_basic(void)
424 {
425 HANDLE thread[NUM_THREADS],event[NUM_THREADS];
426 DWORD threadid[NUM_THREADS],curthreadId;
427 DWORD threadmem[NUM_THREADS];
428 DWORD exitCode;
429 t1Struct tstruct[NUM_THREADS];
430 int error;
431 DWORD i,j;
432 DWORD GLE, ret;
433 DWORD tid;
434 BOOL bRet;
435
436 /* lstrlenA contains an exception handler so this makes sure exceptions work in the main thread */
437 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
438
439 /* Retrieve current Thread ID for later comparisons */
440 curthreadId=GetCurrentThreadId();
441 /* Allocate some local storage */
442 ok((tlsIndex=TlsAlloc())!=TLS_OUT_OF_INDEXES,"TlsAlloc failed\n");
443 /* Create events for thread synchronization */
444 for(i=0;i<NUM_THREADS;i++) {
445 threadmem[i]=0;
446 /* Note that it doesn't matter what type of event we choose here. This
447 test isn't trying to thoroughly test events
448 */
449 event[i]=CreateEventA(NULL,TRUE,FALSE,NULL);
450 tstruct[i].threadnum=i;
451 tstruct[i].threadmem=threadmem;
452 tstruct[i].event=event;
453 }
454
455 /* Test that passing arguments to threads works okay */
456 for(i=0;i<NUM_THREADS;i++) {
457 thread[i] = CreateThread(NULL,0,threadFunc1,
458 &tstruct[i],0,&threadid[i]);
459 ok(thread[i]!=NULL,"Create Thread failed\n");
460 }
461 /* Test that the threads actually complete */
462 for(i=0;i<NUM_THREADS;i++) {
463 error=WaitForSingleObject(thread[i],5000);
464 ok(error==WAIT_OBJECT_0, "Thread did not complete within timelimit\n");
465 if(error!=WAIT_OBJECT_0) {
466 TerminateThread(thread[i],i+NUM_THREADS);
467 }
468 ok(GetExitCodeThread(thread[i],&exitCode),"Could not retrieve ext code\n");
469 ok(exitCode==i+NUM_THREADS,"Thread returned an incorrect exit code\n");
470 }
471 /* Test that each thread executed in its parent's address space
472 (it was able to change threadmem and pass that change back to its parent)
473 and that each thread id was independent). Note that we prove that the
474 threads actually execute concurrently by having them block on each other
475 in threadFunc1
476 */
477 for(i=0;i<NUM_THREADS;i++) {
478 error=0;
479 for(j=i+1;j<NUM_THREADS;j++) {
480 if (threadmem[i]==threadmem[j]) {
481 error=1;
482 }
483 }
484 ok(!error && threadmem[i]==threadid[i] && threadmem[i]!=curthreadId,
485 "Thread did not execute successfully\n");
486 ok(CloseHandle(thread[i])!=0,"CloseHandle failed\n");
487 }
488
489 SetLastError(0xCAFEF00D);
490 bRet = TlsFree(tlsIndex);
491 ok(bRet, "TlsFree failed: %08x\n", GetLastError());
492 ok(GetLastError()==0xCAFEF00D,
493 "GetLastError: expected 0xCAFEF00D, got %08x\n", GetLastError());
494
495 /* Test freeing an already freed TLS index */
496 SetLastError(0xCAFEF00D);
497 ok(TlsFree(tlsIndex)==0,"TlsFree succeeded\n");
498 ok(GetLastError()==ERROR_INVALID_PARAMETER,
499 "GetLastError: expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
500
501 /* Test how passing NULL as a pointer to threadid works */
502 SetLastError(0xFACEaBAD);
503 thread[0] = CreateThread(NULL,0,threadFunc2,NULL,0,&tid);
504 GLE = GetLastError();
505 if (thread[0]) { /* NT */
506 ok(GLE==0xFACEaBAD, "CreateThread set last error to %d, expected 4207848365\n", GLE);
507 ret = WaitForSingleObject(thread[0],100);
508 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
509 ret = GetExitCodeThread(thread[0],&exitCode);
510 ok(ret!=0, "GetExitCodeThread returned %d (expected nonzero)\n", ret);
511 ok(exitCode==99, "threadFunc2 exited with code: %d (expected 99)\n", exitCode);
512 ok(CloseHandle(thread[0])!=0,"Error closing thread handle\n");
513 }
514 else { /* 9x */
515 ok(GLE==ERROR_INVALID_PARAMETER, "CreateThread set last error to %d, expected 87\n", GLE);
516 }
517 }
518
519 /* Check that using the CREATE_SUSPENDED flag works */
520 static VOID test_CreateThread_suspended(void)
521 {
522 HANDLE thread;
523 DWORD threadId;
524 DWORD suspend_count;
525 int error;
526
527 thread = CreateThread(NULL,0,threadFunc2,NULL,
528 CREATE_SUSPENDED,&threadId);
529 ok(thread!=NULL,"Create Thread failed\n");
530 /* Check that the thread is suspended */
531 ok(SuspendThread(thread)==1,"Thread did not start suspended\n");
532 ok(ResumeThread(thread)==2,"Resume thread returned an invalid value\n");
533 /* Check that resume thread didn't actually start the thread. I can't think
534 of a better way of checking this than just waiting. I am not sure if this
535 will work on slow computers.
536 */
537 ok(WaitForSingleObject(thread,1000)==WAIT_TIMEOUT,
538 "ResumeThread should not have actually started the thread\n");
539 /* Now actually resume the thread and make sure that it actually completes*/
540 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
541 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
542 "Thread did not resume\n");
543 if(error!=WAIT_OBJECT_0) {
544 TerminateThread(thread,1);
545 }
546
547 suspend_count = SuspendThread(thread);
548 ok(suspend_count == -1, "SuspendThread returned %d, expected -1\n", suspend_count);
549
550 suspend_count = ResumeThread(thread);
551 ok(suspend_count == 0 ||
552 broken(suspend_count == -1), /* win9x */
553 "ResumeThread returned %d, expected 0\n", suspend_count);
554
555 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
556 }
557
558 /* Check that SuspendThread and ResumeThread work */
559 static VOID test_SuspendThread(void)
560 {
561 HANDLE thread,access_thread;
562 DWORD threadId,exitCode,error;
563 int i;
564
565 thread = CreateThread(NULL,0,threadFunc3,NULL,
566 0,&threadId);
567 ok(thread!=NULL,"Create Thread failed\n");
568 /* Check that the thread is suspended */
569 /* Note that this is a polling method, and there is a race between
570 SuspendThread being called (in the child, and the loop below timing out,
571 so the test could fail on a heavily loaded or slow computer.
572 */
573 error=0;
574 for(i=0;error==0 && i<100;i++) {
575 error=SuspendThread(thread);
576 ResumeThread(thread);
577 if(error==0) {
578 Sleep(50);
579 i++;
580 }
581 }
582 ok(error==1,"SuspendThread did not work\n");
583 /* check that access restrictions are obeyed */
584 if (pOpenThread) {
585 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 & (~THREAD_SUSPEND_RESUME),
586 0,threadId);
587 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
588 if (access_thread!=NULL) {
589 obey_ar(SuspendThread(access_thread)==~0U);
590 obey_ar(ResumeThread(access_thread)==~0U);
591 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
592 }
593 }
594 /* Double check that the thread really is suspended */
595 ok((error=GetExitCodeThread(thread,&exitCode))!=0 && exitCode==STILL_ACTIVE,
596 "Thread did not really suspend\n");
597 /* Resume the thread, and make sure it actually completes */
598 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
599 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
600 "Thread did not resume\n");
601 if(error!=WAIT_OBJECT_0) {
602 TerminateThread(thread,1);
603 }
604 /* Trying to suspend a terminated thread should fail */
605 error=SuspendThread(thread);
606 ok(error==~0U, "wrong return code: %d\n", error);
607 ok(GetLastError()==ERROR_ACCESS_DENIED || GetLastError()==ERROR_NO_MORE_ITEMS, "unexpected error code: %d\n", GetLastError());
608
609 ok(CloseHandle(thread)!=0,"CloseHandle Failed\n");
610 }
611
612 /* Check that TerminateThread works properly
613 */
614 static VOID test_TerminateThread(void)
615 {
616 HANDLE thread,access_thread,event;
617 DWORD threadId,exitCode;
618 event=CreateEventA(NULL,TRUE,FALSE,NULL);
619 thread = CreateThread(NULL,0,threadFunc4,event,0,&threadId);
620 ok(thread!=NULL,"Create Thread failed\n");
621 /* TerminateThread has a race condition in Wine. If the thread is terminated
622 before it starts, it leaves a process behind. Therefore, we wait for the
623 thread to signal that it has started. There is no easy way to force the
624 race to occur, so we don't try to find it.
625 */
626 ok(WaitForSingleObject(event,5000)==WAIT_OBJECT_0,
627 "TerminateThread didn't work\n");
628 /* check that access restrictions are obeyed */
629 if (pOpenThread) {
630 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 & (~THREAD_TERMINATE),
631 0,threadId);
632 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
633 if (access_thread!=NULL) {
634 obey_ar(TerminateThread(access_thread,99)==0);
635 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
636 }
637 }
638 /* terminate a job and make sure it terminates */
639 ok(TerminateThread(thread,99)!=0,"TerminateThread failed\n");
640 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
641 "TerminateThread didn't work\n");
642 ok(GetExitCodeThread(thread,&exitCode)!=STILL_ACTIVE,
643 "TerminateThread should not leave the thread 'STILL_ACTIVE'\n");
644 ok(exitCode==99, "TerminateThread returned invalid exit code\n");
645 ok(CloseHandle(thread)!=0,"Error Closing thread handle\n");
646 }
647
648 /* Check if CreateThread obeys the specified stack size. This code does
649 not work properly, and is currently disabled
650 */
651 static VOID test_CreateThread_stack(void)
652 {
653 #if CHECK_STACK
654 /* The only way I know of to test the stack size is to use alloca
655 and __try/__except. However, this is probably not portable,
656 and I couldn't get it to work under Wine anyhow. However, here
657 is the code which should allow for testing that CreateThread
658 respects the stack-size limit
659 */
660 HANDLE thread;
661 DWORD threadId,exitCode;
662
663 SYSTEM_INFO sysInfo;
664 sysInfo.dwPageSize=0;
665 GetSystemInfo(&sysInfo);
666 ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
667 thread = CreateThread(NULL,sysInfo.dwPageSize,
668 threadFunc5,&exitCode,
669 0,&threadId);
670 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
671 "TerminateThread didn't work\n");
672 ok(exitCode==1,"CreateThread did not obey stack-size-limit\n");
673 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
674 #endif
675 }
676
677 /* Check whether setting/retrieving thread priorities works */
678 static VOID test_thread_priority(void)
679 {
680 HANDLE curthread,access_thread;
681 DWORD curthreadId,exitCode;
682 int min_priority=-2,max_priority=2;
683 BOOL disabled,rc;
684 int i;
685
686 curthread=GetCurrentThread();
687 curthreadId=GetCurrentThreadId();
688 /* Check thread priority */
689 /* NOTE: on Win2k/XP priority can be from -7 to 6. All other platforms it
690 is -2 to 2. However, even on a real Win2k system, using thread
691 priorities beyond the -2 to 2 range does not work. If you want to try
692 anyway, enable USE_EXTENDED_PRIORITIES
693 */
694 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_NORMAL,
695 "GetThreadPriority Failed\n");
696
697 if (pOpenThread) {
698 /* check that access control is obeyed */
699 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 &
700 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
701 0,curthreadId);
702 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
703 if (access_thread!=NULL) {
704 obey_ar(SetThreadPriority(access_thread,1)==0);
705 obey_ar(GetThreadPriority(access_thread)==THREAD_PRIORITY_ERROR_RETURN);
706 obey_ar(GetExitCodeThread(access_thread,&exitCode)==0);
707 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
708 }
709 }
710 #if USE_EXTENDED_PRIORITIES
711 min_priority=-7; max_priority=6;
712 #endif
713 for(i=min_priority;i<=max_priority;i++) {
714 ok(SetThreadPriority(curthread,i)!=0,
715 "SetThreadPriority Failed for priority: %d\n",i);
716 ok(GetThreadPriority(curthread)==i,
717 "GetThreadPriority Failed for priority: %d\n",i);
718 }
719 ok(SetThreadPriority(curthread,THREAD_PRIORITY_TIME_CRITICAL)!=0,
720 "SetThreadPriority Failed\n");
721 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_TIME_CRITICAL,
722 "GetThreadPriority Failed\n");
723 ok(SetThreadPriority(curthread,THREAD_PRIORITY_IDLE)!=0,
724 "SetThreadPriority Failed\n");
725 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_IDLE,
726 "GetThreadPriority Failed\n");
727 ok(SetThreadPriority(curthread,0)!=0,"SetThreadPriority Failed\n");
728
729 /* Check that the thread priority is not changed if SetThreadPriority
730 is called with a value outside of the max/min range */
731 SetThreadPriority(curthread,min_priority);
732 SetLastError(0xdeadbeef);
733 rc = SetThreadPriority(curthread,min_priority-1);
734
735 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
736 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
737 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
738 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
739 GetLastError());
740 ok(GetThreadPriority(curthread)==min_priority,
741 "GetThreadPriority didn't return min_priority\n");
742
743 SetThreadPriority(curthread,max_priority);
744 SetLastError(0xdeadbeef);
745 rc = SetThreadPriority(curthread,max_priority+1);
746
747 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
748 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
749 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
750 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
751 GetLastError());
752 ok(GetThreadPriority(curthread)==max_priority,
753 "GetThreadPriority didn't return max_priority\n");
754
755 /* Check thread priority boost */
756 if (!pGetThreadPriorityBoost || !pSetThreadPriorityBoost)
757 return; /* Win9x */
758
759 SetLastError(0xdeadbeef);
760 rc=pGetThreadPriorityBoost(curthread,&disabled);
761 if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
762 {
763 win_skip("GetThreadPriorityBoost is not implemented on WinME\n");
764 return;
765 }
766
767 ok(rc!=0,"error=%d\n",GetLastError());
768
769 if (pOpenThread) {
770 /* check that access control is obeyed */
771 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 &
772 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
773 0,curthreadId);
774 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
775 if (access_thread!=NULL) {
776 todo_wine obey_ar(pSetThreadPriorityBoost(access_thread,1)==0);
777 todo_wine obey_ar(pGetThreadPriorityBoost(access_thread,&disabled)==0);
778 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
779 }
780 }
781
782 rc = pSetThreadPriorityBoost(curthread,1);
783 ok( rc != 0, "error=%d\n",GetLastError());
784 todo_wine {
785 rc=pGetThreadPriorityBoost(curthread,&disabled);
786 ok(rc!=0 && disabled==1,
787 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
788 }
789
790 rc = pSetThreadPriorityBoost(curthread,0);
791 ok( rc != 0, "error=%d\n",GetLastError());
792 rc=pGetThreadPriorityBoost(curthread,&disabled);
793 ok(rc!=0 && disabled==0,
794 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
795 }
796
797 /* check the GetThreadTimes function */
798 static VOID test_GetThreadTimes(void)
799 {
800 HANDLE thread,access_thread=NULL;
801 FILETIME creationTime,exitTime,kernelTime,userTime;
802 DWORD threadId;
803 int error;
804
805 thread = CreateThread(NULL,0,threadFunc2,NULL,
806 CREATE_SUSPENDED,&threadId);
807
808 ok(thread!=NULL,"Create Thread failed\n");
809 /* check that access control is obeyed */
810 if (pOpenThread) {
811 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 &
812 (~THREAD_QUERY_INFORMATION), 0,threadId);
813 ok(access_thread!=NULL,
814 "OpenThread returned an invalid handle\n");
815 }
816 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
817 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
818 "ResumeThread didn't work\n");
819 creationTime.dwLowDateTime=99; creationTime.dwHighDateTime=99;
820 exitTime.dwLowDateTime=99; exitTime.dwHighDateTime=99;
821 kernelTime.dwLowDateTime=99; kernelTime.dwHighDateTime=99;
822 userTime.dwLowDateTime=99; userTime.dwHighDateTime=99;
823 /* GetThreadTimes should set all of the parameters passed to it */
824 error=GetThreadTimes(thread,&creationTime,&exitTime,
825 &kernelTime,&userTime);
826
827 if (error == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
828 win_skip("GetThreadTimes is not implemented\n");
829 else {
830 ok(error!=0,"GetThreadTimes failed\n");
831 ok(creationTime.dwLowDateTime!=99 || creationTime.dwHighDateTime!=99,
832 "creationTime was invalid\n");
833 ok(exitTime.dwLowDateTime!=99 || exitTime.dwHighDateTime!=99,
834 "exitTime was invalid\n");
835 ok(kernelTime.dwLowDateTime!=99 || kernelTime.dwHighDateTime!=99,
836 "kernelTimewas invalid\n");
837 ok(userTime.dwLowDateTime!=99 || userTime.dwHighDateTime!=99,
838 "userTime was invalid\n");
839 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
840 if(access_thread!=NULL)
841 {
842 error=GetThreadTimes(access_thread,&creationTime,&exitTime,
843 &kernelTime,&userTime);
844 obey_ar(error==0);
845 }
846 }
847 if(access_thread!=NULL) {
848 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
849 }
850 }
851
852 /* Check the processor affinity functions */
853 /* NOTE: These functions should also be checked that they obey access control
854 */
855 static VOID test_thread_processor(void)
856 {
857 HANDLE curthread,curproc;
858 DWORD_PTR processMask,systemMask,retMask;
859 SYSTEM_INFO sysInfo;
860 int error=0;
861 BOOL is_wow64;
862
863 if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
864
865 sysInfo.dwNumberOfProcessors=0;
866 GetSystemInfo(&sysInfo);
867 ok(sysInfo.dwNumberOfProcessors>0,
868 "GetSystemInfo failed to return a valid # of processors\n");
869 /* Use the current Thread/process for all tests */
870 curthread=GetCurrentThread();
871 ok(curthread!=NULL,"GetCurrentThread failed\n");
872 curproc=GetCurrentProcess();
873 ok(curproc!=NULL,"GetCurrentProcess failed\n");
874 /* Check the Affinity Mask functions */
875 ok(GetProcessAffinityMask(curproc,&processMask,&systemMask)!=0,
876 "GetProcessAffinityMask failed\n");
877 ok(SetThreadAffinityMask(curthread,processMask)==processMask,
878 "SetThreadAffinityMask failed\n");
879 ok(SetThreadAffinityMask(curthread,processMask+1)==0,
880 "SetThreadAffinityMask passed for an illegal processor\n");
881 /* NOTE: Pre-Vista does not recognize the "all processors" flag (all bits set) */
882 retMask = SetThreadAffinityMask(curthread,~0);
883 ok(broken(retMask==0) || retMask==processMask,
884 "SetThreadAffinityMask(thread,-1) failed to request all processors.\n");
885
886 if (retMask == processMask)
887 {
888 /* Show that the "all processors" flag is handled in ntdll */
889 DWORD_PTR mask = ~0u;
890 NTSTATUS status = pNtSetInformationThread(curthread, ThreadAffinityMask, &mask, sizeof(mask));
891 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS in NtSetInformationThread, got %x\n", status);
892 }
893
894 if (retMask == processMask && sizeof(ULONG_PTR) > sizeof(ULONG))
895 {
896 /* only the low 32-bits matter */
897 retMask = SetThreadAffinityMask(curthread,~(ULONG_PTR)0);
898 ok(retMask == processMask, "SetThreadAffinityMask failed\n");
899 retMask = SetThreadAffinityMask(curthread,~(ULONG_PTR)0 >> 3);
900 ok(retMask == processMask, "SetThreadAffinityMask failed\n");
901 }
902 /* NOTE: This only works on WinNT/2000/XP) */
903 if (pSetThreadIdealProcessor)
904 {
905 SetLastError(0xdeadbeef);
906 error=pSetThreadIdealProcessor(curthread,0);
907 if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
908 {
909 ok(error!=-1, "SetThreadIdealProcessor failed\n");
910
911 if (is_wow64)
912 {
913 SetLastError(0xdeadbeef);
914 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
915 todo_wine
916 ok(error!=-1, "SetThreadIdealProcessor failed for %u on Wow64\n", MAXIMUM_PROCESSORS+1);
917
918 SetLastError(0xdeadbeef);
919 error=pSetThreadIdealProcessor(curthread,65);
920 ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
921 ok(GetLastError()==ERROR_INVALID_PARAMETER,
922 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
923 }
924 else
925 {
926 SetLastError(0xdeadbeef);
927 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
928 ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
929 ok(GetLastError()==ERROR_INVALID_PARAMETER,
930 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
931 }
932
933 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS);
934 ok(error!=-1, "SetThreadIdealProcessor failed\n");
935 }
936 else
937 win_skip("SetThreadIdealProcessor is not implemented\n");
938 }
939
940 if (pGetThreadGroupAffinity && pSetThreadGroupAffinity)
941 {
942 GROUP_AFFINITY affinity, affinity_new;
943 NTSTATUS status;
944
945 memset(&affinity, 0, sizeof(affinity));
946 ok(pGetThreadGroupAffinity(curthread, &affinity), "GetThreadGroupAffinity failed\n");
947
948 SetLastError(0xdeadbeef);
949 ok(!pGetThreadGroupAffinity(curthread, NULL), "GetThreadGroupAffinity succeeded\n");
950 ok(GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == ERROR_NOACCESS), /* Win 7 and 8 */
951 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
952 ok(affinity.Group == 0, "Expected group 0 got %u\n", affinity.Group);
953
954 memset(&affinity_new, 0, sizeof(affinity_new));
955 affinity_new.Group = 0;
956 affinity_new.Mask = affinity.Mask;
957 ok(pSetThreadGroupAffinity(curthread, &affinity_new, &affinity), "SetThreadGroupAffinity failed\n");
958 ok(affinity_new.Mask == affinity.Mask, "Expected old affinity mask %lx, got %lx\n",
959 affinity_new.Mask, affinity.Mask);
960
961 /* show that the "all processors" flag is not supported for SetThreadGroupAffinity */
962 affinity_new.Group = 0;
963 affinity_new.Mask = ~0u;
964 SetLastError(0xdeadbeef);
965 ok(!pSetThreadGroupAffinity(curthread, &affinity_new, NULL), "SetThreadGroupAffinity succeeded\n");
966 ok(GetLastError() == ERROR_INVALID_PARAMETER,
967 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
968
969 affinity_new.Group = 1; /* assumes that you have less than 64 logical processors */
970 affinity_new.Mask = 0x1;
971 SetLastError(0xdeadbeef);
972 ok(!pSetThreadGroupAffinity(curthread, &affinity_new, NULL), "SetThreadGroupAffinity succeeded\n");
973 ok(GetLastError() == ERROR_INVALID_PARAMETER,
974 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
975
976 SetLastError(0xdeadbeef);
977 ok(!pSetThreadGroupAffinity(curthread, NULL, NULL), "SetThreadGroupAffinity succeeded\n");
978 ok(GetLastError() == ERROR_NOACCESS,
979 "Expected ERROR_NOACCESS, got %d\n", GetLastError());
980
981 /* show that the access violation was detected in ntdll */
982 status = pNtSetInformationThread(curthread, ThreadGroupInformation, NULL, sizeof(affinity_new));
983 ok(status == STATUS_ACCESS_VIOLATION,
984 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
985
986 /* restore original mask */
987 affinity_new.Group = 0;
988 affinity_new.Mask = affinity.Mask;
989 SetLastError(0xdeadbeef);
990 ok(pSetThreadGroupAffinity(curthread, &affinity_new, &affinity), "SetThreadGroupAffinity failed\n");
991 ok(affinity_new.Mask == affinity.Mask, "Expected old affinity mask %lx, got %lx\n",
992 affinity_new.Mask, affinity.Mask);
993 }
994 else
995 win_skip("Get/SetThreadGroupAffinity not available\n");
996 }
997
998 static VOID test_GetThreadExitCode(void)
999 {
1000 DWORD exitCode, threadid;
1001 DWORD GLE, ret;
1002 HANDLE thread;
1003
1004 ret = GetExitCodeThread((HANDLE)0x2bad2bad,&exitCode);
1005 ok(ret==0, "GetExitCodeThread returned non zero value: %d\n", ret);
1006 GLE = GetLastError();
1007 ok(GLE==ERROR_INVALID_HANDLE, "GetLastError returned %d (expected 6)\n", GLE);
1008
1009 thread = CreateThread(NULL,0,threadFunc2,NULL,0,&threadid);
1010 ret = WaitForSingleObject(thread,100);
1011 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
1012 ret = GetExitCodeThread(thread,&exitCode);
1013 ok(ret==exitCode || ret==1,
1014 "GetExitCodeThread returned %d (expected 1 or %d)\n", ret, exitCode);
1015 ok(exitCode==99, "threadFunc2 exited with code %d (expected 99)\n", exitCode);
1016 ok(CloseHandle(thread)!=0,"Error closing thread handle\n");
1017 }
1018
1019 #ifdef __i386__
1020
1021 static int test_value = 0;
1022 static HANDLE event;
1023
1024 static void WINAPI set_test_val( int val )
1025 {
1026 test_value += val;
1027 ExitThread(0);
1028 }
1029
1030 static DWORD WINAPI threadFunc6(LPVOID p)
1031 {
1032 SetEvent( event );
1033 Sleep( 1000 );
1034 test_value *= (int)p;
1035 return 0;
1036 }
1037
1038 static void test_SetThreadContext(void)
1039 {
1040 CONTEXT ctx;
1041 int *stack;
1042 HANDLE thread;
1043 DWORD threadid;
1044 DWORD prevcount;
1045 BOOL ret;
1046
1047 SetLastError(0xdeadbeef);
1048 event = CreateEventW( NULL, TRUE, FALSE, NULL );
1049 thread = CreateThread( NULL, 0, threadFunc6, (void *)2, 0, &threadid );
1050 ok( thread != NULL, "CreateThread failed : (%d)\n", GetLastError() );
1051 if (!thread)
1052 {
1053 trace("Thread creation failed, skipping rest of test\n");
1054 return;
1055 }
1056 WaitForSingleObject( event, INFINITE );
1057 SuspendThread( thread );
1058 CloseHandle( event );
1059
1060 ctx.ContextFlags = CONTEXT_FULL;
1061 SetLastError(0xdeadbeef);
1062 ret = GetThreadContext( thread, &ctx );
1063 ok( ret, "GetThreadContext failed : (%u)\n", GetLastError() );
1064
1065 if (ret)
1066 {
1067 /* simulate a call to set_test_val(10) */
1068 stack = (int *)ctx.Esp;
1069 stack[-1] = 10;
1070 stack[-2] = ctx.Eip;
1071 ctx.Esp -= 2 * sizeof(int *);
1072 ctx.Eip = (DWORD)set_test_val;
1073 SetLastError(0xdeadbeef);
1074 ret = SetThreadContext( thread, &ctx );
1075 ok( ret, "SetThreadContext failed : (%d)\n", GetLastError() );
1076 }
1077
1078 SetLastError(0xdeadbeef);
1079 prevcount = ResumeThread( thread );
1080 ok ( prevcount == 1, "Previous suspend count (%d) instead of 1, last error : (%d)\n",
1081 prevcount, GetLastError() );
1082
1083 WaitForSingleObject( thread, INFINITE );
1084 ok( test_value == 10, "test_value %d\n", test_value );
1085
1086 ctx.ContextFlags = CONTEXT_FULL;
1087 SetLastError(0xdeadbeef);
1088 ret = GetThreadContext( thread, &ctx );
1089 ok( (!ret && ((GetLastError() == ERROR_GEN_FAILURE) || (GetLastError() == ERROR_ACCESS_DENIED))) ||
1090 (!ret && broken(GetLastError() == ERROR_INVALID_HANDLE)) || /* win2k */
1091 broken(ret), /* 32bit application on NT 5.x 64bit */
1092 "got %d with %u (expected FALSE with ERROR_GEN_FAILURE or ERROR_ACCESS_DENIED)\n",
1093 ret, GetLastError() );
1094
1095 SetLastError(0xdeadbeef);
1096 ret = SetThreadContext( thread, &ctx );
1097 ok( (!ret && ((GetLastError() == ERROR_GEN_FAILURE) || (GetLastError() == ERROR_ACCESS_DENIED))) ||
1098 (!ret && broken(GetLastError() == ERROR_INVALID_HANDLE)) || /* win2k */
1099 broken(ret), /* 32bit application on NT 5.x 64bit */
1100 "got %d with %u (expected FALSE with ERROR_GEN_FAILURE or ERROR_ACCESS_DENIED)\n",
1101 ret, GetLastError() );
1102
1103 CloseHandle( thread );
1104 }
1105
1106 static void test_GetThreadSelectorEntry(void)
1107 {
1108 LDT_ENTRY entry;
1109 CONTEXT ctx;
1110 DWORD limit;
1111 void *base;
1112 BOOL ret;
1113
1114 memset(&ctx, 0x11, sizeof(ctx));
1115 ctx.ContextFlags = CONTEXT_SEGMENTS | CONTEXT_CONTROL;
1116 ret = GetThreadContext(GetCurrentThread(), &ctx);
1117 ok(ret, "GetThreadContext error %u\n", GetLastError());
1118 ok(!HIWORD(ctx.SegCs), "expected HIWORD(SegCs) == 0, got %u\n", ctx.SegCs);
1119 ok(!HIWORD(ctx.SegDs), "expected HIWORD(SegDs) == 0, got %u\n", ctx.SegDs);
1120 ok(!HIWORD(ctx.SegFs), "expected HIWORD(SegFs) == 0, got %u\n", ctx.SegFs);
1121
1122 ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegCs, &entry);
1123 ok(ret, "GetThreadSelectorEntry(SegCs) error %u\n", GetLastError());
1124 ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegDs, &entry);
1125 ok(ret, "GetThreadSelectorEntry(SegDs) error %u\n", GetLastError());
1126
1127 memset(&entry, 0x11, sizeof(entry));
1128 ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegFs, &entry);
1129 ok(ret, "GetThreadSelectorEntry(SegFs) error %u\n", GetLastError());
1130 entry.HighWord.Bits.Type &= ~1; /* ignore accessed bit */
1131
1132 base = (void *)((entry.HighWord.Bits.BaseHi << 24) | (entry.HighWord.Bits.BaseMid << 16) | entry.BaseLow);
1133 limit = (entry.HighWord.Bits.LimitHi << 16) | entry.LimitLow;
1134
1135 ok(base == NtCurrentTeb(), "expected %p, got %p\n", NtCurrentTeb(), base);
1136 ok(limit == 0x0fff || limit == 0x4000, "expected 0x0fff or 0x4000, got %#x\n", limit);
1137 ok(entry.HighWord.Bits.Type == 0x12, "expected 0x12, got %#x\n", entry.HighWord.Bits.Type);
1138 ok(entry.HighWord.Bits.Dpl == 3, "expected 3, got %u\n", entry.HighWord.Bits.Dpl);
1139 ok(entry.HighWord.Bits.Pres == 1, "expected 1, got %u\n", entry.HighWord.Bits.Pres);
1140 ok(entry.HighWord.Bits.Sys == 0, "expected 0, got %u\n", entry.HighWord.Bits.Sys);
1141 ok(entry.HighWord.Bits.Reserved_0 == 0, "expected 0, got %u\n", entry.HighWord.Bits.Reserved_0);
1142 ok(entry.HighWord.Bits.Default_Big == 1, "expected 1, got %u\n", entry.HighWord.Bits.Default_Big);
1143 ok(entry.HighWord.Bits.Granularity == 0, "expected 0, got %u\n", entry.HighWord.Bits.Granularity);
1144 }
1145
1146 static void test_NtSetLdtEntries(void)
1147 {
1148 THREAD_DESCRIPTOR_INFORMATION tdi;
1149 LDT_ENTRY ds_entry;
1150 CONTEXT ctx;
1151 DWORD ret;
1152 union
1153 {
1154 LDT_ENTRY entry;
1155 DWORD dw[2];
1156 } sel;
1157
1158 if (!pNtSetLdtEntries)
1159 {
1160 win_skip("NtSetLdtEntries is not available on this platform\n");
1161 return;
1162 }
1163
1164 if (pNtSetLdtEntries(0, 0, 0, 0, 0, 0) == STATUS_NOT_IMPLEMENTED) /* WoW64 */
1165 {
1166 win_skip("NtSetLdtEntries is not implemented on this platform\n");
1167 return;
1168 }
1169
1170 ret = pNtSetLdtEntries(0, 0, 0, 0, 0, 0);
1171 ok(!ret, "NtSetLdtEntries failed: %08x\n", ret);
1172
1173 ctx.ContextFlags = CONTEXT_SEGMENTS;
1174 ret = GetThreadContext(GetCurrentThread(), &ctx);
1175 ok(ret, "GetThreadContext failed\n");
1176
1177 tdi.Selector = ctx.SegDs;
1178 ret = pNtQueryInformationThread(GetCurrentThread(), ThreadDescriptorTableEntry, &tdi, sizeof(tdi), &ret);
1179 ok(!ret, "NtQueryInformationThread failed: %08x\n", ret);
1180 ds_entry = tdi.Entry;
1181
1182 tdi.Selector = 0x000f;
1183 ret = pNtQueryInformationThread(GetCurrentThread(), ThreadDescriptorTableEntry, &tdi, sizeof(tdi), &ret);
1184 ok(ret == STATUS_ACCESS_VIOLATION, "got %08x\n", ret);
1185
1186 tdi.Selector = 0x001f;
1187 ret = pNtQueryInformationThread(GetCurrentThread(), ThreadDescriptorTableEntry, &tdi, sizeof(tdi), &ret);
1188 ok(ret == STATUS_ACCESS_VIOLATION, "NtQueryInformationThread returned %08x\n", ret);
1189
1190 ret = GetThreadSelectorEntry(GetCurrentThread(), 0x000f, &sel.entry);
1191 ok(!ret, "GetThreadSelectorEntry should fail\n");
1192
1193 ret = GetThreadSelectorEntry(GetCurrentThread(), 0x001f, &sel.entry);
1194 ok(!ret, "GetThreadSelectorEntry should fail\n");
1195
1196 memset(&sel.entry, 0x9a, sizeof(sel.entry));
1197 ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegDs, &sel.entry);
1198 ok(ret, "GetThreadSelectorEntry failed\n");
1199 ok(!memcmp(&ds_entry, &sel.entry, sizeof(ds_entry)), "entries do not match\n");
1200
1201 ret = pNtSetLdtEntries(0x000f, sel.dw[0], sel.dw[1], 0x001f, sel.dw[0], sel.dw[1]);
1202 ok(!ret || broken(ret == STATUS_INVALID_LDT_DESCRIPTOR) /*XP*/, "NtSetLdtEntries failed: %08x\n", ret);
1203
1204 if (!ret)
1205 {
1206 memset(&sel.entry, 0x9a, sizeof(sel.entry));
1207 ret = GetThreadSelectorEntry(GetCurrentThread(), 0x000f, &sel.entry);
1208 ok(ret, "GetThreadSelectorEntry failed\n");
1209 ok(!memcmp(&ds_entry, &sel.entry, sizeof(ds_entry)), "entries do not match\n");
1210
1211 memset(&sel.entry, 0x9a, sizeof(sel.entry));
1212 ret = GetThreadSelectorEntry(GetCurrentThread(), 0x001f, &sel.entry);
1213 ok(ret, "GetThreadSelectorEntry failed\n");
1214 ok(!memcmp(&ds_entry, &sel.entry, sizeof(ds_entry)), "entries do not match\n");
1215 }
1216 }
1217
1218 #endif /* __i386__ */
1219
1220 static HANDLE finish_event;
1221 static LONG times_executed;
1222
1223 static DWORD CALLBACK work_function(void *p)
1224 {
1225 LONG executed = InterlockedIncrement(&times_executed);
1226
1227 if (executed == 100)
1228 SetEvent(finish_event);
1229 return 0;
1230 }
1231
1232 static void test_QueueUserWorkItem(void)
1233 {
1234 INT_PTR i;
1235 DWORD wait_result;
1236 DWORD before, after;
1237
1238 /* QueueUserWorkItem not present on win9x */
1239 if (!pQueueUserWorkItem) return;
1240
1241 finish_event = CreateEventW(NULL, TRUE, FALSE, NULL);
1242
1243 before = GetTickCount();
1244
1245 for (i = 0; i < 100; i++)
1246 {
1247 BOOL ret = pQueueUserWorkItem(work_function, (void *)i, WT_EXECUTEDEFAULT);
1248 ok(ret, "QueueUserWorkItem failed with error %d\n", GetLastError());
1249 }
1250
1251 wait_result = WaitForSingleObject(finish_event, 10000);
1252
1253 after = GetTickCount();
1254 trace("100 QueueUserWorkItem calls took %dms\n", after - before);
1255 ok(wait_result == WAIT_OBJECT_0, "wait failed with error 0x%x\n", wait_result);
1256
1257 ok(times_executed == 100, "didn't execute all of the work items\n");
1258 }
1259
1260 static void CALLBACK signaled_function(PVOID p, BOOLEAN TimerOrWaitFired)
1261 {
1262 HANDLE event = p;
1263 SetEvent(event);
1264 ok(!TimerOrWaitFired, "wait shouldn't have timed out\n");
1265 }
1266
1267 static void CALLBACK timeout_function(PVOID p, BOOLEAN TimerOrWaitFired)
1268 {
1269 HANDLE event = p;
1270 SetEvent(event);
1271 ok(TimerOrWaitFired, "wait should have timed out\n");
1272 }
1273
1274 static void test_RegisterWaitForSingleObject(void)
1275 {
1276 BOOL ret;
1277 HANDLE wait_handle;
1278 HANDLE handle;
1279 HANDLE complete_event;
1280
1281 if (!pRegisterWaitForSingleObject || !pUnregisterWait)
1282 {
1283 win_skip("RegisterWaitForSingleObject or UnregisterWait not implemented\n");
1284 return;
1285 }
1286
1287 /* test signaled case */
1288
1289 handle = CreateEventW(NULL, TRUE, TRUE, NULL);
1290 complete_event = CreateEventW(NULL, FALSE, FALSE, NULL);
1291
1292 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1293 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1294
1295 WaitForSingleObject(complete_event, INFINITE);
1296 /* give worker thread chance to complete */
1297 Sleep(100);
1298
1299 ret = pUnregisterWait(wait_handle);
1300 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1301
1302 /* test cancel case */
1303
1304 ResetEvent(handle);
1305
1306 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1307 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1308
1309 ret = pUnregisterWait(wait_handle);
1310 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1311
1312 /* test timeout case */
1313
1314 ret = pRegisterWaitForSingleObject(&wait_handle, handle, timeout_function, complete_event, 0, WT_EXECUTEONLYONCE);
1315 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1316
1317 WaitForSingleObject(complete_event, INFINITE);
1318 /* give worker thread chance to complete */
1319 Sleep(100);
1320
1321 ret = pUnregisterWait(wait_handle);
1322 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1323
1324 SetLastError(0xdeadbeef);
1325 ret = pUnregisterWait(NULL);
1326 ok(!ret, "Expected UnregisterWait to fail\n");
1327 ok(GetLastError() == ERROR_INVALID_HANDLE,
1328 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1329 }
1330
1331 static DWORD LS_main;
1332 static DWORD LS_index0, LS_index1;
1333 static DWORD LS_OutOfIndexesValue;
1334
1335 /* Function pointers to the FLS/TLS functions to test in LS_ThreadProc() */
1336 static DWORD (WINAPI *LS_AllocFunc)(void);
1337 static PVOID (WINAPI *LS_GetValueFunc)(DWORD);
1338 static BOOL (WINAPI *LS_SetValueFunc)(DWORD, PVOID);
1339 static BOOL (WINAPI *LS_FreeFunc)(DWORD);
1340
1341 /* Names of the functions tested in LS_ThreadProc(), for error messages */
1342 static const char* LS_AllocFuncName = "";
1343 static const char* LS_GetValueFuncName = "";
1344 static const char* LS_SetValueFuncName = "";
1345 static const char* LS_FreeFuncName = "";
1346
1347 /* FLS entry points, dynamically loaded in platforms that support them */
1348 static DWORD (WINAPI *pFlsAlloc)(PFLS_CALLBACK_FUNCTION);
1349 static BOOL (WINAPI *pFlsFree)(DWORD);
1350 static PVOID (WINAPI *pFlsGetValue)(DWORD);
1351 static BOOL (WINAPI *pFlsSetValue)(DWORD,PVOID);
1352
1353 /* A thunk function to make FlsAlloc compatible with the signature of TlsAlloc */
1354 static DWORD WINAPI FLS_AllocFuncThunk(void)
1355 {
1356 return pFlsAlloc(NULL);
1357 }
1358
1359 static DWORD WINAPI LS_InheritanceProc(LPVOID p)
1360 {
1361 /* We should NOT inherit the FLS/TLS values from our parent or from the
1362 main thread. */
1363 LPVOID val;
1364
1365 val = LS_GetValueFunc(LS_main);
1366 ok(val == NULL, "%s inheritance failed\n", LS_GetValueFuncName);
1367
1368 val = LS_GetValueFunc(LS_index0);
1369 ok(val == NULL, "%s inheritance failed\n", LS_GetValueFuncName);
1370
1371 val = LS_GetValueFunc(LS_index1);
1372 ok(val == NULL, "%s inheritance failed\n", LS_GetValueFuncName);
1373
1374 return 0;
1375 }
1376
1377 /* Basic FLS/TLS usage test. Make sure we can create slots and the values we
1378 store in them are separate among threads. Also test FLS/TLS value
1379 inheritance with LS_InheritanceProc. */
1380 static DWORD WINAPI LS_ThreadProc(LPVOID p)
1381 {
1382 LONG_PTR id = (LONG_PTR) p;
1383 LPVOID val;
1384 BOOL ret;
1385
1386 if (sync_threads_and_run_one(0, id))
1387 {
1388 LS_index0 = LS_AllocFunc();
1389 ok(LS_index0 != LS_OutOfIndexesValue, "%s failed\n", LS_AllocFuncName);
1390 }
1391 resync_after_run();
1392
1393 if (sync_threads_and_run_one(1, id))
1394 {
1395 LS_index1 = LS_AllocFunc();
1396 ok(LS_index1 != LS_OutOfIndexesValue, "%s failed\n", LS_AllocFuncName);
1397
1398 /* Slot indices should be different even if created in different
1399 threads. */
1400 ok(LS_index0 != LS_index1, "%s failed\n", LS_AllocFuncName);
1401
1402 /* Both slots should be initialized to NULL */
1403 SetLastError(0xdeadbeef);
1404 val = LS_GetValueFunc(LS_index0);
1405 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1406 ok(val == NULL, "Slot not initialized correctly\n");
1407
1408 SetLastError(0xdeadbeef);
1409 val = LS_GetValueFunc(LS_index1);
1410 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1411 ok(val == NULL, "Slot not initialized correctly\n");
1412 }
1413 resync_after_run();
1414
1415 if (sync_threads_and_run_one(0, id))
1416 {
1417 SetLastError(0xdeadbeef);
1418 val = LS_GetValueFunc(LS_index0);
1419 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1420 ok(val == NULL, "Slot not initialized correctly\n");
1421
1422 SetLastError(0xdeadbeef);
1423 val = LS_GetValueFunc(LS_index1);
1424 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1425 ok(val == NULL, "Slot not initialized correctly\n");
1426
1427 ret = LS_SetValueFunc(LS_index0, (LPVOID) 1);
1428 ok(ret, "%s failed\n", LS_SetValueFuncName);
1429
1430 ret = LS_SetValueFunc(LS_index1, (LPVOID) 2);
1431 ok(ret, "%s failed\n", LS_SetValueFuncName);
1432
1433 SetLastError(0xdeadbeef);
1434 val = LS_GetValueFunc(LS_index0);
1435 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1436 ok(val == (LPVOID) 1, "Slot not initialized correctly\n");
1437
1438 SetLastError(0xdeadbeef);
1439 val = LS_GetValueFunc(LS_index1);
1440 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1441 ok(val == (LPVOID) 2, "Slot not initialized correctly\n");
1442 }
1443 resync_after_run();
1444
1445 if (sync_threads_and_run_one(1, id))
1446 {
1447 val = LS_GetValueFunc(LS_index0);
1448 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1449 ok(val == NULL, "Slot not initialized correctly\n");
1450
1451 val = LS_GetValueFunc(LS_index1);
1452 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1453 ok(val == NULL, "Slot not initialized correctly\n");
1454
1455 ret = LS_SetValueFunc(LS_index0, (LPVOID) 3);
1456 ok(ret, "%s failed\n", LS_SetValueFuncName);
1457
1458 ret = LS_SetValueFunc(LS_index1, (LPVOID) 4);
1459 ok(ret, "%s failed\n", LS_SetValueFuncName);
1460
1461 val = LS_GetValueFunc(LS_index0);
1462 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1463 ok(val == (LPVOID) 3, "Slot not initialized correctly\n");
1464
1465 val = LS_GetValueFunc(LS_index1);
1466 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1467 ok(val == (LPVOID) 4, "Slot not initialized correctly\n");
1468 }
1469 resync_after_run();
1470
1471 if (sync_threads_and_run_one(0, id))
1472 {
1473 HANDLE thread;
1474 DWORD waitret, tid;
1475
1476 val = LS_GetValueFunc(LS_index0);
1477 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1478 ok(val == (LPVOID) 1, "Slot not initialized correctly\n");
1479
1480 val = LS_GetValueFunc(LS_index1);
1481 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1482 ok(val == (LPVOID) 2, "Slot not initialized correctly\n");
1483
1484 thread = CreateThread(NULL, 0, LS_InheritanceProc, 0, 0, &tid);
1485 ok(thread != NULL, "CreateThread failed\n");
1486 waitret = WaitForSingleObject(thread, 60000);
1487 ok(waitret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
1488 CloseHandle(thread);
1489
1490 ret = LS_FreeFunc(LS_index0);
1491 ok(ret, "%s failed\n", LS_FreeFuncName);
1492 }
1493 resync_after_run();
1494
1495 if (sync_threads_and_run_one(1, id))
1496 {
1497 ret = LS_FreeFunc(LS_index1);
1498 ok(ret, "%s failed\n", LS_FreeFuncName);
1499 }
1500 resync_after_run();
1501
1502 return 0;
1503 }
1504
1505 static void run_LS_tests(void)
1506 {
1507 HANDLE threads[2];
1508 LONG_PTR i;
1509 DWORD ret;
1510 BOOL suc;
1511
1512 init_thread_sync_helpers();
1513
1514 /* Allocate a slot in the main thread to test for inheritance. */
1515 LS_main = LS_AllocFunc();
1516 ok(LS_main != LS_OutOfIndexesValue, "%s failed\n", LS_AllocFuncName);
1517 suc = LS_SetValueFunc(LS_main, (LPVOID) 4114);
1518 ok(suc, "%s failed\n", LS_SetValueFuncName);
1519
1520 for (i = 0; i < 2; ++i)
1521 {
1522 DWORD tid;
1523
1524 threads[i] = CreateThread(NULL, 0, LS_ThreadProc, (LPVOID) i, 0, &tid);
1525 ok(threads[i] != NULL, "CreateThread failed\n");
1526 }
1527
1528 ret = WaitForMultipleObjects(2, threads, TRUE, 60000);
1529 ok(ret == WAIT_OBJECT_0 || broken(ret == WAIT_OBJECT_0+1 /* nt4,w2k */), "WaitForAllObjects 2 threads %d\n",ret);
1530
1531 for (i = 0; i < 2; ++i)
1532 CloseHandle(threads[i]);
1533
1534 suc = LS_FreeFunc(LS_main);
1535 ok(suc, "%s failed\n", LS_FreeFuncName);
1536 cleanup_thread_sync_helpers();
1537 }
1538
1539 static void test_TLS(void)
1540 {
1541 LS_OutOfIndexesValue = TLS_OUT_OF_INDEXES;
1542
1543 LS_AllocFunc = &TlsAlloc;
1544 LS_GetValueFunc = &TlsGetValue;
1545 LS_SetValueFunc = &TlsSetValue;
1546 LS_FreeFunc = &TlsFree;
1547
1548 LS_AllocFuncName = "TlsAlloc";
1549 LS_GetValueFuncName = "TlsGetValue";
1550 LS_SetValueFuncName = "TlsSetValue";
1551 LS_FreeFuncName = "TlsFree";
1552
1553 run_LS_tests();
1554 }
1555
1556 static void test_FLS(void)
1557 {
1558 if (!pFlsAlloc || !pFlsFree || !pFlsGetValue || !pFlsSetValue)
1559 {
1560 win_skip("Fiber Local Storage not supported\n");
1561 return;
1562 }
1563
1564 LS_OutOfIndexesValue = FLS_OUT_OF_INDEXES;
1565
1566 LS_AllocFunc = &FLS_AllocFuncThunk;
1567 LS_GetValueFunc = pFlsGetValue;
1568 LS_SetValueFunc = pFlsSetValue;
1569 LS_FreeFunc = pFlsFree;
1570
1571 LS_AllocFuncName = "FlsAlloc";
1572 LS_GetValueFuncName = "FlsGetValue";
1573 LS_SetValueFuncName = "FlsSetValue";
1574 LS_FreeFuncName = "FlsFree";
1575
1576 run_LS_tests();
1577 }
1578
1579 static void test_ThreadErrorMode(void)
1580 {
1581 DWORD oldmode;
1582 DWORD mode;
1583 DWORD rtlmode;
1584 BOOL ret;
1585
1586 if (!pSetThreadErrorMode || !pGetThreadErrorMode)
1587 {
1588 win_skip("SetThreadErrorMode and/or GetThreadErrorMode unavailable (added in Windows 7)\n");
1589 return;
1590 }
1591
1592 if (!pRtlGetThreadErrorMode) {
1593 win_skip("RtlGetThreadErrorMode not available\n");
1594 return;
1595 }
1596
1597 oldmode = pGetThreadErrorMode();
1598
1599 ret = pSetThreadErrorMode(0, &mode);
1600 ok(ret, "SetThreadErrorMode failed\n");
1601 ok(mode == oldmode,
1602 "SetThreadErrorMode returned old mode 0x%x, expected 0x%x\n",
1603 mode, oldmode);
1604 mode = pGetThreadErrorMode();
1605 ok(mode == 0, "GetThreadErrorMode returned mode 0x%x, expected 0\n", mode);
1606 rtlmode = pRtlGetThreadErrorMode();
1607 ok(rtlmode == 0,
1608 "RtlGetThreadErrorMode returned mode 0x%x, expected 0\n", mode);
1609
1610 ret = pSetThreadErrorMode(SEM_FAILCRITICALERRORS, &mode);
1611 ok(ret, "SetThreadErrorMode failed\n");
1612 ok(mode == 0,
1613 "SetThreadErrorMode returned old mode 0x%x, expected 0\n", mode);
1614 mode = pGetThreadErrorMode();
1615 ok(mode == SEM_FAILCRITICALERRORS,
1616 "GetThreadErrorMode returned mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1617 mode);
1618 rtlmode = pRtlGetThreadErrorMode();
1619 ok(rtlmode == 0x10,
1620 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x10\n", mode);
1621
1622 ret = pSetThreadErrorMode(SEM_NOGPFAULTERRORBOX, &mode);
1623 ok(ret, "SetThreadErrorMode failed\n");
1624 ok(mode == SEM_FAILCRITICALERRORS,
1625 "SetThreadErrorMode returned old mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1626 mode);
1627 mode = pGetThreadErrorMode();
1628 ok(mode == SEM_NOGPFAULTERRORBOX,
1629 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOGPFAULTERRORBOX\n",
1630 mode);
1631 rtlmode = pRtlGetThreadErrorMode();
1632 ok(rtlmode == 0x20,
1633 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x20\n", mode);
1634
1635 ret = pSetThreadErrorMode(SEM_NOOPENFILEERRORBOX, NULL);
1636 ok(ret, "SetThreadErrorMode failed\n");
1637 mode = pGetThreadErrorMode();
1638 ok(mode == SEM_NOOPENFILEERRORBOX,
1639 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOOPENFILEERRORBOX\n",
1640 mode);
1641 rtlmode = pRtlGetThreadErrorMode();
1642 ok(rtlmode == 0x40,
1643 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x40\n", rtlmode);
1644
1645 for (mode = 1; mode; mode <<= 1)
1646 {
1647 ret = pSetThreadErrorMode(mode, NULL);
1648 if (mode & (SEM_FAILCRITICALERRORS |
1649 SEM_NOGPFAULTERRORBOX |
1650 SEM_NOOPENFILEERRORBOX))
1651 {
1652 ok(ret,
1653 "SetThreadErrorMode(0x%x,NULL) failed with error %d\n",
1654 mode, GetLastError());
1655 }
1656 else
1657 {
1658 DWORD GLE = GetLastError();
1659 ok(!ret,
1660 "SetThreadErrorMode(0x%x,NULL) succeeded, expected failure\n",
1661 mode);
1662 ok(GLE == ERROR_INVALID_PARAMETER,
1663 "SetThreadErrorMode(0x%x,NULL) failed with %d, "
1664 "expected ERROR_INVALID_PARAMETER\n",
1665 mode, GLE);
1666 }
1667 }
1668
1669 pSetThreadErrorMode(oldmode, NULL);
1670 }
1671
1672 #if (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) || (defined(_MSC_VER) && defined(__i386__))
1673 static inline void set_fpu_cw(WORD cw)
1674 {
1675 #ifdef _MSC_VER
1676 __asm { fnclex }
1677 __asm { fldcw [cw] }
1678 #else
1679 __asm__ volatile ("fnclex; fldcw %0" : : "m" (cw));
1680 #endif
1681 }
1682
1683 static inline WORD get_fpu_cw(void)
1684 {
1685 WORD cw = 0;
1686 #ifdef _MSC_VER
1687 __asm { fnstcw [cw] }
1688 #else
1689 __asm__ volatile ("fnstcw %0" : "=m" (cw));
1690 #endif
1691 return cw;
1692 }
1693
1694 struct fpu_thread_ctx
1695 {
1696 WORD cw;
1697 HANDLE finished;
1698 };
1699
1700 static DWORD WINAPI fpu_thread(void *param)
1701 {
1702 struct fpu_thread_ctx *ctx = param;
1703 BOOL ret;
1704
1705 ctx->cw = get_fpu_cw();
1706
1707 ret = SetEvent(ctx->finished);
1708 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
1709
1710 return 0;
1711 }
1712
1713 static WORD get_thread_fpu_cw(void)
1714 {
1715 struct fpu_thread_ctx ctx;
1716 DWORD tid, res;
1717 HANDLE thread;
1718
1719 ctx.finished = CreateEventW(NULL, FALSE, FALSE, NULL);
1720 ok(!!ctx.finished, "Failed to create event, last error %#x.\n", GetLastError());
1721
1722 thread = CreateThread(NULL, 0, fpu_thread, &ctx, 0, &tid);
1723 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
1724
1725 res = WaitForSingleObject(ctx.finished, INFINITE);
1726 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
1727
1728 res = CloseHandle(ctx.finished);
1729 ok(!!res, "Failed to close event handle, last error %#x.\n", GetLastError());
1730
1731 CloseHandle(thread);
1732 return ctx.cw;
1733 }
1734
1735 static void test_thread_fpu_cw(void)
1736 {
1737 WORD initial_cw, cw;
1738
1739 initial_cw = get_fpu_cw();
1740 ok(initial_cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", initial_cw);
1741
1742 cw = get_thread_fpu_cw();
1743 ok(cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", cw);
1744
1745 set_fpu_cw(0xf60);
1746 cw = get_fpu_cw();
1747 ok(cw == 0xf60, "Expected FPU control word 0xf60, got %#x.\n", cw);
1748
1749 cw = get_thread_fpu_cw();
1750 ok(cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", cw);
1751
1752 cw = get_fpu_cw();
1753 ok(cw == 0xf60, "Expected FPU control word 0xf60, got %#x.\n", cw);
1754
1755 set_fpu_cw(initial_cw);
1756 cw = get_fpu_cw();
1757 ok(cw == initial_cw, "Expected FPU control word %#x, got %#x.\n", initial_cw, cw);
1758 }
1759 #endif
1760
1761 static const char manifest_dep[] =
1762 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
1763 "<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH "\"/>"
1764 " <file name=\"testdep.dll\" />"
1765 "</assembly>";
1766
1767 static const char manifest_main[] =
1768 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
1769 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />"
1770 "<dependency>"
1771 " <dependentAssembly>"
1772 " <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH "\" />"
1773 " </dependentAssembly>"
1774 "</dependency>"
1775 "</assembly>";
1776
1777 static void create_manifest_file(const char *filename, const char *manifest)
1778 {
1779 WCHAR path[MAX_PATH];
1780 HANDLE file;
1781 DWORD size;
1782
1783 MultiByteToWideChar( CP_ACP, 0, filename, -1, path, MAX_PATH );
1784 file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1785 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
1786 WriteFile(file, manifest, strlen(manifest), &size, NULL);
1787 CloseHandle(file);
1788 }
1789
1790 static HANDLE test_create(const char *file)
1791 {
1792 WCHAR path[MAX_PATH];
1793 ACTCTXW actctx;
1794 HANDLE handle;
1795
1796 MultiByteToWideChar(CP_ACP, 0, file, -1, path, MAX_PATH);
1797 memset(&actctx, 0, sizeof(ACTCTXW));
1798 actctx.cbSize = sizeof(ACTCTXW);
1799 actctx.lpSource = path;
1800
1801 handle = pCreateActCtxW(&actctx);
1802 ok(handle != INVALID_HANDLE_VALUE, "failed to create context, error %u\n", GetLastError());
1803
1804 ok(actctx.cbSize == sizeof(actctx), "cbSize=%d\n", actctx.cbSize);
1805 ok(actctx.dwFlags == 0, "dwFlags=%d\n", actctx.dwFlags);
1806 ok(actctx.lpSource == path, "lpSource=%p\n", actctx.lpSource);
1807 ok(actctx.wProcessorArchitecture == 0, "wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture);
1808 ok(actctx.wLangId == 0, "wLangId=%d\n", actctx.wLangId);
1809 ok(actctx.lpAssemblyDirectory == NULL, "lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory);
1810 ok(actctx.lpResourceName == NULL, "lpResourceName=%p\n", actctx.lpResourceName);
1811 ok(actctx.lpApplicationName == NULL, "lpApplicationName=%p\n", actctx.lpApplicationName);
1812 ok(actctx.hModule == NULL, "hModule=%p\n", actctx.hModule);
1813
1814 return handle;
1815 }
1816
1817 static void test_thread_actctx(void)
1818 {
1819 struct thread_actctx_param param;
1820 HANDLE thread, handle, context;
1821 ULONG_PTR cookie;
1822 DWORD tid, ret;
1823 BOOL b;
1824
1825 if (!pActivateActCtx)
1826 {
1827 win_skip("skipping activation context tests\n");
1828 return;
1829 }
1830
1831 create_manifest_file("testdep1.manifest", manifest_dep);
1832 create_manifest_file("main.manifest", manifest_main);
1833
1834 context = test_create("main.manifest");
1835 DeleteFileA("testdep1.manifest");
1836 DeleteFileA("main.manifest");
1837
1838 handle = (void*)0xdeadbeef;
1839 b = pGetCurrentActCtx(&handle);
1840 ok(b, "GetCurrentActCtx failed: %u\n", GetLastError());
1841 ok(handle == 0, "active context %p\n", handle);
1842
1843 /* without active context */
1844 param.thread_context = (void*)0xdeadbeef;
1845 param.handle = NULL;
1846 thread = CreateThread(NULL, 0, thread_actctx_func, &param, 0, &tid);
1847 ok(thread != NULL, "failed, got %u\n", GetLastError());
1848
1849 ret = WaitForSingleObject(thread, 1000);
1850 ok(ret == WAIT_OBJECT_0, "wait timeout\n");
1851 ok(param.thread_context == NULL, "got wrong thread context %p\n", param.thread_context);
1852 CloseHandle(thread);
1853
1854 b = pActivateActCtx(context, &cookie);
1855 ok(b, "activation failed: %u\n", GetLastError());
1856
1857 handle = 0;
1858 b = pGetCurrentActCtx(&handle);
1859 ok(b, "GetCurrentActCtx failed: %u\n", GetLastError());
1860 ok(handle != 0, "no active context\n");
1861 pReleaseActCtx(handle);
1862
1863 param.handle = NULL;
1864 b = pGetCurrentActCtx(&param.handle);
1865 ok(b && param.handle != NULL, "failed to get context, %u\n", GetLastError());
1866
1867 param.thread_context = (void*)0xdeadbeef;
1868 thread = CreateThread(NULL, 0, thread_actctx_func, &param, 0, &tid);
1869 ok(thread != NULL, "failed, got %u\n", GetLastError());
1870
1871 ret = WaitForSingleObject(thread, 1000);
1872 ok(ret == WAIT_OBJECT_0, "wait timeout\n");
1873 ok(param.thread_context == context, "got wrong thread context %p, %p\n", param.thread_context, context);
1874 pReleaseActCtx(param.thread_context);
1875 CloseHandle(thread);
1876
1877 /* similar test for CreateRemoteThread() */
1878 param.thread_context = (void*)0xdeadbeef;
1879 thread = CreateRemoteThread(GetCurrentProcess(), NULL, 0, thread_actctx_func, &param, 0, &tid);
1880 ok(thread != NULL, "failed, got %u\n", GetLastError());
1881
1882 ret = WaitForSingleObject(thread, 1000);
1883 ok(ret == WAIT_OBJECT_0, "wait timeout\n");
1884 ok(param.thread_context == context, "got wrong thread context %p, %p\n", param.thread_context, context);
1885 pReleaseActCtx(param.thread_context);
1886 CloseHandle(thread);
1887
1888 pReleaseActCtx(param.handle);
1889
1890 b = pDeactivateActCtx(0, cookie);
1891 ok(b, "DeactivateActCtx failed: %u\n", GetLastError());
1892 pReleaseActCtx(context);
1893 }
1894
1895
1896 static void WINAPI threadpool_workcallback(PTP_CALLBACK_INSTANCE instance, void *context, PTP_WORK work) {
1897 int *foo = (int*)context;
1898
1899 (*foo)++;
1900 }
1901
1902
1903 static void test_threadpool(void)
1904 {
1905 PTP_POOL pool;
1906 PTP_WORK work;
1907 int workcalled = 0;
1908
1909 if (!pCreateThreadpool) {
1910 win_skip("thread pool apis not supported.\n");
1911 return;
1912 }
1913
1914 work = pCreateThreadpoolWork(threadpool_workcallback, &workcalled, NULL);
1915 ok (work != NULL, "Error %d in CreateThreadpoolWork\n", GetLastError());
1916 pSubmitThreadpoolWork(work);
1917 pWaitForThreadpoolWorkCallbacks(work, FALSE);
1918 pCloseThreadpoolWork(work);
1919
1920 ok (workcalled == 1, "expected work to be called once, got %d\n", workcalled);
1921
1922 pool = pCreateThreadpool(NULL);
1923 ok (pool != NULL, "CreateThreadpool failed\n");
1924 pCloseThreadpool(pool);
1925 }
1926
1927 static void test_reserved_tls(void)
1928 {
1929 void *val;
1930 DWORD tls;
1931 BOOL ret;
1932
1933 /* This seems to be a WinXP SP2+ feature. */
1934 if(!pIsWow64Process) {
1935 win_skip("Skipping reserved TLS slot on too old Windows.\n");
1936 return;
1937 }
1938
1939 val = TlsGetValue(0);
1940 ok(!val, "TlsGetValue(0) = %p\n", val);
1941
1942 /* Also make sure that there is a TLS allocated. */
1943 tls = TlsAlloc();
1944 ok(tls && tls != TLS_OUT_OF_INDEXES, "tls = %x\n", tls);
1945 TlsSetValue(tls, (void*)1);
1946
1947 val = TlsGetValue(0);
1948 ok(!val, "TlsGetValue(0) = %p\n", val);
1949
1950 TlsFree(tls);
1951
1952 /* The following is too ugly to be run by default */
1953 if(0) {
1954 /* Set TLS index 0 value and see that this works and doesn't cause problems
1955 * for remaining tests. */
1956 ret = TlsSetValue(0, (void*)1);
1957 ok(ret, "TlsSetValue(0, 1) failed: %u\n", GetLastError());
1958
1959 val = TlsGetValue(0);
1960 ok(val == (void*)1, "TlsGetValue(0) = %p\n", val);
1961 }
1962 }
1963
1964 static void test_thread_info(void)
1965 {
1966 char buf[4096];
1967 static const ULONG info_size[] =
1968 {
1969 sizeof(THREAD_BASIC_INFORMATION), /* ThreadBasicInformation */
1970 sizeof(KERNEL_USER_TIMES), /* ThreadTimes */
1971 sizeof(ULONG), /* ThreadPriority */
1972 sizeof(ULONG), /* ThreadBasePriority */
1973 sizeof(ULONG_PTR), /* ThreadAffinityMask */
1974 sizeof(HANDLE), /* ThreadImpersonationToken */
1975 sizeof(THREAD_DESCRIPTOR_INFORMATION), /* ThreadDescriptorTableEntry */
1976 sizeof(BOOLEAN), /* ThreadEnableAlignmentFaultFixup */
1977 0, /* ThreadEventPair_Reusable */
1978 sizeof(ULONG_PTR), /* ThreadQuerySetWin32StartAddress */
1979 sizeof(ULONG), /* ThreadZeroTlsCell */
1980 sizeof(LARGE_INTEGER), /* ThreadPerformanceCount */
1981 sizeof(ULONG), /* ThreadAmILastThread */
1982 sizeof(ULONG), /* ThreadIdealProcessor */
1983 sizeof(ULONG), /* ThreadPriorityBoost */
1984 sizeof(ULONG_PTR), /* ThreadSetTlsArrayAddress */
1985 sizeof(ULONG), /* ThreadIsIoPending */
1986 sizeof(BOOLEAN), /* ThreadHideFromDebugger */
1987 /* FIXME: Add remaining classes */
1988 };
1989 HANDLE thread;
1990 ULONG i, status, ret_len;
1991
1992 if (!pOpenThread)
1993 {
1994 win_skip("OpenThread is not available on this platform\n");
1995 return;
1996 }
1997
1998 if (!pNtQueryInformationThread)
1999 {
2000 win_skip("NtQueryInformationThread is not available on this platform\n");
2001 return;
2002 }
2003
2004 thread = pOpenThread(THREAD_QUERY_LIMITED_INFORMATION, FALSE, GetCurrentThreadId());
2005 if (!thread)
2006 {
2007 win_skip("THREAD_QUERY_LIMITED_INFORMATION is not supported on this platform\n");
2008 return;
2009 }
2010
2011 for (i = 0; i < sizeof(info_size)/sizeof(info_size[0]); i++)
2012 {
2013 memset(buf, 0, sizeof(buf));
2014
2015 #ifdef __i386__
2016 if (i == ThreadDescriptorTableEntry)
2017 {
2018 CONTEXT ctx;
2019 THREAD_DESCRIPTOR_INFORMATION *tdi = (void *)buf;
2020
2021 ctx.ContextFlags = CONTEXT_SEGMENTS;
2022 GetThreadContext(GetCurrentThread(), &ctx);
2023 tdi->Selector = ctx.SegDs;
2024 }
2025 #endif
2026 ret_len = 0;
2027 status = pNtQueryInformationThread(thread, i, buf, info_size[i], &ret_len);
2028 if (status == STATUS_NOT_IMPLEMENTED) continue;
2029 if (status == STATUS_INVALID_INFO_CLASS) continue;
2030 if (status == STATUS_UNSUCCESSFUL) continue;
2031
2032 switch (i)
2033 {
2034 case ThreadBasicInformation:
2035 case ThreadAmILastThread:
2036 case ThreadPriorityBoost:
2037 ok(status == STATUS_SUCCESS, "for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i, status, ret_len);
2038 break;
2039
2040 #ifdef __i386__
2041 case ThreadDescriptorTableEntry:
2042 ok(status == STATUS_SUCCESS || broken(status == STATUS_ACCESS_DENIED) /* testbot VM is broken */,
2043 "for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i, status, ret_len);
2044 break;
2045 #endif
2046
2047 case ThreadTimes:
2048 todo_wine
2049 ok(status == STATUS_SUCCESS, "for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i, status, ret_len);
2050 break;
2051
2052 case ThreadAffinityMask:
2053 case ThreadQuerySetWin32StartAddress:
2054 case ThreadIsIoPending:
2055 todo_wine
2056 ok(status == STATUS_ACCESS_DENIED, "for info %u expected STATUS_ACCESS_DENIED, got %08x (ret_len %u)\n", i, status, ret_len);
2057 break;
2058
2059 default:
2060 ok(status == STATUS_ACCESS_DENIED, "for info %u expected STATUS_ACCESS_DENIED, got %08x (ret_len %u)\n", i, status, ret_len);
2061 break;
2062 }
2063 }
2064
2065 CloseHandle(thread);
2066 }
2067
2068 static void init_funcs(void)
2069 {
2070 HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
2071 HMODULE ntdll = GetModuleHandleA("ntdll.dll");
2072
2073 /* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
2074 so that the compile passes */
2075
2076 #define X(f) p##f = (void*)GetProcAddress(hKernel32, #f)
2077 X(GetThreadPriorityBoost);
2078 X(OpenThread);
2079 X(QueueUserWorkItem);
2080 X(SetThreadIdealProcessor);
2081 X(SetThreadPriorityBoost);
2082 X(RegisterWaitForSingleObject);
2083 X(UnregisterWait);
2084 X(IsWow64Process);
2085 X(SetThreadErrorMode);
2086 X(GetThreadErrorMode);
2087 X(ActivateActCtx);
2088 X(CreateActCtxW);
2089 X(DeactivateActCtx);
2090 X(GetCurrentActCtx);
2091 X(ReleaseActCtx);
2092
2093 X(CreateThreadpool);
2094 X(CloseThreadpool);
2095 X(CreateThreadpoolWork);
2096 X(SubmitThreadpoolWork);
2097 X(WaitForThreadpoolWorkCallbacks);
2098 X(CloseThreadpoolWork);
2099
2100 X(GetThreadGroupAffinity);
2101 X(SetThreadGroupAffinity);
2102
2103 X(FlsAlloc);
2104 X(FlsFree);
2105 X(FlsSetValue);
2106 X(FlsGetValue);
2107 #undef X
2108
2109 #define X(f) p##f = (void*)GetProcAddress(ntdll, #f)
2110 if (ntdll)
2111 {
2112 X(NtQueryInformationThread);
2113 X(RtlGetThreadErrorMode);
2114 X(NtSetInformationThread);
2115 X(NtSetLdtEntries);
2116 }
2117 #undef X
2118 }
2119
2120 START_TEST(thread)
2121 {
2122 int argc;
2123 char **argv;
2124 argc = winetest_get_mainargs( &argv );
2125
2126 init_funcs();
2127
2128 if (argc >= 3)
2129 {
2130 if (!strcmp(argv[2], "sleep"))
2131 {
2132 HANDLE hAddrEvents[2];
2133 create_function_addr_events(hAddrEvents);
2134 SetEvent(hAddrEvents[0]);
2135 SetEvent(hAddrEvents[1]);
2136 Sleep(5000); /* spawned process runs for at most 5 seconds */
2137 return;
2138 }
2139 while (1)
2140 {
2141 HANDLE hThread;
2142 DWORD tid;
2143 hThread = CreateThread(NULL, 0, threadFunc2, NULL, 0, &tid);
2144 ok(hThread != NULL, "CreateThread failed, error %u\n",
2145 GetLastError());
2146 ok(WaitForSingleObject(hThread, 200) == WAIT_OBJECT_0,
2147 "Thread did not exit in time\n");
2148 if (hThread == NULL) break;
2149 CloseHandle(hThread);
2150 }
2151 return;
2152 }
2153
2154 test_thread_info();
2155 test_reserved_tls();
2156 test_CreateRemoteThread();
2157 test_CreateThread_basic();
2158 test_CreateThread_suspended();
2159 test_SuspendThread();
2160 test_TerminateThread();
2161 test_CreateThread_stack();
2162 test_thread_priority();
2163 test_GetThreadTimes();
2164 test_thread_processor();
2165 test_GetThreadExitCode();
2166 #ifdef __i386__
2167 test_SetThreadContext();
2168 test_GetThreadSelectorEntry();
2169 test_NtSetLdtEntries();
2170 #endif
2171 test_QueueUserWorkItem();
2172 test_RegisterWaitForSingleObject();
2173 test_TLS();
2174 test_FLS();
2175 test_ThreadErrorMode();
2176 #if (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) || (defined(_MSC_VER) && defined(__i386__))
2177 test_thread_fpu_cw();
2178 #endif
2179 test_thread_actctx();
2180
2181 test_threadpool();
2182 }