[KERNEL32_WINETEST]
[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 ok(TlsFree(tlsIndex)!=0,"TlsFree failed\n");
425
426 /* Test how passing NULL as a pointer to threadid works */
427 SetLastError(0xFACEaBAD);
428 thread[0] = CreateThread(NULL,0,threadFunc2,NULL,0,&tid);
429 GLE = GetLastError();
430 if (thread[0]) { /* NT */
431 ok(GLE==0xFACEaBAD, "CreateThread set last error to %d, expected 4207848365\n", GLE);
432 ret = WaitForSingleObject(thread[0],100);
433 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
434 ret = GetExitCodeThread(thread[0],&exitCode);
435 ok(ret!=0, "GetExitCodeThread returned %d (expected nonzero)\n", ret);
436 ok(exitCode==99, "threadFunc2 exited with code: %d (expected 99)\n", exitCode);
437 ok(CloseHandle(thread[0])!=0,"Error closing thread handle\n");
438 }
439 else { /* 9x */
440 ok(GLE==ERROR_INVALID_PARAMETER, "CreateThread set last error to %d, expected 87\n", GLE);
441 }
442 }
443
444 /* Check that using the CREATE_SUSPENDED flag works */
445 static VOID test_CreateThread_suspended(void)
446 {
447 HANDLE thread;
448 DWORD threadId;
449 DWORD suspend_count;
450 int error;
451
452 thread = CreateThread(NULL,0,threadFunc2,NULL,
453 CREATE_SUSPENDED,&threadId);
454 ok(thread!=NULL,"Create Thread failed\n");
455 /* Check that the thread is suspended */
456 ok(SuspendThread(thread)==1,"Thread did not start suspended\n");
457 ok(ResumeThread(thread)==2,"Resume thread returned an invalid value\n");
458 /* Check that resume thread didn't actually start the thread. I can't think
459 of a better way of checking this than just waiting. I am not sure if this
460 will work on slow computers.
461 */
462 ok(WaitForSingleObject(thread,1000)==WAIT_TIMEOUT,
463 "ResumeThread should not have actually started the thread\n");
464 /* Now actually resume the thread and make sure that it actually completes*/
465 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
466 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
467 "Thread did not resume\n");
468 if(error!=WAIT_OBJECT_0) {
469 TerminateThread(thread,1);
470 }
471
472 suspend_count = SuspendThread(thread);
473 ok(suspend_count == -1, "SuspendThread returned %d, expected -1\n", suspend_count);
474
475 suspend_count = ResumeThread(thread);
476 ok(suspend_count == 0 ||
477 broken(suspend_count == -1), /* win9x */
478 "ResumeThread returned %d, expected 0\n", suspend_count);
479
480 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
481 }
482
483 /* Check that SuspendThread and ResumeThread work */
484 static VOID test_SuspendThread(void)
485 {
486 HANDLE thread,access_thread;
487 DWORD threadId,exitCode,error;
488 int i;
489
490 thread = CreateThread(NULL,0,threadFunc3,NULL,
491 0,&threadId);
492 ok(thread!=NULL,"Create Thread failed\n");
493 /* Check that the thread is suspended */
494 /* Note that this is a polling method, and there is a race between
495 SuspendThread being called (in the child, and the loop below timing out,
496 so the test could fail on a heavily loaded or slow computer.
497 */
498 error=0;
499 for(i=0;error==0 && i<100;i++) {
500 error=SuspendThread(thread);
501 ResumeThread(thread);
502 if(error==0) {
503 Sleep(50);
504 i++;
505 }
506 }
507 ok(error==1,"SuspendThread did not work\n");
508 /* check that access restrictions are obeyed */
509 if (pOpenThread) {
510 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_SUSPEND_RESUME),
511 0,threadId);
512 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
513 if (access_thread!=NULL) {
514 obey_ar(SuspendThread(access_thread)==~0U);
515 obey_ar(ResumeThread(access_thread)==~0U);
516 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
517 }
518 }
519 /* Double check that the thread really is suspended */
520 ok((error=GetExitCodeThread(thread,&exitCode))!=0 && exitCode==STILL_ACTIVE,
521 "Thread did not really suspend\n");
522 /* Resume the thread, and make sure it actually completes */
523 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
524 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
525 "Thread did not resume\n");
526 if(error!=WAIT_OBJECT_0) {
527 TerminateThread(thread,1);
528 }
529 /* Trying to suspend a terminated thread should fail */
530 error=SuspendThread(thread);
531 ok(error==~0U, "wrong return code: %d\n", error);
532 ok(GetLastError()==ERROR_ACCESS_DENIED || GetLastError()==ERROR_NO_MORE_ITEMS, "unexpected error code: %d\n", GetLastError());
533
534 ok(CloseHandle(thread)!=0,"CloseHandle Failed\n");
535 }
536
537 /* Check that TerminateThread works properly
538 */
539 static VOID test_TerminateThread(void)
540 {
541 HANDLE thread,access_thread,event;
542 DWORD threadId,exitCode;
543 event=CreateEventA(NULL,TRUE,FALSE,NULL);
544 thread = CreateThread(NULL,0,threadFunc4,event,0,&threadId);
545 ok(thread!=NULL,"Create Thread failed\n");
546 /* TerminateThread has a race condition in Wine. If the thread is terminated
547 before it starts, it leaves a process behind. Therefore, we wait for the
548 thread to signal that it has started. There is no easy way to force the
549 race to occur, so we don't try to find it.
550 */
551 ok(WaitForSingleObject(event,5000)==WAIT_OBJECT_0,
552 "TerminateThread didn't work\n");
553 /* check that access restrictions are obeyed */
554 if (pOpenThread) {
555 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_TERMINATE),
556 0,threadId);
557 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
558 if (access_thread!=NULL) {
559 obey_ar(TerminateThread(access_thread,99)==0);
560 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
561 }
562 }
563 /* terminate a job and make sure it terminates */
564 ok(TerminateThread(thread,99)!=0,"TerminateThread failed\n");
565 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
566 "TerminateThread didn't work\n");
567 ok(GetExitCodeThread(thread,&exitCode)!=STILL_ACTIVE,
568 "TerminateThread should not leave the thread 'STILL_ACTIVE'\n");
569 ok(exitCode==99, "TerminateThread returned invalid exit code\n");
570 ok(CloseHandle(thread)!=0,"Error Closing thread handle\n");
571 }
572
573 /* Check if CreateThread obeys the specified stack size. This code does
574 not work properly, and is currently disabled
575 */
576 static VOID test_CreateThread_stack(void)
577 {
578 #if CHECK_STACK
579 /* The only way I know of to test the stack size is to use alloca
580 and __try/__except. However, this is probably not portable,
581 and I couldn't get it to work under Wine anyhow. However, here
582 is the code which should allow for testing that CreateThread
583 respects the stack-size limit
584 */
585 HANDLE thread;
586 DWORD threadId,exitCode;
587
588 SYSTEM_INFO sysInfo;
589 sysInfo.dwPageSize=0;
590 GetSystemInfo(&sysInfo);
591 ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
592 thread = CreateThread(NULL,sysInfo.dwPageSize,
593 threadFunc5,&exitCode,
594 0,&threadId);
595 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
596 "TerminateThread didn't work\n");
597 ok(exitCode==1,"CreateThread did not obey stack-size-limit\n");
598 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
599 #endif
600 }
601
602 /* Check whether setting/retrieving thread priorities works */
603 static VOID test_thread_priority(void)
604 {
605 HANDLE curthread,access_thread;
606 DWORD curthreadId,exitCode;
607 int min_priority=-2,max_priority=2;
608 BOOL disabled,rc;
609 int i;
610
611 curthread=GetCurrentThread();
612 curthreadId=GetCurrentThreadId();
613 /* Check thread priority */
614 /* NOTE: on Win2k/XP priority can be from -7 to 6. All other platforms it
615 is -2 to 2. However, even on a real Win2k system, using thread
616 priorities beyond the -2 to 2 range does not work. If you want to try
617 anyway, enable USE_EXTENDED_PRIORITIES
618 */
619 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_NORMAL,
620 "GetThreadPriority Failed\n");
621
622 if (pOpenThread) {
623 /* check that access control is obeyed */
624 access_thread=pOpenThread(THREAD_ALL_ACCESS &
625 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
626 0,curthreadId);
627 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
628 if (access_thread!=NULL) {
629 obey_ar(SetThreadPriority(access_thread,1)==0);
630 obey_ar(GetThreadPriority(access_thread)==THREAD_PRIORITY_ERROR_RETURN);
631 obey_ar(GetExitCodeThread(access_thread,&exitCode)==0);
632 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
633 }
634 }
635 #if USE_EXTENDED_PRIORITIES
636 min_priority=-7; max_priority=6;
637 #endif
638 for(i=min_priority;i<=max_priority;i++) {
639 ok(SetThreadPriority(curthread,i)!=0,
640 "SetThreadPriority Failed for priority: %d\n",i);
641 ok(GetThreadPriority(curthread)==i,
642 "GetThreadPriority Failed for priority: %d\n",i);
643 }
644 ok(SetThreadPriority(curthread,THREAD_PRIORITY_TIME_CRITICAL)!=0,
645 "SetThreadPriority Failed\n");
646 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_TIME_CRITICAL,
647 "GetThreadPriority Failed\n");
648 ok(SetThreadPriority(curthread,THREAD_PRIORITY_IDLE)!=0,
649 "SetThreadPriority Failed\n");
650 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_IDLE,
651 "GetThreadPriority Failed\n");
652 ok(SetThreadPriority(curthread,0)!=0,"SetThreadPriority Failed\n");
653
654 /* Check that the thread priority is not changed if SetThreadPriority
655 is called with a value outside of the max/min range */
656 SetThreadPriority(curthread,min_priority);
657 SetLastError(0xdeadbeef);
658 rc = SetThreadPriority(curthread,min_priority-1);
659
660 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
661 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
662 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
663 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
664 GetLastError());
665 ok(GetThreadPriority(curthread)==min_priority,
666 "GetThreadPriority didn't return min_priority\n");
667
668 SetThreadPriority(curthread,max_priority);
669 SetLastError(0xdeadbeef);
670 rc = SetThreadPriority(curthread,max_priority+1);
671
672 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
673 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
674 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
675 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
676 GetLastError());
677 ok(GetThreadPriority(curthread)==max_priority,
678 "GetThreadPriority didn't return max_priority\n");
679
680 /* Check thread priority boost */
681 if (!pGetThreadPriorityBoost || !pSetThreadPriorityBoost)
682 return; /* Win9x */
683
684 SetLastError(0xdeadbeef);
685 rc=pGetThreadPriorityBoost(curthread,&disabled);
686 if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
687 {
688 win_skip("GetThreadPriorityBoost is not implemented on WinME\n");
689 return;
690 }
691
692 ok(rc!=0,"error=%d\n",GetLastError());
693
694 if (pOpenThread) {
695 /* check that access control is obeyed */
696 access_thread=pOpenThread(THREAD_ALL_ACCESS &
697 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
698 0,curthreadId);
699 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
700 if (access_thread!=NULL) {
701 obey_ar(pSetThreadPriorityBoost(access_thread,1)==0);
702 todo_wine obey_ar(pGetThreadPriorityBoost(access_thread,&disabled)==0);
703 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
704 }
705 }
706
707 todo_wine {
708 rc = pSetThreadPriorityBoost(curthread,1);
709 ok( rc != 0, "error=%d\n",GetLastError());
710 rc=pGetThreadPriorityBoost(curthread,&disabled);
711 ok(rc!=0 && disabled==1,
712 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
713
714 rc = pSetThreadPriorityBoost(curthread,0);
715 ok( rc != 0, "error=%d\n",GetLastError());
716 }
717 rc=pGetThreadPriorityBoost(curthread,&disabled);
718 ok(rc!=0 && disabled==0,
719 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
720 }
721
722 /* check the GetThreadTimes function */
723 static VOID test_GetThreadTimes(void)
724 {
725 HANDLE thread,access_thread=NULL;
726 FILETIME creationTime,exitTime,kernelTime,userTime;
727 DWORD threadId;
728 int error;
729
730 thread = CreateThread(NULL,0,threadFunc2,NULL,
731 CREATE_SUSPENDED,&threadId);
732
733 ok(thread!=NULL,"Create Thread failed\n");
734 /* check that access control is obeyed */
735 if (pOpenThread) {
736 access_thread=pOpenThread(THREAD_ALL_ACCESS &
737 (~THREAD_QUERY_INFORMATION), 0,threadId);
738 ok(access_thread!=NULL,
739 "OpenThread returned an invalid handle\n");
740 }
741 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
742 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
743 "ResumeThread didn't work\n");
744 creationTime.dwLowDateTime=99; creationTime.dwHighDateTime=99;
745 exitTime.dwLowDateTime=99; exitTime.dwHighDateTime=99;
746 kernelTime.dwLowDateTime=99; kernelTime.dwHighDateTime=99;
747 userTime.dwLowDateTime=99; userTime.dwHighDateTime=99;
748 /* GetThreadTimes should set all of the parameters passed to it */
749 error=GetThreadTimes(thread,&creationTime,&exitTime,
750 &kernelTime,&userTime);
751
752 if (error == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
753 win_skip("GetThreadTimes is not implemented\n");
754 else {
755 ok(error!=0,"GetThreadTimes failed\n");
756 ok(creationTime.dwLowDateTime!=99 || creationTime.dwHighDateTime!=99,
757 "creationTime was invalid\n");
758 ok(exitTime.dwLowDateTime!=99 || exitTime.dwHighDateTime!=99,
759 "exitTime was invalid\n");
760 ok(kernelTime.dwLowDateTime!=99 || kernelTime.dwHighDateTime!=99,
761 "kernelTimewas invalid\n");
762 ok(userTime.dwLowDateTime!=99 || userTime.dwHighDateTime!=99,
763 "userTime was invalid\n");
764 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
765 if(access_thread!=NULL)
766 {
767 error=GetThreadTimes(access_thread,&creationTime,&exitTime,
768 &kernelTime,&userTime);
769 obey_ar(error==0);
770 }
771 }
772 if(access_thread!=NULL) {
773 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
774 }
775 }
776
777 /* Check the processor affinity functions */
778 /* NOTE: These functions should also be checked that they obey access control
779 */
780 static VOID test_thread_processor(void)
781 {
782 HANDLE curthread,curproc;
783 DWORD_PTR processMask,systemMask;
784 SYSTEM_INFO sysInfo;
785 int error=0;
786 BOOL is_wow64;
787
788 if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
789
790 sysInfo.dwNumberOfProcessors=0;
791 GetSystemInfo(&sysInfo);
792 ok(sysInfo.dwNumberOfProcessors>0,
793 "GetSystemInfo failed to return a valid # of processors\n");
794 /* Use the current Thread/process for all tests */
795 curthread=GetCurrentThread();
796 ok(curthread!=NULL,"GetCurrentThread failed\n");
797 curproc=GetCurrentProcess();
798 ok(curproc!=NULL,"GetCurrentProcess failed\n");
799 /* Check the Affinity Mask functions */
800 ok(GetProcessAffinityMask(curproc,&processMask,&systemMask)!=0,
801 "GetProcessAffinityMask failed\n");
802 ok(SetThreadAffinityMask(curthread,processMask)==processMask,
803 "SetThreadAffinityMask failed\n");
804 ok(SetThreadAffinityMask(curthread,processMask+1)==0,
805 "SetThreadAffinityMask passed for an illegal processor\n");
806 /* NOTE: This only works on WinNT/2000/XP) */
807 if (pSetThreadIdealProcessor) {
808 SetLastError(0xdeadbeef);
809 error=pSetThreadIdealProcessor(curthread,0);
810 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
811 {
812 win_skip("SetThreadIdealProcessor is not implemented\n");
813 return;
814 }
815 ok(error!=-1, "SetThreadIdealProcessor failed\n");
816
817 if (is_wow64)
818 {
819 SetLastError(0xdeadbeef);
820 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
821 todo_wine
822 ok(error!=-1, "SetThreadIdealProcessor failed for %u on Wow64\n", MAXIMUM_PROCESSORS+1);
823
824 SetLastError(0xdeadbeef);
825 error=pSetThreadIdealProcessor(curthread,65);
826 ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
827 ok(GetLastError()==ERROR_INVALID_PARAMETER,
828 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
829 }
830 else
831 {
832 SetLastError(0xdeadbeef);
833 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
834 ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
835 ok(GetLastError()==ERROR_INVALID_PARAMETER,
836 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
837 }
838
839 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS);
840 ok(error==0, "SetThreadIdealProcessor returned an incorrect value\n");
841 }
842 }
843
844 static VOID test_GetThreadExitCode(void)
845 {
846 DWORD exitCode, threadid;
847 DWORD GLE, ret;
848 HANDLE thread;
849
850 ret = GetExitCodeThread((HANDLE)0x2bad2bad,&exitCode);
851 ok(ret==0, "GetExitCodeThread returned non zero value: %d\n", ret);
852 GLE = GetLastError();
853 ok(GLE==ERROR_INVALID_HANDLE, "GetLastError returned %d (expected 6)\n", GLE);
854
855 thread = CreateThread(NULL,0,threadFunc2,NULL,0,&threadid);
856 ret = WaitForSingleObject(thread,100);
857 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
858 ret = GetExitCodeThread(thread,&exitCode);
859 ok(ret==exitCode || ret==1,
860 "GetExitCodeThread returned %d (expected 1 or %d)\n", ret, exitCode);
861 ok(exitCode==99, "threadFunc2 exited with code %d (expected 99)\n", exitCode);
862 ok(CloseHandle(thread)!=0,"Error closing thread handle\n");
863 }
864
865 #ifdef __i386__
866
867 static int test_value = 0;
868 static HANDLE event;
869
870 static void WINAPI set_test_val( int val )
871 {
872 test_value += val;
873 }
874
875 static DWORD WINAPI threadFunc6(LPVOID p)
876 {
877 SetEvent( event );
878 Sleep( 1000 );
879 test_value *= (int)p;
880 return 0;
881 }
882
883 static void test_SetThreadContext(void)
884 {
885 CONTEXT ctx;
886 int *stack;
887 HANDLE thread;
888 DWORD threadid;
889 DWORD prevcount;
890 BOOL ret;
891
892 SetLastError(0xdeadbeef);
893 event = CreateEvent( NULL, TRUE, FALSE, NULL );
894 thread = CreateThread( NULL, 0, threadFunc6, (void *)2, 0, &threadid );
895 ok( thread != NULL, "CreateThread failed : (%d)\n", GetLastError() );
896 if (!thread)
897 {
898 trace("Thread creation failed, skipping rest of test\n");
899 return;
900 }
901 WaitForSingleObject( event, INFINITE );
902 SuspendThread( thread );
903 CloseHandle( event );
904
905 ctx.ContextFlags = CONTEXT_FULL;
906 SetLastError(0xdeadbeef);
907 ret = GetThreadContext( thread, &ctx );
908 ok( ret, "GetThreadContext failed : (%u)\n", GetLastError() );
909
910 if (ret)
911 {
912 /* simulate a call to set_test_val(10) */
913 stack = (int *)ctx.Esp;
914 stack[-1] = 10;
915 stack[-2] = ctx.Eip;
916 ctx.Esp -= 2 * sizeof(int *);
917 ctx.Eip = (DWORD)set_test_val;
918 SetLastError(0xdeadbeef);
919 ok( SetThreadContext( thread, &ctx ), "SetThreadContext failed : (%d)\n", GetLastError() );
920 }
921
922 SetLastError(0xdeadbeef);
923 prevcount = ResumeThread( thread );
924 ok ( prevcount == 1, "Previous suspend count (%d) instead of 1, last error : (%d)\n",
925 prevcount, GetLastError() );
926
927 WaitForSingleObject( thread, INFINITE );
928 ok( test_value == 20, "test_value %d instead of 20\n", test_value );
929 }
930
931 #endif /* __i386__ */
932
933 static HANDLE finish_event;
934 static LONG times_executed;
935
936 static DWORD CALLBACK work_function(void *p)
937 {
938 LONG executed = InterlockedIncrement(&times_executed);
939
940 if (executed == 100)
941 SetEvent(finish_event);
942 return 0;
943 }
944
945 static void test_QueueUserWorkItem(void)
946 {
947 INT_PTR i;
948 DWORD wait_result;
949 DWORD before, after;
950
951 /* QueueUserWorkItem not present on win9x */
952 if (!pQueueUserWorkItem) return;
953
954 finish_event = CreateEvent(NULL, TRUE, FALSE, NULL);
955
956 before = GetTickCount();
957
958 for (i = 0; i < 100; i++)
959 {
960 BOOL ret = pQueueUserWorkItem(work_function, (void *)i, WT_EXECUTEDEFAULT);
961 ok(ret, "QueueUserWorkItem failed with error %d\n", GetLastError());
962 }
963
964 wait_result = WaitForSingleObject(finish_event, 10000);
965
966 after = GetTickCount();
967 trace("100 QueueUserWorkItem calls took %dms\n", after - before);
968 ok(wait_result == WAIT_OBJECT_0, "wait failed with error 0x%x\n", wait_result);
969
970 ok(times_executed == 100, "didn't execute all of the work items\n");
971 }
972
973 static void CALLBACK signaled_function(PVOID p, BOOLEAN TimerOrWaitFired)
974 {
975 HANDLE event = p;
976 SetEvent(event);
977 ok(!TimerOrWaitFired, "wait shouldn't have timed out\n");
978 }
979
980 static void CALLBACK timeout_function(PVOID p, BOOLEAN TimerOrWaitFired)
981 {
982 HANDLE event = p;
983 SetEvent(event);
984 ok(TimerOrWaitFired, "wait should have timed out\n");
985 }
986
987 static void test_RegisterWaitForSingleObject(void)
988 {
989 BOOL ret;
990 HANDLE wait_handle;
991 HANDLE handle;
992 HANDLE complete_event;
993
994 if (!pRegisterWaitForSingleObject || !pUnregisterWait)
995 {
996 win_skip("RegisterWaitForSingleObject or UnregisterWait not implemented\n");
997 return;
998 }
999
1000 /* test signaled case */
1001
1002 handle = CreateEvent(NULL, TRUE, TRUE, NULL);
1003 complete_event = CreateEvent(NULL, FALSE, FALSE, NULL);
1004
1005 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1006 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1007
1008 WaitForSingleObject(complete_event, INFINITE);
1009 /* give worker thread chance to complete */
1010 Sleep(100);
1011
1012 ret = pUnregisterWait(wait_handle);
1013 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1014
1015 /* test cancel case */
1016
1017 ResetEvent(handle);
1018
1019 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1020 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1021
1022 ret = pUnregisterWait(wait_handle);
1023 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1024
1025 /* test timeout case */
1026
1027 ret = pRegisterWaitForSingleObject(&wait_handle, handle, timeout_function, complete_event, 0, WT_EXECUTEONLYONCE);
1028 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1029
1030 WaitForSingleObject(complete_event, INFINITE);
1031 /* give worker thread chance to complete */
1032 Sleep(100);
1033
1034 ret = pUnregisterWait(wait_handle);
1035 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1036 }
1037
1038 static DWORD TLS_main;
1039 static DWORD TLS_index0, TLS_index1;
1040
1041 static DWORD WINAPI TLS_InheritanceProc(LPVOID p)
1042 {
1043 /* We should NOT inherit the TLS values from our parent or from the
1044 main thread. */
1045 LPVOID val;
1046
1047 val = TlsGetValue(TLS_main);
1048 ok(val == NULL, "TLS inheritance failed\n");
1049
1050 val = TlsGetValue(TLS_index0);
1051 ok(val == NULL, "TLS inheritance failed\n");
1052
1053 val = TlsGetValue(TLS_index1);
1054 ok(val == NULL, "TLS inheritance failed\n");
1055
1056 return 0;
1057 }
1058
1059 /* Basic TLS usage test. Make sure we can create slots and the values we
1060 store in them are separate among threads. Also test TLS value
1061 inheritance with TLS_InheritanceProc. */
1062 static DWORD WINAPI TLS_ThreadProc(LPVOID p)
1063 {
1064 LONG_PTR id = (LONG_PTR) p;
1065 LPVOID val;
1066 BOOL ret;
1067
1068 if (sync_threads_and_run_one(0, id))
1069 {
1070 TLS_index0 = TlsAlloc();
1071 ok(TLS_index0 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1072 }
1073 resync_after_run();
1074
1075 if (sync_threads_and_run_one(1, id))
1076 {
1077 TLS_index1 = TlsAlloc();
1078 ok(TLS_index1 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1079
1080 /* Slot indices should be different even if created in different
1081 threads. */
1082 ok(TLS_index0 != TLS_index1, "TlsAlloc failed\n");
1083
1084 /* Both slots should be initialized to NULL */
1085 val = TlsGetValue(TLS_index0);
1086 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1087 ok(val == NULL, "TLS slot not initialized correctly\n");
1088
1089 val = TlsGetValue(TLS_index1);
1090 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1091 ok(val == NULL, "TLS slot not initialized correctly\n");
1092 }
1093 resync_after_run();
1094
1095 if (sync_threads_and_run_one(0, id))
1096 {
1097 val = TlsGetValue(TLS_index0);
1098 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1099 ok(val == NULL, "TLS slot not initialized correctly\n");
1100
1101 val = TlsGetValue(TLS_index1);
1102 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1103 ok(val == NULL, "TLS slot not initialized correctly\n");
1104
1105 ret = TlsSetValue(TLS_index0, (LPVOID) 1);
1106 ok(ret, "TlsSetValue failed\n");
1107
1108 ret = TlsSetValue(TLS_index1, (LPVOID) 2);
1109 ok(ret, "TlsSetValue failed\n");
1110
1111 val = TlsGetValue(TLS_index0);
1112 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1113 ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1114
1115 val = TlsGetValue(TLS_index1);
1116 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1117 ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1118 }
1119 resync_after_run();
1120
1121 if (sync_threads_and_run_one(1, id))
1122 {
1123 val = TlsGetValue(TLS_index0);
1124 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1125 ok(val == NULL, "TLS slot not initialized correctly\n");
1126
1127 val = TlsGetValue(TLS_index1);
1128 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1129 ok(val == NULL, "TLS slot not initialized correctly\n");
1130
1131 ret = TlsSetValue(TLS_index0, (LPVOID) 3);
1132 ok(ret, "TlsSetValue failed\n");
1133
1134 ret = TlsSetValue(TLS_index1, (LPVOID) 4);
1135 ok(ret, "TlsSetValue failed\n");
1136
1137 val = TlsGetValue(TLS_index0);
1138 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1139 ok(val == (LPVOID) 3, "TLS slot not initialized correctly\n");
1140
1141 val = TlsGetValue(TLS_index1);
1142 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1143 ok(val == (LPVOID) 4, "TLS slot not initialized correctly\n");
1144 }
1145 resync_after_run();
1146
1147 if (sync_threads_and_run_one(0, id))
1148 {
1149 HANDLE thread;
1150 DWORD waitret, tid;
1151
1152 val = TlsGetValue(TLS_index0);
1153 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1154 ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1155
1156 val = TlsGetValue(TLS_index1);
1157 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1158 ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1159
1160 thread = CreateThread(NULL, 0, TLS_InheritanceProc, 0, 0, &tid);
1161 ok(thread != NULL, "CreateThread failed\n");
1162 waitret = WaitForSingleObject(thread, 60000);
1163 ok(waitret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
1164 CloseHandle(thread);
1165
1166 ret = TlsFree(TLS_index0);
1167 ok(ret, "TlsFree failed\n");
1168 }
1169 resync_after_run();
1170
1171 if (sync_threads_and_run_one(1, id))
1172 {
1173 ret = TlsFree(TLS_index1);
1174 ok(ret, "TlsFree failed\n");
1175 }
1176 resync_after_run();
1177
1178 return 0;
1179 }
1180
1181 static void test_TLS(void)
1182 {
1183 HANDLE threads[2];
1184 LONG_PTR i;
1185 DWORD ret;
1186 BOOL suc;
1187
1188 init_thread_sync_helpers();
1189
1190 /* Allocate a TLS slot in the main thread to test for inheritance. */
1191 TLS_main = TlsAlloc();
1192 ok(TLS_main != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1193 suc = TlsSetValue(TLS_main, (LPVOID) 4114);
1194 ok(suc, "TlsSetValue failed\n");
1195
1196 for (i = 0; i < 2; ++i)
1197 {
1198 DWORD tid;
1199
1200 threads[i] = CreateThread(NULL, 0, TLS_ThreadProc, (LPVOID) i, 0, &tid);
1201 ok(threads[i] != NULL, "CreateThread failed\n");
1202 }
1203
1204 ret = WaitForMultipleObjects(2, threads, TRUE, 60000);
1205 ok(ret == WAIT_OBJECT_0 || ret == WAIT_OBJECT_0+1 /* nt4 */, "WaitForMultipleObjects failed %u\n",ret);
1206
1207 for (i = 0; i < 2; ++i)
1208 CloseHandle(threads[i]);
1209
1210 suc = TlsFree(TLS_main);
1211 ok(suc, "TlsFree failed\n");
1212 cleanup_thread_sync_helpers();
1213 }
1214
1215 static void test_ThreadErrorMode(void)
1216 {
1217 DWORD oldmode;
1218 DWORD mode;
1219 DWORD rtlmode;
1220 BOOL ret;
1221
1222 if (!pSetThreadErrorMode || !pGetThreadErrorMode)
1223 {
1224 win_skip("SetThreadErrorMode and/or GetThreadErrorMode unavailable (added in Windows 7)\n");
1225 return;
1226 }
1227
1228 if (!pRtlGetThreadErrorMode) {
1229 win_skip("RtlGetThreadErrorMode not available\n");
1230 return;
1231 }
1232
1233 oldmode = pGetThreadErrorMode();
1234
1235 ret = pSetThreadErrorMode(0, &mode);
1236 ok(ret, "SetThreadErrorMode failed\n");
1237 ok(mode == oldmode,
1238 "SetThreadErrorMode returned old mode 0x%x, expected 0x%x\n",
1239 mode, oldmode);
1240 mode = pGetThreadErrorMode();
1241 ok(mode == 0, "GetThreadErrorMode returned mode 0x%x, expected 0\n", mode);
1242 rtlmode = pRtlGetThreadErrorMode();
1243 ok(rtlmode == 0,
1244 "RtlGetThreadErrorMode returned mode 0x%x, expected 0\n", mode);
1245
1246 ret = pSetThreadErrorMode(SEM_FAILCRITICALERRORS, &mode);
1247 ok(ret, "SetThreadErrorMode failed\n");
1248 ok(mode == 0,
1249 "SetThreadErrorMode returned old mode 0x%x, expected 0\n", mode);
1250 mode = pGetThreadErrorMode();
1251 ok(mode == SEM_FAILCRITICALERRORS,
1252 "GetThreadErrorMode returned mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1253 mode);
1254 rtlmode = pRtlGetThreadErrorMode();
1255 ok(rtlmode == 0x10,
1256 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x10\n", mode);
1257
1258 ret = pSetThreadErrorMode(SEM_NOGPFAULTERRORBOX, &mode);
1259 ok(ret, "SetThreadErrorMode failed\n");
1260 ok(mode == SEM_FAILCRITICALERRORS,
1261 "SetThreadErrorMode returned old mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1262 mode);
1263 mode = pGetThreadErrorMode();
1264 ok(mode == SEM_NOGPFAULTERRORBOX,
1265 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOGPFAULTERRORBOX\n",
1266 mode);
1267 rtlmode = pRtlGetThreadErrorMode();
1268 ok(rtlmode == 0x20,
1269 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x20\n", mode);
1270
1271 ret = pSetThreadErrorMode(SEM_NOOPENFILEERRORBOX, NULL);
1272 ok(ret, "SetThreadErrorMode failed\n");
1273 mode = pGetThreadErrorMode();
1274 ok(mode == SEM_NOOPENFILEERRORBOX,
1275 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOOPENFILEERRORBOX\n",
1276 mode);
1277 rtlmode = pRtlGetThreadErrorMode();
1278 ok(rtlmode == 0x40,
1279 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x40\n", rtlmode);
1280
1281 for (mode = 1; mode; mode <<= 1)
1282 {
1283 ret = pSetThreadErrorMode(mode, NULL);
1284 if (mode & (SEM_FAILCRITICALERRORS |
1285 SEM_NOGPFAULTERRORBOX |
1286 SEM_NOOPENFILEERRORBOX))
1287 {
1288 ok(ret,
1289 "SetThreadErrorMode(0x%x,NULL) failed with error %d\n",
1290 mode, GetLastError());
1291 }
1292 else
1293 {
1294 DWORD GLE = GetLastError();
1295 ok(!ret,
1296 "SetThreadErrorMode(0x%x,NULL) succeeded, expected failure\n",
1297 mode);
1298 ok(GLE == ERROR_INVALID_PARAMETER,
1299 "SetThreadErrorMode(0x%x,NULL) failed with %d, "
1300 "expected ERROR_INVALID_PARAMETER\n",
1301 mode, GLE);
1302 }
1303 }
1304
1305 pSetThreadErrorMode(oldmode, NULL);
1306 }
1307
1308 START_TEST(thread)
1309 {
1310 HINSTANCE lib;
1311 HINSTANCE ntdll;
1312 int argc;
1313 char **argv;
1314 argc = winetest_get_mainargs( &argv );
1315 /* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
1316 so that the compile passes
1317 */
1318 lib=GetModuleHandleA("kernel32.dll");
1319 ok(lib!=NULL,"Couldn't get a handle for kernel32.dll\n");
1320 pGetThreadPriorityBoost=(void *)GetProcAddress(lib,"GetThreadPriorityBoost");
1321 pOpenThread=(void *)GetProcAddress(lib,"OpenThread");
1322 pQueueUserWorkItem=(void *)GetProcAddress(lib,"QueueUserWorkItem");
1323 pSetThreadIdealProcessor=(void *)GetProcAddress(lib,"SetThreadIdealProcessor");
1324 pSetThreadPriorityBoost=(void *)GetProcAddress(lib,"SetThreadPriorityBoost");
1325 pRegisterWaitForSingleObject=(void *)GetProcAddress(lib,"RegisterWaitForSingleObject");
1326 pUnregisterWait=(void *)GetProcAddress(lib,"UnregisterWait");
1327 pIsWow64Process=(void *)GetProcAddress(lib,"IsWow64Process");
1328 pSetThreadErrorMode=(void *)GetProcAddress(lib,"SetThreadErrorMode");
1329 pGetThreadErrorMode=(void *)GetProcAddress(lib,"GetThreadErrorMode");
1330
1331 ntdll=GetModuleHandleA("ntdll.dll");
1332 if (ntdll)
1333 {
1334 pRtlGetThreadErrorMode=(void *)GetProcAddress(ntdll,"RtlGetThreadErrorMode");
1335 }
1336
1337 if (argc >= 3)
1338 {
1339 if (!strcmp(argv[2], "sleep"))
1340 {
1341 HANDLE hAddrEvents[2];
1342 create_function_addr_events(hAddrEvents);
1343 SetEvent(hAddrEvents[0]);
1344 SetEvent(hAddrEvents[1]);
1345 Sleep(5000); /* spawned process runs for at most 5 seconds */
1346 return;
1347 }
1348 while (1)
1349 {
1350 HANDLE hThread;
1351 DWORD tid;
1352 hThread = CreateThread(NULL, 0, threadFunc2, NULL, 0, &tid);
1353 ok(hThread != NULL, "CreateThread failed, error %u\n",
1354 GetLastError());
1355 ok(WaitForSingleObject(hThread, 200) == WAIT_OBJECT_0,
1356 "Thread did not exit in time\n");
1357 if (hThread == NULL) break;
1358 CloseHandle(hThread);
1359 }
1360 return;
1361 }
1362
1363 test_CreateRemoteThread();
1364 test_CreateThread_basic();
1365 test_CreateThread_suspended();
1366 test_SuspendThread();
1367 test_TerminateThread();
1368 test_CreateThread_stack();
1369 test_thread_priority();
1370 test_GetThreadTimes();
1371 test_thread_processor();
1372 test_GetThreadExitCode();
1373 #ifdef __i386__
1374 test_SetThreadContext();
1375 #endif
1376 test_QueueUserWorkItem();
1377 test_RegisterWaitForSingleObject();
1378 test_TLS();
1379 test_ThreadErrorMode();
1380 }