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 static HANDLE create_target_process(const char *arg)
74 char cmdline[MAX_PATH];
75 PROCESS_INFORMATION pi;
76 STARTUPINFO si = { 0 };
79 winetest_get_mainargs( &argv );
80 sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
81 ok(CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL,
82 &si, &pi) != 0, "error: %u\n", GetLastError());
83 ok(CloseHandle(pi.hThread) != 0, "error %u\n", GetLastError());
87 /* Functions not tested yet:
92 In addition there are no checks that the inheritance works properly in
104 /* WinME supports OpenThread but doesn't know about access restrictions so
105 we require them to be either completely ignored or always obeyed.
107 INT obeying_ars = 0; /* -1 == no, 0 == dunno yet, 1 == yes */
111 ? (obeying_ars = +1) \
112 : ((obeying_ars = -1), \
113 trace("not restricted, assuming consistent behaviour\n"))) \
114 : (obeying_ars < 0) \
115 ? ok(!(x), "access restrictions obeyed\n") \
116 : ok( (x), "access restrictions not obeyed\n"))
118 /* Basic test that simultaneous threads can access shared memory,
119 that the thread local storage routines work correctly, and that
120 threads actually run concurrently
122 static DWORD WINAPI threadFunc1(LPVOID p)
124 t1Struct *tstruct = (t1Struct *)p;
126 /* write our thread # into shared memory */
127 tstruct->threadmem[tstruct->threadnum]=GetCurrentThreadId();
128 ok(TlsSetValue(tlsIndex,(LPVOID)(tstruct->threadnum+1))!=0,
129 "TlsSetValue failed\n");
130 /* The threads synchronize before terminating. This is done by
131 Signaling an event, and waiting for all events to occur
133 SetEvent(tstruct->event[tstruct->threadnum]);
134 WaitForMultipleObjects(NUM_THREADS,tstruct->event,TRUE,INFINITE);
135 /* Double check that all threads really did run by validating that
136 they have all written to the shared memory. There should be no race
137 here, since all threads were synchronized after the write.*/
138 for(i=0;i<NUM_THREADS;i++) {
139 while(tstruct->threadmem[i]==0) ;
142 /* lstrlenA contains an exception handler so this makes sure exceptions work in threads */
143 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
145 /* Check that no one changed our tls memory */
146 ok((int)TlsGetValue(tlsIndex)-1==tstruct->threadnum,
147 "TlsGetValue failed\n");
148 return NUM_THREADS+tstruct->threadnum;
151 static DWORD WINAPI threadFunc2(LPVOID p)
156 static DWORD WINAPI threadFunc3(LPVOID p)
159 thread=GetCurrentThread();
160 SuspendThread(thread);
164 static DWORD WINAPI threadFunc4(LPVOID p)
166 HANDLE event = (HANDLE)p;
175 static DWORD WINAPI threadFunc5(LPVOID p)
177 DWORD *exitCode = (DWORD *)p;
179 sysInfo.dwPageSize=0;
180 GetSystemInfo(&sysInfo);
184 alloca(2*sysInfo.dwPageSize);
194 static DWORD WINAPI threadFunc_SetEvent(LPVOID p)
196 SetEvent((HANDLE) p);
200 static DWORD WINAPI threadFunc_CloseHandle(LPVOID p)
202 CloseHandle((HANDLE) p);
206 static void create_function_addr_events(HANDLE events[2])
210 sprintf(buffer, "threadFunc_SetEvent %p", threadFunc_SetEvent);
211 events[0] = CreateEvent(NULL, FALSE, FALSE, buffer);
213 sprintf(buffer, "threadFunc_CloseHandle %p", threadFunc_CloseHandle);
214 events[1] = CreateEvent(NULL, FALSE, FALSE, buffer);
217 /* check CreateRemoteThread */
218 static VOID test_CreateRemoteThread(void)
220 HANDLE hProcess, hThread, hEvent, hRemoteEvent;
221 DWORD tid, ret, exitcode;
222 HANDLE hAddrEvents[2];
224 hProcess = create_target_process("sleep");
225 ok(hProcess != NULL, "Can't start process\n");
227 /* ensure threadFunc_SetEvent & threadFunc_CloseHandle are the same
228 * address as in the child process */
229 create_function_addr_events(hAddrEvents);
230 ret = WaitForMultipleObjects(2, hAddrEvents, TRUE, 5000);
231 if (ret == WAIT_TIMEOUT)
233 skip("child process wasn't mapped at same address, so can't do CreateRemoteThread tests.\n");
237 hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
238 ok(hEvent != NULL, "Can't create event, err=%u\n", GetLastError());
239 ret = DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &hRemoteEvent,
240 0, FALSE, DUPLICATE_SAME_ACCESS);
241 ok(ret != 0, "DuplicateHandle failed, err=%u\n", GetLastError());
243 /* create suspended remote thread with entry point SetEvent() */
244 hThread = CreateRemoteThread(hProcess, NULL, 0, threadFunc_SetEvent,
245 hRemoteEvent, CREATE_SUSPENDED, &tid);
246 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
247 ok(tid != 0, "null tid\n");
248 ret = SuspendThread(hThread);
249 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
250 ret = ResumeThread(hThread);
251 ok(ret == 2, "ret=%u, err=%u\n", ret, GetLastError());
253 /* thread still suspended, so wait times out */
254 ret = WaitForSingleObject(hEvent, 100);
255 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
257 ret = ResumeThread(hThread);
258 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
260 /* wait that doesn't time out */
261 ret = WaitForSingleObject(hEvent, 100);
262 ok(ret == WAIT_OBJECT_0, "object not signaled, ret=%u\n", ret);
264 /* wait for thread end */
265 ret = WaitForSingleObject(hThread, 100);
266 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
267 CloseHandle(hThread);
269 /* create and wait for remote thread with entry point CloseHandle() */
270 hThread = CreateRemoteThread(hProcess, NULL, 0,
271 threadFunc_CloseHandle,
272 hRemoteEvent, 0, &tid);
273 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
274 ret = WaitForSingleObject(hThread, 100);
275 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
276 CloseHandle(hThread);
278 /* create remote thread with entry point SetEvent() */
279 hThread = CreateRemoteThread(hProcess, NULL, 0,
281 hRemoteEvent, 0, &tid);
282 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
284 /* closed handle, so wait times out */
285 ret = WaitForSingleObject(hEvent, 100);
286 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
288 /* check that remote SetEvent() failed */
289 ret = GetExitCodeThread(hThread, &exitcode);
290 ok(ret != 0, "GetExitCodeThread failed, err=%u\n", GetLastError());
291 if (ret) ok(exitcode == 0, "SetEvent succeeded, expected to fail\n");
292 CloseHandle(hThread);
294 TerminateProcess(hProcess, 0);
296 CloseHandle(hProcess);
299 /* Check basic funcationality of CreateThread and Tls* functions */
300 static VOID test_CreateThread_basic(void)
302 HANDLE thread[NUM_THREADS],event[NUM_THREADS];
303 DWORD threadid[NUM_THREADS],curthreadId;
304 DWORD threadmem[NUM_THREADS];
306 t1Struct tstruct[NUM_THREADS];
311 /* lstrlenA contains an exception handler so this makes sure exceptions work in the main thread */
312 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
314 /* Retrieve current Thread ID for later comparisons */
315 curthreadId=GetCurrentThreadId();
316 /* Allocate some local storage */
317 ok((tlsIndex=TlsAlloc())!=TLS_OUT_OF_INDEXES,"TlsAlloc failed\n");
318 /* Create events for thread synchronization */
319 for(i=0;i<NUM_THREADS;i++) {
321 /* Note that it doesn't matter what type of event we chose here. This
322 test isn't trying to thoroughly test events
324 event[i]=CreateEventA(NULL,TRUE,FALSE,NULL);
325 tstruct[i].threadnum=i;
326 tstruct[i].threadmem=threadmem;
327 tstruct[i].event=event;
330 /* Test that passing arguments to threads works okay */
331 for(i=0;i<NUM_THREADS;i++) {
332 thread[i] = CreateThread(NULL,0,threadFunc1,
333 &tstruct[i],0,&threadid[i]);
334 ok(thread[i]!=NULL,"Create Thread failed\n");
336 /* Test that the threads actually complete */
337 for(i=0;i<NUM_THREADS;i++) {
338 error=WaitForSingleObject(thread[i],5000);
339 ok(error==WAIT_OBJECT_0, "Thread did not complete within timelimit\n");
340 if(error!=WAIT_OBJECT_0) {
341 TerminateThread(thread[i],i+NUM_THREADS);
343 ok(GetExitCodeThread(thread[i],&exitCode),"Could not retrieve ext code\n");
344 ok(exitCode==i+NUM_THREADS,"Thread returned an incorrect exit code\n");
346 /* Test that each thread executed in its parent's address space
347 (it was able to change threadmem and pass that change back to its parent)
348 and that each thread id was independent). Note that we prove that the
349 threads actually execute concurrently by having them block on each other
352 for(i=0;i<NUM_THREADS;i++) {
354 for(j=i+1;j<NUM_THREADS;j++) {
355 if (threadmem[i]==threadmem[j]) {
359 ok(!error && threadmem[i]==threadid[i] && threadmem[i]!=curthreadId,
360 "Thread did not execute successfully\n");
361 ok(CloseHandle(thread[i])!=0,"CloseHandle failed\n");
363 ok(TlsFree(tlsIndex)!=0,"TlsFree failed\n");
365 /* Test how passing NULL as a pointer to threadid works */
366 SetLastError(0xFACEaBAD);
367 thread[0] = CreateThread(NULL,0,threadFunc2,NULL,0,NULL);
368 GLE = GetLastError();
369 if (thread[0]) { /* NT */
370 ok(GLE==0xFACEaBAD, "CreateThread set last error to %d, expected 4207848365\n", GLE);
371 ret = WaitForSingleObject(thread[0],100);
372 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
373 ret = GetExitCodeThread(thread[0],&exitCode);
374 ok(ret!=0, "GetExitCodeThread returned %d (expected nonzero)\n", ret);
375 ok(exitCode==99, "threadFunc2 exited with code: %d (expected 99)\n", exitCode);
376 ok(CloseHandle(thread[0])!=0,"Error closing thread handle\n");
379 ok(GLE==ERROR_INVALID_PARAMETER, "CreateThread set last error to %d, expected 87\n", GLE);
383 /* Check that using the CREATE_SUSPENDED flag works */
384 static VOID test_CreateThread_suspended(void)
390 thread = CreateThread(NULL,0,threadFunc2,NULL,
391 CREATE_SUSPENDED,&threadId);
392 ok(thread!=NULL,"Create Thread failed\n");
393 /* Check that the thread is suspended */
394 ok(SuspendThread(thread)==1,"Thread did not start suspended\n");
395 ok(ResumeThread(thread)==2,"Resume thread returned an invalid value\n");
396 /* Check that resume thread didn't actually start the thread. I can't think
397 of a better way of checking this than just waiting. I am not sure if this
398 will work on slow computers.
400 ok(WaitForSingleObject(thread,1000)==WAIT_TIMEOUT,
401 "ResumeThread should not have actually started the thread\n");
402 /* Now actually resume the thread and make sure that it actually completes*/
403 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
404 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
405 "Thread did not resume\n");
406 if(error!=WAIT_OBJECT_0) {
407 TerminateThread(thread,1);
409 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
412 /* Check that SuspendThread and ResumeThread work */
413 static VOID test_SuspendThread(void)
415 HANDLE thread,access_thread;
416 DWORD threadId,exitCode,error;
419 thread = CreateThread(NULL,0,threadFunc3,NULL,
421 ok(thread!=NULL,"Create Thread failed\n");
422 /* Check that the thread is suspended */
423 /* Note that this is a polling method, and there is a race between
424 SuspendThread being called (in the child, and the loop below timing out,
425 so the test could fail on a heavily loaded or slow computer.
428 for(i=0;error==0 && i<100;i++) {
429 error=SuspendThread(thread);
430 ResumeThread(thread);
436 ok(error==1,"SuspendThread did not work\n");
437 /* check that access restrictions are obeyed */
439 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_SUSPEND_RESUME),
441 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
442 if (access_thread!=NULL) {
443 obey_ar(SuspendThread(access_thread)==~0U);
444 obey_ar(ResumeThread(access_thread)==~0U);
445 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
448 /* Double check that the thread really is suspended */
449 ok((error=GetExitCodeThread(thread,&exitCode))!=0 && exitCode==STILL_ACTIVE,
450 "Thread did not really suspend\n");
451 /* Resume the thread, and make sure it actually completes */
452 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
453 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
454 "Thread did not resume\n");
455 if(error!=WAIT_OBJECT_0) {
456 TerminateThread(thread,1);
458 /* Trying to suspend a terminated thread should fail */
459 error=SuspendThread(thread);
460 ok(error==~0U, "wrong return code: %d\n", error);
461 ok(GetLastError()==ERROR_ACCESS_DENIED || GetLastError()==ERROR_NO_MORE_ITEMS, "unexpected error code: %d\n", GetLastError());
463 ok(CloseHandle(thread)!=0,"CloseHandle Failed\n");
466 /* Check that TerminateThread works properly
468 static VOID test_TerminateThread(void)
470 HANDLE thread,access_thread,event;
471 DWORD threadId,exitCode;
472 event=CreateEventA(NULL,TRUE,FALSE,NULL);
473 thread = CreateThread(NULL,0,threadFunc4,
474 (LPVOID)event, 0,&threadId);
475 ok(thread!=NULL,"Create Thread failed\n");
476 /* TerminateThread has a race condition in Wine. If the thread is terminated
477 before it starts, it leaves a process behind. Therefore, we wait for the
478 thread to signal that it has started. There is no easy way to force the
479 race to occur, so we don't try to find it.
481 ok(WaitForSingleObject(event,5000)==WAIT_OBJECT_0,
482 "TerminateThread didn't work\n");
483 /* check that access restrictions are obeyed */
485 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_TERMINATE),
487 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
488 if (access_thread!=NULL) {
489 obey_ar(TerminateThread(access_thread,99)==0);
490 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
493 /* terminate a job and make sure it terminates */
494 ok(TerminateThread(thread,99)!=0,"TerminateThread failed\n");
495 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
496 "TerminateThread didn't work\n");
497 ok(GetExitCodeThread(thread,&exitCode)!=STILL_ACTIVE,
498 "TerminateThread should not leave the thread 'STILL_ACTIVE'\n");
499 ok(exitCode==99, "TerminateThread returned invalid exit code\n");
500 ok(CloseHandle(thread)!=0,"Error Closing thread handle\n");
503 /* Check if CreateThread obeys the specified stack size. This code does
504 not work properly, and is currently disabled
506 static VOID test_CreateThread_stack(void)
509 /* The only way I know of to test the stack size is to use alloca
510 and __try/__except. However, this is probably not portable,
511 and I couldn't get it to work under Wine anyhow. However, here
512 is the code which should allow for testing that CreateThread
513 respects the stack-size limit
516 DWORD threadId,exitCode;
519 sysInfo.dwPageSize=0;
520 GetSystemInfo(&sysInfo);
521 ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
522 thread = CreateThread(NULL,sysInfo.dwPageSize,
523 threadFunc5,&exitCode,
525 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
526 "TerminateThread didn't work\n");
527 ok(exitCode==1,"CreateThread did not obey stack-size-limit\n");
528 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
532 /* Check whether setting/retrieving thread priorities works */
533 static VOID test_thread_priority(void)
535 HANDLE curthread,access_thread;
536 DWORD curthreadId,exitCode;
537 int min_priority=-2,max_priority=2;
541 curthread=GetCurrentThread();
542 curthreadId=GetCurrentThreadId();
543 /* Check thread priority */
544 /* NOTE: on Win2k/XP priority can be from -7 to 6. All other platforms it
545 is -2 to 2. However, even on a real Win2k system, using thread
546 priorities beyond the -2 to 2 range does not work. If you want to try
547 anyway, enable USE_EXTENDED_PRIORITIES
549 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_NORMAL,
550 "GetThreadPriority Failed\n");
553 /* check that access control is obeyed */
554 access_thread=pOpenThread(THREAD_ALL_ACCESS &
555 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
557 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
558 if (access_thread!=NULL) {
559 obey_ar(SetThreadPriority(access_thread,1)==0);
560 obey_ar(GetThreadPriority(access_thread)==THREAD_PRIORITY_ERROR_RETURN);
561 obey_ar(GetExitCodeThread(access_thread,&exitCode)==0);
562 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
565 #if USE_EXTENDED_PRIORITIES
566 min_priority=-7; max_priority=6;
568 for(i=min_priority;i<=max_priority;i++) {
569 ok(SetThreadPriority(curthread,i)!=0,
570 "SetThreadPriority Failed for priority: %d\n",i);
571 ok(GetThreadPriority(curthread)==i,
572 "GetThreadPriority Failed for priority: %d\n",i);
574 ok(SetThreadPriority(curthread,THREAD_PRIORITY_TIME_CRITICAL)!=0,
575 "SetThreadPriority Failed\n");
576 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_TIME_CRITICAL,
577 "GetThreadPriority Failed\n");
578 ok(SetThreadPriority(curthread,THREAD_PRIORITY_IDLE)!=0,
579 "SetThreadPriority Failed\n");
580 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_IDLE,
581 "GetThreadPriority Failed\n");
582 ok(SetThreadPriority(curthread,0)!=0,"SetThreadPriority Failed\n");
584 /* Check thread priority boost */
585 if (!pGetThreadPriorityBoost || !pSetThreadPriorityBoost)
588 SetLastError(0xdeadbeef);
589 rc=pGetThreadPriorityBoost(curthread,&disabled);
590 if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
594 ok(rc!=0,"error=%d\n",GetLastError());
597 /* check that access control is obeyed */
598 access_thread=pOpenThread(THREAD_ALL_ACCESS &
599 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
601 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
602 if (access_thread!=NULL) {
603 obey_ar(pSetThreadPriorityBoost(access_thread,1)==0);
604 obey_ar(pGetThreadPriorityBoost(access_thread,&disabled)==0);
605 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
610 rc = pSetThreadPriorityBoost(curthread,1);
611 ok( rc != 0, "error=%d\n",GetLastError());
612 rc=pGetThreadPriorityBoost(curthread,&disabled);
613 ok(rc!=0 && disabled==1,
614 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
616 rc = pSetThreadPriorityBoost(curthread,0);
617 ok( rc != 0, "error=%d\n",GetLastError());
618 rc=pGetThreadPriorityBoost(curthread,&disabled);
619 ok(rc!=0 && disabled==0,
620 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
624 /* check the GetThreadTimes function */
625 static VOID test_GetThreadTimes(void)
627 HANDLE thread,access_thread=NULL;
628 FILETIME creationTime,exitTime,kernelTime,userTime;
632 thread = CreateThread(NULL,0,threadFunc2,NULL,
633 CREATE_SUSPENDED,&threadId);
635 ok(thread!=NULL,"Create Thread failed\n");
636 /* check that access control is obeyed */
638 access_thread=pOpenThread(THREAD_ALL_ACCESS &
639 (~THREAD_QUERY_INFORMATION), 0,threadId);
640 ok(access_thread!=NULL,
641 "OpenThread returned an invalid handle\n");
643 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
644 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
645 "ResumeThread didn't work\n");
646 creationTime.dwLowDateTime=99; creationTime.dwHighDateTime=99;
647 exitTime.dwLowDateTime=99; exitTime.dwHighDateTime=99;
648 kernelTime.dwLowDateTime=99; kernelTime.dwHighDateTime=99;
649 userTime.dwLowDateTime=99; userTime.dwHighDateTime=99;
650 /* GetThreadTimes should set all of the parameters passed to it */
651 error=GetThreadTimes(thread,&creationTime,&exitTime,
652 &kernelTime,&userTime);
653 if (error!=0 || GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
654 ok(error!=0,"GetThreadTimes failed\n");
655 ok(creationTime.dwLowDateTime!=99 || creationTime.dwHighDateTime!=99,
656 "creationTime was invalid\n");
657 ok(exitTime.dwLowDateTime!=99 || exitTime.dwHighDateTime!=99,
658 "exitTime was invalid\n");
659 ok(kernelTime.dwLowDateTime!=99 || kernelTime.dwHighDateTime!=99,
660 "kernelTimewas invalid\n");
661 ok(userTime.dwLowDateTime!=99 || userTime.dwHighDateTime!=99,
662 "userTime was invalid\n");
663 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
664 if(access_thread!=NULL)
666 error=GetThreadTimes(access_thread,&creationTime,&exitTime,
667 &kernelTime,&userTime);
671 if(access_thread!=NULL) {
672 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
676 /* Check the processor affinity functions */
677 /* NOTE: These functions should also be checked that they obey access control
679 static VOID test_thread_processor(void)
681 HANDLE curthread,curproc;
682 DWORD_PTR processMask,systemMask;
686 sysInfo.dwNumberOfProcessors=0;
687 GetSystemInfo(&sysInfo);
688 ok(sysInfo.dwNumberOfProcessors>0,
689 "GetSystemInfo failed to return a valid # of processors\n");
690 /* Use the current Thread/process for all tests */
691 curthread=GetCurrentThread();
692 ok(curthread!=NULL,"GetCurrentThread failed\n");
693 curproc=GetCurrentProcess();
694 ok(curproc!=NULL,"GetCurrentProcess failed\n");
695 /* Check the Affinity Mask functions */
696 ok(GetProcessAffinityMask(curproc,&processMask,&systemMask)!=0,
697 "GetProcessAffinityMask failed\n");
698 ok(SetThreadAffinityMask(curthread,processMask)==processMask,
699 "SetThreadAffinityMask failed\n");
700 ok(SetThreadAffinityMask(curthread,processMask+1)==0,
701 "SetThreadAffinityMask passed for an illegal processor\n");
702 /* NOTE: This only works on WinNT/2000/XP) */
703 if (pSetThreadIdealProcessor) {
706 error=pSetThreadIdealProcessor(curthread,0);
707 if (GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
708 ok(error!=-1, "SetThreadIdealProcessor failed\n");
711 if (GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
712 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
714 "SetThreadIdealProcessor succeeded with an illegal processor #\n");
716 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS);
717 ok(error==0, "SetThreadIdealProcessor returned an incorrect value\n");
723 static VOID test_GetThreadExitCode(void)
725 DWORD exitCode, threadid;
729 ret = GetExitCodeThread((HANDLE)0x2bad2bad,&exitCode);
730 ok(ret==0, "GetExitCodeThread returned non zero value: %d\n", ret);
731 GLE = GetLastError();
732 ok(GLE==ERROR_INVALID_HANDLE, "GetLastError returned %d (expected 6)\n", GLE);
734 thread = CreateThread(NULL,0,threadFunc2,NULL,0,&threadid);
735 ret = WaitForSingleObject(thread,100);
736 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
737 ret = GetExitCodeThread(thread,&exitCode);
738 ok(ret==exitCode || ret==1,
739 "GetExitCodeThread returned %d (expected 1 or %d)\n", ret, exitCode);
740 ok(exitCode==99, "threadFunc2 exited with code %d (expected 99)\n", exitCode);
741 ok(CloseHandle(thread)!=0,"Error closing thread handle\n");
746 static int test_value = 0;
749 static void WINAPI set_test_val( int val )
754 static DWORD WINAPI threadFunc6(LPVOID p)
758 test_value *= (int)p;
762 static void test_SetThreadContext(void)
770 SetLastError(0xdeadbeef);
771 event = CreateEvent( NULL, TRUE, FALSE, NULL );
772 thread = CreateThread( NULL, 0, threadFunc6, (void *)2, 0, &threadid );
773 ok( thread != NULL, "CreateThread failed : (%d)\n", GetLastError() );
776 trace("Thread creation failed, skipping rest of test\n");
779 WaitForSingleObject( event, INFINITE );
780 SuspendThread( thread );
781 CloseHandle( event );
783 ctx.ContextFlags = CONTEXT_FULL;
784 SetLastError(0xdeadbeef);
785 ok( GetThreadContext( thread, &ctx ), "GetThreadContext failed : (%d)\n", GetLastError() );
787 /* simulate a call to set_test_val(10) */
788 stack = (int *)ctx.Esp;
791 ctx.Esp -= 2 * sizeof(int *);
792 ctx.Eip = (DWORD)set_test_val;
793 SetLastError(0xdeadbeef);
794 ok( SetThreadContext( thread, &ctx ), "SetThreadContext failed : (%d)\n", GetLastError() );
796 SetLastError(0xdeadbeef);
797 prevcount = ResumeThread( thread );
798 ok ( prevcount == 1, "Previous suspend count (%d) instead of 1, last error : (%d)\n",
799 prevcount, GetLastError() );
801 WaitForSingleObject( thread, INFINITE );
802 ok( test_value == 20, "test_value %d instead of 20\n", test_value );
805 #endif /* __i386__ */
807 static HANDLE finish_event;
808 static LONG times_executed;
810 static DWORD CALLBACK work_function(void *p)
812 LONG executed = InterlockedIncrement(×_executed);
815 SetEvent(finish_event);
819 static void test_QueueUserWorkItem(void)
825 /* QueueUserWorkItem not present on win9x */
826 if (!pQueueUserWorkItem) return;
828 finish_event = CreateEvent(NULL, TRUE, FALSE, NULL);
830 before = GetTickCount();
832 for (i = 0; i < 100; i++)
834 BOOL ret = pQueueUserWorkItem(work_function, (void *)i, WT_EXECUTEDEFAULT);
835 ok(ret, "QueueUserWorkItem failed with error %d\n", GetLastError());
838 wait_result = WaitForSingleObject(finish_event, 10000);
840 after = GetTickCount();
841 trace("100 QueueUserWorkItem calls took %dms\n", after - before);
842 ok(wait_result == WAIT_OBJECT_0, "wait failed with error 0x%x\n", wait_result);
844 ok(times_executed == 100, "didn't execute all of the work items\n");
852 argc = winetest_get_mainargs( &argv );
853 /* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
854 so that the compile passes
856 lib=GetModuleHandleA("kernel32.dll");
857 ok(lib!=NULL,"Couldn't get a handle for kernel32.dll\n");
858 pGetThreadPriorityBoost=(GetThreadPriorityBoost_t)GetProcAddress(lib,"GetThreadPriorityBoost");
859 pOpenThread=(OpenThread_t)GetProcAddress(lib,"OpenThread");
860 pQueueUserWorkItem=(QueueUserWorkItem_t)GetProcAddress(lib,"QueueUserWorkItem");
861 pSetThreadIdealProcessor=(SetThreadIdealProcessor_t)GetProcAddress(lib,"SetThreadIdealProcessor");
862 pSetThreadPriorityBoost=(SetThreadPriorityBoost_t)GetProcAddress(lib,"SetThreadPriorityBoost");
866 if (!strcmp(argv[2], "sleep"))
868 HANDLE hAddrEvents[2];
869 create_function_addr_events(hAddrEvents);
870 SetEvent(hAddrEvents[0]);
871 SetEvent(hAddrEvents[1]);
872 Sleep(5000); /* spawned process runs for at most 5 seconds */
878 hThread = CreateThread(NULL, 0, threadFunc2, NULL, 0, NULL);
879 ok(hThread != NULL, "CreateThread failed, error %u\n",
881 ok(WaitForSingleObject(hThread, 200) == WAIT_OBJECT_0,
882 "Thread did not exit in time\n");
883 if (hThread == NULL) break;
884 CloseHandle(hThread);
889 test_CreateRemoteThread();
890 test_CreateThread_basic();
891 test_CreateThread_suspended();
892 test_SuspendThread();
893 test_TerminateThread();
894 test_CreateThread_stack();
895 test_thread_priority();
896 test_GetThreadTimes();
897 test_thread_processor();
898 test_GetThreadExitCode();
900 test_SetThreadContext();
902 test_QueueUserWorkItem();