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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 /* Define _WIN32_WINNT to get SetThreadIdealProcessor on Windows */
22 #define _WIN32_WINNT 0x0500
26 #include "wine/test.h"
32 /* Specify the number of simultaneous threads to test */
34 /* Specify whether to test the extended priorities for Win2k/XP */
35 #define USE_EXTENDED_PRIORITIES 0
36 /* Specify whether to test the stack allocation in CreateThread */
39 /* Set CHECK_STACK to 1 if you want to try to test the stack-limit from
40 CreateThread. So far I have been unable to make this work, and
41 I am in doubt as to how portable it is. Also, according to MSDN,
42 you shouldn't mix C-run-time-libraries (i.e. alloca) with CreateThread.
43 Anyhow, the check is currently commented out
48 # define __EXCEPT __except
51 # include "wine/exception.h"
55 typedef BOOL (WINAPI *GetThreadPriorityBoost_t)(HANDLE,PBOOL);
56 static GetThreadPriorityBoost_t pGetThreadPriorityBoost=NULL;
58 typedef HANDLE (WINAPI *OpenThread_t)(DWORD,BOOL,DWORD);
59 static OpenThread_t pOpenThread=NULL;
61 typedef DWORD (WINAPI *SetThreadIdealProcessor_t)(HANDLE,DWORD);
62 static SetThreadIdealProcessor_t pSetThreadIdealProcessor=NULL;
64 typedef BOOL (WINAPI *SetThreadPriorityBoost_t)(HANDLE,BOOL);
65 static SetThreadPriorityBoost_t pSetThreadPriorityBoost=NULL;
67 /* Functions not tested yet:
73 In addition there are no checks that the inheritance works properly in
85 /* WinME supports OpenThread but doesn't know about access restrictions so
86 we require them to be either completely ignored or always obeyed.
88 INT obeying_ars = 0; /* -1 == no, 0 == dunno yet, 1 == yes */
92 ? (obeying_ars = +1) \
93 : ((obeying_ars = -1), \
94 trace("not restricted, assuming consistent behaviour\n"))) \
96 ? ok(!(x), "access restrictions obeyed\n") \
97 : ok( (x), "access restrictions not obeyed\n"))
99 /* Basic test that simultaneous threads can access shared memory,
100 that the thread local storage routines work correctly, and that
101 threads actually run concurrently
103 static DWORD WINAPI threadFunc1(LPVOID p)
105 t1Struct *tstruct = (t1Struct *)p;
107 /* write our thread # into shared memory */
108 tstruct->threadmem[tstruct->threadnum]=GetCurrentThreadId();
109 ok(TlsSetValue(tlsIndex,(LPVOID)(tstruct->threadnum+1))!=0,
110 "TlsSetValue failed\n");
111 /* The threads synchronize before terminating. This is done by
112 Signaling an event, and waiting for all events to occur
114 SetEvent(tstruct->event[tstruct->threadnum]);
115 WaitForMultipleObjects(NUM_THREADS,tstruct->event,TRUE,INFINITE);
116 /* Double check that all threads really did run by validating that
117 they have all written to the shared memory. There should be no race
118 here, since all threads were synchronized after the write.*/
119 for(i=0;i<NUM_THREADS;i++) {
120 while(tstruct->threadmem[i]==0) ;
123 /* lstrlenA contains an exception handler so this makes sure exceptions work in threads */
124 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
126 /* Check that noone changed our tls memory */
127 ok((int)TlsGetValue(tlsIndex)-1==tstruct->threadnum,
128 "TlsGetValue failed\n");
129 return NUM_THREADS+tstruct->threadnum;
132 static DWORD WINAPI threadFunc2(LPVOID p)
137 static DWORD WINAPI threadFunc3(LPVOID p)
140 thread=GetCurrentThread();
141 SuspendThread(thread);
145 static DWORD WINAPI threadFunc4(LPVOID p)
147 HANDLE event = (HANDLE)p;
156 static DWORD WINAPI threadFunc5(LPVOID p)
158 DWORD *exitCode = (DWORD *)p;
160 sysInfo.dwPageSize=0;
161 GetSystemInfo(&sysInfo);
165 alloca(2*sysInfo.dwPageSize);
175 /* Check basic funcationality of CreateThread and Tls* functions */
176 static VOID test_CreateThread_basic(void)
178 HANDLE thread[NUM_THREADS],event[NUM_THREADS];
179 DWORD threadid[NUM_THREADS],curthreadId;
180 DWORD threadmem[NUM_THREADS];
182 t1Struct tstruct[NUM_THREADS];
187 /* lstrlenA contains an exception handler so this makes sure exceptions work in the main thread */
188 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
190 /* Retrieve current Thread ID for later comparisons */
191 curthreadId=GetCurrentThreadId();
192 /* Allocate some local storage */
193 ok((tlsIndex=TlsAlloc())!=TLS_OUT_OF_INDEXES,"TlsAlloc failed\n");
194 /* Create events for thread synchronization */
195 for(i=0;i<NUM_THREADS;i++) {
197 /* Note that it doesn't matter what type of event we chose here. This
198 test isn't trying to thoroughly test events
200 event[i]=CreateEventA(NULL,TRUE,FALSE,NULL);
201 tstruct[i].threadnum=i;
202 tstruct[i].threadmem=threadmem;
203 tstruct[i].event=event;
206 /* Test that passing arguments to threads works okay */
207 for(i=0;i<NUM_THREADS;i++) {
208 thread[i] = CreateThread(NULL,0,threadFunc1,
209 &tstruct[i],0,&threadid[i]);
210 ok(thread[i]!=NULL,"Create Thread failed\n");
212 /* Test that the threads actually complete */
213 for(i=0;i<NUM_THREADS;i++) {
214 error=WaitForSingleObject(thread[i],5000);
215 ok(error==WAIT_OBJECT_0, "Thread did not complete within timelimit\n");
216 if(error!=WAIT_OBJECT_0) {
217 TerminateThread(thread[i],i+NUM_THREADS);
219 ok(GetExitCodeThread(thread[i],&exitCode),"Could not retrieve ext code\n");
220 ok(exitCode==i+NUM_THREADS,"Thread returned an incorrect exit code\n");
222 /* Test that each thread executed in its parent's address space
223 (it was able to change threadmem and pass that change back to its parent)
224 and that each thread id was independant). Note that we prove that the
225 threads actually execute concurrently by having them block on each other
228 for(i=0;i<NUM_THREADS;i++) {
230 for(j=i+1;j<NUM_THREADS;j++) {
231 if (threadmem[i]==threadmem[j]) {
235 ok(!error && threadmem[i]==threadid[i] && threadmem[i]!=curthreadId,
236 "Thread did not execute successfully\n");
237 ok(CloseHandle(thread[i])!=0,"CloseHandle failed\n");
239 ok(TlsFree(tlsIndex)!=0,"TlsFree failed\n");
241 /* Test how passing NULL as a pointer to threadid works */
242 SetLastError(0xFACEaBAD);
243 thread[0] = CreateThread(NULL,0,threadFunc2,NULL,0,NULL);
244 GLE = GetLastError();
245 if (thread[0]) { /* NT */
246 ok(GLE==0xFACEaBAD, "CreateThread set last error to %ld, expected 4207848365\n", GLE);
247 ret = WaitForSingleObject(thread[0],100);
248 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
249 ret = GetExitCodeThread(thread[0],&exitCode);
250 ok(ret!=0, "GetExitCodeThread returned %ld (expected nonzero)\n", ret);
251 ok(exitCode==99, "threadFunc2 exited with code: %ld (expected 99)\n", exitCode);
252 ok(CloseHandle(thread[0])!=0,"Error closing thread handle\n");
255 ok(GLE==ERROR_INVALID_PARAMETER, "CreateThread set last error to %ld, expected 87\n", GLE);
259 /* Check that using the CREATE_SUSPENDED flag works */
260 static VOID test_CreateThread_suspended(void)
266 thread = CreateThread(NULL,0,threadFunc2,NULL,
267 CREATE_SUSPENDED,&threadId);
268 ok(thread!=NULL,"Create Thread failed\n");
269 /* Check that the thread is suspended */
270 ok(SuspendThread(thread)==1,"Thread did not start suspended\n");
271 ok(ResumeThread(thread)==2,"Resume thread returned an invalid value\n");
272 /* Check that resume thread didn't actually start the thread. I can't think
273 of a better way of checking this than just waiting. I am not sure if this
274 will work on slow computers.
276 ok(WaitForSingleObject(thread,1000)==WAIT_TIMEOUT,
277 "ResumeThread should not have actually started the thread\n");
278 /* Now actually resume the thread and make sure that it actually completes*/
279 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
280 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
281 "Thread did not resume\n");
282 if(error!=WAIT_OBJECT_0) {
283 TerminateThread(thread,1);
285 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
288 /* Check that SuspendThread and ResumeThread work */
289 static VOID test_SuspendThread(void)
291 HANDLE thread,access_thread;
292 DWORD threadId,exitCode,error;
295 thread = CreateThread(NULL,0,threadFunc3,NULL,
297 ok(thread!=NULL,"Create Thread failed\n");
298 /* Check that the thread is suspended */
299 /* Note that this is a polling method, and there is a race between
300 SuspendThread being called (in the child, and the loop below timing out,
301 so the test could fail on a heavily loaded or slow computer.
304 for(i=0;error==0 && i<100;i++) {
305 error=SuspendThread(thread);
306 ResumeThread(thread);
312 ok(error==1,"SuspendThread did not work\n");
313 /* check that access restrictions are obeyed */
315 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_SUSPEND_RESUME),
317 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
318 if (access_thread!=NULL) {
319 obey_ar(SuspendThread(access_thread)==~0U);
320 obey_ar(ResumeThread(access_thread)==~0U);
321 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
324 /* Double check that the thread really is suspended */
325 ok((error=GetExitCodeThread(thread,&exitCode))!=0 && exitCode==STILL_ACTIVE,
326 "Thread did not really suspend\n");
327 /* Resume the thread, and make sure it actually completes */
328 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
329 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
330 "Thread did not resume\n");
331 if(error!=WAIT_OBJECT_0) {
332 TerminateThread(thread,1);
334 /* Trying to suspend a terminated thread should fail */
335 error=SuspendThread(thread);
336 ok(error==~0U, "wrong return code: %ld\n", error);
337 ok(GetLastError()==ERROR_ACCESS_DENIED || GetLastError()==ERROR_NO_MORE_ITEMS, "unexpected error code: %ld\n", GetLastError());
339 ok(CloseHandle(thread)!=0,"CloseHandle Failed\n");
342 /* Check that TerminateThread works properly
344 static VOID test_TerminateThread(void)
346 HANDLE thread,access_thread,event;
347 DWORD threadId,exitCode;
348 event=CreateEventA(NULL,TRUE,FALSE,NULL);
349 thread = CreateThread(NULL,0,threadFunc4,
350 (LPVOID)event, 0,&threadId);
351 ok(thread!=NULL,"Create Thread failed\n");
352 /* TerminateThread has a race condition in Wine. If the thread is terminated
353 before it starts, it leaves a process behind. Therefore, we wait for the
354 thread to signal that it has started. There is no easy way to force the
355 race to occur, so we don't try to find it.
357 ok(WaitForSingleObject(event,5000)==WAIT_OBJECT_0,
358 "TerminateThread didn't work\n");
359 /* check that access restrictions are obeyed */
361 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_TERMINATE),
363 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
364 if (access_thread!=NULL) {
365 obey_ar(TerminateThread(access_thread,99)==0);
366 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
369 /* terminate a job and make sure it terminates */
370 ok(TerminateThread(thread,99)!=0,"TerminateThread failed\n");
371 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
372 "TerminateThread didn't work\n");
373 ok(GetExitCodeThread(thread,&exitCode)!=STILL_ACTIVE,
374 "TerminateThread should not leave the thread 'STILL_ACTIVE'\n");
375 ok(exitCode==99, "TerminateThread returned invalid exit code\n");
376 ok(CloseHandle(thread)!=0,"Error Closing thread handle\n");
379 /* Check if CreateThread obeys the specified stack size. This code does
380 not work properly, and is currently disabled
382 static VOID test_CreateThread_stack(void)
385 /* The only way I know of to test the stack size is to use alloca
386 and __try/__except. However, this is probably not portable,
387 and I couldn't get it to work under Wine anyhow. However, here
388 is the code which should allow for testing that CreateThread
389 respects the stack-size limit
392 DWORD threadId,exitCode;
395 sysInfo.dwPageSize=0;
396 GetSystemInfo(&sysInfo);
397 ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
398 thread = CreateThread(NULL,sysInfo.dwPageSize,
399 threadFunc5,&exitCode,
401 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
402 "TerminateThread didn't work\n");
403 ok(exitCode==1,"CreateThread did not obey stack-size-limit\n");
404 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
408 /* Check whether setting/retrieving thread priorities works */
409 static VOID test_thread_priority(void)
411 HANDLE curthread,access_thread;
412 DWORD curthreadId,exitCode;
413 int min_priority=-2,max_priority=2;
417 curthread=GetCurrentThread();
418 curthreadId=GetCurrentThreadId();
419 /* Check thread priority */
420 /* NOTE: on Win2k/XP priority can be from -7 to 6. All other platforms it
421 is -2 to 2. However, even on a real Win2k system, using thread
422 priorities beyond the -2 to 2 range does not work. If you want to try
423 anyway, enable USE_EXTENDED_PRIORITIES
425 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_NORMAL,
426 "GetThreadPriority Failed\n");
429 /* check that access control is obeyed */
430 access_thread=pOpenThread(THREAD_ALL_ACCESS &
431 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
433 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
434 if (access_thread!=NULL) {
435 obey_ar(SetThreadPriority(access_thread,1)==0);
436 obey_ar(GetThreadPriority(access_thread)==THREAD_PRIORITY_ERROR_RETURN);
437 obey_ar(GetExitCodeThread(access_thread,&exitCode)==0);
438 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
440 #if USE_EXTENDED_PRIORITIES
441 min_priority=-7; max_priority=6;
444 for(i=min_priority;i<=max_priority;i++) {
445 ok(SetThreadPriority(curthread,i)!=0,
446 "SetThreadPriority Failed for priority: %d\n",i);
447 ok(GetThreadPriority(curthread)==i,
448 "GetThreadPriority Failed for priority: %d\n",i);
450 ok(SetThreadPriority(curthread,THREAD_PRIORITY_TIME_CRITICAL)!=0,
451 "SetThreadPriority Failed\n");
452 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_TIME_CRITICAL,
453 "GetThreadPriority Failed\n");
454 ok(SetThreadPriority(curthread,THREAD_PRIORITY_IDLE)!=0,
455 "SetThreadPriority Failed\n");
456 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_IDLE,
457 "GetThreadPriority Failed\n");
458 ok(SetThreadPriority(curthread,0)!=0,"SetThreadPriority Failed\n");
460 /* Check thread priority boost */
461 if (!pGetThreadPriorityBoost || !pSetThreadPriorityBoost)
464 SetLastError(0xdeadbeef);
465 rc=pGetThreadPriorityBoost(curthread,&disabled);
466 if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
469 /* check that access control is obeyed */
470 access_thread=pOpenThread(THREAD_ALL_ACCESS &
471 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
473 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
474 if (access_thread!=NULL) {
475 obey_ar(pSetThreadPriorityBoost(access_thread,1)==0);
476 obey_ar(pGetThreadPriorityBoost(access_thread,&disabled)==0);
477 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
481 ok(rc!=0,"error=%ld\n",GetLastError());
483 rc = pSetThreadPriorityBoost(curthread,1);
484 ok( rc != 0, "error=%ld\n",GetLastError());
485 rc=pGetThreadPriorityBoost(curthread,&disabled);
486 ok(rc!=0 && disabled==1,
487 "rc=%d error=%ld disabled=%d\n",rc,GetLastError(),disabled);
489 rc = pSetThreadPriorityBoost(curthread,0);
490 ok( rc != 0, "error=%ld\n",GetLastError());
491 rc=pGetThreadPriorityBoost(curthread,&disabled);
492 ok(rc!=0 && disabled==0,
493 "rc=%d error=%ld disabled=%d\n",rc,GetLastError(),disabled);
497 /* check the GetThreadTimes function */
498 static VOID test_GetThreadTimes(void)
500 HANDLE thread,access_thread=NULL;
501 FILETIME creationTime,exitTime,kernelTime,userTime;
505 thread = CreateThread(NULL,0,threadFunc2,NULL,
506 CREATE_SUSPENDED,&threadId);
508 ok(thread!=NULL,"Create Thread failed\n");
509 /* check that access control is obeyed */
511 access_thread=pOpenThread(THREAD_ALL_ACCESS &
512 (~THREAD_QUERY_INFORMATION), 0,threadId);
513 ok(access_thread!=NULL,
514 "OpenThread returned an invalid handle\n");
516 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
517 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
518 "ResumeThread didn't work\n");
519 creationTime.dwLowDateTime=99; creationTime.dwHighDateTime=99;
520 exitTime.dwLowDateTime=99; exitTime.dwHighDateTime=99;
521 kernelTime.dwLowDateTime=99; kernelTime.dwHighDateTime=99;
522 userTime.dwLowDateTime=99; userTime.dwHighDateTime=99;
523 /* GetThreadTimes should set all of the parameters passed to it */
524 error=GetThreadTimes(thread,&creationTime,&exitTime,
525 &kernelTime,&userTime);
526 if (error!=0 || GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
527 ok(error!=0,"GetThreadTimes failed\n");
528 ok(creationTime.dwLowDateTime!=99 || creationTime.dwHighDateTime!=99,
529 "creationTime was invalid\n");
530 ok(exitTime.dwLowDateTime!=99 || exitTime.dwHighDateTime!=99,
531 "exitTime was invalid\n");
532 ok(kernelTime.dwLowDateTime!=99 || kernelTime.dwHighDateTime!=99,
533 "kernelTimewas invalid\n");
534 ok(userTime.dwLowDateTime!=99 || userTime.dwHighDateTime!=99,
535 "userTime was invalid\n");
536 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
537 if(access_thread!=NULL)
539 error=GetThreadTimes(access_thread,&creationTime,&exitTime,
540 &kernelTime,&userTime);
544 if(access_thread!=NULL) {
545 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
549 /* Check the processor affinity functions */
550 /* NOTE: These functions should also be checked that they obey access control
552 static VOID test_thread_processor(void)
554 HANDLE curthread,curproc;
555 DWORD processMask,systemMask;
559 sysInfo.dwNumberOfProcessors=0;
560 GetSystemInfo(&sysInfo);
561 ok(sysInfo.dwNumberOfProcessors>0,
562 "GetSystemInfo failed to return a valid # of processors\n");
563 /* Use the current Thread/process for all tests */
564 curthread=GetCurrentThread();
565 ok(curthread!=NULL,"GetCurrentThread failed\n");
566 curproc=GetCurrentProcess();
567 ok(curproc!=NULL,"GetCurrentProcess failed\n");
568 /* Check the Affinity Mask functions */
569 ok(GetProcessAffinityMask(curproc,&processMask,&systemMask)!=0,
570 "GetProcessAffinityMask failed\n");
571 ok(SetThreadAffinityMask(curthread,processMask)==processMask,
572 "SetThreadAffinityMask failed\n");
573 ok(SetThreadAffinityMask(curthread,processMask+1)==0,
574 "SetThreadAffinityMask passed for an illegal processor\n");
575 /* NOTE: This only works on WinNT/2000/XP) */
576 if (pSetThreadIdealProcessor) {
579 error=pSetThreadIdealProcessor(curthread,0);
580 if (GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
581 ok(error!=-1, "SetThreadIdealProcessor failed\n");
584 if (GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
585 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
587 "SetThreadIdealProcessor succeeded with an illegal processor #\n");
589 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS);
590 ok(error==0, "SetThreadIdealProcessor returned an incorrect value\n");
596 static VOID test_GetThreadExitCode(void)
598 DWORD exitCode, threadid;
602 ret = GetExitCodeThread((HANDLE)0x2bad2bad,&exitCode);
603 ok(ret==0, "GetExitCodeThread returned non zero value: %ld\n", ret);
604 GLE = GetLastError();
605 ok(GLE==ERROR_INVALID_HANDLE, "GetLastError returned %ld (expected 6)\n", GLE);
607 thread = CreateThread(NULL,0,threadFunc2,NULL,0,&threadid);
608 ret = WaitForSingleObject(thread,100);
609 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
610 ret = GetExitCodeThread(thread,&exitCode);
611 ok(ret==exitCode || ret==1,
612 "GetExitCodeThread returned %ld (expected 1 or %ld)\n", ret, exitCode);
613 ok(exitCode==99, "threadFunc2 exited with code %ld (expected 99)\n", exitCode);
614 ok(CloseHandle(thread)!=0,"Error closing thread handle\n");
619 static int test_value = 0;
622 static void WINAPI set_test_val( int val )
627 static DWORD WINAPI threadFunc6(LPVOID p)
631 test_value *= (int)p;
635 static void test_SetThreadContext(void)
643 SetLastError(0xdeadbeef);
644 event = CreateEvent( NULL, TRUE, FALSE, NULL );
645 thread = CreateThread( NULL, 0, threadFunc6, (void *)2, 0, &threadid );
646 ok( thread != NULL, "CreateThread failed : (%ld)\n", GetLastError() );
649 trace("Thread creation failed, skipping rest of test\n");
652 WaitForSingleObject( event, INFINITE );
653 SuspendThread( thread );
654 CloseHandle( event );
656 ctx.ContextFlags = CONTEXT_FULL;
657 SetLastError(0xdeadbeef);
658 ok( GetThreadContext( thread, &ctx ), "GetThreadContext failed : (%ld)\n", GetLastError() );
660 /* simulate a call to set_test_val(10) */
661 stack = (int *)ctx.Esp;
664 ctx.Esp -= 2 * sizeof(int *);
665 ctx.Eip = (DWORD)set_test_val;
666 SetLastError(0xdeadbeef);
667 ok( SetThreadContext( thread, &ctx ), "SetThreadContext failed : (%ld)\n", GetLastError() );
669 SetLastError(0xdeadbeef);
670 prevcount = ResumeThread( thread );
671 ok ( prevcount == 1, "Previous suspend count (%ld) instead of 1, last error : (%ld)\n",
672 prevcount, GetLastError() );
674 WaitForSingleObject( thread, INFINITE );
675 ok( test_value == 20, "test_value %d instead of 20\n", test_value );
678 #endif /* __i386__ */
684 /* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
685 so that the compile passes
687 lib=GetModuleHandleA("kernel32.dll");
688 ok(lib!=NULL,"Couldn't get a handle for kernel32.dll\n");
689 pGetThreadPriorityBoost=(GetThreadPriorityBoost_t)GetProcAddress(lib,"GetThreadPriorityBoost");
690 pOpenThread=(OpenThread_t)GetProcAddress(lib,"OpenThread");
691 pSetThreadIdealProcessor=(SetThreadIdealProcessor_t)GetProcAddress(lib,"SetThreadIdealProcessor");
692 pSetThreadPriorityBoost=(SetThreadPriorityBoost_t)GetProcAddress(lib,"SetThreadPriorityBoost");
693 test_CreateThread_basic();
694 test_CreateThread_suspended();
695 test_SuspendThread();
696 test_TerminateThread();
697 test_CreateThread_stack();
698 test_thread_priority();
699 test_GetThreadTimes();
700 test_thread_processor();
701 test_GetThreadExitCode();
703 test_SetThreadContext();