2 * Unit test suite for directory functions.
4 * Copyright 2002 Geoffrey Hausheer
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.
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.
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
21 /* Define _WIN32_WINNT to get SetThreadIdealProcessor on Windows */
22 #define _WIN32_WINNT 0x0500
28 #include "wine/test.h"
34 /* Specify the number of simultaneous threads to test */
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 */
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
50 # define __EXCEPT __except
53 # include "wine/exception.h"
57 typedef BOOL (WINAPI *GetThreadPriorityBoost_t)(HANDLE,PBOOL);
58 static GetThreadPriorityBoost_t pGetThreadPriorityBoost=NULL;
60 typedef HANDLE (WINAPI *OpenThread_t)(DWORD,BOOL,DWORD);
61 static OpenThread_t pOpenThread=NULL;
63 typedef BOOL (WINAPI *QueueUserWorkItem_t)(LPTHREAD_START_ROUTINE,PVOID,ULONG);
64 static QueueUserWorkItem_t pQueueUserWorkItem=NULL;
66 typedef DWORD (WINAPI *SetThreadIdealProcessor_t)(HANDLE,DWORD);
67 static SetThreadIdealProcessor_t pSetThreadIdealProcessor=NULL;
69 typedef BOOL (WINAPI *SetThreadPriorityBoost_t)(HANDLE,BOOL);
70 static SetThreadPriorityBoost_t pSetThreadPriorityBoost=NULL;
72 typedef BOOL (WINAPI *RegisterWaitForSingleObject_t)(PHANDLE,HANDLE,WAITORTIMERCALLBACK,PVOID,ULONG,ULONG);
73 static RegisterWaitForSingleObject_t pRegisterWaitForSingleObject=NULL;
75 typedef BOOL (WINAPI *UnregisterWait_t)(HANDLE);
76 static UnregisterWait_t pUnregisterWait=NULL;
78 static HANDLE create_target_process(const char *arg)
81 char cmdline[MAX_PATH];
82 PROCESS_INFORMATION pi;
83 STARTUPINFO si = { 0 };
86 winetest_get_mainargs( &argv );
87 sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
88 ok(CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL,
89 &si, &pi) != 0, "error: %u\n", GetLastError());
90 ok(CloseHandle(pi.hThread) != 0, "error %u\n", GetLastError());
94 /* Functions not tested yet:
99 In addition there are no checks that the inheritance works properly in
103 /* Functions to ensure that from a group of threads, only one executes
104 certain chunks of code at a time, and we know which one is executing
105 it. It basically makes multithreaded execution linear, which defeats
106 the purpose of multiple threads, but makes testing easy. */
107 static HANDLE all_synced;
108 static LONG num_syncing_threads, num_synced;
110 static void init_thread_sync_helpers(LONG num_threads)
112 all_synced = CreateEvent(NULL, FALSE, FALSE, NULL);
113 ok(all_synced != NULL, "CreateEvent failed\n");
114 num_syncing_threads = num_threads;
118 static BOOL sync_threads_and_run_one(DWORD sync_id, DWORD my_id)
120 LONG num = InterlockedIncrement(&num_synced);
121 assert(0 < num && num <= num_syncing_threads);
122 if (num == num_syncing_threads)
123 /* FIXME: MSDN claims PulseEvent is unreliable. For a test this isn't
124 so important, but we could use condition variables with more effort.
125 The given approach is clearer, though. */
126 PulseEvent(all_synced);
129 DWORD ret = WaitForSingleObject(all_synced, 60000);
130 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
132 return sync_id == my_id;
135 static void resync_after_run(void)
137 LONG num = InterlockedDecrement(&num_synced);
138 assert(0 <= num && num < num_syncing_threads);
140 PulseEvent(all_synced);
143 DWORD ret = WaitForSingleObject(all_synced, 60000);
144 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
148 static void cleanup_thread_sync_helpers(void)
150 CloseHandle(all_synced);
162 /* WinME supports OpenThread but doesn't know about access restrictions so
163 we require them to be either completely ignored or always obeyed.
165 INT obeying_ars = 0; /* -1 == no, 0 == dunno yet, 1 == yes */
169 ? (obeying_ars = +1) \
170 : ((obeying_ars = -1), \
171 trace("not restricted, assuming consistent behaviour\n"))) \
172 : (obeying_ars < 0) \
173 ? ok(!(x), "access restrictions obeyed\n") \
174 : ok( (x), "access restrictions not obeyed\n"))
176 /* Basic test that simultaneous threads can access shared memory,
177 that the thread local storage routines work correctly, and that
178 threads actually run concurrently
180 static DWORD WINAPI threadFunc1(LPVOID p)
182 t1Struct *tstruct = (t1Struct *)p;
184 /* write our thread # into shared memory */
185 tstruct->threadmem[tstruct->threadnum]=GetCurrentThreadId();
186 ok(TlsSetValue(tlsIndex,(LPVOID)(tstruct->threadnum+1))!=0,
187 "TlsSetValue failed\n");
188 /* The threads synchronize before terminating. This is done by
189 Signaling an event, and waiting for all events to occur
191 SetEvent(tstruct->event[tstruct->threadnum]);
192 WaitForMultipleObjects(NUM_THREADS,tstruct->event,TRUE,INFINITE);
193 /* Double check that all threads really did run by validating that
194 they have all written to the shared memory. There should be no race
195 here, since all threads were synchronized after the write.*/
196 for(i=0;i<NUM_THREADS;i++) {
197 while(tstruct->threadmem[i]==0) ;
200 /* lstrlenA contains an exception handler so this makes sure exceptions work in threads */
201 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
203 /* Check that no one changed our tls memory */
204 ok((int)TlsGetValue(tlsIndex)-1==tstruct->threadnum,
205 "TlsGetValue failed\n");
206 return NUM_THREADS+tstruct->threadnum;
209 static DWORD WINAPI threadFunc2(LPVOID p)
214 static DWORD WINAPI threadFunc3(LPVOID p)
217 thread=GetCurrentThread();
218 SuspendThread(thread);
222 static DWORD WINAPI threadFunc4(LPVOID p)
224 HANDLE event = (HANDLE)p;
233 static DWORD WINAPI threadFunc5(LPVOID p)
235 DWORD *exitCode = (DWORD *)p;
237 sysInfo.dwPageSize=0;
238 GetSystemInfo(&sysInfo);
242 alloca(2*sysInfo.dwPageSize);
252 static DWORD WINAPI threadFunc_SetEvent(LPVOID p)
254 SetEvent((HANDLE) p);
258 static DWORD WINAPI threadFunc_CloseHandle(LPVOID p)
260 CloseHandle((HANDLE) p);
264 static void create_function_addr_events(HANDLE events[2])
268 sprintf(buffer, "threadFunc_SetEvent %p", threadFunc_SetEvent);
269 events[0] = CreateEvent(NULL, FALSE, FALSE, buffer);
271 sprintf(buffer, "threadFunc_CloseHandle %p", threadFunc_CloseHandle);
272 events[1] = CreateEvent(NULL, FALSE, FALSE, buffer);
275 /* check CreateRemoteThread */
276 static VOID test_CreateRemoteThread(void)
278 HANDLE hProcess, hThread, hEvent, hRemoteEvent;
279 DWORD tid, ret, exitcode;
280 HANDLE hAddrEvents[2];
282 hProcess = create_target_process("sleep");
283 ok(hProcess != NULL, "Can't start process\n");
285 /* ensure threadFunc_SetEvent & threadFunc_CloseHandle are the same
286 * address as in the child process */
287 create_function_addr_events(hAddrEvents);
288 ret = WaitForMultipleObjects(2, hAddrEvents, TRUE, 5000);
289 if (ret == WAIT_TIMEOUT)
291 skip("child process wasn't mapped at same address, so can't do CreateRemoteThread tests.\n");
295 hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
296 ok(hEvent != NULL, "Can't create event, err=%u\n", GetLastError());
297 ret = DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &hRemoteEvent,
298 0, FALSE, DUPLICATE_SAME_ACCESS);
299 ok(ret != 0, "DuplicateHandle failed, err=%u\n", GetLastError());
301 /* create suspended remote thread with entry point SetEvent() */
302 SetLastError(0xdeadbeef);
303 hThread = CreateRemoteThread(hProcess, NULL, 0, threadFunc_SetEvent,
304 hRemoteEvent, CREATE_SUSPENDED, &tid);
305 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
307 skip("CreateRemoteThread is not implemented\n");
310 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
311 ok(tid != 0, "null tid\n");
312 ret = SuspendThread(hThread);
313 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
314 ret = ResumeThread(hThread);
315 ok(ret == 2, "ret=%u, err=%u\n", ret, GetLastError());
317 /* thread still suspended, so wait times out */
318 ret = WaitForSingleObject(hEvent, 100);
319 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
321 ret = ResumeThread(hThread);
322 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
324 /* wait that doesn't time out */
325 ret = WaitForSingleObject(hEvent, 100);
326 ok(ret == WAIT_OBJECT_0, "object not signaled, ret=%u\n", ret);
328 /* wait for thread end */
329 ret = WaitForSingleObject(hThread, 100);
330 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
331 CloseHandle(hThread);
333 /* create and wait for remote thread with entry point CloseHandle() */
334 hThread = CreateRemoteThread(hProcess, NULL, 0,
335 threadFunc_CloseHandle,
336 hRemoteEvent, 0, &tid);
337 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
338 ret = WaitForSingleObject(hThread, 100);
339 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
340 CloseHandle(hThread);
342 /* create remote thread with entry point SetEvent() */
343 hThread = CreateRemoteThread(hProcess, NULL, 0,
345 hRemoteEvent, 0, &tid);
346 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
348 /* closed handle, so wait times out */
349 ret = WaitForSingleObject(hEvent, 100);
350 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
352 /* check that remote SetEvent() failed */
353 ret = GetExitCodeThread(hThread, &exitcode);
354 ok(ret != 0, "GetExitCodeThread failed, err=%u\n", GetLastError());
355 if (ret) ok(exitcode == 0, "SetEvent succeeded, expected to fail\n");
356 CloseHandle(hThread);
359 TerminateProcess(hProcess, 0);
361 CloseHandle(hProcess);
364 /* Check basic functionality of CreateThread and Tls* functions */
365 static VOID test_CreateThread_basic(void)
367 HANDLE thread[NUM_THREADS],event[NUM_THREADS];
368 DWORD threadid[NUM_THREADS],curthreadId;
369 DWORD threadmem[NUM_THREADS];
371 t1Struct tstruct[NUM_THREADS];
376 /* lstrlenA contains an exception handler so this makes sure exceptions work in the main thread */
377 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
379 /* Retrieve current Thread ID for later comparisons */
380 curthreadId=GetCurrentThreadId();
381 /* Allocate some local storage */
382 ok((tlsIndex=TlsAlloc())!=TLS_OUT_OF_INDEXES,"TlsAlloc failed\n");
383 /* Create events for thread synchronization */
384 for(i=0;i<NUM_THREADS;i++) {
386 /* Note that it doesn't matter what type of event we choose here. This
387 test isn't trying to thoroughly test events
389 event[i]=CreateEventA(NULL,TRUE,FALSE,NULL);
390 tstruct[i].threadnum=i;
391 tstruct[i].threadmem=threadmem;
392 tstruct[i].event=event;
395 /* Test that passing arguments to threads works okay */
396 for(i=0;i<NUM_THREADS;i++) {
397 thread[i] = CreateThread(NULL,0,threadFunc1,
398 &tstruct[i],0,&threadid[i]);
399 ok(thread[i]!=NULL,"Create Thread failed\n");
401 /* Test that the threads actually complete */
402 for(i=0;i<NUM_THREADS;i++) {
403 error=WaitForSingleObject(thread[i],5000);
404 ok(error==WAIT_OBJECT_0, "Thread did not complete within timelimit\n");
405 if(error!=WAIT_OBJECT_0) {
406 TerminateThread(thread[i],i+NUM_THREADS);
408 ok(GetExitCodeThread(thread[i],&exitCode),"Could not retrieve ext code\n");
409 ok(exitCode==i+NUM_THREADS,"Thread returned an incorrect exit code\n");
411 /* Test that each thread executed in its parent's address space
412 (it was able to change threadmem and pass that change back to its parent)
413 and that each thread id was independent). Note that we prove that the
414 threads actually execute concurrently by having them block on each other
417 for(i=0;i<NUM_THREADS;i++) {
419 for(j=i+1;j<NUM_THREADS;j++) {
420 if (threadmem[i]==threadmem[j]) {
424 ok(!error && threadmem[i]==threadid[i] && threadmem[i]!=curthreadId,
425 "Thread did not execute successfully\n");
426 ok(CloseHandle(thread[i])!=0,"CloseHandle failed\n");
428 ok(TlsFree(tlsIndex)!=0,"TlsFree failed\n");
430 /* Test how passing NULL as a pointer to threadid works */
431 SetLastError(0xFACEaBAD);
432 thread[0] = CreateThread(NULL,0,threadFunc2,NULL,0,NULL);
433 GLE = GetLastError();
434 if (thread[0]) { /* NT */
435 ok(GLE==0xFACEaBAD, "CreateThread set last error to %d, expected 4207848365\n", GLE);
436 ret = WaitForSingleObject(thread[0],100);
437 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
438 ret = GetExitCodeThread(thread[0],&exitCode);
439 ok(ret!=0, "GetExitCodeThread returned %d (expected nonzero)\n", ret);
440 ok(exitCode==99, "threadFunc2 exited with code: %d (expected 99)\n", exitCode);
441 ok(CloseHandle(thread[0])!=0,"Error closing thread handle\n");
444 ok(GLE==ERROR_INVALID_PARAMETER, "CreateThread set last error to %d, expected 87\n", GLE);
448 /* Check that using the CREATE_SUSPENDED flag works */
449 static VOID test_CreateThread_suspended(void)
455 thread = CreateThread(NULL,0,threadFunc2,NULL,
456 CREATE_SUSPENDED,&threadId);
457 ok(thread!=NULL,"Create Thread failed\n");
458 /* Check that the thread is suspended */
459 ok(SuspendThread(thread)==1,"Thread did not start suspended\n");
460 ok(ResumeThread(thread)==2,"Resume thread returned an invalid value\n");
461 /* Check that resume thread didn't actually start the thread. I can't think
462 of a better way of checking this than just waiting. I am not sure if this
463 will work on slow computers.
465 ok(WaitForSingleObject(thread,1000)==WAIT_TIMEOUT,
466 "ResumeThread should not have actually started the thread\n");
467 /* Now actually resume the thread and make sure that it actually completes*/
468 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
469 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
470 "Thread did not resume\n");
471 if(error!=WAIT_OBJECT_0) {
472 TerminateThread(thread,1);
474 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
477 /* Check that SuspendThread and ResumeThread work */
478 static VOID test_SuspendThread(void)
480 HANDLE thread,access_thread;
481 DWORD threadId,exitCode,error;
484 thread = CreateThread(NULL,0,threadFunc3,NULL,
486 ok(thread!=NULL,"Create Thread failed\n");
487 /* Check that the thread is suspended */
488 /* Note that this is a polling method, and there is a race between
489 SuspendThread being called (in the child, and the loop below timing out,
490 so the test could fail on a heavily loaded or slow computer.
493 for(i=0;error==0 && i<100;i++) {
494 error=SuspendThread(thread);
495 ResumeThread(thread);
501 ok(error==1,"SuspendThread did not work\n");
502 /* check that access restrictions are obeyed */
504 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_SUSPEND_RESUME),
506 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
507 if (access_thread!=NULL) {
508 obey_ar(SuspendThread(access_thread)==~0U);
509 obey_ar(ResumeThread(access_thread)==~0U);
510 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
513 /* Double check that the thread really is suspended */
514 ok((error=GetExitCodeThread(thread,&exitCode))!=0 && exitCode==STILL_ACTIVE,
515 "Thread did not really suspend\n");
516 /* Resume the thread, and make sure it actually completes */
517 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
518 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
519 "Thread did not resume\n");
520 if(error!=WAIT_OBJECT_0) {
521 TerminateThread(thread,1);
523 /* Trying to suspend a terminated thread should fail */
524 error=SuspendThread(thread);
525 ok(error==~0U, "wrong return code: %d\n", error);
526 ok(GetLastError()==ERROR_ACCESS_DENIED || GetLastError()==ERROR_NO_MORE_ITEMS, "unexpected error code: %d\n", GetLastError());
528 ok(CloseHandle(thread)!=0,"CloseHandle Failed\n");
531 /* Check that TerminateThread works properly
533 static VOID test_TerminateThread(void)
535 HANDLE thread,access_thread,event;
536 DWORD threadId,exitCode;
537 event=CreateEventA(NULL,TRUE,FALSE,NULL);
538 thread = CreateThread(NULL,0,threadFunc4,
539 (LPVOID)event, 0,&threadId);
540 ok(thread!=NULL,"Create Thread failed\n");
541 /* TerminateThread has a race condition in Wine. If the thread is terminated
542 before it starts, it leaves a process behind. Therefore, we wait for the
543 thread to signal that it has started. There is no easy way to force the
544 race to occur, so we don't try to find it.
546 ok(WaitForSingleObject(event,5000)==WAIT_OBJECT_0,
547 "TerminateThread didn't work\n");
548 /* check that access restrictions are obeyed */
550 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_TERMINATE),
552 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
553 if (access_thread!=NULL) {
554 obey_ar(TerminateThread(access_thread,99)==0);
555 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
558 /* terminate a job and make sure it terminates */
559 ok(TerminateThread(thread,99)!=0,"TerminateThread failed\n");
560 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
561 "TerminateThread didn't work\n");
562 ok(GetExitCodeThread(thread,&exitCode)!=STILL_ACTIVE,
563 "TerminateThread should not leave the thread 'STILL_ACTIVE'\n");
564 ok(exitCode==99, "TerminateThread returned invalid exit code\n");
565 ok(CloseHandle(thread)!=0,"Error Closing thread handle\n");
568 /* Check if CreateThread obeys the specified stack size. This code does
569 not work properly, and is currently disabled
571 static VOID test_CreateThread_stack(void)
574 /* The only way I know of to test the stack size is to use alloca
575 and __try/__except. However, this is probably not portable,
576 and I couldn't get it to work under Wine anyhow. However, here
577 is the code which should allow for testing that CreateThread
578 respects the stack-size limit
581 DWORD threadId,exitCode;
584 sysInfo.dwPageSize=0;
585 GetSystemInfo(&sysInfo);
586 ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
587 thread = CreateThread(NULL,sysInfo.dwPageSize,
588 threadFunc5,&exitCode,
590 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
591 "TerminateThread didn't work\n");
592 ok(exitCode==1,"CreateThread did not obey stack-size-limit\n");
593 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
597 /* Check whether setting/retrieving thread priorities works */
598 static VOID test_thread_priority(void)
600 HANDLE curthread,access_thread;
601 DWORD curthreadId,exitCode;
602 int min_priority=-2,max_priority=2;
606 curthread=GetCurrentThread();
607 curthreadId=GetCurrentThreadId();
608 /* Check thread priority */
609 /* NOTE: on Win2k/XP priority can be from -7 to 6. All other platforms it
610 is -2 to 2. However, even on a real Win2k system, using thread
611 priorities beyond the -2 to 2 range does not work. If you want to try
612 anyway, enable USE_EXTENDED_PRIORITIES
614 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_NORMAL,
615 "GetThreadPriority Failed\n");
618 /* check that access control is obeyed */
619 access_thread=pOpenThread(THREAD_ALL_ACCESS &
620 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
622 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
623 if (access_thread!=NULL) {
624 obey_ar(SetThreadPriority(access_thread,1)==0);
625 obey_ar(GetThreadPriority(access_thread)==THREAD_PRIORITY_ERROR_RETURN);
626 obey_ar(GetExitCodeThread(access_thread,&exitCode)==0);
627 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
630 #if USE_EXTENDED_PRIORITIES
631 min_priority=-7; max_priority=6;
633 for(i=min_priority;i<=max_priority;i++) {
634 ok(SetThreadPriority(curthread,i)!=0,
635 "SetThreadPriority Failed for priority: %d\n",i);
636 ok(GetThreadPriority(curthread)==i,
637 "GetThreadPriority Failed for priority: %d\n",i);
639 ok(SetThreadPriority(curthread,THREAD_PRIORITY_TIME_CRITICAL)!=0,
640 "SetThreadPriority Failed\n");
641 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_TIME_CRITICAL,
642 "GetThreadPriority Failed\n");
643 ok(SetThreadPriority(curthread,THREAD_PRIORITY_IDLE)!=0,
644 "SetThreadPriority Failed\n");
645 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_IDLE,
646 "GetThreadPriority Failed\n");
647 ok(SetThreadPriority(curthread,0)!=0,"SetThreadPriority Failed\n");
649 /* Check that the thread priority is not changed if SetThreadPriority
650 is called with a value outside of the max/min range */
651 SetThreadPriority(curthread,min_priority);
652 SetLastError(0xdeadbeef);
653 rc = SetThreadPriority(curthread,min_priority-1);
655 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
656 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
657 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
658 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
660 ok(GetThreadPriority(curthread)==min_priority,
661 "GetThreadPriority didn't return min_priority\n");
663 SetThreadPriority(curthread,max_priority);
664 SetLastError(0xdeadbeef);
665 rc = SetThreadPriority(curthread,max_priority+1);
667 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
668 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
669 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
670 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
672 ok(GetThreadPriority(curthread)==max_priority,
673 "GetThreadPriority didn't return max_priority\n");
675 /* Check thread priority boost */
676 if (!pGetThreadPriorityBoost || !pSetThreadPriorityBoost)
679 SetLastError(0xdeadbeef);
680 rc=pGetThreadPriorityBoost(curthread,&disabled);
681 if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
685 ok(rc!=0,"error=%d\n",GetLastError());
688 /* check that access control is obeyed */
689 access_thread=pOpenThread(THREAD_ALL_ACCESS &
690 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
692 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
693 if (access_thread!=NULL) {
694 obey_ar(pSetThreadPriorityBoost(access_thread,1)==0);
695 obey_ar(pGetThreadPriorityBoost(access_thread,&disabled)==0);
696 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
701 rc = pSetThreadPriorityBoost(curthread,1);
702 ok( rc != 0, "error=%d\n",GetLastError());
703 rc=pGetThreadPriorityBoost(curthread,&disabled);
704 ok(rc!=0 && disabled==1,
705 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
707 rc = pSetThreadPriorityBoost(curthread,0);
708 ok( rc != 0, "error=%d\n",GetLastError());
709 rc=pGetThreadPriorityBoost(curthread,&disabled);
710 ok(rc!=0 && disabled==0,
711 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
715 /* check the GetThreadTimes function */
716 static VOID test_GetThreadTimes(void)
718 HANDLE thread,access_thread=NULL;
719 FILETIME creationTime,exitTime,kernelTime,userTime;
723 thread = CreateThread(NULL,0,threadFunc2,NULL,
724 CREATE_SUSPENDED,&threadId);
726 ok(thread!=NULL,"Create Thread failed\n");
727 /* check that access control is obeyed */
729 access_thread=pOpenThread(THREAD_ALL_ACCESS &
730 (~THREAD_QUERY_INFORMATION), 0,threadId);
731 ok(access_thread!=NULL,
732 "OpenThread returned an invalid handle\n");
734 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
735 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
736 "ResumeThread didn't work\n");
737 creationTime.dwLowDateTime=99; creationTime.dwHighDateTime=99;
738 exitTime.dwLowDateTime=99; exitTime.dwHighDateTime=99;
739 kernelTime.dwLowDateTime=99; kernelTime.dwHighDateTime=99;
740 userTime.dwLowDateTime=99; userTime.dwHighDateTime=99;
741 /* GetThreadTimes should set all of the parameters passed to it */
742 error=GetThreadTimes(thread,&creationTime,&exitTime,
743 &kernelTime,&userTime);
744 if (error!=0 || GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
745 ok(error!=0,"GetThreadTimes failed\n");
746 ok(creationTime.dwLowDateTime!=99 || creationTime.dwHighDateTime!=99,
747 "creationTime was invalid\n");
748 ok(exitTime.dwLowDateTime!=99 || exitTime.dwHighDateTime!=99,
749 "exitTime was invalid\n");
750 ok(kernelTime.dwLowDateTime!=99 || kernelTime.dwHighDateTime!=99,
751 "kernelTimewas invalid\n");
752 ok(userTime.dwLowDateTime!=99 || userTime.dwHighDateTime!=99,
753 "userTime was invalid\n");
754 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
755 if(access_thread!=NULL)
757 error=GetThreadTimes(access_thread,&creationTime,&exitTime,
758 &kernelTime,&userTime);
762 if(access_thread!=NULL) {
763 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
767 /* Check the processor affinity functions */
768 /* NOTE: These functions should also be checked that they obey access control
770 static VOID test_thread_processor(void)
772 HANDLE curthread,curproc;
773 DWORD_PTR processMask,systemMask;
777 sysInfo.dwNumberOfProcessors=0;
778 GetSystemInfo(&sysInfo);
779 ok(sysInfo.dwNumberOfProcessors>0,
780 "GetSystemInfo failed to return a valid # of processors\n");
781 /* Use the current Thread/process for all tests */
782 curthread=GetCurrentThread();
783 ok(curthread!=NULL,"GetCurrentThread failed\n");
784 curproc=GetCurrentProcess();
785 ok(curproc!=NULL,"GetCurrentProcess failed\n");
786 /* Check the Affinity Mask functions */
787 ok(GetProcessAffinityMask(curproc,&processMask,&systemMask)!=0,
788 "GetProcessAffinityMask failed\n");
789 ok(SetThreadAffinityMask(curthread,processMask)==processMask,
790 "SetThreadAffinityMask failed\n");
791 ok(SetThreadAffinityMask(curthread,processMask+1)==0,
792 "SetThreadAffinityMask passed for an illegal processor\n");
793 /* NOTE: This only works on WinNT/2000/XP) */
794 if (pSetThreadIdealProcessor) {
797 error=pSetThreadIdealProcessor(curthread,0);
798 if (GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
799 ok(error!=-1, "SetThreadIdealProcessor failed\n");
802 if (GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
803 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
805 "SetThreadIdealProcessor succeeded with an illegal processor #\n");
807 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS);
808 ok(error==0, "SetThreadIdealProcessor returned an incorrect value\n");
814 static VOID test_GetThreadExitCode(void)
816 DWORD exitCode, threadid;
820 ret = GetExitCodeThread((HANDLE)0x2bad2bad,&exitCode);
821 ok(ret==0, "GetExitCodeThread returned non zero value: %d\n", ret);
822 GLE = GetLastError();
823 ok(GLE==ERROR_INVALID_HANDLE, "GetLastError returned %d (expected 6)\n", GLE);
825 thread = CreateThread(NULL,0,threadFunc2,NULL,0,&threadid);
826 ret = WaitForSingleObject(thread,100);
827 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
828 ret = GetExitCodeThread(thread,&exitCode);
829 ok(ret==exitCode || ret==1,
830 "GetExitCodeThread returned %d (expected 1 or %d)\n", ret, exitCode);
831 ok(exitCode==99, "threadFunc2 exited with code %d (expected 99)\n", exitCode);
832 ok(CloseHandle(thread)!=0,"Error closing thread handle\n");
837 static int test_value = 0;
840 static void WINAPI set_test_val( int val )
845 static DWORD WINAPI threadFunc6(LPVOID p)
849 test_value *= (int)p;
853 static void test_SetThreadContext(void)
862 SetLastError(0xdeadbeef);
863 event = CreateEvent( NULL, TRUE, FALSE, NULL );
864 thread = CreateThread( NULL, 0, threadFunc6, (void *)2, 0, &threadid );
865 ok( thread != NULL, "CreateThread failed : (%d)\n", GetLastError() );
868 trace("Thread creation failed, skipping rest of test\n");
871 WaitForSingleObject( event, INFINITE );
872 SuspendThread( thread );
873 CloseHandle( event );
875 ctx.ContextFlags = CONTEXT_FULL;
876 SetLastError(0xdeadbeef);
877 ret = GetThreadContext( thread, &ctx );
878 ok( ret, "GetThreadContext failed : (%u)\n", GetLastError() );
882 /* simulate a call to set_test_val(10) */
883 stack = (int *)ctx.Esp;
886 ctx.Esp -= 2 * sizeof(int *);
887 ctx.Eip = (DWORD)set_test_val;
888 SetLastError(0xdeadbeef);
889 ok( SetThreadContext( thread, &ctx ), "SetThreadContext failed : (%d)\n", GetLastError() );
892 SetLastError(0xdeadbeef);
893 prevcount = ResumeThread( thread );
894 ok ( prevcount == 1, "Previous suspend count (%d) instead of 1, last error : (%d)\n",
895 prevcount, GetLastError() );
897 WaitForSingleObject( thread, INFINITE );
898 ok( test_value == 20, "test_value %d instead of 20\n", test_value );
901 #endif /* __i386__ */
903 static HANDLE finish_event;
904 static LONG times_executed;
906 static DWORD CALLBACK work_function(void *p)
908 LONG executed = InterlockedIncrement(×_executed);
911 SetEvent(finish_event);
915 static void test_QueueUserWorkItem(void)
921 /* QueueUserWorkItem not present on win9x */
922 if (!pQueueUserWorkItem) return;
924 finish_event = CreateEvent(NULL, TRUE, FALSE, NULL);
926 before = GetTickCount();
928 for (i = 0; i < 100; i++)
930 BOOL ret = pQueueUserWorkItem(work_function, (void *)i, WT_EXECUTEDEFAULT);
931 ok(ret, "QueueUserWorkItem failed with error %d\n", GetLastError());
934 wait_result = WaitForSingleObject(finish_event, 10000);
936 after = GetTickCount();
937 trace("100 QueueUserWorkItem calls took %dms\n", after - before);
938 ok(wait_result == WAIT_OBJECT_0, "wait failed with error 0x%x\n", wait_result);
940 ok(times_executed == 100, "didn't execute all of the work items\n");
943 static void CALLBACK signaled_function(PVOID p, BOOLEAN TimerOrWaitFired)
947 ok(!TimerOrWaitFired, "wait shouldn't have timed out\n");
950 static void CALLBACK timeout_function(PVOID p, BOOLEAN TimerOrWaitFired)
954 ok(TimerOrWaitFired, "wait should have timed out\n");
957 static void test_RegisterWaitForSingleObject(void)
962 HANDLE complete_event;
964 if (!pRegisterWaitForSingleObject || !pUnregisterWait)
966 skip("RegisterWaitForSingleObject or UnregisterWait not implemented\n");
970 /* test signaled case */
972 handle = CreateEvent(NULL, TRUE, TRUE, NULL);
973 complete_event = CreateEvent(NULL, FALSE, FALSE, NULL);
975 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
976 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
978 WaitForSingleObject(complete_event, INFINITE);
979 /* give worker thread chance to complete */
982 ret = pUnregisterWait(wait_handle);
983 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
985 /* test cancel case */
989 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
990 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
992 ret = pUnregisterWait(wait_handle);
993 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
995 /* test timeout case */
997 ret = pRegisterWaitForSingleObject(&wait_handle, handle, timeout_function, complete_event, 0, WT_EXECUTEONLYONCE);
998 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1000 WaitForSingleObject(complete_event, INFINITE);
1001 /* give worker thread chance to complete */
1004 ret = pUnregisterWait(wait_handle);
1005 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1008 static DWORD TLS_main;
1009 static DWORD TLS_index0, TLS_index1;
1011 static DWORD WINAPI TLS_InheritanceProc(LPVOID p)
1013 /* We should NOT inherit the TLS values from our parent or from the
1017 val = TlsGetValue(TLS_main);
1018 ok(val == NULL, "TLS inheritance failed\n");
1020 val = TlsGetValue(TLS_index0);
1021 ok(val == NULL, "TLS inheritance failed\n");
1023 val = TlsGetValue(TLS_index1);
1024 ok(val == NULL, "TLS inheritance failed\n");
1029 /* Basic TLS usage test. Make sure we can create slots and the values we
1030 store in them are separate among threads. Also test TLS value
1031 inheritance with TLS_InheritanceProc. */
1032 static DWORD WINAPI TLS_ThreadProc(LPVOID p)
1038 if (sync_threads_and_run_one(0, id))
1040 TLS_index0 = TlsAlloc();
1041 ok(TLS_index0 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1045 if (sync_threads_and_run_one(1, id))
1047 TLS_index1 = TlsAlloc();
1048 ok(TLS_index1 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1050 /* Slot indices should be different even if created in different
1052 ok(TLS_index0 != TLS_index1, "TlsAlloc failed\n");
1054 /* Both slots should be initialized to NULL */
1055 val = TlsGetValue(TLS_index0);
1056 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1057 ok(val == NULL, "TLS slot not initialized correctly\n");
1059 val = TlsGetValue(TLS_index1);
1060 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1061 ok(val == NULL, "TLS slot not initialized correctly\n");
1065 if (sync_threads_and_run_one(0, id))
1067 val = TlsGetValue(TLS_index0);
1068 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1069 ok(val == NULL, "TLS slot not initialized correctly\n");
1071 val = TlsGetValue(TLS_index1);
1072 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1073 ok(val == NULL, "TLS slot not initialized correctly\n");
1075 ret = TlsSetValue(TLS_index0, (LPVOID) 1);
1076 ok(ret, "TlsSetValue failed\n");
1078 ret = TlsSetValue(TLS_index1, (LPVOID) 2);
1079 ok(ret, "TlsSetValue failed\n");
1081 val = TlsGetValue(TLS_index0);
1082 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1083 ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1085 val = TlsGetValue(TLS_index1);
1086 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1087 ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1091 if (sync_threads_and_run_one(1, id))
1093 val = TlsGetValue(TLS_index0);
1094 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1095 ok(val == NULL, "TLS slot not initialized correctly\n");
1097 val = TlsGetValue(TLS_index1);
1098 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1099 ok(val == NULL, "TLS slot not initialized correctly\n");
1101 ret = TlsSetValue(TLS_index0, (LPVOID) 3);
1102 ok(ret, "TlsSetValue failed\n");
1104 ret = TlsSetValue(TLS_index1, (LPVOID) 4);
1105 ok(ret, "TlsSetValue failed\n");
1107 val = TlsGetValue(TLS_index0);
1108 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1109 ok(val == (LPVOID) 3, "TLS slot not initialized correctly\n");
1111 val = TlsGetValue(TLS_index1);
1112 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1113 ok(val == (LPVOID) 4, "TLS slot not initialized correctly\n");
1117 if (sync_threads_and_run_one(0, id))
1122 val = TlsGetValue(TLS_index0);
1123 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1124 ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1126 val = TlsGetValue(TLS_index1);
1127 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1128 ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1130 thread = CreateThread(NULL, 0, TLS_InheritanceProc, 0, 0, NULL);
1131 ok(thread != NULL, "CreateThread failed\n");
1132 waitret = WaitForSingleObject(thread, 60000);
1133 ok(waitret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
1134 CloseHandle(thread);
1136 ret = TlsFree(TLS_index0);
1137 ok(ret, "TlsFree failed\n");
1141 if (sync_threads_and_run_one(1, id))
1143 ret = TlsFree(TLS_index1);
1144 ok(ret, "TlsFree failed\n");
1151 static void test_TLS(void)
1158 init_thread_sync_helpers(2);
1160 /* Allocate a TLS slot in the main thread to test for inheritance. */
1161 TLS_main = TlsAlloc();
1162 ok(TLS_main != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1163 suc = TlsSetValue(TLS_main, (LPVOID) 4114);
1164 ok(suc, "TlsSetValue failed\n");
1166 for (i = 0; i < 2; ++i)
1168 threads[i] = CreateThread(NULL, 0, TLS_ThreadProc, (LPVOID) i, 0, NULL);
1169 ok(threads[i] != NULL, "CreateThread failed\n");
1172 ret = WaitForMultipleObjects(2, threads, TRUE, 60000);
1173 ok(ret == WAIT_OBJECT_0, "WaitForMultipleObjects failed\n");
1175 for (i = 0; i < 2; ++i)
1176 CloseHandle(threads[i]);
1178 suc = TlsFree(TLS_main);
1179 ok(suc, "TlsFree failed\n");
1180 cleanup_thread_sync_helpers();
1188 argc = winetest_get_mainargs( &argv );
1189 /* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
1190 so that the compile passes
1192 lib=GetModuleHandleA("kernel32.dll");
1193 ok(lib!=NULL,"Couldn't get a handle for kernel32.dll\n");
1194 pGetThreadPriorityBoost=(GetThreadPriorityBoost_t)GetProcAddress(lib,"GetThreadPriorityBoost");
1195 pOpenThread=(OpenThread_t)GetProcAddress(lib,"OpenThread");
1196 pQueueUserWorkItem=(QueueUserWorkItem_t)GetProcAddress(lib,"QueueUserWorkItem");
1197 pSetThreadIdealProcessor=(SetThreadIdealProcessor_t)GetProcAddress(lib,"SetThreadIdealProcessor");
1198 pSetThreadPriorityBoost=(SetThreadPriorityBoost_t)GetProcAddress(lib,"SetThreadPriorityBoost");
1199 pRegisterWaitForSingleObject=(RegisterWaitForSingleObject_t)GetProcAddress(lib,"RegisterWaitForSingleObject");
1200 pUnregisterWait=(UnregisterWait_t)GetProcAddress(lib,"UnregisterWait");
1204 if (!strcmp(argv[2], "sleep"))
1206 HANDLE hAddrEvents[2];
1207 create_function_addr_events(hAddrEvents);
1208 SetEvent(hAddrEvents[0]);
1209 SetEvent(hAddrEvents[1]);
1210 Sleep(5000); /* spawned process runs for at most 5 seconds */
1216 hThread = CreateThread(NULL, 0, threadFunc2, NULL, 0, NULL);
1217 ok(hThread != NULL, "CreateThread failed, error %u\n",
1219 ok(WaitForSingleObject(hThread, 200) == WAIT_OBJECT_0,
1220 "Thread did not exit in time\n");
1221 if (hThread == NULL) break;
1222 CloseHandle(hThread);
1227 test_CreateRemoteThread();
1228 test_CreateThread_basic();
1229 test_CreateThread_suspended();
1230 test_SuspendThread();
1231 test_TerminateThread();
1232 test_CreateThread_stack();
1233 test_thread_priority();
1234 test_GetThreadTimes();
1235 test_thread_processor();
1236 test_GetThreadExitCode();
1238 test_SetThreadContext();
1240 test_QueueUserWorkItem();
1241 test_RegisterWaitForSingleObject();