Merge from amd64 branch:
[reactos.git] / rostests / winetests / kernel32 / thread.c
1 /*
2 * Unit test suite for directory 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 #define _WIN32_WINNT 0x0500
23
24 #include <assert.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27
28 #include "wine/test.h"
29 #include <windef.h>
30 #include <winbase.h>
31 #include <winnt.h>
32 #include <winerror.h>
33
34 /* Specify the number of simultaneous threads to test */
35 #define NUM_THREADS 4
36 /* Specify whether to test the extended priorities for Win2k/XP */
37 #define USE_EXTENDED_PRIORITIES 0
38 /* Specify whether to test the stack allocation in CreateThread */
39 #define CHECK_STACK 0
40
41 /* Set CHECK_STACK to 1 if you want to try to test the stack-limit from
42 CreateThread. So far I have been unable to make this work, and
43 I am in doubt as to how portable it is. Also, according to MSDN,
44 you shouldn't mix C-run-time-libraries (i.e. alloca) with CreateThread.
45 Anyhow, the check is currently commented out
46 */
47 #if CHECK_STACK
48 # ifdef __try
49 # define __TRY __try
50 # define __EXCEPT __except
51 # define __ENDTRY
52 # else
53 # include "wine/exception.h"
54 # endif
55 #endif
56
57 typedef BOOL (WINAPI *GetThreadPriorityBoost_t)(HANDLE,PBOOL);
58 static GetThreadPriorityBoost_t pGetThreadPriorityBoost=NULL;
59
60 typedef HANDLE (WINAPI *OpenThread_t)(DWORD,BOOL,DWORD);
61 static OpenThread_t pOpenThread=NULL;
62
63 typedef BOOL (WINAPI *QueueUserWorkItem_t)(LPTHREAD_START_ROUTINE,PVOID,ULONG);
64 static QueueUserWorkItem_t pQueueUserWorkItem=NULL;
65
66 typedef DWORD (WINAPI *SetThreadIdealProcessor_t)(HANDLE,DWORD);
67 static SetThreadIdealProcessor_t pSetThreadIdealProcessor=NULL;
68
69 typedef BOOL (WINAPI *SetThreadPriorityBoost_t)(HANDLE,BOOL);
70 static SetThreadPriorityBoost_t pSetThreadPriorityBoost=NULL;
71
72 typedef BOOL (WINAPI *RegisterWaitForSingleObject_t)(PHANDLE,HANDLE,WAITORTIMERCALLBACK,PVOID,ULONG,ULONG);
73 static RegisterWaitForSingleObject_t pRegisterWaitForSingleObject=NULL;
74
75 typedef BOOL (WINAPI *UnregisterWait_t)(HANDLE);
76 static UnregisterWait_t pUnregisterWait=NULL;
77
78 static HANDLE create_target_process(const char *arg)
79 {
80 char **argv;
81 char cmdline[MAX_PATH];
82 PROCESS_INFORMATION pi;
83 STARTUPINFO si = { 0 };
84 si.cb = sizeof(si);
85
86 winetest_get_mainargs( &argv );
87 sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
88 ok(CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL,
89 &si, &pi) != 0, "error: %u\n", GetLastError());
90 ok(CloseHandle(pi.hThread) != 0, "error %u\n", GetLastError());
91 return pi.hProcess;
92 }
93
94 /* Functions not tested yet:
95 AttachThreadInput
96 SetThreadContext
97 SwitchToThread
98
99 In addition there are no checks that the inheritance works properly in
100 CreateThread
101 */
102
103 /* Functions to ensure that from a group of threads, only one executes
104 certain chunks of code at a time, and we know which one is executing
105 it. It basically makes multithreaded execution linear, which defeats
106 the purpose of multiple threads, but makes testing easy. */
107 static HANDLE start_event, stop_event;
108 static LONG num_synced;
109
110 static void init_thread_sync_helpers(void)
111 {
112 start_event = CreateEvent(NULL, TRUE, FALSE, NULL);
113 ok(start_event != NULL, "CreateEvent failed\n");
114 stop_event = CreateEvent(NULL, TRUE, FALSE, NULL);
115 ok(stop_event != NULL, "CreateEvent failed\n");
116 num_synced = -1;
117 }
118
119 static BOOL sync_threads_and_run_one(DWORD sync_id, DWORD my_id)
120 {
121 LONG num = InterlockedIncrement(&num_synced);
122 assert(-1 <= num && num <= 1);
123 if (num == 1)
124 {
125 ResetEvent( stop_event );
126 SetEvent( start_event );
127 }
128 else
129 {
130 DWORD ret = WaitForSingleObject(start_event, 10000);
131 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed %x\n",ret);
132 }
133 return sync_id == my_id;
134 }
135
136 static void resync_after_run(void)
137 {
138 LONG num = InterlockedDecrement(&num_synced);
139 assert(-1 <= num && num <= 1);
140 if (num == -1)
141 {
142 ResetEvent( start_event );
143 SetEvent( stop_event );
144 }
145 else
146 {
147 DWORD ret = WaitForSingleObject(stop_event, 10000);
148 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
149 }
150 }
151
152 static void cleanup_thread_sync_helpers(void)
153 {
154 CloseHandle(start_event);
155 CloseHandle(stop_event);
156 }
157
158 DWORD tlsIndex;
159
160 typedef struct {
161 int threadnum;
162 HANDLE *event;
163 DWORD *threadmem;
164 } t1Struct;
165
166 /* WinME supports OpenThread but doesn't know about access restrictions so
167 we require them to be either completely ignored or always obeyed.
168 */
169 INT obeying_ars = 0; /* -1 == no, 0 == dunno yet, 1 == yes */
170 #define obey_ar(x) \
171 (obeying_ars == 0 \
172 ? ((x) \
173 ? (obeying_ars = +1) \
174 : ((obeying_ars = -1), \
175 trace("not restricted, assuming consistent behaviour\n"))) \
176 : (obeying_ars < 0) \
177 ? ok(!(x), "access restrictions obeyed\n") \
178 : ok( (x), "access restrictions not obeyed\n"))
179
180 /* Basic test that simultaneous threads can access shared memory,
181 that the thread local storage routines work correctly, and that
182 threads actually run concurrently
183 */
184 static DWORD WINAPI threadFunc1(LPVOID p)
185 {
186 t1Struct *tstruct = p;
187 int i;
188 /* write our thread # into shared memory */
189 tstruct->threadmem[tstruct->threadnum]=GetCurrentThreadId();
190 ok(TlsSetValue(tlsIndex,(LPVOID)(INT_PTR)(tstruct->threadnum+1))!=0,
191 "TlsSetValue failed\n");
192 /* The threads synchronize before terminating. This is done by
193 Signaling an event, and waiting for all events to occur
194 */
195 SetEvent(tstruct->event[tstruct->threadnum]);
196 WaitForMultipleObjects(NUM_THREADS,tstruct->event,TRUE,INFINITE);
197 /* Double check that all threads really did run by validating that
198 they have all written to the shared memory. There should be no race
199 here, since all threads were synchronized after the write.*/
200 for(i=0;i<NUM_THREADS;i++) {
201 while(tstruct->threadmem[i]==0) ;
202 }
203
204 /* lstrlenA contains an exception handler so this makes sure exceptions work in threads */
205 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
206
207 /* Check that no one changed our tls memory */
208 ok((INT_PTR)TlsGetValue(tlsIndex)-1==tstruct->threadnum,
209 "TlsGetValue failed\n");
210 return NUM_THREADS+tstruct->threadnum;
211 }
212
213 static DWORD WINAPI threadFunc2(LPVOID p)
214 {
215 return 99;
216 }
217
218 static DWORD WINAPI threadFunc3(LPVOID p)
219 {
220 HANDLE thread;
221 thread=GetCurrentThread();
222 SuspendThread(thread);
223 return 99;
224 }
225
226 static DWORD WINAPI threadFunc4(LPVOID p)
227 {
228 HANDLE event = p;
229 if(event != NULL) {
230 SetEvent(event);
231 }
232 Sleep(99000);
233 return 0;
234 }
235
236 #if CHECK_STACK
237 static DWORD WINAPI threadFunc5(LPVOID p)
238 {
239 DWORD *exitCode = p;
240 SYSTEM_INFO sysInfo;
241 sysInfo.dwPageSize=0;
242 GetSystemInfo(&sysInfo);
243 *exitCode=0;
244 __TRY
245 {
246 alloca(2*sysInfo.dwPageSize);
247 }
248 __EXCEPT(1) {
249 *exitCode=1;
250 }
251 __ENDTRY
252 return 0;
253 }
254 #endif
255
256 static DWORD WINAPI threadFunc_SetEvent(LPVOID p)
257 {
258 SetEvent(p);
259 return 0;
260 }
261
262 static DWORD WINAPI threadFunc_CloseHandle(LPVOID p)
263 {
264 CloseHandle(p);
265 return 0;
266 }
267
268 static void create_function_addr_events(HANDLE events[2])
269 {
270 char buffer[256];
271
272 sprintf(buffer, "threadFunc_SetEvent %p", threadFunc_SetEvent);
273 events[0] = CreateEvent(NULL, FALSE, FALSE, buffer);
274
275 sprintf(buffer, "threadFunc_CloseHandle %p", threadFunc_CloseHandle);
276 events[1] = CreateEvent(NULL, FALSE, FALSE, buffer);
277 }
278
279 /* check CreateRemoteThread */
280 static VOID test_CreateRemoteThread(void)
281 {
282 HANDLE hProcess, hThread, hEvent, hRemoteEvent;
283 DWORD tid, ret, exitcode;
284 HANDLE hAddrEvents[2];
285
286 hProcess = create_target_process("sleep");
287 ok(hProcess != NULL, "Can't start process\n");
288
289 /* ensure threadFunc_SetEvent & threadFunc_CloseHandle are the same
290 * address as in the child process */
291 create_function_addr_events(hAddrEvents);
292 ret = WaitForMultipleObjects(2, hAddrEvents, TRUE, 5000);
293 if (ret == WAIT_TIMEOUT)
294 {
295 skip("child process wasn't mapped at same address, so can't do CreateRemoteThread tests.\n");
296 return;
297 }
298
299 hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
300 ok(hEvent != NULL, "Can't create event, err=%u\n", GetLastError());
301 ret = DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &hRemoteEvent,
302 0, FALSE, DUPLICATE_SAME_ACCESS);
303 ok(ret != 0, "DuplicateHandle failed, err=%u\n", GetLastError());
304
305 /* create suspended remote thread with entry point SetEvent() */
306 SetLastError(0xdeadbeef);
307 hThread = CreateRemoteThread(hProcess, NULL, 0, threadFunc_SetEvent,
308 hRemoteEvent, CREATE_SUSPENDED, &tid);
309 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
310 {
311 win_skip("CreateRemoteThread is not implemented\n");
312 goto cleanup;
313 }
314 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
315 ok(tid != 0, "null tid\n");
316 ret = SuspendThread(hThread);
317 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
318 ret = ResumeThread(hThread);
319 ok(ret == 2, "ret=%u, err=%u\n", ret, GetLastError());
320
321 /* thread still suspended, so wait times out */
322 ret = WaitForSingleObject(hEvent, 100);
323 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
324
325 ret = ResumeThread(hThread);
326 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
327
328 /* wait that doesn't time out */
329 ret = WaitForSingleObject(hEvent, 100);
330 ok(ret == WAIT_OBJECT_0, "object not signaled, ret=%u\n", ret);
331
332 /* wait for thread end */
333 ret = WaitForSingleObject(hThread, 100);
334 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
335 CloseHandle(hThread);
336
337 /* create and wait for remote thread with entry point CloseHandle() */
338 hThread = CreateRemoteThread(hProcess, NULL, 0,
339 threadFunc_CloseHandle,
340 hRemoteEvent, 0, &tid);
341 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
342 ret = WaitForSingleObject(hThread, 100);
343 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
344 CloseHandle(hThread);
345
346 /* create remote thread with entry point SetEvent() */
347 hThread = CreateRemoteThread(hProcess, NULL, 0,
348 threadFunc_SetEvent,
349 hRemoteEvent, 0, &tid);
350 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
351
352 /* closed handle, so wait times out */
353 ret = WaitForSingleObject(hEvent, 100);
354 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
355
356 /* check that remote SetEvent() failed */
357 ret = GetExitCodeThread(hThread, &exitcode);
358 ok(ret != 0, "GetExitCodeThread failed, err=%u\n", GetLastError());
359 if (ret) ok(exitcode == 0, "SetEvent succeeded, expected to fail\n");
360 CloseHandle(hThread);
361
362 cleanup:
363 TerminateProcess(hProcess, 0);
364 CloseHandle(hEvent);
365 CloseHandle(hProcess);
366 }
367
368 /* Check basic functionality of CreateThread and Tls* functions */
369 static VOID test_CreateThread_basic(void)
370 {
371 HANDLE thread[NUM_THREADS],event[NUM_THREADS];
372 DWORD threadid[NUM_THREADS],curthreadId;
373 DWORD threadmem[NUM_THREADS];
374 DWORD exitCode;
375 t1Struct tstruct[NUM_THREADS];
376 int error;
377 DWORD i,j;
378 DWORD GLE, ret;
379 DWORD tid;
380
381 /* lstrlenA contains an exception handler so this makes sure exceptions work in the main thread */
382 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
383
384 /* Retrieve current Thread ID for later comparisons */
385 curthreadId=GetCurrentThreadId();
386 /* Allocate some local storage */
387 ok((tlsIndex=TlsAlloc())!=TLS_OUT_OF_INDEXES,"TlsAlloc failed\n");
388 /* Create events for thread synchronization */
389 for(i=0;i<NUM_THREADS;i++) {
390 threadmem[i]=0;
391 /* Note that it doesn't matter what type of event we choose here. This
392 test isn't trying to thoroughly test events
393 */
394 event[i]=CreateEventA(NULL,TRUE,FALSE,NULL);
395 tstruct[i].threadnum=i;
396 tstruct[i].threadmem=threadmem;
397 tstruct[i].event=event;
398 }
399
400 /* Test that passing arguments to threads works okay */
401 for(i=0;i<NUM_THREADS;i++) {
402 thread[i] = CreateThread(NULL,0,threadFunc1,
403 &tstruct[i],0,&threadid[i]);
404 ok(thread[i]!=NULL,"Create Thread failed\n");
405 }
406 /* Test that the threads actually complete */
407 for(i=0;i<NUM_THREADS;i++) {
408 error=WaitForSingleObject(thread[i],5000);
409 ok(error==WAIT_OBJECT_0, "Thread did not complete within timelimit\n");
410 if(error!=WAIT_OBJECT_0) {
411 TerminateThread(thread[i],i+NUM_THREADS);
412 }
413 ok(GetExitCodeThread(thread[i],&exitCode),"Could not retrieve ext code\n");
414 ok(exitCode==i+NUM_THREADS,"Thread returned an incorrect exit code\n");
415 }
416 /* Test that each thread executed in its parent's address space
417 (it was able to change threadmem and pass that change back to its parent)
418 and that each thread id was independent). Note that we prove that the
419 threads actually execute concurrently by having them block on each other
420 in threadFunc1
421 */
422 for(i=0;i<NUM_THREADS;i++) {
423 error=0;
424 for(j=i+1;j<NUM_THREADS;j++) {
425 if (threadmem[i]==threadmem[j]) {
426 error=1;
427 }
428 }
429 ok(!error && threadmem[i]==threadid[i] && threadmem[i]!=curthreadId,
430 "Thread did not execute successfully\n");
431 ok(CloseHandle(thread[i])!=0,"CloseHandle failed\n");
432 }
433 ok(TlsFree(tlsIndex)!=0,"TlsFree failed\n");
434
435 /* Test how passing NULL as a pointer to threadid works */
436 SetLastError(0xFACEaBAD);
437 thread[0] = CreateThread(NULL,0,threadFunc2,NULL,0,&tid);
438 GLE = GetLastError();
439 if (thread[0]) { /* NT */
440 ok(GLE==0xFACEaBAD, "CreateThread set last error to %d, expected 4207848365\n", GLE);
441 ret = WaitForSingleObject(thread[0],100);
442 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
443 ret = GetExitCodeThread(thread[0],&exitCode);
444 ok(ret!=0, "GetExitCodeThread returned %d (expected nonzero)\n", ret);
445 ok(exitCode==99, "threadFunc2 exited with code: %d (expected 99)\n", exitCode);
446 ok(CloseHandle(thread[0])!=0,"Error closing thread handle\n");
447 }
448 else { /* 9x */
449 ok(GLE==ERROR_INVALID_PARAMETER, "CreateThread set last error to %d, expected 87\n", GLE);
450 }
451 }
452
453 /* Check that using the CREATE_SUSPENDED flag works */
454 static VOID test_CreateThread_suspended(void)
455 {
456 HANDLE thread;
457 DWORD threadId;
458 DWORD suspend_count;
459 int error;
460
461 thread = CreateThread(NULL,0,threadFunc2,NULL,
462 CREATE_SUSPENDED,&threadId);
463 ok(thread!=NULL,"Create Thread failed\n");
464 /* Check that the thread is suspended */
465 ok(SuspendThread(thread)==1,"Thread did not start suspended\n");
466 ok(ResumeThread(thread)==2,"Resume thread returned an invalid value\n");
467 /* Check that resume thread didn't actually start the thread. I can't think
468 of a better way of checking this than just waiting. I am not sure if this
469 will work on slow computers.
470 */
471 ok(WaitForSingleObject(thread,1000)==WAIT_TIMEOUT,
472 "ResumeThread should not have actually started the thread\n");
473 /* Now actually resume the thread and make sure that it actually completes*/
474 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
475 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
476 "Thread did not resume\n");
477 if(error!=WAIT_OBJECT_0) {
478 TerminateThread(thread,1);
479 }
480
481 suspend_count = SuspendThread(thread);
482 ok(suspend_count == -1, "SuspendThread returned %d, expected -1\n", suspend_count);
483
484 suspend_count = ResumeThread(thread);
485 ok(suspend_count == 0 ||
486 broken(suspend_count == -1), /* win9x */
487 "ResumeThread returned %d, expected 0\n", suspend_count);
488
489 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
490 }
491
492 /* Check that SuspendThread and ResumeThread work */
493 static VOID test_SuspendThread(void)
494 {
495 HANDLE thread,access_thread;
496 DWORD threadId,exitCode,error;
497 int i;
498
499 thread = CreateThread(NULL,0,threadFunc3,NULL,
500 0,&threadId);
501 ok(thread!=NULL,"Create Thread failed\n");
502 /* Check that the thread is suspended */
503 /* Note that this is a polling method, and there is a race between
504 SuspendThread being called (in the child, and the loop below timing out,
505 so the test could fail on a heavily loaded or slow computer.
506 */
507 error=0;
508 for(i=0;error==0 && i<100;i++) {
509 error=SuspendThread(thread);
510 ResumeThread(thread);
511 if(error==0) {
512 Sleep(50);
513 i++;
514 }
515 }
516 ok(error==1,"SuspendThread did not work\n");
517 /* check that access restrictions are obeyed */
518 if (pOpenThread) {
519 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_SUSPEND_RESUME),
520 0,threadId);
521 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
522 if (access_thread!=NULL) {
523 obey_ar(SuspendThread(access_thread)==~0U);
524 obey_ar(ResumeThread(access_thread)==~0U);
525 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
526 }
527 }
528 /* Double check that the thread really is suspended */
529 ok((error=GetExitCodeThread(thread,&exitCode))!=0 && exitCode==STILL_ACTIVE,
530 "Thread did not really suspend\n");
531 /* Resume the thread, and make sure it actually completes */
532 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
533 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
534 "Thread did not resume\n");
535 if(error!=WAIT_OBJECT_0) {
536 TerminateThread(thread,1);
537 }
538 /* Trying to suspend a terminated thread should fail */
539 error=SuspendThread(thread);
540 ok(error==~0U, "wrong return code: %d\n", error);
541 ok(GetLastError()==ERROR_ACCESS_DENIED || GetLastError()==ERROR_NO_MORE_ITEMS, "unexpected error code: %d\n", GetLastError());
542
543 ok(CloseHandle(thread)!=0,"CloseHandle Failed\n");
544 }
545
546 /* Check that TerminateThread works properly
547 */
548 static VOID test_TerminateThread(void)
549 {
550 HANDLE thread,access_thread,event;
551 DWORD threadId,exitCode;
552 event=CreateEventA(NULL,TRUE,FALSE,NULL);
553 thread = CreateThread(NULL,0,threadFunc4,event,0,&threadId);
554 ok(thread!=NULL,"Create Thread failed\n");
555 /* TerminateThread has a race condition in Wine. If the thread is terminated
556 before it starts, it leaves a process behind. Therefore, we wait for the
557 thread to signal that it has started. There is no easy way to force the
558 race to occur, so we don't try to find it.
559 */
560 ok(WaitForSingleObject(event,5000)==WAIT_OBJECT_0,
561 "TerminateThread didn't work\n");
562 /* check that access restrictions are obeyed */
563 if (pOpenThread) {
564 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_TERMINATE),
565 0,threadId);
566 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
567 if (access_thread!=NULL) {
568 obey_ar(TerminateThread(access_thread,99)==0);
569 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
570 }
571 }
572 /* terminate a job and make sure it terminates */
573 ok(TerminateThread(thread,99)!=0,"TerminateThread failed\n");
574 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
575 "TerminateThread didn't work\n");
576 ok(GetExitCodeThread(thread,&exitCode)!=STILL_ACTIVE,
577 "TerminateThread should not leave the thread 'STILL_ACTIVE'\n");
578 ok(exitCode==99, "TerminateThread returned invalid exit code\n");
579 ok(CloseHandle(thread)!=0,"Error Closing thread handle\n");
580 }
581
582 /* Check if CreateThread obeys the specified stack size. This code does
583 not work properly, and is currently disabled
584 */
585 static VOID test_CreateThread_stack(void)
586 {
587 #if CHECK_STACK
588 /* The only way I know of to test the stack size is to use alloca
589 and __try/__except. However, this is probably not portable,
590 and I couldn't get it to work under Wine anyhow. However, here
591 is the code which should allow for testing that CreateThread
592 respects the stack-size limit
593 */
594 HANDLE thread;
595 DWORD threadId,exitCode;
596
597 SYSTEM_INFO sysInfo;
598 sysInfo.dwPageSize=0;
599 GetSystemInfo(&sysInfo);
600 ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
601 thread = CreateThread(NULL,sysInfo.dwPageSize,
602 threadFunc5,&exitCode,
603 0,&threadId);
604 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
605 "TerminateThread didn't work\n");
606 ok(exitCode==1,"CreateThread did not obey stack-size-limit\n");
607 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
608 #endif
609 }
610
611 /* Check whether setting/retrieving thread priorities works */
612 static VOID test_thread_priority(void)
613 {
614 HANDLE curthread,access_thread;
615 DWORD curthreadId,exitCode;
616 int min_priority=-2,max_priority=2;
617 BOOL disabled,rc;
618 int i;
619
620 curthread=GetCurrentThread();
621 curthreadId=GetCurrentThreadId();
622 /* Check thread priority */
623 /* NOTE: on Win2k/XP priority can be from -7 to 6. All other platforms it
624 is -2 to 2. However, even on a real Win2k system, using thread
625 priorities beyond the -2 to 2 range does not work. If you want to try
626 anyway, enable USE_EXTENDED_PRIORITIES
627 */
628 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_NORMAL,
629 "GetThreadPriority Failed\n");
630
631 if (pOpenThread) {
632 /* check that access control is obeyed */
633 access_thread=pOpenThread(THREAD_ALL_ACCESS &
634 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
635 0,curthreadId);
636 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
637 if (access_thread!=NULL) {
638 obey_ar(SetThreadPriority(access_thread,1)==0);
639 obey_ar(GetThreadPriority(access_thread)==THREAD_PRIORITY_ERROR_RETURN);
640 obey_ar(GetExitCodeThread(access_thread,&exitCode)==0);
641 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
642 }
643 }
644 #if USE_EXTENDED_PRIORITIES
645 min_priority=-7; max_priority=6;
646 #endif
647 for(i=min_priority;i<=max_priority;i++) {
648 ok(SetThreadPriority(curthread,i)!=0,
649 "SetThreadPriority Failed for priority: %d\n",i);
650 ok(GetThreadPriority(curthread)==i,
651 "GetThreadPriority Failed for priority: %d\n",i);
652 }
653 ok(SetThreadPriority(curthread,THREAD_PRIORITY_TIME_CRITICAL)!=0,
654 "SetThreadPriority Failed\n");
655 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_TIME_CRITICAL,
656 "GetThreadPriority Failed\n");
657 ok(SetThreadPriority(curthread,THREAD_PRIORITY_IDLE)!=0,
658 "SetThreadPriority Failed\n");
659 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_IDLE,
660 "GetThreadPriority Failed\n");
661 ok(SetThreadPriority(curthread,0)!=0,"SetThreadPriority Failed\n");
662
663 /* Check that the thread priority is not changed if SetThreadPriority
664 is called with a value outside of the max/min range */
665 SetThreadPriority(curthread,min_priority);
666 SetLastError(0xdeadbeef);
667 rc = SetThreadPriority(curthread,min_priority-1);
668
669 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
670 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
671 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
672 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
673 GetLastError());
674 ok(GetThreadPriority(curthread)==min_priority,
675 "GetThreadPriority didn't return min_priority\n");
676
677 SetThreadPriority(curthread,max_priority);
678 SetLastError(0xdeadbeef);
679 rc = SetThreadPriority(curthread,max_priority+1);
680
681 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
682 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
683 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
684 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
685 GetLastError());
686 ok(GetThreadPriority(curthread)==max_priority,
687 "GetThreadPriority didn't return max_priority\n");
688
689 /* Check thread priority boost */
690 if (!pGetThreadPriorityBoost || !pSetThreadPriorityBoost)
691 return; /* Win9x */
692
693 SetLastError(0xdeadbeef);
694 rc=pGetThreadPriorityBoost(curthread,&disabled);
695 if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
696 {
697 win_skip("GetThreadPriorityBoost is not implemented on WinME\n");
698 return;
699 }
700
701 ok(rc!=0,"error=%d\n",GetLastError());
702
703 if (pOpenThread) {
704 /* check that access control is obeyed */
705 access_thread=pOpenThread(THREAD_ALL_ACCESS &
706 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
707 0,curthreadId);
708 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
709 if (access_thread!=NULL) {
710 obey_ar(pSetThreadPriorityBoost(access_thread,1)==0);
711 todo_wine obey_ar(pGetThreadPriorityBoost(access_thread,&disabled)==0);
712 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
713 }
714 }
715
716 todo_wine {
717 rc = pSetThreadPriorityBoost(curthread,1);
718 ok( rc != 0, "error=%d\n",GetLastError());
719 rc=pGetThreadPriorityBoost(curthread,&disabled);
720 ok(rc!=0 && disabled==1,
721 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
722
723 rc = pSetThreadPriorityBoost(curthread,0);
724 ok( rc != 0, "error=%d\n",GetLastError());
725 }
726 rc=pGetThreadPriorityBoost(curthread,&disabled);
727 ok(rc!=0 && disabled==0,
728 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
729 }
730
731 /* check the GetThreadTimes function */
732 static VOID test_GetThreadTimes(void)
733 {
734 HANDLE thread,access_thread=NULL;
735 FILETIME creationTime,exitTime,kernelTime,userTime;
736 DWORD threadId;
737 int error;
738
739 thread = CreateThread(NULL,0,threadFunc2,NULL,
740 CREATE_SUSPENDED,&threadId);
741
742 ok(thread!=NULL,"Create Thread failed\n");
743 /* check that access control is obeyed */
744 if (pOpenThread) {
745 access_thread=pOpenThread(THREAD_ALL_ACCESS &
746 (~THREAD_QUERY_INFORMATION), 0,threadId);
747 ok(access_thread!=NULL,
748 "OpenThread returned an invalid handle\n");
749 }
750 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
751 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
752 "ResumeThread didn't work\n");
753 creationTime.dwLowDateTime=99; creationTime.dwHighDateTime=99;
754 exitTime.dwLowDateTime=99; exitTime.dwHighDateTime=99;
755 kernelTime.dwLowDateTime=99; kernelTime.dwHighDateTime=99;
756 userTime.dwLowDateTime=99; userTime.dwHighDateTime=99;
757 /* GetThreadTimes should set all of the parameters passed to it */
758 error=GetThreadTimes(thread,&creationTime,&exitTime,
759 &kernelTime,&userTime);
760
761 if (error == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
762 win_skip("GetThreadTimes is not implemented\n");
763 else {
764 ok(error!=0,"GetThreadTimes failed\n");
765 ok(creationTime.dwLowDateTime!=99 || creationTime.dwHighDateTime!=99,
766 "creationTime was invalid\n");
767 ok(exitTime.dwLowDateTime!=99 || exitTime.dwHighDateTime!=99,
768 "exitTime was invalid\n");
769 ok(kernelTime.dwLowDateTime!=99 || kernelTime.dwHighDateTime!=99,
770 "kernelTimewas invalid\n");
771 ok(userTime.dwLowDateTime!=99 || userTime.dwHighDateTime!=99,
772 "userTime was invalid\n");
773 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
774 if(access_thread!=NULL)
775 {
776 error=GetThreadTimes(access_thread,&creationTime,&exitTime,
777 &kernelTime,&userTime);
778 obey_ar(error==0);
779 }
780 }
781 if(access_thread!=NULL) {
782 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
783 }
784 }
785
786 /* Check the processor affinity functions */
787 /* NOTE: These functions should also be checked that they obey access control
788 */
789 static VOID test_thread_processor(void)
790 {
791 HANDLE curthread,curproc;
792 DWORD_PTR processMask,systemMask;
793 SYSTEM_INFO sysInfo;
794 int error=0;
795
796 sysInfo.dwNumberOfProcessors=0;
797 GetSystemInfo(&sysInfo);
798 ok(sysInfo.dwNumberOfProcessors>0,
799 "GetSystemInfo failed to return a valid # of processors\n");
800 /* Use the current Thread/process for all tests */
801 curthread=GetCurrentThread();
802 ok(curthread!=NULL,"GetCurrentThread failed\n");
803 curproc=GetCurrentProcess();
804 ok(curproc!=NULL,"GetCurrentProcess failed\n");
805 /* Check the Affinity Mask functions */
806 ok(GetProcessAffinityMask(curproc,&processMask,&systemMask)!=0,
807 "GetProcessAffinityMask failed\n");
808 ok(SetThreadAffinityMask(curthread,processMask)==processMask,
809 "SetThreadAffinityMask failed\n");
810 ok(SetThreadAffinityMask(curthread,processMask+1)==0,
811 "SetThreadAffinityMask passed for an illegal processor\n");
812 /* NOTE: This only works on WinNT/2000/XP) */
813 if (pSetThreadIdealProcessor) {
814 SetLastError(0xdeadbeef);
815 error=pSetThreadIdealProcessor(curthread,0);
816 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
817 {
818 win_skip("SetThreadIdealProcessor is not implemented\n");
819 return;
820 }
821 ok(error!=-1, "SetThreadIdealProcessor failed\n");
822
823 SetLastError(0xdeadbeef);
824 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
825 ok(error==-1,
826 "SetThreadIdealProcessor succeeded with an illegal processor #\n");
827 ok(GetLastError()==ERROR_INVALID_PARAMETER,
828 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
829
830 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS);
831 ok(error==0, "SetThreadIdealProcessor returned an incorrect value\n");
832 }
833 }
834
835 static VOID test_GetThreadExitCode(void)
836 {
837 DWORD exitCode, threadid;
838 DWORD GLE, ret;
839 HANDLE thread;
840
841 ret = GetExitCodeThread((HANDLE)0x2bad2bad,&exitCode);
842 ok(ret==0, "GetExitCodeThread returned non zero value: %d\n", ret);
843 GLE = GetLastError();
844 ok(GLE==ERROR_INVALID_HANDLE, "GetLastError returned %d (expected 6)\n", GLE);
845
846 thread = CreateThread(NULL,0,threadFunc2,NULL,0,&threadid);
847 ret = WaitForSingleObject(thread,100);
848 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
849 ret = GetExitCodeThread(thread,&exitCode);
850 ok(ret==exitCode || ret==1,
851 "GetExitCodeThread returned %d (expected 1 or %d)\n", ret, exitCode);
852 ok(exitCode==99, "threadFunc2 exited with code %d (expected 99)\n", exitCode);
853 ok(CloseHandle(thread)!=0,"Error closing thread handle\n");
854 }
855
856 #ifdef __i386__
857
858 static int test_value = 0;
859 static HANDLE event;
860
861 static void WINAPI set_test_val( int val )
862 {
863 test_value += val;
864 }
865
866 static DWORD WINAPI threadFunc6(LPVOID p)
867 {
868 SetEvent( event );
869 Sleep( 1000 );
870 test_value *= (int)p;
871 return 0;
872 }
873
874 static void test_SetThreadContext(void)
875 {
876 CONTEXT ctx;
877 int *stack;
878 HANDLE thread;
879 DWORD threadid;
880 DWORD prevcount;
881 BOOL ret;
882
883 SetLastError(0xdeadbeef);
884 event = CreateEvent( NULL, TRUE, FALSE, NULL );
885 thread = CreateThread( NULL, 0, threadFunc6, (void *)2, 0, &threadid );
886 ok( thread != NULL, "CreateThread failed : (%d)\n", GetLastError() );
887 if (!thread)
888 {
889 trace("Thread creation failed, skipping rest of test\n");
890 return;
891 }
892 WaitForSingleObject( event, INFINITE );
893 SuspendThread( thread );
894 CloseHandle( event );
895
896 ctx.ContextFlags = CONTEXT_FULL;
897 SetLastError(0xdeadbeef);
898 ret = GetThreadContext( thread, &ctx );
899 ok( ret, "GetThreadContext failed : (%u)\n", GetLastError() );
900
901 if (ret)
902 {
903 /* simulate a call to set_test_val(10) */
904 stack = (int *)ctx.Esp;
905 stack[-1] = 10;
906 stack[-2] = ctx.Eip;
907 ctx.Esp -= 2 * sizeof(int *);
908 ctx.Eip = (DWORD)set_test_val;
909 SetLastError(0xdeadbeef);
910 ok( SetThreadContext( thread, &ctx ), "SetThreadContext failed : (%d)\n", GetLastError() );
911 }
912
913 SetLastError(0xdeadbeef);
914 prevcount = ResumeThread( thread );
915 ok ( prevcount == 1, "Previous suspend count (%d) instead of 1, last error : (%d)\n",
916 prevcount, GetLastError() );
917
918 WaitForSingleObject( thread, INFINITE );
919 ok( test_value == 20, "test_value %d instead of 20\n", test_value );
920 }
921
922 #endif /* __i386__ */
923
924 static HANDLE finish_event;
925 static LONG times_executed;
926
927 static DWORD CALLBACK work_function(void *p)
928 {
929 LONG executed = InterlockedIncrement(&times_executed);
930
931 if (executed == 100)
932 SetEvent(finish_event);
933 return 0;
934 }
935
936 static void test_QueueUserWorkItem(void)
937 {
938 INT_PTR i;
939 DWORD wait_result;
940 DWORD before, after;
941
942 /* QueueUserWorkItem not present on win9x */
943 if (!pQueueUserWorkItem) return;
944
945 finish_event = CreateEvent(NULL, TRUE, FALSE, NULL);
946
947 before = GetTickCount();
948
949 for (i = 0; i < 100; i++)
950 {
951 BOOL ret = pQueueUserWorkItem(work_function, (void *)i, WT_EXECUTEDEFAULT);
952 ok(ret, "QueueUserWorkItem failed with error %d\n", GetLastError());
953 }
954
955 wait_result = WaitForSingleObject(finish_event, 10000);
956
957 after = GetTickCount();
958 trace("100 QueueUserWorkItem calls took %dms\n", after - before);
959 ok(wait_result == WAIT_OBJECT_0, "wait failed with error 0x%x\n", wait_result);
960
961 ok(times_executed == 100, "didn't execute all of the work items\n");
962 }
963
964 static void CALLBACK signaled_function(PVOID p, BOOLEAN TimerOrWaitFired)
965 {
966 HANDLE event = p;
967 SetEvent(event);
968 ok(!TimerOrWaitFired, "wait shouldn't have timed out\n");
969 }
970
971 static void CALLBACK timeout_function(PVOID p, BOOLEAN TimerOrWaitFired)
972 {
973 HANDLE event = p;
974 SetEvent(event);
975 ok(TimerOrWaitFired, "wait should have timed out\n");
976 }
977
978 static void test_RegisterWaitForSingleObject(void)
979 {
980 BOOL ret;
981 HANDLE wait_handle;
982 HANDLE handle;
983 HANDLE complete_event;
984
985 if (!pRegisterWaitForSingleObject || !pUnregisterWait)
986 {
987 win_skip("RegisterWaitForSingleObject or UnregisterWait not implemented\n");
988 return;
989 }
990
991 /* test signaled case */
992
993 handle = CreateEvent(NULL, TRUE, TRUE, NULL);
994 complete_event = CreateEvent(NULL, FALSE, FALSE, NULL);
995
996 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
997 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
998
999 WaitForSingleObject(complete_event, INFINITE);
1000 /* give worker thread chance to complete */
1001 Sleep(100);
1002
1003 ret = pUnregisterWait(wait_handle);
1004 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1005
1006 /* test cancel case */
1007
1008 ResetEvent(handle);
1009
1010 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1011 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1012
1013 ret = pUnregisterWait(wait_handle);
1014 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1015
1016 /* test timeout case */
1017
1018 ret = pRegisterWaitForSingleObject(&wait_handle, handle, timeout_function, complete_event, 0, WT_EXECUTEONLYONCE);
1019 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1020
1021 WaitForSingleObject(complete_event, INFINITE);
1022 /* give worker thread chance to complete */
1023 Sleep(100);
1024
1025 ret = pUnregisterWait(wait_handle);
1026 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1027 }
1028
1029 static DWORD TLS_main;
1030 static DWORD TLS_index0, TLS_index1;
1031
1032 static DWORD WINAPI TLS_InheritanceProc(LPVOID p)
1033 {
1034 /* We should NOT inherit the TLS values from our parent or from the
1035 main thread. */
1036 LPVOID val;
1037
1038 val = TlsGetValue(TLS_main);
1039 ok(val == NULL, "TLS inheritance failed\n");
1040
1041 val = TlsGetValue(TLS_index0);
1042 ok(val == NULL, "TLS inheritance failed\n");
1043
1044 val = TlsGetValue(TLS_index1);
1045 ok(val == NULL, "TLS inheritance failed\n");
1046
1047 return 0;
1048 }
1049
1050 /* Basic TLS usage test. Make sure we can create slots and the values we
1051 store in them are separate among threads. Also test TLS value
1052 inheritance with TLS_InheritanceProc. */
1053 static DWORD WINAPI TLS_ThreadProc(LPVOID p)
1054 {
1055 LONG_PTR id = (LONG_PTR) p;
1056 LPVOID val;
1057 BOOL ret;
1058
1059 if (sync_threads_and_run_one(0, id))
1060 {
1061 TLS_index0 = TlsAlloc();
1062 ok(TLS_index0 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1063 }
1064 resync_after_run();
1065
1066 if (sync_threads_and_run_one(1, id))
1067 {
1068 TLS_index1 = TlsAlloc();
1069 ok(TLS_index1 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1070
1071 /* Slot indices should be different even if created in different
1072 threads. */
1073 ok(TLS_index0 != TLS_index1, "TlsAlloc failed\n");
1074
1075 /* Both slots should be initialized to NULL */
1076 val = TlsGetValue(TLS_index0);
1077 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1078 ok(val == NULL, "TLS slot not initialized correctly\n");
1079
1080 val = TlsGetValue(TLS_index1);
1081 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1082 ok(val == NULL, "TLS slot not initialized correctly\n");
1083 }
1084 resync_after_run();
1085
1086 if (sync_threads_and_run_one(0, id))
1087 {
1088 val = TlsGetValue(TLS_index0);
1089 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1090 ok(val == NULL, "TLS slot not initialized correctly\n");
1091
1092 val = TlsGetValue(TLS_index1);
1093 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1094 ok(val == NULL, "TLS slot not initialized correctly\n");
1095
1096 ret = TlsSetValue(TLS_index0, (LPVOID) 1);
1097 ok(ret, "TlsSetValue failed\n");
1098
1099 ret = TlsSetValue(TLS_index1, (LPVOID) 2);
1100 ok(ret, "TlsSetValue failed\n");
1101
1102 val = TlsGetValue(TLS_index0);
1103 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1104 ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1105
1106 val = TlsGetValue(TLS_index1);
1107 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1108 ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1109 }
1110 resync_after_run();
1111
1112 if (sync_threads_and_run_one(1, id))
1113 {
1114 val = TlsGetValue(TLS_index0);
1115 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1116 ok(val == NULL, "TLS slot not initialized correctly\n");
1117
1118 val = TlsGetValue(TLS_index1);
1119 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1120 ok(val == NULL, "TLS slot not initialized correctly\n");
1121
1122 ret = TlsSetValue(TLS_index0, (LPVOID) 3);
1123 ok(ret, "TlsSetValue failed\n");
1124
1125 ret = TlsSetValue(TLS_index1, (LPVOID) 4);
1126 ok(ret, "TlsSetValue failed\n");
1127
1128 val = TlsGetValue(TLS_index0);
1129 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1130 ok(val == (LPVOID) 3, "TLS slot not initialized correctly\n");
1131
1132 val = TlsGetValue(TLS_index1);
1133 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1134 ok(val == (LPVOID) 4, "TLS slot not initialized correctly\n");
1135 }
1136 resync_after_run();
1137
1138 if (sync_threads_and_run_one(0, id))
1139 {
1140 HANDLE thread;
1141 DWORD waitret, tid;
1142
1143 val = TlsGetValue(TLS_index0);
1144 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1145 ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1146
1147 val = TlsGetValue(TLS_index1);
1148 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1149 ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1150
1151 thread = CreateThread(NULL, 0, TLS_InheritanceProc, 0, 0, &tid);
1152 ok(thread != NULL, "CreateThread failed\n");
1153 waitret = WaitForSingleObject(thread, 60000);
1154 ok(waitret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
1155 CloseHandle(thread);
1156
1157 ret = TlsFree(TLS_index0);
1158 ok(ret, "TlsFree failed\n");
1159 }
1160 resync_after_run();
1161
1162 if (sync_threads_and_run_one(1, id))
1163 {
1164 ret = TlsFree(TLS_index1);
1165 ok(ret, "TlsFree failed\n");
1166 }
1167 resync_after_run();
1168
1169 return 0;
1170 }
1171
1172 static void test_TLS(void)
1173 {
1174 HANDLE threads[2];
1175 LONG_PTR i;
1176 DWORD ret;
1177 BOOL suc;
1178
1179 init_thread_sync_helpers();
1180
1181 /* Allocate a TLS slot in the main thread to test for inheritance. */
1182 TLS_main = TlsAlloc();
1183 ok(TLS_main != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1184 suc = TlsSetValue(TLS_main, (LPVOID) 4114);
1185 ok(suc, "TlsSetValue failed\n");
1186
1187 for (i = 0; i < 2; ++i)
1188 {
1189 DWORD tid;
1190
1191 threads[i] = CreateThread(NULL, 0, TLS_ThreadProc, (LPVOID) i, 0, &tid);
1192 ok(threads[i] != NULL, "CreateThread failed\n");
1193 }
1194
1195 ret = WaitForMultipleObjects(2, threads, TRUE, 60000);
1196 ok(ret == WAIT_OBJECT_0 || ret == WAIT_OBJECT_0+1 /* nt4 */, "WaitForMultipleObjects failed %u\n",ret);
1197
1198 for (i = 0; i < 2; ++i)
1199 CloseHandle(threads[i]);
1200
1201 suc = TlsFree(TLS_main);
1202 ok(suc, "TlsFree failed\n");
1203 cleanup_thread_sync_helpers();
1204 }
1205
1206 START_TEST(thread)
1207 {
1208 HINSTANCE lib;
1209 int argc;
1210 char **argv;
1211 argc = winetest_get_mainargs( &argv );
1212 /* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
1213 so that the compile passes
1214 */
1215 lib=GetModuleHandleA("kernel32.dll");
1216 ok(lib!=NULL,"Couldn't get a handle for kernel32.dll\n");
1217 pGetThreadPriorityBoost=(GetThreadPriorityBoost_t)GetProcAddress(lib,"GetThreadPriorityBoost");
1218 pOpenThread=(OpenThread_t)GetProcAddress(lib,"OpenThread");
1219 pQueueUserWorkItem=(QueueUserWorkItem_t)GetProcAddress(lib,"QueueUserWorkItem");
1220 pSetThreadIdealProcessor=(SetThreadIdealProcessor_t)GetProcAddress(lib,"SetThreadIdealProcessor");
1221 pSetThreadPriorityBoost=(SetThreadPriorityBoost_t)GetProcAddress(lib,"SetThreadPriorityBoost");
1222 pRegisterWaitForSingleObject=(RegisterWaitForSingleObject_t)GetProcAddress(lib,"RegisterWaitForSingleObject");
1223 pUnregisterWait=(UnregisterWait_t)GetProcAddress(lib,"UnregisterWait");
1224
1225 if (argc >= 3)
1226 {
1227 if (!strcmp(argv[2], "sleep"))
1228 {
1229 HANDLE hAddrEvents[2];
1230 create_function_addr_events(hAddrEvents);
1231 SetEvent(hAddrEvents[0]);
1232 SetEvent(hAddrEvents[1]);
1233 Sleep(5000); /* spawned process runs for at most 5 seconds */
1234 return;
1235 }
1236 while (1)
1237 {
1238 HANDLE hThread;
1239 DWORD tid;
1240 hThread = CreateThread(NULL, 0, threadFunc2, NULL, 0, &tid);
1241 ok(hThread != NULL, "CreateThread failed, error %u\n",
1242 GetLastError());
1243 ok(WaitForSingleObject(hThread, 200) == WAIT_OBJECT_0,
1244 "Thread did not exit in time\n");
1245 if (hThread == NULL) break;
1246 CloseHandle(hThread);
1247 }
1248 return;
1249 }
1250
1251 test_CreateRemoteThread();
1252 test_CreateThread_basic();
1253 test_CreateThread_suspended();
1254 test_SuspendThread();
1255 test_TerminateThread();
1256 test_CreateThread_stack();
1257 test_thread_priority();
1258 test_GetThreadTimes();
1259 test_thread_processor();
1260 test_GetThreadExitCode();
1261 #ifdef __i386__
1262 test_SetThreadContext();
1263 #endif
1264 test_QueueUserWorkItem();
1265 test_RegisterWaitForSingleObject();
1266 test_TLS();
1267 }