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