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 /* check CreateRemoteThread */
207 static VOID test_CreateRemoteThread(void)
209 HANDLE hProcess, hThread, hEvent, hRemoteEvent;
210 DWORD tid, ret, exitcode;
212 hProcess = create_target_process("sleep");
213 ok(hProcess != NULL, "Can't start process\n");
215 hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
216 ok(hEvent != NULL, "Can't create event, err=%u\n", GetLastError());
217 ret = DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &hRemoteEvent,
218 0, FALSE, DUPLICATE_SAME_ACCESS);
219 ok(ret != 0, "DuplicateHandle failed, err=%u\n", GetLastError());
221 /* create suspended remote thread with entry point SetEvent() */
222 hThread = CreateRemoteThread(hProcess, NULL, 0, threadFunc_SetEvent,
223 hRemoteEvent, CREATE_SUSPENDED, &tid);
224 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
225 ok(tid != 0, "null tid\n");
226 ret = SuspendThread(hThread);
227 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
228 ret = ResumeThread(hThread);
229 ok(ret == 2, "ret=%u, err=%u\n", ret, GetLastError());
231 /* thread still suspended, so wait times out */
232 ret = WaitForSingleObject(hEvent, 100);
233 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
235 ret = ResumeThread(hThread);
236 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
238 /* wait that doesn't time out */
239 ret = WaitForSingleObject(hEvent, 100);
240 ok(ret == WAIT_OBJECT_0, "object not signaled, ret=%u\n", ret);
242 /* wait for thread end */
243 ret = WaitForSingleObject(hThread, 100);
244 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
245 CloseHandle(hThread);
247 /* create and wait for remote thread with entry point CloseHandle() */
248 hThread = CreateRemoteThread(hProcess, NULL, 0,
249 threadFunc_CloseHandle,
250 hRemoteEvent, 0, &tid);
251 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
252 ret = WaitForSingleObject(hThread, 100);
253 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
254 CloseHandle(hThread);
256 /* create remote thread with entry point SetEvent() */
257 hThread = CreateRemoteThread(hProcess, NULL, 0,
259 hRemoteEvent, 0, &tid);
260 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
262 /* closed handle, so wait times out */
263 ret = WaitForSingleObject(hEvent, 100);
264 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
266 /* check that remote SetEvent() failed */
267 ret = GetExitCodeThread(hThread, &exitcode);
268 ok(ret != 0, "GetExitCodeThread failed, err=%u\n", GetLastError());
269 if (ret) ok(exitcode == 0, "SetEvent succeeded, expected to fail\n");
270 CloseHandle(hThread);
272 TerminateProcess(hProcess, 0);
274 CloseHandle(hProcess);
277 /* Check basic funcationality of CreateThread and Tls* functions */
278 static VOID test_CreateThread_basic(void)
280 HANDLE thread[NUM_THREADS],event[NUM_THREADS];
281 DWORD threadid[NUM_THREADS],curthreadId;
282 DWORD threadmem[NUM_THREADS];
284 t1Struct tstruct[NUM_THREADS];
289 /* lstrlenA contains an exception handler so this makes sure exceptions work in the main thread */
290 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
292 /* Retrieve current Thread ID for later comparisons */
293 curthreadId=GetCurrentThreadId();
294 /* Allocate some local storage */
295 ok((tlsIndex=TlsAlloc())!=TLS_OUT_OF_INDEXES,"TlsAlloc failed\n");
296 /* Create events for thread synchronization */
297 for(i=0;i<NUM_THREADS;i++) {
299 /* Note that it doesn't matter what type of event we chose here. This
300 test isn't trying to thoroughly test events
302 event[i]=CreateEventA(NULL,TRUE,FALSE,NULL);
303 tstruct[i].threadnum=i;
304 tstruct[i].threadmem=threadmem;
305 tstruct[i].event=event;
308 /* Test that passing arguments to threads works okay */
309 for(i=0;i<NUM_THREADS;i++) {
310 thread[i] = CreateThread(NULL,0,threadFunc1,
311 &tstruct[i],0,&threadid[i]);
312 ok(thread[i]!=NULL,"Create Thread failed\n");
314 /* Test that the threads actually complete */
315 for(i=0;i<NUM_THREADS;i++) {
316 error=WaitForSingleObject(thread[i],5000);
317 ok(error==WAIT_OBJECT_0, "Thread did not complete within timelimit\n");
318 if(error!=WAIT_OBJECT_0) {
319 TerminateThread(thread[i],i+NUM_THREADS);
321 ok(GetExitCodeThread(thread[i],&exitCode),"Could not retrieve ext code\n");
322 ok(exitCode==i+NUM_THREADS,"Thread returned an incorrect exit code\n");
324 /* Test that each thread executed in its parent's address space
325 (it was able to change threadmem and pass that change back to its parent)
326 and that each thread id was independent). Note that we prove that the
327 threads actually execute concurrently by having them block on each other
330 for(i=0;i<NUM_THREADS;i++) {
332 for(j=i+1;j<NUM_THREADS;j++) {
333 if (threadmem[i]==threadmem[j]) {
337 ok(!error && threadmem[i]==threadid[i] && threadmem[i]!=curthreadId,
338 "Thread did not execute successfully\n");
339 ok(CloseHandle(thread[i])!=0,"CloseHandle failed\n");
341 ok(TlsFree(tlsIndex)!=0,"TlsFree failed\n");
343 /* Test how passing NULL as a pointer to threadid works */
344 SetLastError(0xFACEaBAD);
345 thread[0] = CreateThread(NULL,0,threadFunc2,NULL,0,NULL);
346 GLE = GetLastError();
347 if (thread[0]) { /* NT */
348 ok(GLE==0xFACEaBAD, "CreateThread set last error to %d, expected 4207848365\n", GLE);
349 ret = WaitForSingleObject(thread[0],100);
350 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
351 ret = GetExitCodeThread(thread[0],&exitCode);
352 ok(ret!=0, "GetExitCodeThread returned %d (expected nonzero)\n", ret);
353 ok(exitCode==99, "threadFunc2 exited with code: %d (expected 99)\n", exitCode);
354 ok(CloseHandle(thread[0])!=0,"Error closing thread handle\n");
357 ok(GLE==ERROR_INVALID_PARAMETER, "CreateThread set last error to %d, expected 87\n", GLE);
361 /* Check that using the CREATE_SUSPENDED flag works */
362 static VOID test_CreateThread_suspended(void)
368 thread = CreateThread(NULL,0,threadFunc2,NULL,
369 CREATE_SUSPENDED,&threadId);
370 ok(thread!=NULL,"Create Thread failed\n");
371 /* Check that the thread is suspended */
372 ok(SuspendThread(thread)==1,"Thread did not start suspended\n");
373 ok(ResumeThread(thread)==2,"Resume thread returned an invalid value\n");
374 /* Check that resume thread didn't actually start the thread. I can't think
375 of a better way of checking this than just waiting. I am not sure if this
376 will work on slow computers.
378 ok(WaitForSingleObject(thread,1000)==WAIT_TIMEOUT,
379 "ResumeThread should not have actually started the thread\n");
380 /* Now actually resume the thread and make sure that it actually completes*/
381 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
382 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
383 "Thread did not resume\n");
384 if(error!=WAIT_OBJECT_0) {
385 TerminateThread(thread,1);
387 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
390 /* Check that SuspendThread and ResumeThread work */
391 static VOID test_SuspendThread(void)
393 HANDLE thread,access_thread;
394 DWORD threadId,exitCode,error;
397 thread = CreateThread(NULL,0,threadFunc3,NULL,
399 ok(thread!=NULL,"Create Thread failed\n");
400 /* Check that the thread is suspended */
401 /* Note that this is a polling method, and there is a race between
402 SuspendThread being called (in the child, and the loop below timing out,
403 so the test could fail on a heavily loaded or slow computer.
406 for(i=0;error==0 && i<100;i++) {
407 error=SuspendThread(thread);
408 ResumeThread(thread);
414 ok(error==1,"SuspendThread did not work\n");
415 /* check that access restrictions are obeyed */
417 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_SUSPEND_RESUME),
419 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
420 if (access_thread!=NULL) {
421 obey_ar(SuspendThread(access_thread)==~0U);
422 obey_ar(ResumeThread(access_thread)==~0U);
423 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
426 /* Double check that the thread really is suspended */
427 ok((error=GetExitCodeThread(thread,&exitCode))!=0 && exitCode==STILL_ACTIVE,
428 "Thread did not really suspend\n");
429 /* Resume the thread, and make sure it actually completes */
430 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
431 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
432 "Thread did not resume\n");
433 if(error!=WAIT_OBJECT_0) {
434 TerminateThread(thread,1);
436 /* Trying to suspend a terminated thread should fail */
437 error=SuspendThread(thread);
438 ok(error==~0U, "wrong return code: %d\n", error);
439 ok(GetLastError()==ERROR_ACCESS_DENIED || GetLastError()==ERROR_NO_MORE_ITEMS, "unexpected error code: %d\n", GetLastError());
441 ok(CloseHandle(thread)!=0,"CloseHandle Failed\n");
444 /* Check that TerminateThread works properly
446 static VOID test_TerminateThread(void)
448 HANDLE thread,access_thread,event;
449 DWORD threadId,exitCode;
450 event=CreateEventA(NULL,TRUE,FALSE,NULL);
451 thread = CreateThread(NULL,0,threadFunc4,
452 (LPVOID)event, 0,&threadId);
453 ok(thread!=NULL,"Create Thread failed\n");
454 /* TerminateThread has a race condition in Wine. If the thread is terminated
455 before it starts, it leaves a process behind. Therefore, we wait for the
456 thread to signal that it has started. There is no easy way to force the
457 race to occur, so we don't try to find it.
459 ok(WaitForSingleObject(event,5000)==WAIT_OBJECT_0,
460 "TerminateThread didn't work\n");
461 /* check that access restrictions are obeyed */
463 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_TERMINATE),
465 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
466 if (access_thread!=NULL) {
467 obey_ar(TerminateThread(access_thread,99)==0);
468 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
471 /* terminate a job and make sure it terminates */
472 ok(TerminateThread(thread,99)!=0,"TerminateThread failed\n");
473 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
474 "TerminateThread didn't work\n");
475 ok(GetExitCodeThread(thread,&exitCode)!=STILL_ACTIVE,
476 "TerminateThread should not leave the thread 'STILL_ACTIVE'\n");
477 ok(exitCode==99, "TerminateThread returned invalid exit code\n");
478 ok(CloseHandle(thread)!=0,"Error Closing thread handle\n");
481 /* Check if CreateThread obeys the specified stack size. This code does
482 not work properly, and is currently disabled
484 static VOID test_CreateThread_stack(void)
487 /* The only way I know of to test the stack size is to use alloca
488 and __try/__except. However, this is probably not portable,
489 and I couldn't get it to work under Wine anyhow. However, here
490 is the code which should allow for testing that CreateThread
491 respects the stack-size limit
494 DWORD threadId,exitCode;
497 sysInfo.dwPageSize=0;
498 GetSystemInfo(&sysInfo);
499 ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
500 thread = CreateThread(NULL,sysInfo.dwPageSize,
501 threadFunc5,&exitCode,
503 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
504 "TerminateThread didn't work\n");
505 ok(exitCode==1,"CreateThread did not obey stack-size-limit\n");
506 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
510 /* Check whether setting/retrieving thread priorities works */
511 static VOID test_thread_priority(void)
513 HANDLE curthread,access_thread;
514 DWORD curthreadId,exitCode;
515 int min_priority=-2,max_priority=2;
519 curthread=GetCurrentThread();
520 curthreadId=GetCurrentThreadId();
521 /* Check thread priority */
522 /* NOTE: on Win2k/XP priority can be from -7 to 6. All other platforms it
523 is -2 to 2. However, even on a real Win2k system, using thread
524 priorities beyond the -2 to 2 range does not work. If you want to try
525 anyway, enable USE_EXTENDED_PRIORITIES
527 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_NORMAL,
528 "GetThreadPriority Failed\n");
531 /* check that access control is obeyed */
532 access_thread=pOpenThread(THREAD_ALL_ACCESS &
533 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
535 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
536 if (access_thread!=NULL) {
537 obey_ar(SetThreadPriority(access_thread,1)==0);
538 obey_ar(GetThreadPriority(access_thread)==THREAD_PRIORITY_ERROR_RETURN);
539 obey_ar(GetExitCodeThread(access_thread,&exitCode)==0);
540 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
543 #if USE_EXTENDED_PRIORITIES
544 min_priority=-7; max_priority=6;
546 for(i=min_priority;i<=max_priority;i++) {
547 ok(SetThreadPriority(curthread,i)!=0,
548 "SetThreadPriority Failed for priority: %d\n",i);
549 ok(GetThreadPriority(curthread)==i,
550 "GetThreadPriority Failed for priority: %d\n",i);
552 ok(SetThreadPriority(curthread,THREAD_PRIORITY_TIME_CRITICAL)!=0,
553 "SetThreadPriority Failed\n");
554 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_TIME_CRITICAL,
555 "GetThreadPriority Failed\n");
556 ok(SetThreadPriority(curthread,THREAD_PRIORITY_IDLE)!=0,
557 "SetThreadPriority Failed\n");
558 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_IDLE,
559 "GetThreadPriority Failed\n");
560 ok(SetThreadPriority(curthread,0)!=0,"SetThreadPriority Failed\n");
562 /* Check thread priority boost */
563 if (!pGetThreadPriorityBoost || !pSetThreadPriorityBoost)
566 SetLastError(0xdeadbeef);
567 rc=pGetThreadPriorityBoost(curthread,&disabled);
568 if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
572 ok(rc!=0,"error=%d\n",GetLastError());
575 /* check that access control is obeyed */
576 access_thread=pOpenThread(THREAD_ALL_ACCESS &
577 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
579 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
580 if (access_thread!=NULL) {
581 obey_ar(pSetThreadPriorityBoost(access_thread,1)==0);
582 obey_ar(pGetThreadPriorityBoost(access_thread,&disabled)==0);
583 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
588 rc = pSetThreadPriorityBoost(curthread,1);
589 ok( rc != 0, "error=%d\n",GetLastError());
590 rc=pGetThreadPriorityBoost(curthread,&disabled);
591 ok(rc!=0 && disabled==1,
592 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
594 rc = pSetThreadPriorityBoost(curthread,0);
595 ok( rc != 0, "error=%d\n",GetLastError());
596 rc=pGetThreadPriorityBoost(curthread,&disabled);
597 ok(rc!=0 && disabled==0,
598 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
602 /* check the GetThreadTimes function */
603 static VOID test_GetThreadTimes(void)
605 HANDLE thread,access_thread=NULL;
606 FILETIME creationTime,exitTime,kernelTime,userTime;
610 thread = CreateThread(NULL,0,threadFunc2,NULL,
611 CREATE_SUSPENDED,&threadId);
613 ok(thread!=NULL,"Create Thread failed\n");
614 /* check that access control is obeyed */
616 access_thread=pOpenThread(THREAD_ALL_ACCESS &
617 (~THREAD_QUERY_INFORMATION), 0,threadId);
618 ok(access_thread!=NULL,
619 "OpenThread returned an invalid handle\n");
621 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
622 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
623 "ResumeThread didn't work\n");
624 creationTime.dwLowDateTime=99; creationTime.dwHighDateTime=99;
625 exitTime.dwLowDateTime=99; exitTime.dwHighDateTime=99;
626 kernelTime.dwLowDateTime=99; kernelTime.dwHighDateTime=99;
627 userTime.dwLowDateTime=99; userTime.dwHighDateTime=99;
628 /* GetThreadTimes should set all of the parameters passed to it */
629 error=GetThreadTimes(thread,&creationTime,&exitTime,
630 &kernelTime,&userTime);
631 if (error!=0 || GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
632 ok(error!=0,"GetThreadTimes failed\n");
633 ok(creationTime.dwLowDateTime!=99 || creationTime.dwHighDateTime!=99,
634 "creationTime was invalid\n");
635 ok(exitTime.dwLowDateTime!=99 || exitTime.dwHighDateTime!=99,
636 "exitTime was invalid\n");
637 ok(kernelTime.dwLowDateTime!=99 || kernelTime.dwHighDateTime!=99,
638 "kernelTimewas invalid\n");
639 ok(userTime.dwLowDateTime!=99 || userTime.dwHighDateTime!=99,
640 "userTime was invalid\n");
641 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
642 if(access_thread!=NULL)
644 error=GetThreadTimes(access_thread,&creationTime,&exitTime,
645 &kernelTime,&userTime);
649 if(access_thread!=NULL) {
650 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
654 /* Check the processor affinity functions */
655 /* NOTE: These functions should also be checked that they obey access control
657 static VOID test_thread_processor(void)
659 HANDLE curthread,curproc;
660 DWORD_PTR processMask,systemMask;
664 sysInfo.dwNumberOfProcessors=0;
665 GetSystemInfo(&sysInfo);
666 ok(sysInfo.dwNumberOfProcessors>0,
667 "GetSystemInfo failed to return a valid # of processors\n");
668 /* Use the current Thread/process for all tests */
669 curthread=GetCurrentThread();
670 ok(curthread!=NULL,"GetCurrentThread failed\n");
671 curproc=GetCurrentProcess();
672 ok(curproc!=NULL,"GetCurrentProcess failed\n");
673 /* Check the Affinity Mask functions */
674 ok(GetProcessAffinityMask(curproc,&processMask,&systemMask)!=0,
675 "GetProcessAffinityMask failed\n");
676 ok(SetThreadAffinityMask(curthread,processMask)==processMask,
677 "SetThreadAffinityMask failed\n");
678 ok(SetThreadAffinityMask(curthread,processMask+1)==0,
679 "SetThreadAffinityMask passed for an illegal processor\n");
680 /* NOTE: This only works on WinNT/2000/XP) */
681 if (pSetThreadIdealProcessor) {
684 error=pSetThreadIdealProcessor(curthread,0);
685 if (GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
686 ok(error!=-1, "SetThreadIdealProcessor failed\n");
689 if (GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
690 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
692 "SetThreadIdealProcessor succeeded with an illegal processor #\n");
694 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS);
695 ok(error==0, "SetThreadIdealProcessor returned an incorrect value\n");
701 static VOID test_GetThreadExitCode(void)
703 DWORD exitCode, threadid;
707 ret = GetExitCodeThread((HANDLE)0x2bad2bad,&exitCode);
708 ok(ret==0, "GetExitCodeThread returned non zero value: %d\n", ret);
709 GLE = GetLastError();
710 ok(GLE==ERROR_INVALID_HANDLE, "GetLastError returned %d (expected 6)\n", GLE);
712 thread = CreateThread(NULL,0,threadFunc2,NULL,0,&threadid);
713 ret = WaitForSingleObject(thread,100);
714 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
715 ret = GetExitCodeThread(thread,&exitCode);
716 ok(ret==exitCode || ret==1,
717 "GetExitCodeThread returned %d (expected 1 or %d)\n", ret, exitCode);
718 ok(exitCode==99, "threadFunc2 exited with code %d (expected 99)\n", exitCode);
719 ok(CloseHandle(thread)!=0,"Error closing thread handle\n");
724 static int test_value = 0;
727 static void WINAPI set_test_val( int val )
732 static DWORD WINAPI threadFunc6(LPVOID p)
736 test_value *= (int)p;
740 static void test_SetThreadContext(void)
748 SetLastError(0xdeadbeef);
749 event = CreateEvent( NULL, TRUE, FALSE, NULL );
750 thread = CreateThread( NULL, 0, threadFunc6, (void *)2, 0, &threadid );
751 ok( thread != NULL, "CreateThread failed : (%d)\n", GetLastError() );
754 trace("Thread creation failed, skipping rest of test\n");
757 WaitForSingleObject( event, INFINITE );
758 SuspendThread( thread );
759 CloseHandle( event );
761 ctx.ContextFlags = CONTEXT_FULL;
762 SetLastError(0xdeadbeef);
763 ok( GetThreadContext( thread, &ctx ), "GetThreadContext failed : (%d)\n", GetLastError() );
765 /* simulate a call to set_test_val(10) */
766 stack = (int *)ctx.Esp;
769 ctx.Esp -= 2 * sizeof(int *);
770 ctx.Eip = (DWORD)set_test_val;
771 SetLastError(0xdeadbeef);
772 ok( SetThreadContext( thread, &ctx ), "SetThreadContext failed : (%d)\n", GetLastError() );
774 SetLastError(0xdeadbeef);
775 prevcount = ResumeThread( thread );
776 ok ( prevcount == 1, "Previous suspend count (%d) instead of 1, last error : (%d)\n",
777 prevcount, GetLastError() );
779 WaitForSingleObject( thread, INFINITE );
780 ok( test_value == 20, "test_value %d instead of 20\n", test_value );
783 #endif /* __i386__ */
785 static HANDLE finish_event;
786 static LONG times_executed;
788 static DWORD CALLBACK work_function(void *p)
790 LONG executed = InterlockedIncrement(×_executed);
793 SetEvent(finish_event);
797 static void test_QueueUserWorkItem(void)
803 /* QueueUserWorkItem not present on win9x */
804 if (!pQueueUserWorkItem) return;
806 finish_event = CreateEvent(NULL, TRUE, FALSE, NULL);
808 before = GetTickCount();
810 for (i = 0; i < 100; i++)
812 BOOL ret = pQueueUserWorkItem(work_function, (void *)i, WT_EXECUTEDEFAULT);
813 ok(ret, "QueueUserWorkItem failed with error %d\n", GetLastError());
816 wait_result = WaitForSingleObject(finish_event, 10000);
818 after = GetTickCount();
819 trace("100 QueueUserWorkItem calls took %dms\n", after - before);
820 ok(wait_result == WAIT_OBJECT_0, "wait failed with error 0x%x\n", wait_result);
822 ok(times_executed == 100, "didn't execute all of the work items\n");
830 argc = winetest_get_mainargs( &argv );
831 /* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
832 so that the compile passes
834 lib=GetModuleHandleA("kernel32.dll");
835 ok(lib!=NULL,"Couldn't get a handle for kernel32.dll\n");
836 pGetThreadPriorityBoost=(GetThreadPriorityBoost_t)GetProcAddress(lib,"GetThreadPriorityBoost");
837 pOpenThread=(OpenThread_t)GetProcAddress(lib,"OpenThread");
838 pQueueUserWorkItem=(QueueUserWorkItem_t)GetProcAddress(lib,"QueueUserWorkItem");
839 pSetThreadIdealProcessor=(SetThreadIdealProcessor_t)GetProcAddress(lib,"SetThreadIdealProcessor");
840 pSetThreadPriorityBoost=(SetThreadPriorityBoost_t)GetProcAddress(lib,"SetThreadPriorityBoost");
844 if (!strcmp(argv[2], "sleep"))
846 Sleep(5000); /* spawned process runs for at most 5 seconds */
852 hThread = CreateThread(NULL, 0, threadFunc2, NULL, 0, NULL);
853 ok(hThread != NULL, "CreateThread failed, error %u\n",
855 ok(WaitForSingleObject(hThread, 200) == WAIT_OBJECT_0,
856 "Thread did not exit in time\n");
857 if (hThread == NULL) break;
858 CloseHandle(hThread);
863 test_CreateRemoteThread();
864 test_CreateThread_basic();
865 test_CreateThread_suspended();
866 test_SuspendThread();
867 test_TerminateThread();
868 test_CreateThread_stack();
869 test_thread_priority();
870 test_GetThreadTimes();
871 test_thread_processor();
872 test_GetThreadExitCode();
874 test_SetThreadContext();
876 test_QueueUserWorkItem();