ReactOS 0.4.15-dev-7842-g558ab78
thread.c
Go to the documentation of this file.
1/*
2 * Unit test suite for thread functions.
3 *
4 * Copyright 2002 Geoffrey Hausheer
5 *
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.
10 *
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.
15 *
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
19 */
20
21#include <assert.h>
22#include <stdarg.h>
23#include <stdio.h>
24
25/* the tests intentionally pass invalid pointers and need an exception handler */
26#define WINE_NO_INLINE_STRING
27
28#include <ntstatus.h>
29#define WIN32_NO_STATUS
30#include <windef.h>
31#include <winbase.h>
32#include <winnt.h>
33#include <winerror.h>
34#include <winnls.h>
35#include <winternl.h>
36#include "wine/test.h"
37
38/* THREAD_ALL_ACCESS in Vista+ PSDKs is incompatible with older Windows versions */
39#define THREAD_ALL_ACCESS_NT4 (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3ff)
40
41/* Specify the number of simultaneous threads to test */
42#define NUM_THREADS 4
43/* Specify whether to test the extended priorities for Win2k/XP */
44#define USE_EXTENDED_PRIORITIES 0
45/* Specify whether to test the stack allocation in CreateThread */
46#define CHECK_STACK 0
47
48/* Set CHECK_STACK to 1 if you want to try to test the stack-limit from
49 CreateThread. So far I have been unable to make this work, and
50 I am in doubt as to how portable it is. Also, according to MSDN,
51 you shouldn't mix C-run-time-libraries (i.e. alloca) with CreateThread.
52 Anyhow, the check is currently commented out
53*/
54#if CHECK_STACK
55# ifdef __try
56# define __TRY __try
57# define __EXCEPT __except
58# define __ENDTRY
59# else
60# include "wine/exception.h"
61# endif
62#endif
63
64#ifdef __i386__
65#define ARCH "x86"
66#elif defined __x86_64__
67#define ARCH "amd64"
68#elif defined __arm__
69#define ARCH "arm"
70#elif defined __aarch64__
71#define ARCH "arm64"
72#else
73#define ARCH "none"
74#endif
75
76static BOOL (WINAPI *pGetThreadPriorityBoost)(HANDLE,PBOOL);
77static HANDLE (WINAPI *pOpenThread)(DWORD,BOOL,DWORD);
78static BOOL (WINAPI *pQueueUserWorkItem)(LPTHREAD_START_ROUTINE,PVOID,ULONG);
79static DWORD (WINAPI *pSetThreadIdealProcessor)(HANDLE,DWORD);
80static BOOL (WINAPI *pSetThreadPriorityBoost)(HANDLE,BOOL);
81static BOOL (WINAPI *pRegisterWaitForSingleObject)(PHANDLE,HANDLE,WAITORTIMERCALLBACK,PVOID,ULONG,ULONG);
82static BOOL (WINAPI *pUnregisterWait)(HANDLE);
83static BOOL (WINAPI *pIsWow64Process)(HANDLE,PBOOL);
84static BOOL (WINAPI *pSetThreadErrorMode)(DWORD,PDWORD);
85static DWORD (WINAPI *pGetThreadErrorMode)(void);
86static DWORD (WINAPI *pRtlGetThreadErrorMode)(void);
87static BOOL (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*);
88static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW);
89static BOOL (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR);
90static BOOL (WINAPI *pGetCurrentActCtx)(HANDLE *);
91static void (WINAPI *pReleaseActCtx)(HANDLE);
92static PTP_POOL (WINAPI *pCreateThreadpool)(PVOID);
93static void (WINAPI *pCloseThreadpool)(PTP_POOL);
95static void (WINAPI *pSubmitThreadpoolWork)(PTP_WORK);
96static void (WINAPI *pWaitForThreadpoolWorkCallbacks)(PTP_WORK,BOOL);
97static void (WINAPI *pCloseThreadpoolWork)(PTP_WORK);
98static NTSTATUS (WINAPI *pNtQueryInformationThread)(HANDLE,THREADINFOCLASS,PVOID,ULONG,PULONG);
99static BOOL (WINAPI *pGetThreadGroupAffinity)(HANDLE,GROUP_AFFINITY*);
100static BOOL (WINAPI *pSetThreadGroupAffinity)(HANDLE,const GROUP_AFFINITY*,GROUP_AFFINITY*);
101static NTSTATUS (WINAPI *pNtSetInformationThread)(HANDLE,THREADINFOCLASS,LPCVOID,ULONG);
102static NTSTATUS (WINAPI *pNtSetLdtEntries)(ULONG,ULONG,ULONG,ULONG,ULONG,ULONG);
103
105{
106 char **argv;
107 char cmdline[MAX_PATH];
109 BOOL ret;
110 STARTUPINFOA si = { 0 };
111 si.cb = sizeof(si);
112
114 sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
115 ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
116 ok(ret, "error: %u\n", GetLastError());
117 ret = CloseHandle(pi.hThread);
118 ok(ret, "error %u\n", GetLastError());
119 return pi.hProcess;
120}
121
122/* Functions not tested yet:
123 AttachThreadInput
124 SetThreadContext
125 SwitchToThread
126
127In addition there are no checks that the inheritance works properly in
128CreateThread
129*/
130
131/* Functions to ensure that from a group of threads, only one executes
132 certain chunks of code at a time, and we know which one is executing
133 it. It basically makes multithreaded execution linear, which defeats
134 the purpose of multiple threads, but makes testing easy. */
137
139{
141 ok(start_event != NULL, "CreateEvent failed\n");
143 ok(stop_event != NULL, "CreateEvent failed\n");
144 num_synced = -1;
145}
146
148{
150 assert(-1 <= num && num <= 1);
151 if (num == 1)
152 {
155 }
156 else
157 {
159 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed %x\n",ret);
160 }
161 return sync_id == my_id;
162}
163
164static void resync_after_run(void)
165{
167 assert(-1 <= num && num <= 1);
168 if (num == -1)
169 {
172 }
173 else
174 {
176 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
177 }
178}
179
181{
184}
185
187
188typedef struct {
192} t1Struct;
193
194/* WinME supports OpenThread but doesn't know about access restrictions so
195 we require them to be either completely ignored or always obeyed.
196*/
197static INT obeying_ars = 0; /* -1 == no, 0 == dunno yet, 1 == yes */
198#define obey_ar(x) \
199 (obeying_ars == 0 \
200 ? ((x) \
201 ? (obeying_ars = +1) \
202 : ((obeying_ars = -1), \
203 trace("not restricted, assuming consistent behaviour\n"))) \
204 : (obeying_ars < 0) \
205 ? ok(!(x), "access restrictions obeyed\n") \
206 : ok( (x), "access restrictions not obeyed\n"))
207
208/* Basic test that simultaneous threads can access shared memory,
209 that the thread local storage routines work correctly, and that
210 threads actually run concurrently
211*/
213{
214 t1Struct *tstruct = p;
215 int i;
216/* write our thread # into shared memory */
217 tstruct->threadmem[tstruct->threadnum]=GetCurrentThreadId();
218 ok(TlsSetValue(tlsIndex,(LPVOID)(INT_PTR)(tstruct->threadnum+1))!=0,
219 "TlsSetValue failed\n");
220/* The threads synchronize before terminating. This is done by
221 Signaling an event, and waiting for all events to occur
222*/
223 SetEvent(tstruct->event[tstruct->threadnum]);
225/* Double check that all threads really did run by validating that
226 they have all written to the shared memory. There should be no race
227 here, since all threads were synchronized after the write.*/
228 for (i = 0; i < NUM_THREADS; i++)
229 ok(tstruct->threadmem[i] != 0, "expected threadmem[%d] != 0\n", i);
230
231 /* lstrlenA contains an exception handler so this makes sure exceptions work in threads */
232 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
233
234/* Check that no one changed our tls memory */
236 "TlsGetValue failed\n");
237 return NUM_THREADS+tstruct->threadnum;
238}
239
241{
242 return 99;
243}
244
246{
250 return 99;
251}
252
254{
255 HANDLE event = p;
256 if(event != NULL) {
258 }
259 Sleep(99000);
260 return 0;
261}
262
263#if CHECK_STACK
264static DWORD WINAPI threadFunc5(LPVOID p)
265{
266 DWORD *exitCode = p;
267 SYSTEM_INFO sysInfo;
268 sysInfo.dwPageSize=0;
269 GetSystemInfo(&sysInfo);
270 *exitCode=0;
271 __TRY
272 {
273 alloca(2*sysInfo.dwPageSize);
274 }
275 __EXCEPT(1) {
276 *exitCode=1;
277 }
279 return 0;
280}
281#endif
282
284{
285 SetEvent(p);
286 return 0;
287}
288
290{
291 CloseHandle(p);
292 return 0;
293}
294
296{
299};
300
302{
304 HANDLE cur;
305 BOOL ret;
306
307 cur = (void*)0xdeadbeef;
308 ret = pGetCurrentActCtx(&cur);
309 ok(ret, "thread GetCurrentActCtx failed, %u\n", GetLastError());
310 ok(cur == param->handle, "got %p, expected %p\n", cur, param->handle);
311 param->thread_context = cur;
312
313 return 0;
314}
315
317{
318 char buffer[256];
319
320 sprintf(buffer, "threadFunc_SetEvent %p", threadFunc_SetEvent);
322
323 sprintf(buffer, "threadFunc_CloseHandle %p", threadFunc_CloseHandle);
325}
326
327/* check CreateRemoteThread */
329{
330 HANDLE hProcess, hThread, hEvent, hRemoteEvent;
331 DWORD tid, ret, exitcode;
332 HANDLE hAddrEvents[2];
333
335 ok(hProcess != NULL, "Can't start process\n");
336
337 /* ensure threadFunc_SetEvent & threadFunc_CloseHandle are the same
338 * address as in the child process */
339 create_function_addr_events(hAddrEvents);
340 ret = WaitForMultipleObjects(2, hAddrEvents, TRUE, 5000);
341 if (ret == WAIT_TIMEOUT)
342 {
343 skip("child process wasn't mapped at same address, so can't do CreateRemoteThread tests.\n");
344 return;
345 }
346 ok(ret == WAIT_OBJECT_0 || broken(ret == WAIT_OBJECT_0+1 /* nt4,w2k */), "WaitForAllObjects 2 events %d\n", ret);
347
349 ok(hEvent != NULL, "Can't create event, err=%u\n", GetLastError());
352 ok(ret != 0, "DuplicateHandle failed, err=%u\n", GetLastError());
353
354 /* create suspended remote thread with entry point SetEvent() */
355 SetLastError(0xdeadbeef);
357 hRemoteEvent, CREATE_SUSPENDED, &tid);
359 {
360 win_skip("CreateRemoteThread is not implemented\n");
361 goto cleanup;
362 }
363 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
364 ok(tid != 0, "null tid\n");
366 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
368 ok(ret == 2, "ret=%u, err=%u\n", ret, GetLastError());
369
370 /* thread still suspended, so wait times out */
372 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
373
375 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
376
377 /* wait that doesn't time out */
379 ok(ret == WAIT_OBJECT_0, "object not signaled, ret=%u\n", ret);
380
381 /* wait for thread end */
383 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
385
386 /* create and wait for remote thread with entry point CloseHandle() */
389 hRemoteEvent, 0, &tid);
390 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
392 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
394
395 /* create remote thread with entry point SetEvent() */
398 hRemoteEvent, 0, &tid);
399 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
400
401 /* closed handle, so wait times out */
403 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
404
405 /* check that remote SetEvent() failed */
406 ret = GetExitCodeThread(hThread, &exitcode);
407 ok(ret != 0, "GetExitCodeThread failed, err=%u\n", GetLastError());
408 if (ret) ok(exitcode == 0, "SetEvent succeeded, expected to fail\n");
410
411cleanup:
415}
416
417/* Check basic functionality of CreateThread and Tls* functions */
419{
421 DWORD threadid[NUM_THREADS],curthreadId;
422 DWORD threadmem[NUM_THREADS];
423 DWORD exitCode;
424 t1Struct tstruct[NUM_THREADS];
425 int error;
426 DWORD i,j;
427 DWORD GLE, ret;
428 DWORD tid;
429 BOOL bRet;
430
431 /* lstrlenA contains an exception handler so this makes sure exceptions work in the main thread */
432 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
433
434/* Retrieve current Thread ID for later comparisons */
435 curthreadId=GetCurrentThreadId();
436/* Allocate some local storage */
437 ok((tlsIndex=TlsAlloc())!=TLS_OUT_OF_INDEXES,"TlsAlloc failed\n");
438/* Create events for thread synchronization */
439 for(i=0;i<NUM_THREADS;i++) {
440 threadmem[i]=0;
441/* Note that it doesn't matter what type of event we choose here. This
442 test isn't trying to thoroughly test events
443*/
445 tstruct[i].threadnum=i;
446 tstruct[i].threadmem=threadmem;
447 tstruct[i].event=event;
448 }
449
450/* Test that passing arguments to threads works okay */
451 for(i=0;i<NUM_THREADS;i++) {
453 &tstruct[i],0,&threadid[i]);
454 ok(thread[i]!=NULL,"Create Thread failed\n");
455 }
456/* Test that the threads actually complete */
457 for(i=0;i<NUM_THREADS;i++) {
459 ok(error==WAIT_OBJECT_0, "Thread did not complete within timelimit\n");
460 if(error!=WAIT_OBJECT_0) {
462 }
463 ok(GetExitCodeThread(thread[i],&exitCode),"Could not retrieve ext code\n");
464 ok(exitCode==i+NUM_THREADS,"Thread returned an incorrect exit code\n");
465 }
466/* Test that each thread executed in its parent's address space
467 (it was able to change threadmem and pass that change back to its parent)
468 and that each thread id was independent). Note that we prove that the
469 threads actually execute concurrently by having them block on each other
470 in threadFunc1
471*/
472 for(i=0;i<NUM_THREADS;i++) {
473 error=0;
474 for(j=i+1;j<NUM_THREADS;j++) {
475 if (threadmem[i]==threadmem[j]) {
476 error=1;
477 }
478 }
479 ok(!error && threadmem[i]==threadid[i] && threadmem[i]!=curthreadId,
480 "Thread did not execute successfully\n");
481 ok(CloseHandle(thread[i])!=0,"CloseHandle failed\n");
482 }
483
484 SetLastError(0xCAFEF00D);
485 bRet = TlsFree(tlsIndex);
486 ok(bRet, "TlsFree failed: %08x\n", GetLastError());
487 ok(GetLastError()==0xCAFEF00D,
488 "GetLastError: expected 0xCAFEF00D, got %08x\n", GetLastError());
489
490 /* Test freeing an already freed TLS index */
491 SetLastError(0xCAFEF00D);
492 ok(TlsFree(tlsIndex)==0,"TlsFree succeeded\n");
494 "GetLastError: expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
495
496 /* Test how passing NULL as a pointer to threadid works */
497 SetLastError(0xFACEaBAD);
499 GLE = GetLastError();
500 if (thread[0]) { /* NT */
501 ok(GLE==0xFACEaBAD, "CreateThread set last error to %d, expected 4207848365\n", GLE);
503 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
504 ret = GetExitCodeThread(thread[0],&exitCode);
505 ok(ret!=0, "GetExitCodeThread returned %d (expected nonzero)\n", ret);
506 ok(exitCode==99, "threadFunc2 exited with code: %d (expected 99)\n", exitCode);
507 ok(CloseHandle(thread[0])!=0,"Error closing thread handle\n");
508 }
509 else { /* 9x */
510 ok(GLE==ERROR_INVALID_PARAMETER, "CreateThread set last error to %d, expected 87\n", GLE);
511 }
512}
513
514/* Check that using the CREATE_SUSPENDED flag works */
516{
518 DWORD threadId;
519 DWORD suspend_count;
520 int error;
521
523 CREATE_SUSPENDED,&threadId);
524 ok(thread!=NULL,"Create Thread failed\n");
525/* Check that the thread is suspended */
526 ok(SuspendThread(thread)==1,"Thread did not start suspended\n");
527 ok(ResumeThread(thread)==2,"Resume thread returned an invalid value\n");
528/* Check that resume thread didn't actually start the thread. I can't think
529 of a better way of checking this than just waiting. I am not sure if this
530 will work on slow computers.
531*/
533 "ResumeThread should not have actually started the thread\n");
534/* Now actually resume the thread and make sure that it actually completes*/
535 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
537 "Thread did not resume\n");
538 if(error!=WAIT_OBJECT_0) {
540 }
541
542 suspend_count = SuspendThread(thread);
543 ok(suspend_count == -1, "SuspendThread returned %d, expected -1\n", suspend_count);
544
545 suspend_count = ResumeThread(thread);
546 ok(suspend_count == 0 ||
547 broken(suspend_count == -1), /* win9x */
548 "ResumeThread returned %d, expected 0\n", suspend_count);
549
550 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
551}
552
553/* Check that SuspendThread and ResumeThread work */
555{
556 HANDLE thread,access_thread;
557 DWORD threadId,exitCode,error;
558 int i;
559
561 0,&threadId);
562 ok(thread!=NULL,"Create Thread failed\n");
563/* Check that the thread is suspended */
564/* Note that this is a polling method, and there is a race between
565 SuspendThread being called (in the child, and the loop below timing out,
566 so the test could fail on a heavily loaded or slow computer.
567*/
568 error=0;
569 for(i=0;error==0 && i<100;i++) {
572 if(error==0) {
573 Sleep(50);
574 i++;
575 }
576 }
577 ok(error==1,"SuspendThread did not work\n");
578/* check that access restrictions are obeyed */
579 if (pOpenThread) {
580 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 & (~THREAD_SUSPEND_RESUME),
581 0,threadId);
582 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
583 if (access_thread!=NULL) {
584 obey_ar(SuspendThread(access_thread)==~0U);
585 obey_ar(ResumeThread(access_thread)==~0U);
586 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
587 }
588 }
589/* Double check that the thread really is suspended */
590 ok((error=GetExitCodeThread(thread,&exitCode))!=0 && exitCode==STILL_ACTIVE,
591 "Thread did not really suspend\n");
592/* Resume the thread, and make sure it actually completes */
593 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
595 "Thread did not resume\n");
596 if(error!=WAIT_OBJECT_0) {
598 }
599 /* Trying to suspend a terminated thread should fail */
601 ok(error==~0U, "wrong return code: %d\n", error);
602 ok(GetLastError()==ERROR_ACCESS_DENIED || GetLastError()==ERROR_NO_MORE_ITEMS, "unexpected error code: %d\n", GetLastError());
603
604 ok(CloseHandle(thread)!=0,"CloseHandle Failed\n");
605}
606
607/* Check that TerminateThread works properly
608*/
610{
611 HANDLE thread,access_thread,event;
612 DWORD threadId,exitCode;
614 thread = CreateThread(NULL,0,threadFunc4,event,0,&threadId);
615 ok(thread!=NULL,"Create Thread failed\n");
616/* TerminateThread has a race condition in Wine. If the thread is terminated
617 before it starts, it leaves a process behind. Therefore, we wait for the
618 thread to signal that it has started. There is no easy way to force the
619 race to occur, so we don't try to find it.
620*/
622 "TerminateThread didn't work\n");
623/* check that access restrictions are obeyed */
624 if (pOpenThread) {
625 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 & (~THREAD_TERMINATE),
626 0,threadId);
627 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
628 if (access_thread!=NULL) {
629 obey_ar(TerminateThread(access_thread,99)==0);
630 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
631 }
632 }
633/* terminate a job and make sure it terminates */
634 ok(TerminateThread(thread,99)!=0,"TerminateThread failed\n");
636 "TerminateThread didn't work\n");
638 "TerminateThread should not leave the thread 'STILL_ACTIVE'\n");
639 ok(exitCode==99, "TerminateThread returned invalid exit code\n");
640 ok(CloseHandle(thread)!=0,"Error Closing thread handle\n");
641}
642
643/* Check if CreateThread obeys the specified stack size. This code does
644 not work properly, and is currently disabled
645*/
647{
648#if CHECK_STACK
649/* The only way I know of to test the stack size is to use alloca
650 and __try/__except. However, this is probably not portable,
651 and I couldn't get it to work under Wine anyhow. However, here
652 is the code which should allow for testing that CreateThread
653 respects the stack-size limit
654*/
656 DWORD threadId,exitCode;
657
658 SYSTEM_INFO sysInfo;
659 sysInfo.dwPageSize=0;
660 GetSystemInfo(&sysInfo);
661 ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
663 threadFunc5,&exitCode,
664 0,&threadId);
666 "TerminateThread didn't work\n");
667 ok(exitCode==1,"CreateThread did not obey stack-size-limit\n");
668 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
669#endif
670}
671
672/* Check whether setting/retrieving thread priorities works */
674{
675 HANDLE curthread,access_thread;
676 DWORD curthreadId,exitCode;
677 int min_priority=-2,max_priority=2;
678 BOOL disabled,rc;
679 int i;
680
681 curthread=GetCurrentThread();
682 curthreadId=GetCurrentThreadId();
683/* Check thread priority */
684/* NOTE: on Win2k/XP priority can be from -7 to 6. All other platforms it
685 is -2 to 2. However, even on a real Win2k system, using thread
686 priorities beyond the -2 to 2 range does not work. If you want to try
687 anyway, enable USE_EXTENDED_PRIORITIES
688*/
690 "GetThreadPriority Failed\n");
691
692 if (pOpenThread) {
693/* check that access control is obeyed */
694 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 &
696 0,curthreadId);
697 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
698 if (access_thread!=NULL) {
699 obey_ar(SetThreadPriority(access_thread,1)==0);
701 obey_ar(GetExitCodeThread(access_thread,&exitCode)==0);
702 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
703 }
704 }
705#if USE_EXTENDED_PRIORITIES
706 min_priority=-7; max_priority=6;
707#endif
708 for(i=min_priority;i<=max_priority;i++) {
709 ok(SetThreadPriority(curthread,i)!=0,
710 "SetThreadPriority Failed for priority: %d\n",i);
711 ok(GetThreadPriority(curthread)==i,
712 "GetThreadPriority Failed for priority: %d\n",i);
713 }
715 "SetThreadPriority Failed\n");
717 "GetThreadPriority Failed\n");
719 "SetThreadPriority Failed\n");
721 "GetThreadPriority Failed\n");
722 ok(SetThreadPriority(curthread,0)!=0,"SetThreadPriority Failed\n");
723
724/* Check that the thread priority is not changed if SetThreadPriority
725 is called with a value outside of the max/min range */
726 SetThreadPriority(curthread,min_priority);
727 SetLastError(0xdeadbeef);
728 rc = SetThreadPriority(curthread,min_priority-1);
729
730 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
732 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
733 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
734 GetLastError());
735 ok(GetThreadPriority(curthread)==min_priority,
736 "GetThreadPriority didn't return min_priority\n");
737
738 SetThreadPriority(curthread,max_priority);
739 SetLastError(0xdeadbeef);
740 rc = SetThreadPriority(curthread,max_priority+1);
741
742 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
744 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
745 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
746 GetLastError());
747 ok(GetThreadPriority(curthread)==max_priority,
748 "GetThreadPriority didn't return max_priority\n");
749
750/* Check thread priority boost */
751 if (!pGetThreadPriorityBoost || !pSetThreadPriorityBoost)
752 return; /* Win9x */
753
754 SetLastError(0xdeadbeef);
755 rc=pGetThreadPriorityBoost(curthread,&disabled);
757 {
758 win_skip("GetThreadPriorityBoost is not implemented on WinME\n");
759 return;
760 }
761
762 ok(rc!=0,"error=%d\n",GetLastError());
763
764 if (pOpenThread) {
765/* check that access control is obeyed */
766 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 &
768 0,curthreadId);
769 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
770 if (access_thread!=NULL) {
771 todo_wine obey_ar(pSetThreadPriorityBoost(access_thread,1)==0);
772 todo_wine obey_ar(pGetThreadPriorityBoost(access_thread,&disabled)==0);
773 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
774 }
775 }
776
777 rc = pSetThreadPriorityBoost(curthread,1);
778 ok( rc != 0, "error=%d\n",GetLastError());
779 todo_wine {
780 rc=pGetThreadPriorityBoost(curthread,&disabled);
781 ok(rc!=0 && disabled==1,
782 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
783 }
784
785 rc = pSetThreadPriorityBoost(curthread,0);
786 ok( rc != 0, "error=%d\n",GetLastError());
787 rc=pGetThreadPriorityBoost(curthread,&disabled);
788 ok(rc!=0 && disabled==0,
789 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
790}
791
792/* check the GetThreadTimes function */
794{
795 HANDLE thread,access_thread=NULL;
796 FILETIME creationTime,exitTime,kernelTime,userTime;
797 DWORD threadId;
798 int error;
799
801 CREATE_SUSPENDED,&threadId);
802
803 ok(thread!=NULL,"Create Thread failed\n");
804/* check that access control is obeyed */
805 if (pOpenThread) {
806 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 &
807 (~THREAD_QUERY_INFORMATION), 0,threadId);
808 ok(access_thread!=NULL,
809 "OpenThread returned an invalid handle\n");
810 }
811 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
813 "ResumeThread didn't work\n");
814 creationTime.dwLowDateTime=99; creationTime.dwHighDateTime=99;
815 exitTime.dwLowDateTime=99; exitTime.dwHighDateTime=99;
816 kernelTime.dwLowDateTime=99; kernelTime.dwHighDateTime=99;
817 userTime.dwLowDateTime=99; userTime.dwHighDateTime=99;
818/* GetThreadTimes should set all of the parameters passed to it */
819 error=GetThreadTimes(thread,&creationTime,&exitTime,
820 &kernelTime,&userTime);
821
823 win_skip("GetThreadTimes is not implemented\n");
824 else {
825 ok(error!=0,"GetThreadTimes failed\n");
826 ok(creationTime.dwLowDateTime!=99 || creationTime.dwHighDateTime!=99,
827 "creationTime was invalid\n");
828 ok(exitTime.dwLowDateTime!=99 || exitTime.dwHighDateTime!=99,
829 "exitTime was invalid\n");
830 ok(kernelTime.dwLowDateTime!=99 || kernelTime.dwHighDateTime!=99,
831 "kernelTimewas invalid\n");
832 ok(userTime.dwLowDateTime!=99 || userTime.dwHighDateTime!=99,
833 "userTime was invalid\n");
834 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
835 if(access_thread!=NULL)
836 {
837 error=GetThreadTimes(access_thread,&creationTime,&exitTime,
838 &kernelTime,&userTime);
839 obey_ar(error==0);
840 }
841 }
842 if(access_thread!=NULL) {
843 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
844 }
845}
846
847/* Check the processor affinity functions */
848/* NOTE: These functions should also be checked that they obey access control
849*/
851{
852 HANDLE curthread,curproc;
853 DWORD_PTR processMask,systemMask,retMask;
854 SYSTEM_INFO sysInfo;
855 int error=0;
857
858 if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
859
860 sysInfo.dwNumberOfProcessors=0;
861 GetSystemInfo(&sysInfo);
862 ok(sysInfo.dwNumberOfProcessors>0,
863 "GetSystemInfo failed to return a valid # of processors\n");
864/* Use the current Thread/process for all tests */
865 curthread=GetCurrentThread();
866 ok(curthread!=NULL,"GetCurrentThread failed\n");
867 curproc=GetCurrentProcess();
868 ok(curproc!=NULL,"GetCurrentProcess failed\n");
869/* Check the Affinity Mask functions */
870 ok(GetProcessAffinityMask(curproc,&processMask,&systemMask)!=0,
871 "GetProcessAffinityMask failed\n");
872 ok(SetThreadAffinityMask(curthread,processMask)==processMask,
873 "SetThreadAffinityMask failed\n");
874 ok(SetThreadAffinityMask(curthread,processMask+1)==0,
875 "SetThreadAffinityMask passed for an illegal processor\n");
876/* NOTE: Pre-Vista does not recognize the "all processors" flag (all bits set) */
877 retMask = SetThreadAffinityMask(curthread,~0);
878 ok(broken(retMask==0) || retMask==processMask,
879 "SetThreadAffinityMask(thread,-1) failed to request all processors.\n");
880
881 if (retMask == processMask)
882 {
883 /* Show that the "all processors" flag is handled in ntdll */
884 DWORD_PTR mask = ~0u;
885 NTSTATUS status = pNtSetInformationThread(curthread, ThreadAffinityMask, &mask, sizeof(mask));
886 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS in NtSetInformationThread, got %x\n", status);
887 }
888
889 if (retMask == processMask && sizeof(ULONG_PTR) > sizeof(ULONG))
890 {
891 /* only the low 32-bits matter */
892 retMask = SetThreadAffinityMask(curthread,~(ULONG_PTR)0);
893 ok(retMask == processMask, "SetThreadAffinityMask failed\n");
894 retMask = SetThreadAffinityMask(curthread,~(ULONG_PTR)0 >> 3);
895 ok(retMask == processMask, "SetThreadAffinityMask failed\n");
896 }
897/* NOTE: This only works on WinNT/2000/XP) */
898 if (pSetThreadIdealProcessor)
899 {
900 SetLastError(0xdeadbeef);
901 error=pSetThreadIdealProcessor(curthread,0);
903 {
904 ok(error!=-1, "SetThreadIdealProcessor failed\n");
905
906 if (is_wow64)
907 {
908 SetLastError(0xdeadbeef);
909 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
911 ok(error!=-1, "SetThreadIdealProcessor failed for %u on Wow64\n", MAXIMUM_PROCESSORS+1);
912
913 SetLastError(0xdeadbeef);
914 error=pSetThreadIdealProcessor(curthread,65);
915 ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
917 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
918 }
919 else
920 {
921 SetLastError(0xdeadbeef);
922 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
923 ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
925 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
926 }
927
928 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS);
929 ok(error!=-1, "SetThreadIdealProcessor failed\n");
930 }
931 else
932 win_skip("SetThreadIdealProcessor is not implemented\n");
933 }
934
935 if (pGetThreadGroupAffinity && pSetThreadGroupAffinity)
936 {
937 GROUP_AFFINITY affinity, affinity_new;
939
940 memset(&affinity, 0, sizeof(affinity));
941 ok(pGetThreadGroupAffinity(curthread, &affinity), "GetThreadGroupAffinity failed\n");
942
943 SetLastError(0xdeadbeef);
944 ok(!pGetThreadGroupAffinity(curthread, NULL), "GetThreadGroupAffinity succeeded\n");
946 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
947 ok(affinity.Group == 0, "Expected group 0 got %u\n", affinity.Group);
948
949 memset(&affinity_new, 0, sizeof(affinity_new));
950 affinity_new.Group = 0;
951 affinity_new.Mask = affinity.Mask;
952 ok(pSetThreadGroupAffinity(curthread, &affinity_new, &affinity), "SetThreadGroupAffinity failed\n");
953 ok(affinity_new.Mask == affinity.Mask, "Expected old affinity mask %lx, got %lx\n",
954 affinity_new.Mask, affinity.Mask);
955
956 /* show that the "all processors" flag is not supported for SetThreadGroupAffinity */
957 affinity_new.Group = 0;
958 affinity_new.Mask = ~0u;
959 SetLastError(0xdeadbeef);
960 ok(!pSetThreadGroupAffinity(curthread, &affinity_new, NULL), "SetThreadGroupAffinity succeeded\n");
962 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
963
964 affinity_new.Group = 1; /* assumes that you have less than 64 logical processors */
965 affinity_new.Mask = 0x1;
966 SetLastError(0xdeadbeef);
967 ok(!pSetThreadGroupAffinity(curthread, &affinity_new, NULL), "SetThreadGroupAffinity succeeded\n");
969 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
970
971 SetLastError(0xdeadbeef);
972 ok(!pSetThreadGroupAffinity(curthread, NULL, NULL), "SetThreadGroupAffinity succeeded\n");
974 "Expected ERROR_NOACCESS, got %d\n", GetLastError());
975
976 /* show that the access violation was detected in ntdll */
977 status = pNtSetInformationThread(curthread, ThreadGroupInformation, NULL, sizeof(affinity_new));
979 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
980
981 /* restore original mask */
982 affinity_new.Group = 0;
983 affinity_new.Mask = affinity.Mask;
984 SetLastError(0xdeadbeef);
985 ok(pSetThreadGroupAffinity(curthread, &affinity_new, &affinity), "SetThreadGroupAffinity failed\n");
986 ok(affinity_new.Mask == affinity.Mask, "Expected old affinity mask %lx, got %lx\n",
987 affinity_new.Mask, affinity.Mask);
988 }
989 else
990 win_skip("Get/SetThreadGroupAffinity not available\n");
991}
992
994{
995 DWORD exitCode, threadid;
996 DWORD GLE, ret;
998
999 ret = GetExitCodeThread((HANDLE)0x2bad2bad,&exitCode);
1000 ok(ret==0, "GetExitCodeThread returned non zero value: %d\n", ret);
1001 GLE = GetLastError();
1002 ok(GLE==ERROR_INVALID_HANDLE, "GetLastError returned %d (expected 6)\n", GLE);
1003
1004 thread = CreateThread(NULL,0,threadFunc2,NULL,0,&threadid);
1006 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
1007 ret = GetExitCodeThread(thread,&exitCode);
1008 ok(ret==exitCode || ret==1,
1009 "GetExitCodeThread returned %d (expected 1 or %d)\n", ret, exitCode);
1010 ok(exitCode==99, "threadFunc2 exited with code %d (expected 99)\n", exitCode);
1011 ok(CloseHandle(thread)!=0,"Error closing thread handle\n");
1012}
1013
1014#ifdef __i386__
1015
1016static int test_value = 0;
1017static HANDLE event;
1018
1019static void WINAPI set_test_val( int val )
1020{
1021 test_value += val;
1022 ExitThread(0);
1023}
1024
1025static DWORD WINAPI threadFunc6(LPVOID p)
1026{
1027 SetEvent( event );
1028 Sleep( 1000 );
1029 test_value *= (int)p;
1030 return 0;
1031}
1032
1033static void test_SetThreadContext(void)
1034{
1035 CONTEXT ctx;
1036 int *stack;
1037 HANDLE thread;
1038 DWORD threadid;
1039 DWORD prevcount;
1040 BOOL ret;
1041
1042 SetLastError(0xdeadbeef);
1043 event = CreateEventW( NULL, TRUE, FALSE, NULL );
1044 thread = CreateThread( NULL, 0, threadFunc6, (void *)2, 0, &threadid );
1045 ok( thread != NULL, "CreateThread failed : (%d)\n", GetLastError() );
1046 if (!thread)
1047 {
1048 trace("Thread creation failed, skipping rest of test\n");
1049 return;
1050 }
1053 CloseHandle( event );
1054
1055 ctx.ContextFlags = CONTEXT_FULL;
1056 SetLastError(0xdeadbeef);
1058 ok( ret, "GetThreadContext failed : (%u)\n", GetLastError() );
1059
1060 if (ret)
1061 {
1062 /* simulate a call to set_test_val(10) */
1063 stack = (int *)ctx.Esp;
1064 stack[-1] = 10;
1065 stack[-2] = ctx.Eip;
1066 ctx.Esp -= 2 * sizeof(int *);
1067 ctx.Eip = (DWORD)set_test_val;
1068 SetLastError(0xdeadbeef);
1070 ok( ret, "SetThreadContext failed : (%d)\n", GetLastError() );
1071 }
1072
1073 SetLastError(0xdeadbeef);
1074 prevcount = ResumeThread( thread );
1075 ok ( prevcount == 1, "Previous suspend count (%d) instead of 1, last error : (%d)\n",
1076 prevcount, GetLastError() );
1077
1079 ok( test_value == 10, "test_value %d\n", test_value );
1080
1081 ctx.ContextFlags = CONTEXT_FULL;
1082 SetLastError(0xdeadbeef);
1085 (!ret && broken(GetLastError() == ERROR_INVALID_HANDLE)) || /* win2k */
1086 broken(ret), /* 32bit application on NT 5.x 64bit */
1087 "got %d with %u (expected FALSE with ERROR_GEN_FAILURE or ERROR_ACCESS_DENIED)\n",
1088 ret, GetLastError() );
1089
1090 SetLastError(0xdeadbeef);
1093 (!ret && broken(GetLastError() == ERROR_INVALID_HANDLE)) || /* win2k */
1094 broken(ret), /* 32bit application on NT 5.x 64bit */
1095 "got %d with %u (expected FALSE with ERROR_GEN_FAILURE or ERROR_ACCESS_DENIED)\n",
1096 ret, GetLastError() );
1097
1099}
1100
1101static void test_GetThreadSelectorEntry(void)
1102{
1104 CONTEXT ctx;
1105 DWORD limit;
1106 void *base;
1107 BOOL ret;
1108
1109 memset(&ctx, 0x11, sizeof(ctx));
1110 ctx.ContextFlags = CONTEXT_SEGMENTS | CONTEXT_CONTROL;
1112 ok(ret, "GetThreadContext error %u\n", GetLastError());
1113 ok(!HIWORD(ctx.SegCs), "expected HIWORD(SegCs) == 0, got %u\n", ctx.SegCs);
1114 ok(!HIWORD(ctx.SegDs), "expected HIWORD(SegDs) == 0, got %u\n", ctx.SegDs);
1115 ok(!HIWORD(ctx.SegFs), "expected HIWORD(SegFs) == 0, got %u\n", ctx.SegFs);
1116
1118 ok(ret, "GetThreadSelectorEntry(SegCs) error %u\n", GetLastError());
1120 ok(ret, "GetThreadSelectorEntry(SegDs) error %u\n", GetLastError());
1121
1122 memset(&entry, 0x11, sizeof(entry));
1124 ok(ret, "GetThreadSelectorEntry(SegFs) error %u\n", GetLastError());
1125 entry.HighWord.Bits.Type &= ~1; /* ignore accessed bit */
1126
1127 base = (void *)((entry.HighWord.Bits.BaseHi << 24) | (entry.HighWord.Bits.BaseMid << 16) | entry.BaseLow);
1128 limit = (entry.HighWord.Bits.LimitHi << 16) | entry.LimitLow;
1129
1130 ok(base == NtCurrentTeb(), "expected %p, got %p\n", NtCurrentTeb(), base);
1131 ok(limit == 0x0fff || limit == 0x4000, "expected 0x0fff or 0x4000, got %#x\n", limit);
1132 ok(entry.HighWord.Bits.Type == 0x12, "expected 0x12, got %#x\n", entry.HighWord.Bits.Type);
1133 ok(entry.HighWord.Bits.Dpl == 3, "expected 3, got %u\n", entry.HighWord.Bits.Dpl);
1134 ok(entry.HighWord.Bits.Pres == 1, "expected 1, got %u\n", entry.HighWord.Bits.Pres);
1135 ok(entry.HighWord.Bits.Sys == 0, "expected 0, got %u\n", entry.HighWord.Bits.Sys);
1136 ok(entry.HighWord.Bits.Reserved_0 == 0, "expected 0, got %u\n", entry.HighWord.Bits.Reserved_0);
1137 ok(entry.HighWord.Bits.Default_Big == 1, "expected 1, got %u\n", entry.HighWord.Bits.Default_Big);
1138 ok(entry.HighWord.Bits.Granularity == 0, "expected 0, got %u\n", entry.HighWord.Bits.Granularity);
1139}
1140
1141static void test_NtSetLdtEntries(void)
1142{
1144 LDT_ENTRY ds_entry;
1145 CONTEXT ctx;
1146 DWORD ret;
1147 union
1148 {
1150 DWORD dw[2];
1151 } sel;
1152
1153 if (!pNtSetLdtEntries)
1154 {
1155 win_skip("NtSetLdtEntries is not available on this platform\n");
1156 return;
1157 }
1158
1159 if (pNtSetLdtEntries(0, 0, 0, 0, 0, 0) == STATUS_NOT_IMPLEMENTED) /* WoW64 */
1160 {
1161 win_skip("NtSetLdtEntries is not implemented on this platform\n");
1162 return;
1163 }
1164
1165 ret = pNtSetLdtEntries(0, 0, 0, 0, 0, 0);
1166 ok(!ret, "NtSetLdtEntries failed: %08x\n", ret);
1167
1168 ctx.ContextFlags = CONTEXT_SEGMENTS;
1170 ok(ret, "GetThreadContext failed\n");
1171
1172 tdi.Selector = ctx.SegDs;
1173 ret = pNtQueryInformationThread(GetCurrentThread(), ThreadDescriptorTableEntry, &tdi, sizeof(tdi), &ret);
1174 ok(!ret, "NtQueryInformationThread failed: %08x\n", ret);
1175 ds_entry = tdi.Entry;
1176
1177 tdi.Selector = 0x000f;
1178 ret = pNtQueryInformationThread(GetCurrentThread(), ThreadDescriptorTableEntry, &tdi, sizeof(tdi), &ret);
1179 ok(ret == STATUS_ACCESS_VIOLATION, "got %08x\n", ret);
1180
1181 tdi.Selector = 0x001f;
1182 ret = pNtQueryInformationThread(GetCurrentThread(), ThreadDescriptorTableEntry, &tdi, sizeof(tdi), &ret);
1183 ok(ret == STATUS_ACCESS_VIOLATION, "NtQueryInformationThread returned %08x\n", ret);
1184
1185 ret = GetThreadSelectorEntry(GetCurrentThread(), 0x000f, &sel.entry);
1186 ok(!ret, "GetThreadSelectorEntry should fail\n");
1187
1188 ret = GetThreadSelectorEntry(GetCurrentThread(), 0x001f, &sel.entry);
1189 ok(!ret, "GetThreadSelectorEntry should fail\n");
1190
1191 memset(&sel.entry, 0x9a, sizeof(sel.entry));
1192 ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegDs, &sel.entry);
1193 ok(ret, "GetThreadSelectorEntry failed\n");
1194 ok(!memcmp(&ds_entry, &sel.entry, sizeof(ds_entry)), "entries do not match\n");
1195
1196 ret = pNtSetLdtEntries(0x000f, sel.dw[0], sel.dw[1], 0x001f, sel.dw[0], sel.dw[1]);
1197 ok(!ret || broken(ret == STATUS_INVALID_LDT_DESCRIPTOR) /*XP*/, "NtSetLdtEntries failed: %08x\n", ret);
1198
1199 if (!ret)
1200 {
1201 memset(&sel.entry, 0x9a, sizeof(sel.entry));
1202 ret = GetThreadSelectorEntry(GetCurrentThread(), 0x000f, &sel.entry);
1203 ok(ret, "GetThreadSelectorEntry failed\n");
1204 ok(!memcmp(&ds_entry, &sel.entry, sizeof(ds_entry)), "entries do not match\n");
1205
1206 memset(&sel.entry, 0x9a, sizeof(sel.entry));
1207 ret = GetThreadSelectorEntry(GetCurrentThread(), 0x001f, &sel.entry);
1208 ok(ret, "GetThreadSelectorEntry failed\n");
1209 ok(!memcmp(&ds_entry, &sel.entry, sizeof(ds_entry)), "entries do not match\n");
1210 }
1211}
1212
1213#endif /* __i386__ */
1214
1217
1219{
1221
1222 if (executed == 100)
1224 return 0;
1225}
1226
1227static void test_QueueUserWorkItem(void)
1228{
1229 INT_PTR i;
1230 DWORD wait_result;
1232
1233 /* QueueUserWorkItem not present on win9x */
1234 if (!pQueueUserWorkItem) return;
1235
1237
1238 before = GetTickCount();
1239
1240 for (i = 0; i < 100; i++)
1241 {
1242 BOOL ret = pQueueUserWorkItem(work_function, (void *)i, WT_EXECUTEDEFAULT);
1243 ok(ret, "QueueUserWorkItem failed with error %d\n", GetLastError());
1244 }
1245
1246 wait_result = WaitForSingleObject(finish_event, 10000);
1247
1248 after = GetTickCount();
1249 trace("100 QueueUserWorkItem calls took %dms\n", after - before);
1250 ok(wait_result == WAIT_OBJECT_0, "wait failed with error 0x%x\n", wait_result);
1251
1252 ok(times_executed == 100, "didn't execute all of the work items\n");
1253}
1254
1255static void CALLBACK signaled_function(PVOID p, BOOLEAN TimerOrWaitFired)
1256{
1257 HANDLE event = p;
1258 SetEvent(event);
1259 ok(!TimerOrWaitFired, "wait shouldn't have timed out\n");
1260}
1261
1262static void CALLBACK timeout_function(PVOID p, BOOLEAN TimerOrWaitFired)
1263{
1264 HANDLE event = p;
1265 SetEvent(event);
1266 ok(TimerOrWaitFired, "wait should have timed out\n");
1267}
1268
1270{
1271 BOOL ret;
1272 HANDLE wait_handle;
1273 HANDLE handle;
1275
1276 if (!pRegisterWaitForSingleObject || !pUnregisterWait)
1277 {
1278 win_skip("RegisterWaitForSingleObject or UnregisterWait not implemented\n");
1279 return;
1280 }
1281
1282 /* test signaled case */
1283
1286
1287 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1288 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1289
1291 /* give worker thread chance to complete */
1292 Sleep(100);
1293
1294 ret = pUnregisterWait(wait_handle);
1295 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1296
1297 /* test cancel case */
1298
1300
1301 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1302 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1303
1304 ret = pUnregisterWait(wait_handle);
1305 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1306
1307 /* test timeout case */
1308
1309 ret = pRegisterWaitForSingleObject(&wait_handle, handle, timeout_function, complete_event, 0, WT_EXECUTEONLYONCE);
1310 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1311
1313 /* give worker thread chance to complete */
1314 Sleep(100);
1315
1316 ret = pUnregisterWait(wait_handle);
1317 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1318
1319 SetLastError(0xdeadbeef);
1320 ret = pUnregisterWait(NULL);
1321 ok(!ret, "Expected UnregisterWait to fail\n");
1323 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1324}
1325
1329
1330/* Function pointers to the FLS/TLS functions to test in LS_ThreadProc() */
1331static DWORD (WINAPI *LS_AllocFunc)(void);
1332static PVOID (WINAPI *LS_GetValueFunc)(DWORD);
1333static BOOL (WINAPI *LS_SetValueFunc)(DWORD, PVOID);
1334static BOOL (WINAPI *LS_FreeFunc)(DWORD);
1335
1336/* Names of the functions tested in LS_ThreadProc(), for error messages */
1337static const char* LS_AllocFuncName = "";
1338static const char* LS_GetValueFuncName = "";
1339static const char* LS_SetValueFuncName = "";
1340static const char* LS_FreeFuncName = "";
1341
1342/* FLS entry points, dynamically loaded in platforms that support them */
1343static DWORD (WINAPI *pFlsAlloc)(PFLS_CALLBACK_FUNCTION);
1344static BOOL (WINAPI *pFlsFree)(DWORD);
1345static PVOID (WINAPI *pFlsGetValue)(DWORD);
1346static BOOL (WINAPI *pFlsSetValue)(DWORD,PVOID);
1347
1348/* A thunk function to make FlsAlloc compatible with the signature of TlsAlloc */
1350{
1351 return pFlsAlloc(NULL);
1352}
1353
1355{
1356 /* We should NOT inherit the FLS/TLS values from our parent or from the
1357 main thread. */
1358 LPVOID val;
1359
1360 val = LS_GetValueFunc(LS_main);
1361 ok(val == NULL, "%s inheritance failed\n", LS_GetValueFuncName);
1362
1363 val = LS_GetValueFunc(LS_index0);
1364 ok(val == NULL, "%s inheritance failed\n", LS_GetValueFuncName);
1365
1366 val = LS_GetValueFunc(LS_index1);
1367 ok(val == NULL, "%s inheritance failed\n", LS_GetValueFuncName);
1368
1369 return 0;
1370}
1371
1372/* Basic FLS/TLS usage test. Make sure we can create slots and the values we
1373 store in them are separate among threads. Also test FLS/TLS value
1374 inheritance with LS_InheritanceProc. */
1376{
1377 LONG_PTR id = (LONG_PTR) p;
1378 LPVOID val;
1379 BOOL ret;
1380
1381 if (sync_threads_and_run_one(0, id))
1382 {
1383 LS_index0 = LS_AllocFunc();
1385 }
1387
1388 if (sync_threads_and_run_one(1, id))
1389 {
1390 LS_index1 = LS_AllocFunc();
1392
1393 /* Slot indices should be different even if created in different
1394 threads. */
1395 ok(LS_index0 != LS_index1, "%s failed\n", LS_AllocFuncName);
1396
1397 /* Both slots should be initialized to NULL */
1398 SetLastError(0xdeadbeef);
1399 val = LS_GetValueFunc(LS_index0);
1400 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1401 ok(val == NULL, "Slot not initialized correctly\n");
1402
1403 SetLastError(0xdeadbeef);
1404 val = LS_GetValueFunc(LS_index1);
1405 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1406 ok(val == NULL, "Slot not initialized correctly\n");
1407 }
1409
1410 if (sync_threads_and_run_one(0, id))
1411 {
1412 SetLastError(0xdeadbeef);
1413 val = LS_GetValueFunc(LS_index0);
1414 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1415 ok(val == NULL, "Slot not initialized correctly\n");
1416
1417 SetLastError(0xdeadbeef);
1418 val = LS_GetValueFunc(LS_index1);
1419 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1420 ok(val == NULL, "Slot not initialized correctly\n");
1421
1422 ret = LS_SetValueFunc(LS_index0, (LPVOID) 1);
1423 ok(ret, "%s failed\n", LS_SetValueFuncName);
1424
1425 ret = LS_SetValueFunc(LS_index1, (LPVOID) 2);
1426 ok(ret, "%s failed\n", LS_SetValueFuncName);
1427
1428 SetLastError(0xdeadbeef);
1429 val = LS_GetValueFunc(LS_index0);
1430 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1431 ok(val == (LPVOID) 1, "Slot not initialized correctly\n");
1432
1433 SetLastError(0xdeadbeef);
1434 val = LS_GetValueFunc(LS_index1);
1435 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1436 ok(val == (LPVOID) 2, "Slot not initialized correctly\n");
1437 }
1439
1440 if (sync_threads_and_run_one(1, id))
1441 {
1442 val = LS_GetValueFunc(LS_index0);
1443 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1444 ok(val == NULL, "Slot not initialized correctly\n");
1445
1446 val = LS_GetValueFunc(LS_index1);
1447 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1448 ok(val == NULL, "Slot not initialized correctly\n");
1449
1450 ret = LS_SetValueFunc(LS_index0, (LPVOID) 3);
1451 ok(ret, "%s failed\n", LS_SetValueFuncName);
1452
1453 ret = LS_SetValueFunc(LS_index1, (LPVOID) 4);
1454 ok(ret, "%s failed\n", LS_SetValueFuncName);
1455
1456 val = LS_GetValueFunc(LS_index0);
1457 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1458 ok(val == (LPVOID) 3, "Slot not initialized correctly\n");
1459
1460 val = LS_GetValueFunc(LS_index1);
1461 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1462 ok(val == (LPVOID) 4, "Slot not initialized correctly\n");
1463 }
1465
1466 if (sync_threads_and_run_one(0, id))
1467 {
1468 HANDLE thread;
1469 DWORD waitret, tid;
1470
1471 val = LS_GetValueFunc(LS_index0);
1472 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1473 ok(val == (LPVOID) 1, "Slot not initialized correctly\n");
1474
1475 val = LS_GetValueFunc(LS_index1);
1476 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1477 ok(val == (LPVOID) 2, "Slot not initialized correctly\n");
1478
1480 ok(thread != NULL, "CreateThread failed\n");
1481 waitret = WaitForSingleObject(thread, 60000);
1482 ok(waitret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
1484
1485 ret = LS_FreeFunc(LS_index0);
1486 ok(ret, "%s failed\n", LS_FreeFuncName);
1487 }
1489
1490 if (sync_threads_and_run_one(1, id))
1491 {
1492 ret = LS_FreeFunc(LS_index1);
1493 ok(ret, "%s failed\n", LS_FreeFuncName);
1494 }
1496
1497 return 0;
1498}
1499
1500static void run_LS_tests(void)
1501{
1502 HANDLE threads[2];
1503 LONG_PTR i;
1504 DWORD ret;
1505 BOOL suc;
1506
1508
1509 /* Allocate a slot in the main thread to test for inheritance. */
1510 LS_main = LS_AllocFunc();
1511 ok(LS_main != LS_OutOfIndexesValue, "%s failed\n", LS_AllocFuncName);
1512 suc = LS_SetValueFunc(LS_main, (LPVOID) 4114);
1513 ok(suc, "%s failed\n", LS_SetValueFuncName);
1514
1515 for (i = 0; i < 2; ++i)
1516 {
1517 DWORD tid;
1518
1520 ok(threads[i] != NULL, "CreateThread failed\n");
1521 }
1522
1523 ret = WaitForMultipleObjects(2, threads, TRUE, 60000);
1524 ok(ret == WAIT_OBJECT_0 || broken(ret == WAIT_OBJECT_0+1 /* nt4,w2k */), "WaitForAllObjects 2 threads %d\n",ret);
1525
1526 for (i = 0; i < 2; ++i)
1528
1529 suc = LS_FreeFunc(LS_main);
1530 ok(suc, "%s failed\n", LS_FreeFuncName);
1532}
1533
1534static void test_TLS(void)
1535{
1537
1538 LS_AllocFunc = &TlsAlloc;
1539 LS_GetValueFunc = &TlsGetValue;
1540 LS_SetValueFunc = &TlsSetValue;
1541 LS_FreeFunc = &TlsFree;
1542
1543 LS_AllocFuncName = "TlsAlloc";
1544 LS_GetValueFuncName = "TlsGetValue";
1545 LS_SetValueFuncName = "TlsSetValue";
1546 LS_FreeFuncName = "TlsFree";
1547
1548 run_LS_tests();
1549}
1550
1551static void test_FLS(void)
1552{
1553 if (!pFlsAlloc || !pFlsFree || !pFlsGetValue || !pFlsSetValue)
1554 {
1555 win_skip("Fiber Local Storage not supported\n");
1556 return;
1557 }
1558
1560
1561 LS_AllocFunc = &FLS_AllocFuncThunk;
1562 LS_GetValueFunc = pFlsGetValue;
1563 LS_SetValueFunc = pFlsSetValue;
1564 LS_FreeFunc = pFlsFree;
1565
1566 LS_AllocFuncName = "FlsAlloc";
1567 LS_GetValueFuncName = "FlsGetValue";
1568 LS_SetValueFuncName = "FlsSetValue";
1569 LS_FreeFuncName = "FlsFree";
1570
1571 run_LS_tests();
1572}
1573
1574static void test_ThreadErrorMode(void)
1575{
1576 DWORD oldmode;
1577 DWORD mode;
1578 DWORD rtlmode;
1579 BOOL ret;
1580
1581 if (!pSetThreadErrorMode || !pGetThreadErrorMode)
1582 {
1583 win_skip("SetThreadErrorMode and/or GetThreadErrorMode unavailable (added in Windows 7)\n");
1584 return;
1585 }
1586
1587 if (!pRtlGetThreadErrorMode) {
1588 win_skip("RtlGetThreadErrorMode not available\n");
1589 return;
1590 }
1591
1592 oldmode = pGetThreadErrorMode();
1593
1594 ret = pSetThreadErrorMode(0, &mode);
1595 ok(ret, "SetThreadErrorMode failed\n");
1596 ok(mode == oldmode,
1597 "SetThreadErrorMode returned old mode 0x%x, expected 0x%x\n",
1598 mode, oldmode);
1599 mode = pGetThreadErrorMode();
1600 ok(mode == 0, "GetThreadErrorMode returned mode 0x%x, expected 0\n", mode);
1601 rtlmode = pRtlGetThreadErrorMode();
1602 ok(rtlmode == 0,
1603 "RtlGetThreadErrorMode returned mode 0x%x, expected 0\n", mode);
1604
1605 ret = pSetThreadErrorMode(SEM_FAILCRITICALERRORS, &mode);
1606 ok(ret, "SetThreadErrorMode failed\n");
1607 ok(mode == 0,
1608 "SetThreadErrorMode returned old mode 0x%x, expected 0\n", mode);
1609 mode = pGetThreadErrorMode();
1611 "GetThreadErrorMode returned mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1612 mode);
1613 rtlmode = pRtlGetThreadErrorMode();
1614 ok(rtlmode == 0x10,
1615 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x10\n", mode);
1616
1617 ret = pSetThreadErrorMode(SEM_NOGPFAULTERRORBOX, &mode);
1618 ok(ret, "SetThreadErrorMode failed\n");
1620 "SetThreadErrorMode returned old mode 0x%x, expected SEM_FAILCRITICALERRORS\n",
1621 mode);
1622 mode = pGetThreadErrorMode();
1624 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOGPFAULTERRORBOX\n",
1625 mode);
1626 rtlmode = pRtlGetThreadErrorMode();
1627 ok(rtlmode == 0x20,
1628 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x20\n", mode);
1629
1630 ret = pSetThreadErrorMode(SEM_NOOPENFILEERRORBOX, NULL);
1631 ok(ret, "SetThreadErrorMode failed\n");
1632 mode = pGetThreadErrorMode();
1634 "GetThreadErrorMode returned mode 0x%x, expected SEM_NOOPENFILEERRORBOX\n",
1635 mode);
1636 rtlmode = pRtlGetThreadErrorMode();
1637 ok(rtlmode == 0x40,
1638 "RtlGetThreadErrorMode returned mode 0x%x, expected 0x40\n", rtlmode);
1639
1640 for (mode = 1; mode; mode <<= 1)
1641 {
1642 ret = pSetThreadErrorMode(mode, NULL);
1646 {
1647 ok(ret,
1648 "SetThreadErrorMode(0x%x,NULL) failed with error %d\n",
1649 mode, GetLastError());
1650 }
1651 else
1652 {
1654 ok(!ret,
1655 "SetThreadErrorMode(0x%x,NULL) succeeded, expected failure\n",
1656 mode);
1658 "SetThreadErrorMode(0x%x,NULL) failed with %d, "
1659 "expected ERROR_INVALID_PARAMETER\n",
1660 mode, GLE);
1661 }
1662 }
1663
1664 pSetThreadErrorMode(oldmode, NULL);
1665}
1666
1667#if (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) || (defined(_MSC_VER) && defined(__i386__))
1668static inline void set_fpu_cw(WORD cw)
1669{
1670#ifdef _MSC_VER
1671 __asm { fnclex }
1672 __asm { fldcw [cw] }
1673#else
1674 __asm__ volatile ("fnclex; fldcw %0" : : "m" (cw));
1675#endif
1676}
1677
1678static inline WORD get_fpu_cw(void)
1679{
1680 WORD cw = 0;
1681#ifdef _MSC_VER
1682 __asm { fnstcw [cw] }
1683#else
1684 __asm__ volatile ("fnstcw %0" : "=m" (cw));
1685#endif
1686 return cw;
1687}
1688
1689struct fpu_thread_ctx
1690{
1691 WORD cw;
1692 HANDLE finished;
1693};
1694
1695static DWORD WINAPI fpu_thread(void *param)
1696{
1697 struct fpu_thread_ctx *ctx = param;
1698 BOOL ret;
1699
1700 ctx->cw = get_fpu_cw();
1701
1702 ret = SetEvent(ctx->finished);
1703 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
1704
1705 return 0;
1706}
1707
1708static WORD get_thread_fpu_cw(void)
1709{
1710 struct fpu_thread_ctx ctx;
1711 DWORD tid, res;
1712 HANDLE thread;
1713
1714 ctx.finished = CreateEventW(NULL, FALSE, FALSE, NULL);
1715 ok(!!ctx.finished, "Failed to create event, last error %#x.\n", GetLastError());
1716
1717 thread = CreateThread(NULL, 0, fpu_thread, &ctx, 0, &tid);
1718 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
1719
1720 res = WaitForSingleObject(ctx.finished, INFINITE);
1721 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
1722
1723 res = CloseHandle(ctx.finished);
1724 ok(!!res, "Failed to close event handle, last error %#x.\n", GetLastError());
1725
1727 return ctx.cw;
1728}
1729
1730static void test_thread_fpu_cw(void)
1731{
1732 WORD initial_cw, cw;
1733
1734 initial_cw = get_fpu_cw();
1735 ok(initial_cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", initial_cw);
1736
1737 cw = get_thread_fpu_cw();
1738 ok(cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", cw);
1739
1740 set_fpu_cw(0xf60);
1741 cw = get_fpu_cw();
1742 ok(cw == 0xf60, "Expected FPU control word 0xf60, got %#x.\n", cw);
1743
1744 cw = get_thread_fpu_cw();
1745 ok(cw == 0x27f, "Expected FPU control word 0x27f, got %#x.\n", cw);
1746
1747 cw = get_fpu_cw();
1748 ok(cw == 0xf60, "Expected FPU control word 0xf60, got %#x.\n", cw);
1749
1750 set_fpu_cw(initial_cw);
1751 cw = get_fpu_cw();
1752 ok(cw == initial_cw, "Expected FPU control word %#x, got %#x.\n", initial_cw, cw);
1753}
1754#endif
1755
1756static const char manifest_dep[] =
1757"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
1758"<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH "\"/>"
1759" <file name=\"testdep.dll\" />"
1760"</assembly>";
1761
1762static const char manifest_main[] =
1763"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
1764"<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />"
1765"<dependency>"
1766" <dependentAssembly>"
1767" <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH "\" />"
1768" </dependentAssembly>"
1769"</dependency>"
1770"</assembly>";
1771
1772static void create_manifest_file(const char *filename, const char *manifest)
1773{
1775 HANDLE file;
1776 DWORD size;
1777
1780 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
1783}
1784
1785static HANDLE test_create(const char *file)
1786{
1788 ACTCTXW actctx;
1789 HANDLE handle;
1790
1792 memset(&actctx, 0, sizeof(ACTCTXW));
1793 actctx.cbSize = sizeof(ACTCTXW);
1794 actctx.lpSource = path;
1795
1796 handle = pCreateActCtxW(&actctx);
1797 ok(handle != INVALID_HANDLE_VALUE, "failed to create context, error %u\n", GetLastError());
1798
1799 ok(actctx.cbSize == sizeof(actctx), "cbSize=%d\n", actctx.cbSize);
1800 ok(actctx.dwFlags == 0, "dwFlags=%d\n", actctx.dwFlags);
1801 ok(actctx.lpSource == path, "lpSource=%p\n", actctx.lpSource);
1802 ok(actctx.wProcessorArchitecture == 0, "wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture);
1803 ok(actctx.wLangId == 0, "wLangId=%d\n", actctx.wLangId);
1804 ok(actctx.lpAssemblyDirectory == NULL, "lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory);
1805 ok(actctx.lpResourceName == NULL, "lpResourceName=%p\n", actctx.lpResourceName);
1806 ok(actctx.lpApplicationName == NULL, "lpApplicationName=%p\n", actctx.lpApplicationName);
1807 ok(actctx.hModule == NULL, "hModule=%p\n", actctx.hModule);
1808
1809 return handle;
1810}
1811
1812static void test_thread_actctx(void)
1813{
1817 DWORD tid, ret;
1818 BOOL b;
1819
1820 if (!pActivateActCtx)
1821 {
1822 win_skip("skipping activation context tests\n");
1823 return;
1824 }
1825
1826 create_manifest_file("testdep1.manifest", manifest_dep);
1827 create_manifest_file("main.manifest", manifest_main);
1828
1829 context = test_create("main.manifest");
1830 DeleteFileA("testdep1.manifest");
1831 DeleteFileA("main.manifest");
1832
1833 handle = (void*)0xdeadbeef;
1834 b = pGetCurrentActCtx(&handle);
1835 ok(b, "GetCurrentActCtx failed: %u\n", GetLastError());
1836 ok(handle == 0, "active context %p\n", handle);
1837
1838 /* without active context */
1839 param.thread_context = (void*)0xdeadbeef;
1840 param.handle = NULL;
1842 ok(thread != NULL, "failed, got %u\n", GetLastError());
1843
1845 ok(ret == WAIT_OBJECT_0, "wait timeout\n");
1846 ok(param.thread_context == NULL, "got wrong thread context %p\n", param.thread_context);
1848
1849 b = pActivateActCtx(context, &cookie);
1850 ok(b, "activation failed: %u\n", GetLastError());
1851
1852 handle = 0;
1853 b = pGetCurrentActCtx(&handle);
1854 ok(b, "GetCurrentActCtx failed: %u\n", GetLastError());
1855 ok(handle != 0, "no active context\n");
1856 pReleaseActCtx(handle);
1857
1858 param.handle = NULL;
1859 b = pGetCurrentActCtx(&param.handle);
1860 ok(b && param.handle != NULL, "failed to get context, %u\n", GetLastError());
1861
1862 param.thread_context = (void*)0xdeadbeef;
1864 ok(thread != NULL, "failed, got %u\n", GetLastError());
1865
1867 ok(ret == WAIT_OBJECT_0, "wait timeout\n");
1868 ok(param.thread_context == context, "got wrong thread context %p, %p\n", param.thread_context, context);
1869 pReleaseActCtx(param.thread_context);
1871
1872 /* similar test for CreateRemoteThread() */
1873 param.thread_context = (void*)0xdeadbeef;
1875 ok(thread != NULL, "failed, got %u\n", GetLastError());
1876
1878 ok(ret == WAIT_OBJECT_0, "wait timeout\n");
1879 ok(param.thread_context == context, "got wrong thread context %p, %p\n", param.thread_context, context);
1880 pReleaseActCtx(param.thread_context);
1882
1883 pReleaseActCtx(param.handle);
1884
1885 b = pDeactivateActCtx(0, cookie);
1886 ok(b, "DeactivateActCtx failed: %u\n", GetLastError());
1887 pReleaseActCtx(context);
1888}
1889
1890
1892 int *foo = (int*)context;
1893
1894 (*foo)++;
1895}
1896
1897
1898static void test_threadpool(void)
1899{
1900 PTP_POOL pool;
1901 PTP_WORK work;
1902 int workcalled = 0;
1903
1904 if (!pCreateThreadpool) {
1905 win_skip("thread pool apis not supported.\n");
1906 return;
1907 }
1908
1909 work = pCreateThreadpoolWork(threadpool_workcallback, &workcalled, NULL);
1910 ok (work != NULL, "Error %d in CreateThreadpoolWork\n", GetLastError());
1911 pSubmitThreadpoolWork(work);
1912 pWaitForThreadpoolWorkCallbacks(work, FALSE);
1913 pCloseThreadpoolWork(work);
1914
1915 ok (workcalled == 1, "expected work to be called once, got %d\n", workcalled);
1916
1917 pool = pCreateThreadpool(NULL);
1918 ok (pool != NULL, "CreateThreadpool failed\n");
1919 pCloseThreadpool(pool);
1920}
1921
1922static void test_reserved_tls(void)
1923{
1924 void *val;
1925 DWORD tls;
1926 BOOL ret;
1927
1928 /* This seems to be a WinXP SP2+ feature. */
1929 if(!pIsWow64Process) {
1930 win_skip("Skipping reserved TLS slot on too old Windows.\n");
1931 return;
1932 }
1933
1934 val = TlsGetValue(0);
1935 ok(!val, "TlsGetValue(0) = %p\n", val);
1936
1937 /* Also make sure that there is a TLS allocated. */
1938 tls = TlsAlloc();
1939 ok(tls && tls != TLS_OUT_OF_INDEXES, "tls = %x\n", tls);
1940 TlsSetValue(tls, (void*)1);
1941
1942 val = TlsGetValue(0);
1943 ok(!val, "TlsGetValue(0) = %p\n", val);
1944
1945 TlsFree(tls);
1946
1947 /* The following is too ugly to be run by default */
1948 if(0) {
1949 /* Set TLS index 0 value and see that this works and doesn't cause problems
1950 * for remaining tests. */
1951 ret = TlsSetValue(0, (void*)1);
1952 ok(ret, "TlsSetValue(0, 1) failed: %u\n", GetLastError());
1953
1954 val = TlsGetValue(0);
1955 ok(val == (void*)1, "TlsGetValue(0) = %p\n", val);
1956 }
1957}
1958
1959static void test_thread_info(void)
1960{
1961 char buf[4096];
1962 static const ULONG info_size[] =
1963 {
1964 sizeof(THREAD_BASIC_INFORMATION), /* ThreadBasicInformation */
1965 sizeof(KERNEL_USER_TIMES), /* ThreadTimes */
1966 sizeof(ULONG), /* ThreadPriority */
1967 sizeof(ULONG), /* ThreadBasePriority */
1968 sizeof(ULONG_PTR), /* ThreadAffinityMask */
1969 sizeof(HANDLE), /* ThreadImpersonationToken */
1970 sizeof(THREAD_DESCRIPTOR_INFORMATION), /* ThreadDescriptorTableEntry */
1971 sizeof(BOOLEAN), /* ThreadEnableAlignmentFaultFixup */
1972 0, /* ThreadEventPair_Reusable */
1973 sizeof(ULONG_PTR), /* ThreadQuerySetWin32StartAddress */
1974 sizeof(ULONG), /* ThreadZeroTlsCell */
1975 sizeof(LARGE_INTEGER), /* ThreadPerformanceCount */
1976 sizeof(ULONG), /* ThreadAmILastThread */
1977 sizeof(ULONG), /* ThreadIdealProcessor */
1978 sizeof(ULONG), /* ThreadPriorityBoost */
1979 sizeof(ULONG_PTR), /* ThreadSetTlsArrayAddress */
1980 sizeof(ULONG), /* ThreadIsIoPending */
1981 sizeof(BOOLEAN), /* ThreadHideFromDebugger */
1982 /* FIXME: Add remaining classes */
1983 };
1984 HANDLE thread;
1986
1987 if (!pOpenThread)
1988 {
1989 win_skip("OpenThread is not available on this platform\n");
1990 return;
1991 }
1992
1993 if (!pNtQueryInformationThread)
1994 {
1995 win_skip("NtQueryInformationThread is not available on this platform\n");
1996 return;
1997 }
1998
2000 if (!thread)
2001 {
2002 win_skip("THREAD_QUERY_LIMITED_INFORMATION is not supported on this platform\n");
2003 return;
2004 }
2005
2006 for (i = 0; i < sizeof(info_size)/sizeof(info_size[0]); i++)
2007 {
2008 memset(buf, 0, sizeof(buf));
2009
2010#ifdef __i386__
2012 {
2013 CONTEXT ctx;
2014 THREAD_DESCRIPTOR_INFORMATION *tdi = (void *)buf;
2015
2016 ctx.ContextFlags = CONTEXT_SEGMENTS;
2018 tdi->Selector = ctx.SegDs;
2019 }
2020#endif
2021 ret_len = 0;
2022 status = pNtQueryInformationThread(thread, i, buf, info_size[i], &ret_len);
2023 if (status == STATUS_NOT_IMPLEMENTED) continue;
2024 if (status == STATUS_INVALID_INFO_CLASS) continue;
2025 if (status == STATUS_UNSUCCESSFUL) continue;
2026
2027 switch (i)
2028 {
2032 ok(status == STATUS_SUCCESS, "for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i, status, ret_len);
2033 break;
2034
2035#ifdef __i386__
2037 ok(status == STATUS_SUCCESS || broken(status == STATUS_ACCESS_DENIED) /* testbot VM is broken */,
2038 "for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i, status, ret_len);
2039 break;
2040#endif
2041
2042 case ThreadTimes:
2044 ok(status == STATUS_SUCCESS, "for info %u expected STATUS_SUCCESS, got %08x (ret_len %u)\n", i, status, ret_len);
2045 break;
2046
2047 case ThreadAffinityMask:
2049 case ThreadIsIoPending:
2051 ok(status == STATUS_ACCESS_DENIED, "for info %u expected STATUS_ACCESS_DENIED, got %08x (ret_len %u)\n", i, status, ret_len);
2052 break;
2053
2054 default:
2055 ok(status == STATUS_ACCESS_DENIED, "for info %u expected STATUS_ACCESS_DENIED, got %08x (ret_len %u)\n", i, status, ret_len);
2056 break;
2057 }
2058 }
2059
2061}
2062
2063static void init_funcs(void)
2064{
2065 HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
2066 HMODULE ntdll = GetModuleHandleA("ntdll.dll");
2067
2068/* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
2069 so that the compile passes */
2070
2071#define X(f) p##f = (void*)GetProcAddress(hKernel32, #f)
2073 X(OpenThread);
2080 X(SetThreadErrorMode);
2081 X(GetThreadErrorMode);
2087
2088 X(CreateThreadpool);
2089 X(CloseThreadpool);
2090 X(CreateThreadpoolWork);
2091 X(SubmitThreadpoolWork);
2092 X(WaitForThreadpoolWorkCallbacks);
2093 X(CloseThreadpoolWork);
2094
2095 X(GetThreadGroupAffinity);
2096 X(SetThreadGroupAffinity);
2097
2098 X(FlsAlloc);
2099 X(FlsFree);
2100 X(FlsSetValue);
2101 X(FlsGetValue);
2102#undef X
2103
2104#define X(f) p##f = (void*)GetProcAddress(ntdll, #f)
2105 if (ntdll)
2106 {
2111 }
2112#undef X
2113}
2114
2116{
2117 int argc;
2118 char **argv;
2120
2121 init_funcs();
2122
2123 if (argc >= 3)
2124 {
2125 if (!strcmp(argv[2], "sleep"))
2126 {
2127 HANDLE hAddrEvents[2];
2128 create_function_addr_events(hAddrEvents);
2129 SetEvent(hAddrEvents[0]);
2130 SetEvent(hAddrEvents[1]);
2131 Sleep(5000); /* spawned process runs for at most 5 seconds */
2132 return;
2133 }
2134 while (1)
2135 {
2137 DWORD tid;
2139 ok(hThread != NULL, "CreateThread failed, error %u\n",
2140 GetLastError());
2142 "Thread did not exit in time\n");
2143 if (hThread == NULL) break;
2145 }
2146 return;
2147 }
2148
2161#ifdef __i386__
2162 test_SetThreadContext();
2163 test_GetThreadSelectorEntry();
2164 test_NtSetLdtEntries();
2165#endif
2168 test_TLS();
2169 test_FLS();
2171#if (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) || (defined(_MSC_VER) && defined(__i386__))
2172 test_thread_fpu_cw();
2173#endif
2175
2177}
unsigned char BOOLEAN
static int argc
Definition: ServiceArgs.c:12
#define broken(x)
Definition: _sntprintf.h:21
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
LONG NTSTATUS
Definition: precomp.h:26
#define U(x)
Definition: wordpad.c:45
static HANDLE thread
Definition: service.c:33
Definition: _stack.h:55
#define WAIT_TIMEOUT
Definition: dderror.h:14
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static HINSTANCE instance
Definition: main.c:40
#define NTSTATUS
Definition: precomp.h:21
#define CloseHandle
Definition: compat.h:739
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
struct _THREAD_BASIC_INFORMATION THREAD_BASIC_INFORMATION
#define CP_ACP
Definition: compat.h:109
#define SetLastError(x)
Definition: compat.h:752
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
@ ThreadDescriptorTableEntry
Definition: compat.h:941
@ ThreadAmILastThread
Definition: compat.h:947
@ ThreadTimes
Definition: compat.h:936
@ ThreadGroupInformation
Definition: compat.h:965
@ ThreadQuerySetWin32StartAddress
Definition: compat.h:944
@ ThreadAffinityMask
Definition: compat.h:939
@ ThreadBasicInformation
Definition: compat.h:935
@ ThreadPriorityBoost
Definition: compat.h:949
@ ThreadIsIoPending
Definition: compat.h:951
#define __TRY
Definition: compat.h:80
#define GetCurrentProcess()
Definition: compat.h:759
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
#define IsWow64Process
Definition: compat.h:760
#define MAX_PATH
Definition: compat.h:34
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
#define CreateFileW
Definition: compat.h:741
#define __ENDTRY
Definition: compat.h:82
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define CALLBACK
Definition: compat.h:35
#define MultiByteToWideChar
Definition: compat.h:110
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
static void cleanup(void)
Definition: main.c:1335
VOID WINAPI ReleaseActCtx(IN HANDLE hActCtx)
Definition: actctx.c:208
BOOL WINAPI DeactivateActCtx(IN DWORD dwFlags, IN ULONG_PTR ulCookie)
Definition: actctx.c:268
BOOL WINAPI GetCurrentActCtx(OUT PHANDLE phActCtx)
Definition: actctx.c:298
BOOL WINAPI ActivateActCtx(IN HANDLE hActCtx, OUT PULONG_PTR ulCookie)
Definition: actctx.c:237
PVOID WINAPI FlsGetValue(DWORD dwFlsIndex)
Definition: fiber.c:460
BOOL WINAPI FlsSetValue(DWORD dwFlsIndex, PVOID lpFlsData)
Definition: fiber.c:481
BOOL WINAPI FlsFree(DWORD dwFlsIndex)
Definition: fiber.c:400
DWORD WINAPI FlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback)
Definition: fiber.c:341
BOOL WINAPI DeleteFileA(IN LPCSTR lpFileName)
Definition: delete.c:24
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
BOOL WINAPI DuplicateHandle(IN HANDLE hSourceProcessHandle, IN HANDLE hSourceHandle, IN HANDLE hTargetProcessHandle, OUT LPHANDLE lpTargetHandle, IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwOptions)
Definition: handle.c:149
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
Definition: proc.c:4741
BOOL WINAPI TerminateProcess(IN HANDLE hProcess, IN UINT uExitCode)
Definition: proc.c:1532
BOOL WINAPI GetProcessAffinityMask(IN HANDLE hProcess, OUT PDWORD_PTR lpProcessAffinityMask, OUT PDWORD_PTR lpSystemAffinityMask)
Definition: proc.c:863
VOID WINAPI GetSystemInfo(IN LPSYSTEM_INFO lpSystemInfo)
Definition: sysinfo.c:143
LPVOID WINAPI TlsGetValue(IN DWORD Index)
Definition: thread.c:1240
DWORD WINAPI ResumeThread(IN HANDLE hThread)
Definition: thread.c:567
BOOL WINAPI SetThreadPriority(IN HANDLE hThread, IN int nPriority)
Definition: thread.c:700
HANDLE WINAPI CreateRemoteThread(IN HANDLE hProcess, IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:159
DWORD_PTR WINAPI SetThreadAffinityMask(IN HANDLE hThread, IN DWORD_PTR dwThreadAffinityMask)
Definition: thread.c:662
BOOL WINAPI SetThreadContext(IN HANDLE hThread, IN CONST CONTEXT *lpContext)
Definition: thread.c:521
DWORD WINAPI TlsAlloc(VOID)
Definition: thread.c:1100
DWORD WINAPI SuspendThread(IN HANDLE hThread)
Definition: thread.c:642
BOOL NTAPI GetThreadTimes(IN HANDLE hThread, OUT LPFILETIME lpCreationTime, OUT LPFILETIME lpExitTime, OUT LPFILETIME lpKernelTime, OUT LPFILETIME lpUserTime)
Definition: thread.c:469
VOID WINAPI ExitThread(IN DWORD uExitCode)
Definition: thread.c:365
HANDLE WINAPI OpenThread(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwThreadId)
Definition: thread.c:403
BOOL WINAPI QueueUserWorkItem(IN LPTHREAD_START_ROUTINE Function, IN PVOID Context, IN ULONG Flags)
Definition: thread.c:1076
BOOL WINAPI TlsSetValue(IN DWORD Index, IN LPVOID Value)
Definition: thread.c:1276
BOOL WINAPI GetThreadSelectorEntry(IN HANDLE hThread, IN DWORD dwSelector, OUT LPLDT_ENTRY lpSelectorEntry)
Definition: thread.c:830
DWORD WINAPI SetThreadIdealProcessor(IN HANDLE hThread, IN DWORD dwIdealProcessor)
Definition: thread.c:866
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
BOOL WINAPI TerminateThread(IN HANDLE hThread, IN DWORD dwExitCode)
Definition: thread.c:587
BOOL WINAPI TlsFree(IN DWORD Index)
Definition: thread.c:1166
BOOL WINAPI GetThreadPriorityBoost(IN HANDLE hThread, OUT PBOOL pDisablePriorityBoost)
Definition: thread.c:778
BOOL NTAPI SetThreadPriorityBoost(IN HANDLE hThread, IN BOOL bDisablePriorityBoost)
Definition: thread.c:804
int WINAPI GetThreadPriority(IN HANDLE hThread)
Definition: thread.c:739
BOOL WINAPI GetExitCodeThread(IN HANDLE hThread, OUT LPDWORD lpExitCode)
Definition: thread.c:541
BOOL WINAPI GetThreadContext(IN HANDLE hThread, OUT LPCONTEXT lpContext)
Definition: thread.c:501
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:455
HANDLE WINAPI CreateActCtxW(PCACTCTXW pActCtx)
Definition: actctx.c:104
BOOL is_wow64
Definition: msi.c:54
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define assert(x)
Definition: debug.h:53
KAFFINITY affinity
Definition: wave.h:2
#define INFINITE
Definition: serial.h:102
#define MAXIMUM_PROCESSORS
Definition: rwlock.h:5
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
FxCollectionEntry * cur
GLsizeiptr size
Definition: glext.h:5919
struct _cl_event * event
Definition: glext.h:7739
GLuint res
Definition: glext.h:9613
GLuint buffer
Definition: glext.h:5915
GLenum GLint GLuint mask
Definition: glext.h:6028
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLint limit
Definition: glext.h:10326
GLenum mode
Definition: glext.h:6217
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint GLfloat * val
Definition: glext.h:7180
GLfloat GLfloat p
Definition: glext.h:8902
GLuint GLuint num
Definition: glext.h:9618
GLfloat param
Definition: glext.h:5796
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define THREAD_QUERY_INFORMATION
Definition: pstypes.h:149
REFIID LPVOID DWORD_PTR dw
Definition: atlbase.h:40
NTSYSAPI DWORD WINAPI RtlGetThreadErrorMode(void)
Definition: error.c:217
struct _THREAD_DESCRIPTOR_INFORMATION THREAD_DESCRIPTOR_INFORMATION
#define THREAD_SUSPEND_RESUME
const char * filename
Definition: ioapi.h:137
#define NtCurrentTeb
uint32_t entry
Definition: isohybrid.c:63
#define b
Definition: ke_i.h:79
#define actctx
Definition: kernel32.h:8
int WINAPI lstrlenA(LPCSTR lpString)
Definition: lstring.c:145
#define alloca
Definition: malloc.h:357
_In_ BOOL _In_ HANDLE hProcess
Definition: mapping.h:71
#define error(str)
Definition: mkdosfs.c:1605
#define CREATE_ALWAYS
Definition: disk.h:72
HANDLE hKernel32
Definition: locale.c:13
#define sprintf(buf, format,...)
Definition: sprintf.c:55
HANDLE events[2]
Definition: event.c:4
static DWORD GLE
Definition: registry.c:38
#define THREAD_QUERY_LIMITED_INFORMATION
Definition: security.c:62
static void test_create(void)
Definition: monthcal.c:1595
static HANDLE hEvent
Definition: comm.c:54
static JOBOBJECTINFOCLASS LPVOID DWORD LPDWORD ret_len
Definition: process.c:79
static HANDLE ULONG_PTR DWORD threads
Definition: process.c:81
static const char * LS_SetValueFuncName
Definition: thread.c:1339
static DWORD LS_index1
Definition: thread.c:1327
static DWORD WINAPI threadFunc1(LPVOID p)
Definition: thread.c:212
static const char * LS_AllocFuncName
Definition: thread.c:1337
static DWORD CALLBACK work_function(void *p)
Definition: thread.c:1218
static VOID test_GetThreadTimes(void)
Definition: thread.c:793
static WAITORTIMERCALLBACK
Definition: thread.c:81
static void test_thread_actctx(void)
Definition: thread.c:1812
static VOID test_CreateThread_stack(void)
Definition: thread.c:646
static void test_threadpool(void)
Definition: thread.c:1898
static VOID test_SuspendThread(void)
Definition: thread.c:554
static const char manifest_dep[]
Definition: thread.c:1756
static void create_function_addr_events(HANDLE events[2])
Definition: thread.c:316
static DWORD WINAPI threadFunc3(LPVOID p)
Definition: thread.c:245
static const char * LS_FreeFuncName
Definition: thread.c:1340
static DWORD LS_main
Definition: thread.c:1326
static void cleanup_thread_sync_helpers(void)
Definition: thread.c:180
#define X(f)
static BOOL
Definition: thread.c:77
static void CALLBACK timeout_function(PVOID p, BOOLEAN TimerOrWaitFired)
Definition: thread.c:1262
static HANDLE
Definition: thread.c:81
static DWORD WINAPI LS_InheritanceProc(LPVOID p)
Definition: thread.c:1354
static VOID test_CreateThread_basic(void)
Definition: thread.c:418
static DWORD WINAPI threadFunc_SetEvent(LPVOID p)
Definition: thread.c:283
static VOID test_CreateThread_suspended(void)
Definition: thread.c:515
static void test_RegisterWaitForSingleObject(void)
Definition: thread.c:1269
static THREADINFOCLASS
Definition: thread.c:98
#define ARCH
Definition: thread.c:73
static ULONG
Definition: thread.c:78
static void create_manifest_file(const char *filename, const char *manifest)
Definition: thread.c:1772
static HANDLE finish_event
Definition: thread.c:1215
static INT obeying_ars
Definition: thread.c:197
static DWORD WINAPI threadFunc_CloseHandle(LPVOID p)
Definition: thread.c:289
static HANDLE create_target_process(const char *arg)
Definition: thread.c:104
#define NUM_THREADS
Definition: thread.c:42
#define THREAD_ALL_ACCESS_NT4
Definition: thread.c:39
static VOID test_thread_processor(void)
Definition: thread.c:850
static VOID test_thread_priority(void)
Definition: thread.c:673
static VOID test_CreateRemoteThread(void)
Definition: thread.c:328
static DWORD
Definition: thread.c:77
static DWORD WINAPI threadFunc4(LPVOID p)
Definition: thread.c:253
static DWORD tlsIndex
Definition: thread.c:186
static PBOOL
Definition: thread.c:76
static void test_reserved_tls(void)
Definition: thread.c:1922
static void WINAPI threadpool_workcallback(PTP_CALLBACK_INSTANCE instance, void *context, PTP_WORK work)
Definition: thread.c:1891
#define obey_ar(x)
Definition: thread.c:198
static void CALLBACK signaled_function(PVOID p, BOOLEAN TimerOrWaitFired)
Definition: thread.c:1255
static HANDLE stop_event
Definition: thread.c:135
static DWORD WINAPI threadFunc2(LPVOID p)
Definition: thread.c:240
static DWORD WINAPI thread_actctx_func(void *p)
Definition: thread.c:301
static PVOID
Definition: thread.c:78
static void resync_after_run(void)
Definition: thread.c:164
static GROUP_AFFINITY *static const GROUP_AFFINITY GROUP_AFFINITY *static LPCVOID
Definition: thread.c:101
static DWORD LS_index0
Definition: thread.c:1327
static void test_FLS(void)
Definition: thread.c:1551
static void run_LS_tests(void)
Definition: thread.c:1500
static HANDLE start_event
Definition: thread.c:135
static DWORD WINAPI LS_ThreadProc(LPVOID p)
Definition: thread.c:1375
static VOID test_TerminateThread(void)
Definition: thread.c:609
static ULONG_PTR
Definition: thread.c:89
static BOOL sync_threads_and_run_one(DWORD sync_id, DWORD my_id)
Definition: thread.c:147
static LONG num_synced
Definition: thread.c:136
static void init_funcs(void)
Definition: thread.c:2063
static void test_QueueUserWorkItem(void)
Definition: thread.c:1227
static DWORD WINAPI FLS_AllocFuncThunk(void)
Definition: thread.c:1349
static PDWORD
Definition: thread.c:84
static PTP_CALLBACK_ENVIRON
Definition: thread.c:94
static void init_thread_sync_helpers(void)
Definition: thread.c:138
static void test_TLS(void)
Definition: thread.c:1534
static LONG times_executed
Definition: thread.c:1216
static void test_thread_info(void)
Definition: thread.c:1959
static void test_ThreadErrorMode(void)
Definition: thread.c:1574
static PULONG
Definition: thread.c:98
static const char * LS_GetValueFuncName
Definition: thread.c:1338
static VOID test_GetThreadExitCode(void)
Definition: thread.c:993
static DWORD LS_OutOfIndexesValue
Definition: thread.c:1328
static const char manifest_main[]
Definition: thread.c:1762
static TfClientId tid
#define todo_wine
Definition: custom.c:79
static int test_value
Definition: signal.c:25
static refpint_t pi[]
Definition: server.c:96
static HANDLE complete_event
Definition: url.c:179
#define argv
Definition: mplay32.c:18
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
#define SEM_FAILCRITICALERRORS
Definition: rtltypes.h:69
#define SEM_NOGPFAULTERRORBOX
Definition: rtltypes.h:70
#define SEM_NOOPENFILEERRORBOX
Definition: rtltypes.h:72
HANDLE hThread
Definition: wizard.c:28
#define CONTEXT_CONTROL
Definition: nt_native.h:1369
#define THREAD_TERMINATE
Definition: nt_native.h:1336
#define CONTEXT_SEGMENTS
Definition: nt_native.h:1371
#define CONTEXT_FULL
Definition: nt_native.h:1375
#define GENERIC_WRITE
Definition: nt_native.h:90
#define THREAD_SET_INFORMATION
Definition: nt_native.h:1337
NTSTATUS NTAPI NtSetLdtEntries(ULONG Selector1, LDT_ENTRY LdtEntry1, ULONG Selector2, LDT_ENTRY LdtEntry2)
Definition: stubs.c:185
NTSTATUS NTAPI NtQueryInformationThread(IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, OUT PVOID ThreadInformation, IN ULONG ThreadInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: query.c:2624
NTSTATUS NTAPI NtSetInformationThread(IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, IN PVOID ThreadInformation, IN ULONG ThreadInformationLength)
Definition: query.c:2018
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_INVALID_LDT_DESCRIPTOR
Definition: ntstatus.h:518
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:240
#define BOOLEAN
Definition: pedump.c:73
long LONG
Definition: pedump.c:60
__asm__(".p2align 4, 0x90\n" ".seh_proc __seh2_global_filter_func\n" "__seh2_global_filter_func:\n" "\tpush %rbp\n" "\t.seh_pushreg %rbp\n" "\tsub $32, %rsp\n" "\t.seh_stackalloc 32\n" "\t.seh_endprologue\n" "\tmov %rdx, %rbp\n" "\tjmp *%rax\n" "__seh2_global_filter_func_exit:\n" "\t.p2align 4\n" "\tadd $32, %rsp\n" "\tpop %rbp\n" "\tret\n" "\t.seh_endproc")
#define __EXCEPT(func)
Definition: exception.h:84
#define win_skip
Definition: test.h:160
int winetest_get_mainargs(char ***pargv)
#define memset(x, y, z)
Definition: compat.h:39
#define STATUS_SUCCESS
Definition: shellext.h:65
static DWORD tls
Definition: sock.c:229
TCHAR * cmdline
Definition: stretchblt.cpp:32
DWORD dwHighDateTime
Definition: mapidefs.h:66
DWORD dwLowDateTime
Definition: mapidefs.h:65
$USHORT Group
Definition: ntbasedef.h:661
KAFFINITY Mask
Definition: ntbasedef.h:660
Definition: compat.h:777
DWORD cb
Definition: winbase.h:831
DWORD dwPageSize
Definition: winbase.h:1173
DWORD dwNumberOfProcessors
Definition: winbase.h:1177
Definition: http.c:7252
Definition: cookie.c:34
Definition: fci.c:127
Definition: ps.c:97
int threadnum
Definition: thread.c:189
DWORD * threadmem
Definition: thread.c:191
HANDLE * event
Definition: thread.c:190
HANDLE thread_context
Definition: thread.c:297
DWORD WINAPI WaitForMultipleObjects(IN DWORD nCount, IN CONST HANDLE *lpHandles, IN BOOL bWaitAll, IN DWORD dwMilliseconds)
Definition: synch.c:151
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventA(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCSTR lpName OPTIONAL)
Definition: synch.c:637
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:651
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
BOOL WINAPI DECLSPEC_HOTPATCH ResetEvent(IN HANDLE hEvent)
Definition: synch.c:714
BOOL WINAPI RegisterWaitForSingleObject(OUT PHANDLE phNewWaitObject, IN HANDLE hObject, IN WAITORTIMERCALLBACK Callback, IN PVOID Context, IN ULONG dwMilliseconds, IN ULONG dwFlags)
Definition: synch.c:850
BOOL WINAPI UnregisterWait(IN HANDLE WaitHandle)
Definition: synch.c:934
__inline int before(__u32 seq1, __u32 seq2)
Definition: tcpcore.h:2390
__inline int after(__u32 seq1, __u32 seq2)
Definition: tcpcore.h:2395
#define LONG_PTR
Definition: treelist.c:79
int32_t INT_PTR
Definition: typedefs.h:64
uint32_t DWORD_PTR
Definition: typedefs.h:65
union _LARGE_INTEGER LARGE_INTEGER
int32_t INT
Definition: typedefs.h:58
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
#define HIWORD(l)
Definition: typedefs.h:247
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
static const CHAR manifest[]
Definition: v6util.h:39
int ret
#define STILL_ACTIVE
Definition: winbase.h:233
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
HANDLE WINAPI GetCurrentThread(void)
Definition: proc.c:1148
#define FLS_OUT_OF_INDEXES
Definition: winbase.h:576
DWORD WINAPI GetCurrentThreadId(void)
Definition: thread.c:459
#define CREATE_SUSPENDED
Definition: winbase.h:178
VOID(WINAPI * PFLS_CALLBACK_FUNCTION)(PVOID)
Definition: winbase.h:1444
#define TLS_OUT_OF_INDEXES
Definition: winbase.h:549
#define WAIT_OBJECT_0
Definition: winbase.h:406
#define THREAD_PRIORITY_TIME_CRITICAL
Definition: winbase.h:281
DWORD(WINAPI * LPTHREAD_START_ROUTINE)(LPVOID)
Definition: winbase.h:729
#define THREAD_PRIORITY_ERROR_RETURN
Definition: winbase.h:282
#define THREAD_PRIORITY_NORMAL
Definition: winbase.h:280
#define THREAD_PRIORITY_IDLE
Definition: winbase.h:278
#define WINAPI
Definition: msvc.h:6
#define ERROR_INVALID_PRIORITY
Definition: winerror.h:1107
#define ERROR_GEN_FAILURE
Definition: winerror.h:134
#define ERROR_NOACCESS
Definition: winerror.h:578
struct _TP_CALLBACK_INSTANCE * PTP_CALLBACK_INSTANCE
Definition: winnt_old.h:4453
#define WT_EXECUTEONLYONCE
Definition: winnt_old.h:1042
struct _TP_WORK * PTP_WORK
Definition: winnt_old.h:4452
VOID(NTAPI * PTP_WORK_CALLBACK)(_Inout_ PTP_CALLBACK_INSTANCE Instance, _Inout_opt_ PVOID Context, _Inout_ PTP_WORK Work)
Definition: winnt_old.h:4466
struct _TP_POOL * PTP_POOL
Definition: winnt_old.h:4451
#define WT_EXECUTEDEFAULT
Definition: winnt_old.h:1038
#define DUPLICATE_SAME_ACCESS
__wchar_t WCHAR
Definition: xmlstorage.h:180