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
27 #include "wine/test.h"
33 /* Specify the number of simultaneous threads to test */
35 /* Specify whether to test the extended priorities for Win2k/XP */
36 #define USE_EXTENDED_PRIORITIES 0
37 /* Specify whether to test the stack allocation in CreateThread */
40 /* Set CHECK_STACK to 1 if you want to try to test the stack-limit from
41 CreateThread. So far I have been unable to make this work, and
42 I am in doubt as to how portable it is. Also, according to MSDN,
43 you shouldn't mix C-run-time-libraries (i.e. alloca) with CreateThread.
44 Anyhow, the check is currently commented out
49 # define __EXCEPT __except
52 # include "wine/exception.h"
56 typedef BOOL (WINAPI *GetThreadPriorityBoost_t)(HANDLE,PBOOL);
57 static GetThreadPriorityBoost_t pGetThreadPriorityBoost=NULL;
59 typedef HANDLE (WINAPI *OpenThread_t)(DWORD,BOOL,DWORD);
60 static OpenThread_t pOpenThread=NULL;
62 typedef BOOL (WINAPI *QueueUserWorkItem_t)(LPTHREAD_START_ROUTINE,PVOID,ULONG);
63 static QueueUserWorkItem_t pQueueUserWorkItem=NULL;
65 typedef DWORD (WINAPI *SetThreadIdealProcessor_t)(HANDLE,DWORD);
66 static SetThreadIdealProcessor_t pSetThreadIdealProcessor=NULL;
68 typedef BOOL (WINAPI *SetThreadPriorityBoost_t)(HANDLE,BOOL);
69 static SetThreadPriorityBoost_t pSetThreadPriorityBoost=NULL;
71 typedef BOOL (WINAPI *RegisterWaitForSingleObject_t)(PHANDLE,HANDLE,WAITORTIMERCALLBACK,PVOID,ULONG,ULONG);
72 static RegisterWaitForSingleObject_t pRegisterWaitForSingleObject=NULL;
74 typedef BOOL (WINAPI *UnregisterWait_t)(HANDLE);
75 static UnregisterWait_t pUnregisterWait=NULL;
77 static HANDLE create_target_process(const char *arg)
80 char cmdline[MAX_PATH];
81 PROCESS_INFORMATION pi;
82 STARTUPINFO si = { 0 };
85 winetest_get_mainargs( &argv );
86 sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
87 ok(CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL,
88 &si, &pi) != 0, "error: %u\n", GetLastError());
89 ok(CloseHandle(pi.hThread) != 0, "error %u\n", GetLastError());
93 /* Functions not tested yet:
98 In addition there are no checks that the inheritance works properly in
110 /* WinME supports OpenThread but doesn't know about access restrictions so
111 we require them to be either completely ignored or always obeyed.
113 INT obeying_ars = 0; /* -1 == no, 0 == dunno yet, 1 == yes */
117 ? (obeying_ars = +1) \
118 : ((obeying_ars = -1), \
119 trace("not restricted, assuming consistent behaviour\n"))) \
120 : (obeying_ars < 0) \
121 ? ok(!(x), "access restrictions obeyed\n") \
122 : ok( (x), "access restrictions not obeyed\n"))
124 /* Basic test that simultaneous threads can access shared memory,
125 that the thread local storage routines work correctly, and that
126 threads actually run concurrently
128 static DWORD WINAPI threadFunc1(LPVOID p)
130 t1Struct *tstruct = (t1Struct *)p;
132 /* write our thread # into shared memory */
133 tstruct->threadmem[tstruct->threadnum]=GetCurrentThreadId();
134 ok(TlsSetValue(tlsIndex,(LPVOID)(tstruct->threadnum+1))!=0,
135 "TlsSetValue failed\n");
136 /* The threads synchronize before terminating. This is done by
137 Signaling an event, and waiting for all events to occur
139 SetEvent(tstruct->event[tstruct->threadnum]);
140 WaitForMultipleObjects(NUM_THREADS,tstruct->event,TRUE,INFINITE);
141 /* Double check that all threads really did run by validating that
142 they have all written to the shared memory. There should be no race
143 here, since all threads were synchronized after the write.*/
144 for(i=0;i<NUM_THREADS;i++) {
145 while(tstruct->threadmem[i]==0) ;
148 /* lstrlenA contains an exception handler so this makes sure exceptions work in threads */
149 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
151 /* Check that no one changed our tls memory */
152 ok((int)TlsGetValue(tlsIndex)-1==tstruct->threadnum,
153 "TlsGetValue failed\n");
154 return NUM_THREADS+tstruct->threadnum;
157 static DWORD WINAPI threadFunc2(LPVOID p)
162 static DWORD WINAPI threadFunc3(LPVOID p)
165 thread=GetCurrentThread();
166 SuspendThread(thread);
170 static DWORD WINAPI threadFunc4(LPVOID p)
172 HANDLE event = (HANDLE)p;
181 static DWORD WINAPI threadFunc5(LPVOID p)
183 DWORD *exitCode = (DWORD *)p;
185 sysInfo.dwPageSize=0;
186 GetSystemInfo(&sysInfo);
190 alloca(2*sysInfo.dwPageSize);
200 static DWORD WINAPI threadFunc_SetEvent(LPVOID p)
202 SetEvent((HANDLE) p);
206 static DWORD WINAPI threadFunc_CloseHandle(LPVOID p)
208 CloseHandle((HANDLE) p);
212 static void create_function_addr_events(HANDLE events[2])
216 sprintf(buffer, "threadFunc_SetEvent %p", threadFunc_SetEvent);
217 events[0] = CreateEvent(NULL, FALSE, FALSE, buffer);
219 sprintf(buffer, "threadFunc_CloseHandle %p", threadFunc_CloseHandle);
220 events[1] = CreateEvent(NULL, FALSE, FALSE, buffer);
223 /* check CreateRemoteThread */
224 static VOID test_CreateRemoteThread(void)
226 HANDLE hProcess, hThread, hEvent, hRemoteEvent;
227 DWORD tid, ret, exitcode;
228 HANDLE hAddrEvents[2];
230 hProcess = create_target_process("sleep");
231 ok(hProcess != NULL, "Can't start process\n");
233 /* ensure threadFunc_SetEvent & threadFunc_CloseHandle are the same
234 * address as in the child process */
235 create_function_addr_events(hAddrEvents);
236 ret = WaitForMultipleObjects(2, hAddrEvents, TRUE, 5000);
237 if (ret == WAIT_TIMEOUT)
239 skip("child process wasn't mapped at same address, so can't do CreateRemoteThread tests.\n");
243 hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
244 ok(hEvent != NULL, "Can't create event, err=%u\n", GetLastError());
245 ret = DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &hRemoteEvent,
246 0, FALSE, DUPLICATE_SAME_ACCESS);
247 ok(ret != 0, "DuplicateHandle failed, err=%u\n", GetLastError());
249 /* create suspended remote thread with entry point SetEvent() */
250 SetLastError(0xdeadbeef);
251 hThread = CreateRemoteThread(hProcess, NULL, 0, threadFunc_SetEvent,
252 hRemoteEvent, CREATE_SUSPENDED, &tid);
253 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
255 skip("CreateRemoteThread is not implemented\n");
258 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
259 ok(tid != 0, "null tid\n");
260 ret = SuspendThread(hThread);
261 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
262 ret = ResumeThread(hThread);
263 ok(ret == 2, "ret=%u, err=%u\n", ret, GetLastError());
265 /* thread still suspended, so wait times out */
266 ret = WaitForSingleObject(hEvent, 100);
267 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
269 ret = ResumeThread(hThread);
270 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
272 /* wait that doesn't time out */
273 ret = WaitForSingleObject(hEvent, 100);
274 ok(ret == WAIT_OBJECT_0, "object not signaled, ret=%u\n", ret);
276 /* wait for thread end */
277 ret = WaitForSingleObject(hThread, 100);
278 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
279 CloseHandle(hThread);
281 /* create and wait for remote thread with entry point CloseHandle() */
282 hThread = CreateRemoteThread(hProcess, NULL, 0,
283 threadFunc_CloseHandle,
284 hRemoteEvent, 0, &tid);
285 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
286 ret = WaitForSingleObject(hThread, 100);
287 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
288 CloseHandle(hThread);
290 /* create remote thread with entry point SetEvent() */
291 hThread = CreateRemoteThread(hProcess, NULL, 0,
293 hRemoteEvent, 0, &tid);
294 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
296 /* closed handle, so wait times out */
297 ret = WaitForSingleObject(hEvent, 100);
298 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
300 /* check that remote SetEvent() failed */
301 ret = GetExitCodeThread(hThread, &exitcode);
302 ok(ret != 0, "GetExitCodeThread failed, err=%u\n", GetLastError());
303 if (ret) ok(exitcode == 0, "SetEvent succeeded, expected to fail\n");
304 CloseHandle(hThread);
307 TerminateProcess(hProcess, 0);
309 CloseHandle(hProcess);
312 /* Check basic funcationality of CreateThread and Tls* functions */
313 static VOID test_CreateThread_basic(void)
315 HANDLE thread[NUM_THREADS],event[NUM_THREADS];
316 DWORD threadid[NUM_THREADS],curthreadId;
317 DWORD threadmem[NUM_THREADS];
319 t1Struct tstruct[NUM_THREADS];
324 /* lstrlenA contains an exception handler so this makes sure exceptions work in the main thread */
325 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
327 /* Retrieve current Thread ID for later comparisons */
328 curthreadId=GetCurrentThreadId();
329 /* Allocate some local storage */
330 ok((tlsIndex=TlsAlloc())!=TLS_OUT_OF_INDEXES,"TlsAlloc failed\n");
331 /* Create events for thread synchronization */
332 for(i=0;i<NUM_THREADS;i++) {
334 /* Note that it doesn't matter what type of event we chose here. This
335 test isn't trying to thoroughly test events
337 event[i]=CreateEventA(NULL,TRUE,FALSE,NULL);
338 tstruct[i].threadnum=i;
339 tstruct[i].threadmem=threadmem;
340 tstruct[i].event=event;
343 /* Test that passing arguments to threads works okay */
344 for(i=0;i<NUM_THREADS;i++) {
345 thread[i] = CreateThread(NULL,0,threadFunc1,
346 &tstruct[i],0,&threadid[i]);
347 ok(thread[i]!=NULL,"Create Thread failed\n");
349 /* Test that the threads actually complete */
350 for(i=0;i<NUM_THREADS;i++) {
351 error=WaitForSingleObject(thread[i],5000);
352 ok(error==WAIT_OBJECT_0, "Thread did not complete within timelimit\n");
353 if(error!=WAIT_OBJECT_0) {
354 TerminateThread(thread[i],i+NUM_THREADS);
356 ok(GetExitCodeThread(thread[i],&exitCode),"Could not retrieve ext code\n");
357 ok(exitCode==i+NUM_THREADS,"Thread returned an incorrect exit code\n");
359 /* Test that each thread executed in its parent's address space
360 (it was able to change threadmem and pass that change back to its parent)
361 and that each thread id was independent). Note that we prove that the
362 threads actually execute concurrently by having them block on each other
365 for(i=0;i<NUM_THREADS;i++) {
367 for(j=i+1;j<NUM_THREADS;j++) {
368 if (threadmem[i]==threadmem[j]) {
372 ok(!error && threadmem[i]==threadid[i] && threadmem[i]!=curthreadId,
373 "Thread did not execute successfully\n");
374 ok(CloseHandle(thread[i])!=0,"CloseHandle failed\n");
376 ok(TlsFree(tlsIndex)!=0,"TlsFree failed\n");
378 /* Test how passing NULL as a pointer to threadid works */
379 SetLastError(0xFACEaBAD);
380 thread[0] = CreateThread(NULL,0,threadFunc2,NULL,0,NULL);
381 GLE = GetLastError();
382 if (thread[0]) { /* NT */
383 ok(GLE==0xFACEaBAD, "CreateThread set last error to %d, expected 4207848365\n", GLE);
384 ret = WaitForSingleObject(thread[0],100);
385 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
386 ret = GetExitCodeThread(thread[0],&exitCode);
387 ok(ret!=0, "GetExitCodeThread returned %d (expected nonzero)\n", ret);
388 ok(exitCode==99, "threadFunc2 exited with code: %d (expected 99)\n", exitCode);
389 ok(CloseHandle(thread[0])!=0,"Error closing thread handle\n");
392 ok(GLE==ERROR_INVALID_PARAMETER, "CreateThread set last error to %d, expected 87\n", GLE);
396 /* Check that using the CREATE_SUSPENDED flag works */
397 static VOID test_CreateThread_suspended(void)
403 thread = CreateThread(NULL,0,threadFunc2,NULL,
404 CREATE_SUSPENDED,&threadId);
405 ok(thread!=NULL,"Create Thread failed\n");
406 /* Check that the thread is suspended */
407 ok(SuspendThread(thread)==1,"Thread did not start suspended\n");
408 ok(ResumeThread(thread)==2,"Resume thread returned an invalid value\n");
409 /* Check that resume thread didn't actually start the thread. I can't think
410 of a better way of checking this than just waiting. I am not sure if this
411 will work on slow computers.
413 ok(WaitForSingleObject(thread,1000)==WAIT_TIMEOUT,
414 "ResumeThread should not have actually started the thread\n");
415 /* Now actually resume the thread and make sure that it actually completes*/
416 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
417 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
418 "Thread did not resume\n");
419 if(error!=WAIT_OBJECT_0) {
420 TerminateThread(thread,1);
422 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
425 /* Check that SuspendThread and ResumeThread work */
426 static VOID test_SuspendThread(void)
428 HANDLE thread,access_thread;
429 DWORD threadId,exitCode,error;
432 thread = CreateThread(NULL,0,threadFunc3,NULL,
434 ok(thread!=NULL,"Create Thread failed\n");
435 /* Check that the thread is suspended */
436 /* Note that this is a polling method, and there is a race between
437 SuspendThread being called (in the child, and the loop below timing out,
438 so the test could fail on a heavily loaded or slow computer.
441 for(i=0;error==0 && i<100;i++) {
442 error=SuspendThread(thread);
443 ResumeThread(thread);
449 ok(error==1,"SuspendThread did not work\n");
450 /* check that access restrictions are obeyed */
452 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_SUSPEND_RESUME),
454 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
455 if (access_thread!=NULL) {
456 obey_ar(SuspendThread(access_thread)==~0U);
457 obey_ar(ResumeThread(access_thread)==~0U);
458 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
461 /* Double check that the thread really is suspended */
462 ok((error=GetExitCodeThread(thread,&exitCode))!=0 && exitCode==STILL_ACTIVE,
463 "Thread did not really suspend\n");
464 /* Resume the thread, and make sure 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);
471 /* Trying to suspend a terminated thread should fail */
472 error=SuspendThread(thread);
473 ok(error==~0U, "wrong return code: %d\n", error);
474 ok(GetLastError()==ERROR_ACCESS_DENIED || GetLastError()==ERROR_NO_MORE_ITEMS, "unexpected error code: %d\n", GetLastError());
476 ok(CloseHandle(thread)!=0,"CloseHandle Failed\n");
479 /* Check that TerminateThread works properly
481 static VOID test_TerminateThread(void)
483 HANDLE thread,access_thread,event;
484 DWORD threadId,exitCode;
485 event=CreateEventA(NULL,TRUE,FALSE,NULL);
486 thread = CreateThread(NULL,0,threadFunc4,
487 (LPVOID)event, 0,&threadId);
488 ok(thread!=NULL,"Create Thread failed\n");
489 /* TerminateThread has a race condition in Wine. If the thread is terminated
490 before it starts, it leaves a process behind. Therefore, we wait for the
491 thread to signal that it has started. There is no easy way to force the
492 race to occur, so we don't try to find it.
494 ok(WaitForSingleObject(event,5000)==WAIT_OBJECT_0,
495 "TerminateThread didn't work\n");
496 /* check that access restrictions are obeyed */
498 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_TERMINATE),
500 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
501 if (access_thread!=NULL) {
502 obey_ar(TerminateThread(access_thread,99)==0);
503 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
506 /* terminate a job and make sure it terminates */
507 ok(TerminateThread(thread,99)!=0,"TerminateThread failed\n");
508 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
509 "TerminateThread didn't work\n");
510 ok(GetExitCodeThread(thread,&exitCode)!=STILL_ACTIVE,
511 "TerminateThread should not leave the thread 'STILL_ACTIVE'\n");
512 ok(exitCode==99, "TerminateThread returned invalid exit code\n");
513 ok(CloseHandle(thread)!=0,"Error Closing thread handle\n");
516 /* Check if CreateThread obeys the specified stack size. This code does
517 not work properly, and is currently disabled
519 static VOID test_CreateThread_stack(void)
522 /* The only way I know of to test the stack size is to use alloca
523 and __try/__except. However, this is probably not portable,
524 and I couldn't get it to work under Wine anyhow. However, here
525 is the code which should allow for testing that CreateThread
526 respects the stack-size limit
529 DWORD threadId,exitCode;
532 sysInfo.dwPageSize=0;
533 GetSystemInfo(&sysInfo);
534 ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
535 thread = CreateThread(NULL,sysInfo.dwPageSize,
536 threadFunc5,&exitCode,
538 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
539 "TerminateThread didn't work\n");
540 ok(exitCode==1,"CreateThread did not obey stack-size-limit\n");
541 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
545 /* Check whether setting/retrieving thread priorities works */
546 static VOID test_thread_priority(void)
548 HANDLE curthread,access_thread;
549 DWORD curthreadId,exitCode;
550 int min_priority=-2,max_priority=2;
554 curthread=GetCurrentThread();
555 curthreadId=GetCurrentThreadId();
556 /* Check thread priority */
557 /* NOTE: on Win2k/XP priority can be from -7 to 6. All other platforms it
558 is -2 to 2. However, even on a real Win2k system, using thread
559 priorities beyond the -2 to 2 range does not work. If you want to try
560 anyway, enable USE_EXTENDED_PRIORITIES
562 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_NORMAL,
563 "GetThreadPriority Failed\n");
566 /* check that access control is obeyed */
567 access_thread=pOpenThread(THREAD_ALL_ACCESS &
568 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
570 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
571 if (access_thread!=NULL) {
572 obey_ar(SetThreadPriority(access_thread,1)==0);
573 obey_ar(GetThreadPriority(access_thread)==THREAD_PRIORITY_ERROR_RETURN);
574 obey_ar(GetExitCodeThread(access_thread,&exitCode)==0);
575 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
578 #if USE_EXTENDED_PRIORITIES
579 min_priority=-7; max_priority=6;
581 for(i=min_priority;i<=max_priority;i++) {
582 ok(SetThreadPriority(curthread,i)!=0,
583 "SetThreadPriority Failed for priority: %d\n",i);
584 ok(GetThreadPriority(curthread)==i,
585 "GetThreadPriority Failed for priority: %d\n",i);
587 ok(SetThreadPriority(curthread,THREAD_PRIORITY_TIME_CRITICAL)!=0,
588 "SetThreadPriority Failed\n");
589 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_TIME_CRITICAL,
590 "GetThreadPriority Failed\n");
591 ok(SetThreadPriority(curthread,THREAD_PRIORITY_IDLE)!=0,
592 "SetThreadPriority Failed\n");
593 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_IDLE,
594 "GetThreadPriority Failed\n");
595 ok(SetThreadPriority(curthread,0)!=0,"SetThreadPriority Failed\n");
597 /* Check that the thread priority is not changed if SetThreadPriority
598 is called with a value outside of the max/min range */
599 SetThreadPriority(curthread,min_priority);
600 SetLastError(0xdeadbeef);
601 rc = SetThreadPriority(curthread,min_priority-1);
603 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
604 ok(GetLastError() == ERROR_INVALID_PARAMETER,
605 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER (87)\n", GetLastError());
606 ok(GetThreadPriority(curthread)==min_priority,
607 "GetThreadPriority didn't return min_priority\n");
609 SetThreadPriority(curthread,max_priority);
610 SetLastError(0xdeadbeef);
611 rc = SetThreadPriority(curthread,max_priority+1);
613 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
614 ok(GetLastError() == ERROR_INVALID_PARAMETER,
615 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER (87)\n", GetLastError());
616 ok(GetThreadPriority(curthread)==max_priority,
617 "GetThreadPriority didn't return max_priority\n");
619 /* Check thread priority boost */
620 if (!pGetThreadPriorityBoost || !pSetThreadPriorityBoost)
623 SetLastError(0xdeadbeef);
624 rc=pGetThreadPriorityBoost(curthread,&disabled);
625 if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
629 ok(rc!=0,"error=%d\n",GetLastError());
632 /* check that access control is obeyed */
633 access_thread=pOpenThread(THREAD_ALL_ACCESS &
634 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
636 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
637 if (access_thread!=NULL) {
638 obey_ar(pSetThreadPriorityBoost(access_thread,1)==0);
639 obey_ar(pGetThreadPriorityBoost(access_thread,&disabled)==0);
640 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
645 rc = pSetThreadPriorityBoost(curthread,1);
646 ok( rc != 0, "error=%d\n",GetLastError());
647 rc=pGetThreadPriorityBoost(curthread,&disabled);
648 ok(rc!=0 && disabled==1,
649 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
651 rc = pSetThreadPriorityBoost(curthread,0);
652 ok( rc != 0, "error=%d\n",GetLastError());
653 rc=pGetThreadPriorityBoost(curthread,&disabled);
654 ok(rc!=0 && disabled==0,
655 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
659 /* check the GetThreadTimes function */
660 static VOID test_GetThreadTimes(void)
662 HANDLE thread,access_thread=NULL;
663 FILETIME creationTime,exitTime,kernelTime,userTime;
667 thread = CreateThread(NULL,0,threadFunc2,NULL,
668 CREATE_SUSPENDED,&threadId);
670 ok(thread!=NULL,"Create Thread failed\n");
671 /* check that access control is obeyed */
673 access_thread=pOpenThread(THREAD_ALL_ACCESS &
674 (~THREAD_QUERY_INFORMATION), 0,threadId);
675 ok(access_thread!=NULL,
676 "OpenThread returned an invalid handle\n");
678 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
679 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
680 "ResumeThread didn't work\n");
681 creationTime.dwLowDateTime=99; creationTime.dwHighDateTime=99;
682 exitTime.dwLowDateTime=99; exitTime.dwHighDateTime=99;
683 kernelTime.dwLowDateTime=99; kernelTime.dwHighDateTime=99;
684 userTime.dwLowDateTime=99; userTime.dwHighDateTime=99;
685 /* GetThreadTimes should set all of the parameters passed to it */
686 error=GetThreadTimes(thread,&creationTime,&exitTime,
687 &kernelTime,&userTime);
688 if (error!=0 || GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
689 ok(error!=0,"GetThreadTimes failed\n");
690 ok(creationTime.dwLowDateTime!=99 || creationTime.dwHighDateTime!=99,
691 "creationTime was invalid\n");
692 ok(exitTime.dwLowDateTime!=99 || exitTime.dwHighDateTime!=99,
693 "exitTime was invalid\n");
694 ok(kernelTime.dwLowDateTime!=99 || kernelTime.dwHighDateTime!=99,
695 "kernelTimewas invalid\n");
696 ok(userTime.dwLowDateTime!=99 || userTime.dwHighDateTime!=99,
697 "userTime was invalid\n");
698 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
699 if(access_thread!=NULL)
701 error=GetThreadTimes(access_thread,&creationTime,&exitTime,
702 &kernelTime,&userTime);
706 if(access_thread!=NULL) {
707 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
711 /* Check the processor affinity functions */
712 /* NOTE: These functions should also be checked that they obey access control
714 static VOID test_thread_processor(void)
716 HANDLE curthread,curproc;
717 DWORD_PTR processMask,systemMask;
721 sysInfo.dwNumberOfProcessors=0;
722 GetSystemInfo(&sysInfo);
723 ok(sysInfo.dwNumberOfProcessors>0,
724 "GetSystemInfo failed to return a valid # of processors\n");
725 /* Use the current Thread/process for all tests */
726 curthread=GetCurrentThread();
727 ok(curthread!=NULL,"GetCurrentThread failed\n");
728 curproc=GetCurrentProcess();
729 ok(curproc!=NULL,"GetCurrentProcess failed\n");
730 /* Check the Affinity Mask functions */
731 ok(GetProcessAffinityMask(curproc,&processMask,&systemMask)!=0,
732 "GetProcessAffinityMask failed\n");
733 ok(SetThreadAffinityMask(curthread,processMask)==processMask,
734 "SetThreadAffinityMask failed\n");
735 ok(SetThreadAffinityMask(curthread,processMask+1)==0,
736 "SetThreadAffinityMask passed for an illegal processor\n");
737 /* NOTE: This only works on WinNT/2000/XP) */
738 if (pSetThreadIdealProcessor) {
741 error=pSetThreadIdealProcessor(curthread,0);
742 if (GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
743 ok(error!=-1, "SetThreadIdealProcessor failed\n");
746 if (GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
747 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
749 "SetThreadIdealProcessor succeeded with an illegal processor #\n");
751 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS);
752 ok(error==0, "SetThreadIdealProcessor returned an incorrect value\n");
758 static VOID test_GetThreadExitCode(void)
760 DWORD exitCode, threadid;
764 ret = GetExitCodeThread((HANDLE)0x2bad2bad,&exitCode);
765 ok(ret==0, "GetExitCodeThread returned non zero value: %d\n", ret);
766 GLE = GetLastError();
767 ok(GLE==ERROR_INVALID_HANDLE, "GetLastError returned %d (expected 6)\n", GLE);
769 thread = CreateThread(NULL,0,threadFunc2,NULL,0,&threadid);
770 ret = WaitForSingleObject(thread,100);
771 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
772 ret = GetExitCodeThread(thread,&exitCode);
773 ok(ret==exitCode || ret==1,
774 "GetExitCodeThread returned %d (expected 1 or %d)\n", ret, exitCode);
775 ok(exitCode==99, "threadFunc2 exited with code %d (expected 99)\n", exitCode);
776 ok(CloseHandle(thread)!=0,"Error closing thread handle\n");
781 static int test_value = 0;
784 static void WINAPI set_test_val( int val )
789 static DWORD WINAPI threadFunc6(LPVOID p)
793 test_value *= (int)p;
797 static void test_SetThreadContext(void)
806 SetLastError(0xdeadbeef);
807 event = CreateEvent( NULL, TRUE, FALSE, NULL );
808 thread = CreateThread( NULL, 0, threadFunc6, (void *)2, 0, &threadid );
809 ok( thread != NULL, "CreateThread failed : (%d)\n", GetLastError() );
812 trace("Thread creation failed, skipping rest of test\n");
815 WaitForSingleObject( event, INFINITE );
816 SuspendThread( thread );
817 CloseHandle( event );
819 ctx.ContextFlags = CONTEXT_FULL;
820 SetLastError(0xdeadbeef);
821 ret = GetThreadContext( thread, &ctx );
822 ok( ret, "GetThreadContext failed : (%u)\n", GetLastError() );
826 /* simulate a call to set_test_val(10) */
827 stack = (int *)ctx.Esp;
830 ctx.Esp -= 2 * sizeof(int *);
831 ctx.Eip = (DWORD)set_test_val;
832 SetLastError(0xdeadbeef);
833 ok( SetThreadContext( thread, &ctx ), "SetThreadContext failed : (%d)\n", GetLastError() );
836 SetLastError(0xdeadbeef);
837 prevcount = ResumeThread( thread );
838 ok ( prevcount == 1, "Previous suspend count (%d) instead of 1, last error : (%d)\n",
839 prevcount, GetLastError() );
841 WaitForSingleObject( thread, INFINITE );
842 ok( test_value == 20, "test_value %d instead of 20\n", test_value );
845 #endif /* __i386__ */
847 static HANDLE finish_event;
848 static LONG times_executed;
850 static DWORD CALLBACK work_function(void *p)
852 LONG executed = InterlockedIncrement(×_executed);
855 SetEvent(finish_event);
859 static void test_QueueUserWorkItem(void)
865 /* QueueUserWorkItem not present on win9x */
866 if (!pQueueUserWorkItem) return;
868 finish_event = CreateEvent(NULL, TRUE, FALSE, NULL);
870 before = GetTickCount();
872 for (i = 0; i < 100; i++)
874 BOOL ret = pQueueUserWorkItem(work_function, (void *)i, WT_EXECUTEDEFAULT);
875 ok(ret, "QueueUserWorkItem failed with error %d\n", GetLastError());
878 wait_result = WaitForSingleObject(finish_event, 10000);
880 after = GetTickCount();
881 trace("100 QueueUserWorkItem calls took %dms\n", after - before);
882 ok(wait_result == WAIT_OBJECT_0, "wait failed with error 0x%x\n", wait_result);
884 ok(times_executed == 100, "didn't execute all of the work items\n");
887 static void CALLBACK signaled_function(PVOID p, BOOLEAN TimerOrWaitFired)
891 ok(!TimerOrWaitFired, "wait shouldn't have timed out\n");
894 static void CALLBACK timeout_function(PVOID p, BOOLEAN TimerOrWaitFired)
898 ok(TimerOrWaitFired, "wait should have timed out\n");
901 static void test_RegisterWaitForSingleObject(void)
906 HANDLE complete_event;
908 if (!pRegisterWaitForSingleObject || !pUnregisterWait)
910 skip("RegisterWaitForSingleObject or UnregisterWait not implemented\n");
914 /* test signaled case */
916 handle = CreateEvent(NULL, TRUE, TRUE, NULL);
917 complete_event = CreateEvent(NULL, FALSE, FALSE, NULL);
919 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
920 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
922 WaitForSingleObject(complete_event, INFINITE);
923 /* give worker thread chance to complete */
926 ret = pUnregisterWait(wait_handle);
927 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
929 /* test cancel case */
933 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
934 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
936 ret = pUnregisterWait(wait_handle);
937 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
939 /* test timeout case */
941 ret = pRegisterWaitForSingleObject(&wait_handle, handle, timeout_function, complete_event, 0, WT_EXECUTEONLYONCE);
942 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
944 WaitForSingleObject(complete_event, INFINITE);
945 /* give worker thread chance to complete */
948 ret = pUnregisterWait(wait_handle);
949 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
957 argc = winetest_get_mainargs( &argv );
958 /* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
959 so that the compile passes
961 lib=GetModuleHandleA("kernel32.dll");
962 ok(lib!=NULL,"Couldn't get a handle for kernel32.dll\n");
963 pGetThreadPriorityBoost=(GetThreadPriorityBoost_t)GetProcAddress(lib,"GetThreadPriorityBoost");
964 pOpenThread=(OpenThread_t)GetProcAddress(lib,"OpenThread");
965 pQueueUserWorkItem=(QueueUserWorkItem_t)GetProcAddress(lib,"QueueUserWorkItem");
966 pSetThreadIdealProcessor=(SetThreadIdealProcessor_t)GetProcAddress(lib,"SetThreadIdealProcessor");
967 pSetThreadPriorityBoost=(SetThreadPriorityBoost_t)GetProcAddress(lib,"SetThreadPriorityBoost");
968 pRegisterWaitForSingleObject=(RegisterWaitForSingleObject_t)GetProcAddress(lib,"RegisterWaitForSingleObject");
969 pUnregisterWait=(UnregisterWait_t)GetProcAddress(lib,"UnregisterWait");
973 if (!strcmp(argv[2], "sleep"))
975 HANDLE hAddrEvents[2];
976 create_function_addr_events(hAddrEvents);
977 SetEvent(hAddrEvents[0]);
978 SetEvent(hAddrEvents[1]);
979 Sleep(5000); /* spawned process runs for at most 5 seconds */
985 hThread = CreateThread(NULL, 0, threadFunc2, NULL, 0, NULL);
986 ok(hThread != NULL, "CreateThread failed, error %u\n",
988 ok(WaitForSingleObject(hThread, 200) == WAIT_OBJECT_0,
989 "Thread did not exit in time\n");
990 if (hThread == NULL) break;
991 CloseHandle(hThread);
996 test_CreateRemoteThread();
997 test_CreateThread_basic();
998 test_CreateThread_suspended();
999 test_SuspendThread();
1000 test_TerminateThread();
1001 test_CreateThread_stack();
1002 test_thread_priority();
1003 test_GetThreadTimes();
1004 test_thread_processor();
1005 test_GetThreadExitCode();
1007 test_SetThreadContext();
1009 test_QueueUserWorkItem();
1010 test_RegisterWaitForSingleObject();