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