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