ReactOS 0.4.16-dev-2206-gc56950d
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#include <float.h>
25#include <math.h>
26
27/* the tests intentionally pass invalid pointers and need an exception handler */
28#define WINE_NO_INLINE_STRING
29
30#include <ntstatus.h>
31#define WIN32_NO_STATUS
32#include <windef.h>
33#include <winbase.h>
34#include <winnt.h>
35#include <winerror.h>
36#include <winnls.h>
37#include <winternl.h>
38#include "wine/test.h"
39
40/* THREAD_ALL_ACCESS in Vista+ PSDKs is incompatible with older Windows versions */
41#define THREAD_ALL_ACCESS_NT4 (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3ff)
42
43/* Specify the number of simultaneous threads to test */
44#define NUM_THREADS 4
45/* Specify whether to test the extended priorities for Win2k/XP */
46#define USE_EXTENDED_PRIORITIES 0
47/* Specify whether to test the stack allocation in CreateThread */
48#define CHECK_STACK 0
49
50/* Set CHECK_STACK to 1 if you want to try to test the stack-limit from
51 CreateThread. So far I have been unable to make this work, and
52 I am in doubt as to how portable it is. Also, according to MSDN,
53 you shouldn't mix C-run-time-libraries (i.e. alloca) with CreateThread.
54 Anyhow, the check is currently commented out
55*/
56#if CHECK_STACK
57# ifdef __try
58# define __TRY __try
59# define __EXCEPT __except
60# define __ENDTRY
61# else
62# include "wine/exception.h"
63# endif
64#endif
65
66#ifdef __i386__
67#define ARCH "x86"
68#elif defined __x86_64__
69#define ARCH "amd64"
70#elif defined __arm__
71#define ARCH "arm"
72#elif defined __aarch64__
73#define ARCH "arm64"
74#else
75#define ARCH "none"
76#endif
77
78static void (WINAPI *pGetCurrentThreadStackLimits)(PULONG_PTR,PULONG_PTR);
79static BOOL (WINAPI *pGetThreadPriorityBoost)(HANDLE,PBOOL);
80static HANDLE (WINAPI *pOpenThread)(DWORD,BOOL,DWORD);
81static BOOL (WINAPI *pQueueUserWorkItem)(LPTHREAD_START_ROUTINE,PVOID,ULONG);
82static BOOL (WINAPI *pSetThreadPriorityBoost)(HANDLE,BOOL);
83static BOOL (WINAPI *pSetThreadStackGuarantee)(ULONG*);
84static BOOL (WINAPI *pRegisterWaitForSingleObject)(PHANDLE,HANDLE,WAITORTIMERCALLBACK,PVOID,ULONG,ULONG);
85static BOOL (WINAPI *pUnregisterWait)(HANDLE);
86static BOOL (WINAPI *pIsWow64Process)(HANDLE,PBOOL);
87static BOOL (WINAPI *pSetThreadErrorMode)(DWORD,PDWORD);
88static DWORD (WINAPI *pGetThreadErrorMode)(void);
89static DWORD (WINAPI *pRtlGetThreadErrorMode)(void);
90static PTP_POOL (WINAPI *pCreateThreadpool)(PVOID);
91static void (WINAPI *pCloseThreadpool)(PTP_POOL);
93static void (WINAPI *pSubmitThreadpoolWork)(PTP_WORK);
94static void (WINAPI *pWaitForThreadpoolWorkCallbacks)(PTP_WORK,BOOL);
95static void (WINAPI *pCloseThreadpoolWork)(PTP_WORK);
96static NTSTATUS (WINAPI *pNtQueryInformationThread)(HANDLE,THREADINFOCLASS,PVOID,ULONG,PULONG);
97static BOOL (WINAPI *pGetThreadGroupAffinity)(HANDLE,GROUP_AFFINITY*);
98static BOOL (WINAPI *pSetThreadGroupAffinity)(HANDLE,const GROUP_AFFINITY*,GROUP_AFFINITY*);
99static NTSTATUS (WINAPI *pNtSetInformationThread)(HANDLE,THREADINFOCLASS,LPCVOID,ULONG);
100static HRESULT (WINAPI *pSetThreadDescription)(HANDLE,const WCHAR *);
101static HRESULT (WINAPI *pGetThreadDescription)(HANDLE,WCHAR **);
102static PVOID (WINAPI *pRtlAddVectoredExceptionHandler)(ULONG,PVECTORED_EXCEPTION_HANDLER);
103static ULONG (WINAPI *pRtlRemoveVectoredExceptionHandler)(PVOID);
104
106{
107 char **argv;
108 char cmdline[MAX_PATH];
110 BOOL ret;
111 STARTUPINFOA si = { 0 };
112 si.cb = sizeof(si);
113
115 sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
117 ok(ret, "error: %lu\n", GetLastError());
119 ok(ret, "error %lu\n", GetLastError());
120 return pi.hProcess;
121}
122
123/* Functions not tested yet:
124 AttachThreadInput
125 SetThreadContext
126 SwitchToThread
127
128In addition there are no checks that the inheritance works properly in
129CreateThread
130*/
131
132/* Functions to ensure that from a group of threads, only one executes
133 certain chunks of code at a time, and we know which one is executing
134 it. It basically makes multithreaded execution linear, which defeats
135 the purpose of multiple threads, but makes testing easy. */
138
140{
142 ok(start_event != NULL, "CreateEvent failed\n");
144 ok(stop_event != NULL, "CreateEvent failed\n");
145 num_synced = -1;
146}
147
149{
151 assert(-1 <= num && num <= 1);
152 if (num == 1)
153 {
156 }
157 else
158 {
160 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed %lx\n",ret);
161 }
162 return sync_id == my_id;
163}
164
165static void resync_after_run(void)
166{
168 assert(-1 <= num && num <= 1);
169 if (num == -1)
170 {
173 }
174 else
175 {
177 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
178 }
179}
180
182{
185}
186
188
189typedef struct {
193} t1Struct;
194
195/* WinME supports OpenThread but doesn't know about access restrictions so
196 we require them to be either completely ignored or always obeyed.
197*/
198static INT obeying_ars = 0; /* -1 == no, 0 == dunno yet, 1 == yes */
199#define obey_ar(x) \
200 (obeying_ars == 0 \
201 ? ((x) \
202 ? (obeying_ars = +1) \
203 : ((obeying_ars = -1), \
204 trace("not restricted, assuming consistent behaviour\n"))) \
205 : (obeying_ars < 0) \
206 ? ok(!(x), "access restrictions obeyed\n") \
207 : ok( (x), "access restrictions not obeyed\n"))
208
209/* Basic test that simultaneous threads can access shared memory,
210 that the thread local storage routines work correctly, and that
211 threads actually run concurrently
212*/
214{
215 t1Struct *tstruct = p;
216 int i;
217/* write our thread # into shared memory */
218 tstruct->threadmem[tstruct->threadnum]=GetCurrentThreadId();
219 ok(TlsSetValue(tlsIndex,(LPVOID)(INT_PTR)(tstruct->threadnum+1))!=0,
220 "TlsSetValue failed\n");
221/* The threads synchronize before terminating. This is done by
222 Signaling an event, and waiting for all events to occur
223*/
224 SetEvent(tstruct->event[tstruct->threadnum]);
226/* Double check that all threads really did run by validating that
227 they have all written to the shared memory. There should be no race
228 here, since all threads were synchronized after the write.*/
229 for (i = 0; i < NUM_THREADS; i++)
230 ok(tstruct->threadmem[i] != 0, "expected threadmem[%d] != 0\n", i);
231
232 /* lstrlenA contains an exception handler so this makes sure exceptions work in threads */
233 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
234
235/* Check that no one changed our tls memory */
237 "TlsGetValue failed\n");
238 return NUM_THREADS+tstruct->threadnum;
239}
240
242{
243 return 99;
244}
245
247{
251 return 99;
252}
253
255{
256 HANDLE event = p;
257 if(event != NULL) {
259 }
260 Sleep(99000);
261 return 0;
262}
263
264#if CHECK_STACK
265static DWORD WINAPI threadFunc5(LPVOID p)
266{
267 DWORD *exitCode = p;
268 SYSTEM_INFO sysInfo;
269 sysInfo.dwPageSize=0;
270 GetSystemInfo(&sysInfo);
271 *exitCode=0;
272 __TRY
273 {
274 alloca(2*sysInfo.dwPageSize);
275 }
276 __EXCEPT(1) {
277 *exitCode=1;
278 }
280 return 0;
281}
282#endif
283
285{
286 SetEvent(p);
287 return 0;
288}
289
291{
292 CloseHandle(p);
293 return 0;
294}
295
297{
300};
301
303{
305 HANDLE cur;
306 BOOL ret;
307
308 cur = (void*)0xdeadbeef;
310 ok(ret, "thread GetCurrentActCtx failed, %lu\n", GetLastError());
311 ok(cur == param->handle, "got %p, expected %p\n", cur, param->handle);
312 param->thread_context = cur;
313
314 return 0;
315}
316
318{
319 char buffer[256];
320
321 sprintf(buffer, "threadFunc_SetEvent %p", threadFunc_SetEvent);
323
324 sprintf(buffer, "threadFunc_CloseHandle %p", threadFunc_CloseHandle);
326}
327
328/* check CreateRemoteThread */
330{
331 HANDLE hProcess, hThread, hEvent, hRemoteEvent;
332 DWORD tid, ret, exitcode;
333 HANDLE hAddrEvents[2];
334
336 ok(hProcess != NULL, "Can't start process\n");
337
338 /* ensure threadFunc_SetEvent & threadFunc_CloseHandle are the same
339 * address as in the child process */
340 create_function_addr_events(hAddrEvents);
341 ret = WaitForMultipleObjects(2, hAddrEvents, TRUE, 5000);
342 if (ret == WAIT_TIMEOUT)
343 {
344 skip("child process wasn't mapped at same address, so can't do CreateRemoteThread tests.\n");
345 return;
346 }
347 ok(ret == WAIT_OBJECT_0 || broken(ret == WAIT_OBJECT_0+1 /* nt4,w2k */), "WaitForAllObjects 2 events %ld\n", ret);
348
350 ok(hEvent != NULL, "Can't create event, err=%lu\n", GetLastError());
353 ok(ret != 0, "DuplicateHandle failed, err=%lu\n", GetLastError());
354
355 /* create suspended remote thread with entry point SetEvent() */
356 SetLastError(0xdeadbeef);
358 hRemoteEvent, CREATE_SUSPENDED, &tid);
360 {
361 win_skip("CreateRemoteThread is not implemented\n");
362 goto cleanup;
363 }
364 ok(hThread != NULL, "CreateRemoteThread failed, err=%lu\n", GetLastError());
365 ok(tid != 0, "null tid\n");
367 ok(ret == 1, "ret=%lu, err=%lu\n", ret, GetLastError());
369 ok(ret == 2, "ret=%lu, err=%lu\n", ret, GetLastError());
370
371 /* thread still suspended, so wait times out */
373 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%lu\n", ret);
374
376 ok(ret == 1, "ret=%lu, err=%lu\n", ret, GetLastError());
377
378 /* wait that doesn't time out */
380 ok(ret == WAIT_OBJECT_0, "object not signaled, ret=%lu\n", ret);
381
382 /* wait for thread end */
384 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%lu\n", ret);
386
387 /* create and wait for remote thread with entry point CloseHandle() */
390 hRemoteEvent, 0, &tid);
391 ok(hThread != NULL, "CreateRemoteThread failed, err=%lu\n", GetLastError());
393 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%lu\n", ret);
395
396 /* create remote thread with entry point SetEvent() */
399 hRemoteEvent, 0, &tid);
400 ok(hThread != NULL, "CreateRemoteThread failed, err=%lu\n", GetLastError());
401
402 /* closed handle, so wait times out */
404 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%lu\n", ret);
405
406 /* check that remote SetEvent() failed */
407 ret = GetExitCodeThread(hThread, &exitcode);
408 ok(ret != 0, "GetExitCodeThread failed, err=%lu\n", GetLastError());
409 if (ret) ok(exitcode == 0, "SetEvent succeeded, expected to fail\n");
411
412cleanup:
416}
417
418/* Check basic functionality of CreateThread and Tls* functions */
420{
422 DWORD threadid[NUM_THREADS],curthreadId;
423 DWORD threadmem[NUM_THREADS];
424 DWORD exitCode;
425 t1Struct tstruct[NUM_THREADS];
426 int error;
427 DWORD i,j;
428 DWORD GLE, ret;
429 DWORD tid;
430 BOOL bRet;
431
432 /* lstrlenA contains an exception handler so this makes sure exceptions work in the main thread */
433 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
434
435/* Retrieve current Thread ID for later comparisons */
436 curthreadId=GetCurrentThreadId();
437/* Allocate some local storage */
438 ok((tlsIndex=TlsAlloc())!=TLS_OUT_OF_INDEXES,"TlsAlloc failed\n");
439/* Create events for thread synchronization */
440 for(i=0;i<NUM_THREADS;i++) {
441 threadmem[i]=0;
442/* Note that it doesn't matter what type of event we choose here. This
443 test isn't trying to thoroughly test events
444*/
446 tstruct[i].threadnum=i;
447 tstruct[i].threadmem=threadmem;
448 tstruct[i].event=event;
449 }
450
451/* Test that passing arguments to threads works okay */
452 for(i=0;i<NUM_THREADS;i++) {
454 &tstruct[i],0,&threadid[i]);
455 ok(thread[i]!=NULL,"Create Thread failed\n");
456 }
457/* Test that the threads actually complete */
458 for(i=0;i<NUM_THREADS;i++) {
460 ok(error==WAIT_OBJECT_0, "Thread did not complete within timelimit\n");
461 if(error!=WAIT_OBJECT_0) {
463 }
464 ok(GetExitCodeThread(thread[i],&exitCode),"Could not retrieve ext code\n");
465 ok(exitCode==i+NUM_THREADS,"Thread returned an incorrect exit code\n");
466 }
467/* Test that each thread executed in its parent's address space
468 (it was able to change threadmem and pass that change back to its parent)
469 and that each thread id was independent). Note that we prove that the
470 threads actually execute concurrently by having them block on each other
471 in threadFunc1
472*/
473 for(i=0;i<NUM_THREADS;i++) {
474 error=0;
475 for(j=i+1;j<NUM_THREADS;j++) {
476 if (threadmem[i]==threadmem[j]) {
477 error=1;
478 }
479 }
480 ok(!error && threadmem[i]==threadid[i] && threadmem[i]!=curthreadId,
481 "Thread did not execute successfully\n");
482 ok(CloseHandle(thread[i])!=0,"CloseHandle failed\n");
483 }
484
485 SetLastError(0xCAFEF00D);
486 bRet = TlsFree(tlsIndex);
487 ok(bRet, "TlsFree failed: %08lx\n", GetLastError());
488 ok(GetLastError()==0xCAFEF00D,
489 "GetLastError: expected 0xCAFEF00D, got %08lx\n", GetLastError());
490
491 /* Test freeing an already freed TLS index */
492 SetLastError(0xCAFEF00D);
493 ok(TlsFree(tlsIndex)==0,"TlsFree succeeded\n");
495 "GetLastError: expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
496
497 /* Test how passing NULL as a pointer to threadid works */
498 SetLastError(0xFACEaBAD);
500 GLE = GetLastError();
501 if (thread[0]) { /* NT */
502 ok(GLE==0xFACEaBAD, "CreateThread set last error to %ld, expected 4207848365\n", GLE);
504 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
505 ret = GetExitCodeThread(thread[0],&exitCode);
506 ok(ret!=0, "GetExitCodeThread returned %ld (expected nonzero)\n", ret);
507 ok(exitCode==99, "threadFunc2 exited with code: %ld (expected 99)\n", exitCode);
508 ok(CloseHandle(thread[0])!=0,"Error closing thread handle\n");
509 }
510 else { /* 9x */
511 ok(GLE==ERROR_INVALID_PARAMETER, "CreateThread set last error to %ld, expected 87\n", GLE);
512 }
513}
514
515/* Check that using the CREATE_SUSPENDED flag works */
517{
519 DWORD threadId;
520 DWORD suspend_count;
521 int error;
522
524 CREATE_SUSPENDED,&threadId);
525 ok(thread!=NULL,"Create Thread failed\n");
526/* Check that the thread is suspended */
527 ok(SuspendThread(thread)==1,"Thread did not start suspended\n");
528 ok(ResumeThread(thread)==2,"Resume thread returned an invalid value\n");
529/* Check that resume thread didn't actually start the thread. I can't think
530 of a better way of checking this than just waiting. I am not sure if this
531 will work on slow computers.
532*/
534 "ResumeThread should not have actually started the thread\n");
535/* Now actually resume the thread and make sure that it actually completes*/
536 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
538 "Thread did not resume\n");
539 if(error!=WAIT_OBJECT_0) {
541 }
542
543 suspend_count = SuspendThread(thread);
544 ok(suspend_count == -1, "SuspendThread returned %ld, expected -1\n", suspend_count);
545
546 suspend_count = ResumeThread(thread);
547 ok(suspend_count == 0 ||
548 broken(suspend_count == -1), /* win9x */
549 "ResumeThread returned %ld, expected 0\n", suspend_count);
550
551 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
552}
553
554/* Check that SuspendThread and ResumeThread work */
556{
557 HANDLE thread,access_thread;
558 DWORD threadId,exitCode,error;
559 int i;
560
562 0,&threadId);
563 ok(thread!=NULL,"Create Thread failed\n");
564/* Check that the thread is suspended */
565/* Note that this is a polling method, and there is a race between
566 SuspendThread being called (in the child, and the loop below timing out,
567 so the test could fail on a heavily loaded or slow computer.
568*/
569 error=0;
570 for(i=0;error==0 && i<100;i++) {
573 if(error==0) {
574 Sleep(50);
575 i++;
576 }
577 }
578 ok(error==1,"SuspendThread did not work\n");
579/* check that access restrictions are obeyed */
580 if (pOpenThread) {
581 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 & (~THREAD_SUSPEND_RESUME),
582 0,threadId);
583 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
584 if (access_thread!=NULL) {
585 obey_ar(SuspendThread(access_thread)==~0U);
586 obey_ar(ResumeThread(access_thread)==~0U);
587 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
588 }
589 }
590/* Double check that the thread really is suspended */
591 ok((error=GetExitCodeThread(thread,&exitCode))!=0 && exitCode==STILL_ACTIVE,
592 "Thread did not really suspend\n");
593/* Resume the thread, and make sure it actually completes */
594 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
596 "Thread did not resume\n");
597 if(error!=WAIT_OBJECT_0) {
599 }
600 /* Trying to suspend a terminated thread should fail */
602 ok(error==~0U, "wrong return code: %ld\n", error);
603 ok(GetLastError()==ERROR_ACCESS_DENIED || GetLastError()==ERROR_NO_MORE_ITEMS, "unexpected error code: %ld\n", GetLastError());
604
605 ok(CloseHandle(thread)!=0,"CloseHandle Failed\n");
606}
607
608/* Check that TerminateThread works properly
609*/
611{
612 HANDLE thread,access_thread,event;
613 DWORD threadId,exitCode;
615 thread = CreateThread(NULL,0,threadFunc4,event,0,&threadId);
616 ok(thread!=NULL,"Create Thread failed\n");
617/* TerminateThread has a race condition in Wine. If the thread is terminated
618 before it starts, it leaves a process behind. Therefore, we wait for the
619 thread to signal that it has started. There is no easy way to force the
620 race to occur, so we don't try to find it.
621*/
623 "TerminateThread didn't work\n");
624/* check that access restrictions are obeyed */
625 if (pOpenThread) {
626 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 & (~THREAD_TERMINATE),
627 0,threadId);
628 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
629 if (access_thread!=NULL) {
630 obey_ar(TerminateThread(access_thread,99)==0);
631 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
632 }
633 }
634/* terminate a job and make sure it terminates */
635 ok(TerminateThread(thread,99)!=0,"TerminateThread failed\n");
637 "TerminateThread didn't work\n");
639 "TerminateThread should not leave the thread 'STILL_ACTIVE'\n");
640 ok(exitCode==99, "TerminateThread returned invalid exit code\n");
641 ok(CloseHandle(thread)!=0,"Error Closing thread handle\n");
642}
643
644/* Check if CreateThread obeys the specified stack size. This code does
645 not work properly, and is currently disabled
646*/
648{
649#if CHECK_STACK
650/* The only way I know of to test the stack size is to use alloca
651 and __try/__except. However, this is probably not portable,
652 and I couldn't get it to work under Wine anyhow. However, here
653 is the code which should allow for testing that CreateThread
654 respects the stack-size limit
655*/
657 DWORD threadId,exitCode;
658
659 SYSTEM_INFO sysInfo;
660 sysInfo.dwPageSize=0;
661 GetSystemInfo(&sysInfo);
662 ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
664 threadFunc5,&exitCode,
665 0,&threadId);
667 "TerminateThread didn't work\n");
668 ok(exitCode==1,"CreateThread did not obey stack-size-limit\n");
669 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
670#endif
671}
672
673/* Check whether setting/retrieving thread priorities works */
675{
676 HANDLE curthread,access_thread;
677 DWORD curthreadId,exitCode;
678 int min_priority=-2,max_priority=2;
679 BOOL disabled,rc;
680 int i;
681
682 curthread=GetCurrentThread();
683 curthreadId=GetCurrentThreadId();
684/* Check thread priority */
685/* NOTE: on Win2k/XP priority can be from -7 to 6. All other platforms it
686 is -2 to 2. However, even on a real Win2k system, using thread
687 priorities beyond the -2 to 2 range does not work. If you want to try
688 anyway, enable USE_EXTENDED_PRIORITIES
689*/
691 "GetThreadPriority Failed\n");
692
693 if (pOpenThread) {
694/* check that access control is obeyed */
695 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 &
697 0,curthreadId);
698 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
699 if (access_thread!=NULL) {
700 obey_ar(SetThreadPriority(access_thread,1)==0);
702 obey_ar(GetExitCodeThread(access_thread,&exitCode)==0);
703 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
704 }
705 }
706#if USE_EXTENDED_PRIORITIES
707 min_priority=-7; max_priority=6;
708#endif
709 for(i=min_priority;i<=max_priority;i++) {
710 ok(SetThreadPriority(curthread,i)!=0,
711 "SetThreadPriority Failed for priority: %d\n",i);
712 ok(GetThreadPriority(curthread)==i,
713 "GetThreadPriority Failed for priority: %d\n",i);
714 }
716 "SetThreadPriority Failed\n");
718 "GetThreadPriority Failed\n");
720 "SetThreadPriority Failed\n");
722 "GetThreadPriority Failed\n");
723 ok(SetThreadPriority(curthread,0)!=0,"SetThreadPriority Failed\n");
724
725/* Check that the thread priority is not changed if SetThreadPriority
726 is called with a value outside of the max/min range */
727 SetThreadPriority(curthread,min_priority);
728 SetLastError(0xdeadbeef);
729 rc = SetThreadPriority(curthread,min_priority-1);
730
731 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
733 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
734 "SetThreadPriority error %ld, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
735 GetLastError());
736 ok(GetThreadPriority(curthread)==min_priority,
737 "GetThreadPriority didn't return min_priority\n");
738
739 SetThreadPriority(curthread,max_priority);
740 SetLastError(0xdeadbeef);
741 rc = SetThreadPriority(curthread,max_priority+1);
742
743 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
745 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
746 "SetThreadPriority error %ld, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
747 GetLastError());
748 ok(GetThreadPriority(curthread)==max_priority,
749 "GetThreadPriority didn't return max_priority\n");
750
751/* Check thread priority boost */
752 if (!pGetThreadPriorityBoost || !pSetThreadPriorityBoost)
753 return; /* Win9x */
754
755 SetLastError(0xdeadbeef);
756 rc=pGetThreadPriorityBoost(curthread,&disabled);
758 {
759 win_skip("GetThreadPriorityBoost is not implemented on WinME\n");
760 return;
761 }
762
763 ok(rc!=0,"error=%ld\n",GetLastError());
764
765 if (pOpenThread) {
766/* check that access control is obeyed */
767 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 &
769 0,curthreadId);
770 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
771 if (access_thread!=NULL) {
772 todo_wine obey_ar(pSetThreadPriorityBoost(access_thread,1)==0);
773 todo_wine obey_ar(pGetThreadPriorityBoost(access_thread,&disabled)==0);
774 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
775 }
776 }
777
778 rc = pSetThreadPriorityBoost(curthread,1);
779 ok( rc != 0, "error=%ld\n",GetLastError());
780 todo_wine {
781 rc=pGetThreadPriorityBoost(curthread,&disabled);
782 ok(rc!=0 && disabled==1,
783 "rc=%d error=%ld disabled=%d\n",rc,GetLastError(),disabled);
784 }
785
786 rc = pSetThreadPriorityBoost(curthread,0);
787 ok( rc != 0, "error=%ld\n",GetLastError());
788 rc=pGetThreadPriorityBoost(curthread,&disabled);
789 ok(rc!=0 && disabled==0,
790 "rc=%d error=%ld disabled=%d\n",rc,GetLastError(),disabled);
791}
792
793/* check the GetThreadTimes function */
795{
796 HANDLE thread,access_thread=NULL;
797 FILETIME creationTime,exitTime,kernelTime,userTime;
798 DWORD threadId;
799 int error;
800
802 CREATE_SUSPENDED,&threadId);
803
804 ok(thread!=NULL,"Create Thread failed\n");
805/* check that access control is obeyed */
806 if (pOpenThread) {
807 access_thread=pOpenThread(THREAD_ALL_ACCESS_NT4 &
808 (~THREAD_QUERY_INFORMATION), 0,threadId);
809 ok(access_thread!=NULL,
810 "OpenThread returned an invalid handle\n");
811 }
812 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
814 "ResumeThread didn't work\n");
815 creationTime.dwLowDateTime=99; creationTime.dwHighDateTime=99;
816 exitTime.dwLowDateTime=99; exitTime.dwHighDateTime=99;
817 kernelTime.dwLowDateTime=99; kernelTime.dwHighDateTime=99;
818 userTime.dwLowDateTime=99; userTime.dwHighDateTime=99;
819/* GetThreadTimes should set all of the parameters passed to it */
820 error=GetThreadTimes(thread,&creationTime,&exitTime,
821 &kernelTime,&userTime);
822
824 win_skip("GetThreadTimes is not implemented\n");
825 else {
826 ok(error!=0,"GetThreadTimes failed\n");
827 ok(creationTime.dwLowDateTime!=99 || creationTime.dwHighDateTime!=99,
828 "creationTime was invalid\n");
829 ok(exitTime.dwLowDateTime!=99 || exitTime.dwHighDateTime!=99,
830 "exitTime was invalid\n");
831 ok(kernelTime.dwLowDateTime!=99 || kernelTime.dwHighDateTime!=99,
832 "kernelTimewas invalid\n");
833 ok(userTime.dwLowDateTime!=99 || userTime.dwHighDateTime!=99,
834 "userTime was invalid\n");
835 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
836 if(access_thread!=NULL)
837 {
838 error=GetThreadTimes(access_thread,&creationTime,&exitTime,
839 &kernelTime,&userTime);
840 obey_ar(error==0);
841 }
842 }
843 if(access_thread!=NULL) {
844 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
845 }
846}
847
848/* Check the processor affinity functions */
849/* NOTE: These functions should also be checked that they obey access control
850*/
852{
853 HANDLE curthread,curproc;
854 DWORD_PTR processMask,systemMask,retMask;
855 SYSTEM_INFO sysInfo;
856 BOOL is_wow64, old_wow64 = FALSE;
857 DWORD ret;
858
859 if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
860
861 if (is_wow64)
862 {
863 TEB64 *teb64 = ULongToPtr(NtCurrentTeb()->GdiBatchCount);
864 if (teb64)
865 {
866 PEB64 *peb64 = ULongToPtr(teb64->Peb);
867 old_wow64 = !peb64->LdrData;
868 }
869 }
870
871 sysInfo.dwNumberOfProcessors=0;
872 GetSystemInfo(&sysInfo);
873 ok(sysInfo.dwNumberOfProcessors>0,
874 "GetSystemInfo failed to return a valid # of processors\n");
875/* Use the current Thread/process for all tests */
876 curthread=GetCurrentThread();
877 ok(curthread!=NULL,"GetCurrentThread failed\n");
878 curproc=GetCurrentProcess();
879 ok(curproc!=NULL,"GetCurrentProcess failed\n");
880/* Check the Affinity Mask functions */
881 ok(GetProcessAffinityMask(curproc,&processMask,&systemMask)!=0,
882 "GetProcessAffinityMask failed\n");
883 ok(SetThreadAffinityMask(curthread,processMask)==processMask,
884 "SetThreadAffinityMask failed\n");
885 ok(SetThreadAffinityMask(curthread,processMask+1)==0,
886 "SetThreadAffinityMask passed for an illegal processor\n");
887/* NOTE: Pre-Vista does not recognize the "all processors" flag (all bits set) */
888 retMask = SetThreadAffinityMask(curthread,~0);
889 ok(broken(retMask==0) || retMask==processMask,
890 "SetThreadAffinityMask(thread,-1) failed to request all processors.\n");
891
892 if (retMask == processMask)
893 {
894 /* Show that the "all processors" flag is handled in ntdll */
895 DWORD_PTR mask = ~0u;
896 NTSTATUS status = pNtSetInformationThread(curthread, ThreadAffinityMask, &mask, sizeof(mask));
897 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS in NtSetInformationThread, got %lx\n", status);
898 }
899
900 if (retMask == processMask && sizeof(ULONG_PTR) > sizeof(ULONG))
901 {
902 /* only the low 32-bits matter */
903 retMask = SetThreadAffinityMask(curthread,~(ULONG_PTR)0);
904 ok(retMask == processMask, "SetThreadAffinityMask failed\n");
905 retMask = SetThreadAffinityMask(curthread,~(ULONG_PTR)0 >> 3);
906 ok(retMask == processMask, "SetThreadAffinityMask failed\n");
907 }
908
909 SetLastError(0xdeadbeef);
911 ok(ret != ~0u, "Unexpected return value %lu.\n", ret);
912
913 if (is_wow64)
914 {
915 SetLastError(0xdeadbeef);
917 todo_wine_if(old_wow64)
918 ok(ret != ~0u, "Unexpected return value %lu.\n", ret);
919
920 SetLastError(0xdeadbeef);
922 ok(ret == ~0u, "Unexpected return value %lu.\n", ret);
923 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Unexpected error %ld.\n", GetLastError());
924 }
925 else
926 {
927 SetLastError(0xdeadbeef);
929#if defined(__REACTOS__) && defined(_WIN64)
930 ok(ret == ~0u || broken(ret == 0) /* x86_64 */, "Unexpected return value %lu.\n", ret);
931 ok(GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == 0xdeadbeef) /* x86_64 */, "Unexpected error %ld.\n", GetLastError());
932#else
933 ok(ret == ~0u, "Unexpected return value %lu.\n", ret);
934 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Unexpected error %ld.\n", GetLastError());
935#endif
936 }
937
939 ok(ret != ~0u, "Unexpected return value %lu.\n", ret);
940
941 if (pGetThreadGroupAffinity && pSetThreadGroupAffinity)
942 {
943 GROUP_AFFINITY affinity, affinity_new;
945
946 memset(&affinity, 0, sizeof(affinity));
947 ok(pGetThreadGroupAffinity(curthread, &affinity), "GetThreadGroupAffinity failed\n");
948
949 SetLastError(0xdeadbeef);
950 ok(!pGetThreadGroupAffinity(curthread, NULL), "GetThreadGroupAffinity succeeded\n");
952 "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
953 ok(affinity.Group == 0, "Expected group 0 got %u\n", affinity.Group);
954
955 memset(&affinity_new, 0, sizeof(affinity_new));
956 affinity_new.Group = 0;
957 affinity_new.Mask = affinity.Mask;
958 ok(pSetThreadGroupAffinity(curthread, &affinity_new, &affinity), "SetThreadGroupAffinity failed\n");
959 ok(affinity_new.Mask == affinity.Mask, "Expected old affinity mask %Ix, got %Ix\n",
960 affinity_new.Mask, affinity.Mask);
961
962 /* show that the "all processors" flag is not supported for SetThreadGroupAffinity */
963 if (sysInfo.dwNumberOfProcessors < 8 * sizeof(DWORD_PTR))
964 {
965 affinity_new.Group = 0;
966 affinity_new.Mask = ~(DWORD_PTR)0;
967 SetLastError(0xdeadbeef);
968 ok(!pSetThreadGroupAffinity(curthread, &affinity_new, NULL), "SetThreadGroupAffinity succeeded\n");
970 "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
971 }
972
973 affinity_new.Group = 1; /* assumes that you have less than 64 logical processors */
974 affinity_new.Mask = 0x1;
975 SetLastError(0xdeadbeef);
976 ok(!pSetThreadGroupAffinity(curthread, &affinity_new, NULL), "SetThreadGroupAffinity succeeded\n");
978 "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
979
980 SetLastError(0xdeadbeef);
981 ok(!pSetThreadGroupAffinity(curthread, NULL, NULL), "SetThreadGroupAffinity succeeded\n");
983 "Expected ERROR_NOACCESS, got %ld\n", GetLastError());
984
985 /* show that the access violation was detected in ntdll */
986 status = pNtSetInformationThread(curthread, ThreadGroupInformation, NULL, sizeof(affinity_new));
988 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", status);
989
990 /* restore original mask */
991 affinity_new.Group = 0;
992 affinity_new.Mask = affinity.Mask;
993 SetLastError(0xdeadbeef);
994 ok(pSetThreadGroupAffinity(curthread, &affinity_new, &affinity), "SetThreadGroupAffinity failed\n");
995 ok(affinity_new.Mask == affinity.Mask, "Expected old affinity mask %Ix, got %Ix\n",
996 affinity_new.Mask, affinity.Mask);
997 }
998 else
999 win_skip("Get/SetThreadGroupAffinity not available\n");
1000}
1001
1003{
1004 ULONG_PTR low = 0, high = 0;
1005
1006 if (!pGetCurrentThreadStackLimits)
1007 {
1008 win_skip("GetCurrentThreadStackLimits not available.\n");
1009 return;
1010 }
1011
1012 if (0)
1013 {
1014 /* crashes on native */
1015 pGetCurrentThreadStackLimits(NULL, NULL);
1016 pGetCurrentThreadStackLimits(NULL, &high);
1017 pGetCurrentThreadStackLimits(&low, NULL);
1018 }
1019
1020 pGetCurrentThreadStackLimits(&low, &high);
1021 ok(low == (ULONG_PTR)NtCurrentTeb()->DeallocationStack, "expected %p, got %Ix\n", NtCurrentTeb()->DeallocationStack, low);
1022 ok(high == (ULONG_PTR)NtCurrentTeb()->Tib.StackBase, "expected %p, got %Ix\n", NtCurrentTeb()->Tib.StackBase, high);
1023}
1024
1026{
1027 ULONG size;
1028 BOOL ret;
1029
1030 if (!pSetThreadStackGuarantee)
1031 {
1032 win_skip("SetThreadStackGuarantee not available.\n");
1033 return;
1034 }
1035 size = 0;
1036 ret = pSetThreadStackGuarantee( &size );
1037 ok( ret, "failed err %lu\n", GetLastError() );
1038 ok( size == 0, "wrong size %lu\n", size );
1039 ok( NtCurrentTeb()->GuaranteedStackBytes == 0, "wrong teb %lu\n",
1040 NtCurrentTeb()->GuaranteedStackBytes );
1041 size = 0xdeadbef;
1042 ret = pSetThreadStackGuarantee( &size );
1043 ok( !ret, "succeeded\n" );
1045 "wrong error %lu\n", GetLastError());
1046 ok( size == 0, "wrong size %lu\n", size );
1047 ok( NtCurrentTeb()->GuaranteedStackBytes == 0, "wrong teb %lu\n",
1048 NtCurrentTeb()->GuaranteedStackBytes );
1049 size = 200;
1050 ret = pSetThreadStackGuarantee( &size );
1051 ok( ret, "failed err %lu\n", GetLastError() );
1052 ok( size == 0, "wrong size %lu\n", size );
1053 ok( NtCurrentTeb()->GuaranteedStackBytes == 4096 * sizeof(void *) / 4, "wrong teb %lu\n",
1054 NtCurrentTeb()->GuaranteedStackBytes );
1055 size = 5000;
1056 ret = pSetThreadStackGuarantee( &size );
1057 ok( ret, "failed err %lu\n", GetLastError() );
1058 ok( size == 4096 * sizeof(void *) / 4, "wrong size %lu\n", size );
1059 ok( NtCurrentTeb()->GuaranteedStackBytes == 8192, "wrong teb %lu\n",
1060 NtCurrentTeb()->GuaranteedStackBytes );
1061 size = 2000;
1062 ret = pSetThreadStackGuarantee( &size );
1063 ok( ret, "failed err %lu\n", GetLastError() );
1064 ok( size == 8192, "wrong size %lu\n", size );
1065 ok( NtCurrentTeb()->GuaranteedStackBytes == 8192, "wrong teb %lu\n",
1066 NtCurrentTeb()->GuaranteedStackBytes );
1067 size = 10000;
1068 ret = pSetThreadStackGuarantee( &size );
1069 ok( ret, "failed err %lu\n", GetLastError() );
1070 ok( size == 8192, "wrong size %lu\n", size );
1071 ok( NtCurrentTeb()->GuaranteedStackBytes == 12288, "wrong teb %lu\n",
1072 NtCurrentTeb()->GuaranteedStackBytes );
1073 ret = pSetThreadStackGuarantee( &size );
1074 ok( ret, "failed err %lu\n", GetLastError() );
1075 ok( size == 12288, "wrong size %lu\n", size );
1076 ok( NtCurrentTeb()->GuaranteedStackBytes == 12288, "wrong teb %lu\n",
1077 NtCurrentTeb()->GuaranteedStackBytes );
1078}
1079
1081{
1082 DWORD exitCode, threadid;
1083 DWORD GLE, ret;
1084 HANDLE thread;
1085
1086 ret = GetExitCodeThread((HANDLE)0x2bad2bad,&exitCode);
1087 ok(ret==0, "GetExitCodeThread returned non zero value: %ld\n", ret);
1088 GLE = GetLastError();
1089 ok(GLE==ERROR_INVALID_HANDLE, "GetLastError returned %ld (expected 6)\n", GLE);
1090
1091 thread = CreateThread(NULL,0,threadFunc2,NULL,0,&threadid);
1093 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
1094 ret = GetExitCodeThread(thread,&exitCode);
1095 ok(ret==exitCode || ret==1,
1096 "GetExitCodeThread returned %ld (expected 1 or %ld)\n", ret, exitCode);
1097 ok(exitCode==99, "threadFunc2 exited with code %ld (expected 99)\n", exitCode);
1098 ok(CloseHandle(thread)!=0,"Error closing thread handle\n");
1099}
1100
1101#ifdef __i386__
1102
1103static int test_value = 0;
1104static HANDLE event;
1105
1106static void WINAPI set_test_val( int val )
1107{
1108 test_value += val;
1109 ExitThread(0);
1110}
1111
1112static DWORD WINAPI threadFunc6(LPVOID p)
1113{
1114 SetEvent( event );
1115 Sleep( 1000 );
1116 test_value *= (int)p;
1117 return 0;
1118}
1119
1120static void test_SetThreadContext(void)
1121{
1122 CONTEXT ctx;
1123 int *stack;
1124 HANDLE thread;
1125 DWORD threadid;
1126 DWORD prevcount;
1127 BOOL ret;
1128
1129 SetLastError(0xdeadbeef);
1130 event = CreateEventW( NULL, TRUE, FALSE, NULL );
1131 thread = CreateThread( NULL, 0, threadFunc6, (void *)2, 0, &threadid );
1132 ok( thread != NULL, "CreateThread failed : (%ld)\n", GetLastError() );
1133 if (!thread)
1134 {
1135 trace("Thread creation failed, skipping rest of test\n");
1136 return;
1137 }
1140 CloseHandle( event );
1141
1142 ctx.ContextFlags = CONTEXT_FULL;
1143 SetLastError(0xdeadbeef);
1145 ok( ret, "GetThreadContext failed : (%lu)\n", GetLastError() );
1146
1147 if (ret)
1148 {
1149 /* simulate a call to set_test_val(10) */
1150 stack = (int *)ctx.Esp;
1151 stack[-1] = 10;
1152 stack[-2] = ctx.Eip;
1153 ctx.Esp -= 2 * sizeof(int *);
1154 ctx.Eip = (DWORD)set_test_val;
1155 SetLastError(0xdeadbeef);
1157 ok( ret, "SetThreadContext failed : (%ld)\n", GetLastError() );
1158 }
1159
1160 SetLastError(0xdeadbeef);
1161 prevcount = ResumeThread( thread );
1162 ok ( prevcount == 1, "Previous suspend count (%ld) instead of 1, last error : (%ld)\n",
1163 prevcount, GetLastError() );
1164
1166 ok( test_value == 10, "test_value %d\n", test_value );
1167
1168 ctx.ContextFlags = CONTEXT_FULL;
1169 SetLastError(0xdeadbeef);
1172 (!ret && broken(GetLastError() == ERROR_INVALID_HANDLE)) || /* win2k */
1173 broken(ret), /* 32bit application on NT 5.x 64bit */
1174 "got %d with %lu (expected FALSE with ERROR_GEN_FAILURE or ERROR_ACCESS_DENIED)\n",
1175 ret, GetLastError() );
1176
1177 SetLastError(0xdeadbeef);
1180 (!ret && broken(GetLastError() == ERROR_INVALID_HANDLE)) || /* win2k */
1181 broken(ret), /* 32bit application on NT 5.x 64bit */
1182 "got %d with %lu (expected FALSE with ERROR_GEN_FAILURE or ERROR_ACCESS_DENIED)\n",
1183 ret, GetLastError() );
1184
1186}
1187
1188static DWORD WINAPI test_stack( void *arg )
1189{
1190 DWORD *stack = (DWORD *)(((DWORD)&arg & ~0xfff) + 0x1000);
1191
1192 ok( stack == NtCurrentTeb()->Tib.StackBase, "wrong stack %p/%p\n",
1193 stack, NtCurrentTeb()->Tib.StackBase );
1194 ok( !stack[-1], "wrong data %p = %08lx\n", stack - 1, stack[-1] );
1195 return 0;
1196}
1197
1198static void test_GetThreadContext(void)
1199{
1200 CONTEXT ctx;
1201 BOOL ret;
1202 HANDLE thread;
1203
1204 memset(&ctx, 0xcc, sizeof(ctx));
1205 ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
1207 ok(ret, "GetThreadContext failed: %lu\n", GetLastError());
1208 ok(ctx.ContextFlags == CONTEXT_DEBUG_REGISTERS, "ContextFlags = %lx\n", ctx.ContextFlags);
1209 ok(!ctx.Dr0, "Dr0 = %lx\n", ctx.Dr0);
1210 ok(!ctx.Dr1, "Dr0 = %lx\n", ctx.Dr0);
1211
1212 thread = CreateThread( NULL, 0, test_stack, (void *)0x1234, 0, NULL );
1213 WaitForSingleObject( thread, 1000 );
1215}
1216
1217static void test_GetThreadSelectorEntry(void)
1218{
1220 CONTEXT ctx;
1221 DWORD limit;
1222 void *base;
1223 BOOL ret;
1224
1225 memset(&ctx, 0x11, sizeof(ctx));
1226 ctx.ContextFlags = CONTEXT_SEGMENTS | CONTEXT_CONTROL;
1228 ok(ret, "GetThreadContext error %lu\n", GetLastError());
1229 ok(!HIWORD(ctx.SegCs), "expected HIWORD(SegCs) == 0, got %lu\n", ctx.SegCs);
1230 ok(!HIWORD(ctx.SegDs), "expected HIWORD(SegDs) == 0, got %lu\n", ctx.SegDs);
1231 ok(!HIWORD(ctx.SegFs), "expected HIWORD(SegFs) == 0, got %lu\n", ctx.SegFs);
1232
1234 ok(ret, "GetThreadSelectorEntry(SegCs) error %lu\n", GetLastError());
1236 ok(ret, "GetThreadSelectorEntry(SegDs) error %lu\n", GetLastError());
1238 ok(ret, "GetThreadSelectorEntry(SegDs) error %lu\n", GetLastError());
1240 ok(ret, "GetThreadSelectorEntry(SegDs) error %lu\n", GetLastError());
1242 ok(ret, "GetThreadSelectorEntry(SegDs) error %lu\n", GetLastError());
1243 SetLastError( 0xdeadbeef );
1245 ok(!ret, "GetThreadSelectorEntry(invalid) succeeded\n");
1247 || GetLastError() == ERROR_INVALID_THREAD_ID /* 32-bit */, "wrong error %lu\n", GetLastError() );
1248 ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegDs + 0x100, &entry);
1249 ok(!ret, "GetThreadSelectorEntry(invalid) succeeded\n");
1251 || GetLastError() == ERROR_NOACCESS /* 32-bit */, "wrong error %lu\n", GetLastError() );
1252
1253 memset(&entry, 0x11, sizeof(entry));
1255 ok(ret, "GetThreadSelectorEntry(SegFs) error %lu\n", GetLastError());
1256 entry.HighWord.Bits.Type &= ~1; /* ignore accessed bit */
1257
1258 base = (void *)((entry.HighWord.Bits.BaseHi << 24) | (entry.HighWord.Bits.BaseMid << 16) | entry.BaseLow);
1259 limit = (entry.HighWord.Bits.LimitHi << 16) | entry.LimitLow;
1260
1261 ok(base == NtCurrentTeb(), "expected %p, got %p\n", NtCurrentTeb(), base);
1262 ok(limit == 0x0fff || limit == 0x4000, "expected 0x0fff or 0x4000, got %#lx\n", limit);
1263 ok(entry.HighWord.Bits.Type == 0x12, "expected 0x12, got %#x\n", entry.HighWord.Bits.Type);
1264 ok(entry.HighWord.Bits.Dpl == 3, "expected 3, got %u\n", entry.HighWord.Bits.Dpl);
1265 ok(entry.HighWord.Bits.Pres == 1, "expected 1, got %u\n", entry.HighWord.Bits.Pres);
1266 ok(entry.HighWord.Bits.Sys == 0, "expected 0, got %u\n", entry.HighWord.Bits.Sys);
1267 ok(entry.HighWord.Bits.Reserved_0 == 0, "expected 0, got %u\n", entry.HighWord.Bits.Reserved_0);
1268 ok(entry.HighWord.Bits.Default_Big == 1, "expected 1, got %u\n", entry.HighWord.Bits.Default_Big);
1269 ok(entry.HighWord.Bits.Granularity == 0, "expected 0, got %u\n", entry.HighWord.Bits.Granularity);
1270
1271 memset(&entry, 0x11, sizeof(entry));
1273 ok(ret, "GetThreadSelectorEntry(SegDs) error %lu\n", GetLastError());
1274 entry.HighWord.Bits.Type &= ~1; /* ignore accessed bit */
1275 base = (void *)((entry.HighWord.Bits.BaseHi << 24) | (entry.HighWord.Bits.BaseMid << 16) | entry.BaseLow);
1276 limit = (entry.HighWord.Bits.LimitHi << 16) | entry.LimitLow;
1277
1278 ok(base == 0, "got base %p\n", base);
1279 ok(limit == ~0u >> 12, "got limit %#lx\n", limit);
1280 ok(entry.HighWord.Bits.Type == 0x1a, "expected 0x12, got %#x\n", entry.HighWord.Bits.Type);
1281 ok(entry.HighWord.Bits.Dpl == 3, "expected 3, got %u\n", entry.HighWord.Bits.Dpl);
1282 ok(entry.HighWord.Bits.Pres == 1, "expected 1, got %u\n", entry.HighWord.Bits.Pres);
1283 ok(entry.HighWord.Bits.Sys == 0, "expected 0, got %u\n", entry.HighWord.Bits.Sys);
1284 ok(entry.HighWord.Bits.Reserved_0 == 0, "expected 0, got %u\n", entry.HighWord.Bits.Reserved_0);
1285 ok(entry.HighWord.Bits.Default_Big == 1, "expected 1, got %u\n", entry.HighWord.Bits.Default_Big);
1286 ok(entry.HighWord.Bits.Granularity == 1, "expected 1, got %u\n", entry.HighWord.Bits.Granularity);
1287
1288 memset(&entry, 0x11, sizeof(entry));
1290 ok(ret, "GetThreadSelectorEntry(SegDs) error %lu\n", GetLastError());
1291 entry.HighWord.Bits.Type &= ~1; /* ignore accessed bit */
1292 base = (void *)((entry.HighWord.Bits.BaseHi << 24) | (entry.HighWord.Bits.BaseMid << 16) | entry.BaseLow);
1293 limit = (entry.HighWord.Bits.LimitHi << 16) | entry.LimitLow;
1294
1295 ok(base == 0, "got base %p\n", base);
1296 ok(limit == ~0u >> 12, "got limit %#lx\n", limit);
1297 ok(entry.HighWord.Bits.Type == 0x12, "expected 0x12, got %#x\n", entry.HighWord.Bits.Type);
1298 ok(entry.HighWord.Bits.Dpl == 3, "expected 3, got %u\n", entry.HighWord.Bits.Dpl);
1299 ok(entry.HighWord.Bits.Pres == 1, "expected 1, got %u\n", entry.HighWord.Bits.Pres);
1300 ok(entry.HighWord.Bits.Sys == 0, "expected 0, got %u\n", entry.HighWord.Bits.Sys);
1301 ok(entry.HighWord.Bits.Reserved_0 == 0, "expected 0, got %u\n", entry.HighWord.Bits.Reserved_0);
1302 ok(entry.HighWord.Bits.Default_Big == 1, "expected 1, got %u\n", entry.HighWord.Bits.Default_Big);
1303 ok(entry.HighWord.Bits.Granularity == 1, "expected 1, got %u\n", entry.HighWord.Bits.Granularity);
1304}
1305
1306#endif /* __i386__ */
1307
1310
1312{
1314
1315 if (executed == 100)
1317 return 0;
1318}
1319
1320static void test_QueueUserWorkItem(void)
1321{
1322 INT_PTR i;
1323 DWORD wait_result;
1325
1326 /* QueueUserWorkItem not present on win9x */
1327 if (!pQueueUserWorkItem) return;
1328
1330
1331 before = GetTickCount();
1332
1333 for (i = 0; i < 100; i++)
1334 {
1335 BOOL ret = pQueueUserWorkItem(work_function, (void *)i, WT_EXECUTEDEFAULT);
1336 ok(ret, "QueueUserWorkItem failed with error %ld\n", GetLastError());
1337 }
1338
1339 wait_result = WaitForSingleObject(finish_event, 10000);
1340
1341 after = GetTickCount();
1342 trace("100 QueueUserWorkItem calls took %ldms\n", after - before);
1343 ok(wait_result == WAIT_OBJECT_0, "wait failed with error 0x%lx\n", wait_result);
1344
1345 ok(times_executed == 100, "didn't execute all of the work items\n");
1346}
1347
1348static void CALLBACK signaled_function(PVOID p, BOOLEAN TimerOrWaitFired)
1349{
1350 HANDLE event = p;
1351 SetEvent(event);
1352 ok(!TimerOrWaitFired, "wait shouldn't have timed out\n");
1353}
1354
1355static void CALLBACK wait_complete_function(PVOID p, BOOLEAN TimerOrWaitFired)
1356{
1357 HANDLE event = p;
1358 DWORD res;
1359 ok(!TimerOrWaitFired, "wait shouldn't have timed out\n");
1361 ok(res == WAIT_OBJECT_0, "WaitForSingleObject returned %lx\n", res);
1362}
1363
1364static void CALLBACK timeout_function(PVOID p, BOOLEAN TimerOrWaitFired)
1365{
1366 HANDLE event = p;
1367 SetEvent(event);
1368 ok(TimerOrWaitFired, "wait should have timed out\n");
1369}
1370
1372{
1376};
1377
1378static void CALLBACK waitthread_test_function(PVOID p, BOOLEAN TimerOrWaitFired)
1379{
1380 struct waitthread_test_param *param = p;
1381 DWORD ret;
1382
1383 SetEvent(param->trigger_event);
1384 ret = WaitForSingleObject(param->wait_event, 100);
1385 ok(ret == WAIT_TIMEOUT, "wait should have timed out\n");
1386 SetEvent(param->complete_event);
1387}
1388
1390{
1393};
1394
1395static void CALLBACK unregister_function(PVOID p, BOOLEAN TimerOrWaitFired)
1396{
1397 struct unregister_params *param = p;
1398 HANDLE wait_handle = param->wait_handle;
1399 BOOL ret;
1400 ok(wait_handle != INVALID_HANDLE_VALUE, "invalid wait handle\n");
1401 ret = pUnregisterWait(param->wait_handle);
1402 todo_wine ok(ret, "UnregisterWait failed with error %ld\n", GetLastError());
1403 SetEvent(param->complete_event);
1404}
1405
1407{
1408 BOOL ret;
1409 HANDLE wait_handle, wait_handle2;
1410 HANDLE handle;
1412 HANDLE waitthread_trigger_event, waitthread_wait_event;
1414 struct unregister_params unregister_param;
1415 DWORD i;
1416
1417 if (!pRegisterWaitForSingleObject || !pUnregisterWait)
1418 {
1419 win_skip("RegisterWaitForSingleObject or UnregisterWait not implemented\n");
1420 return;
1421 }
1422
1423 /* test signaled case */
1424
1427
1429 ok(ret, "RegisterWaitForSingleObject failed with error %ld\n", GetLastError());
1430
1432 /* give worker thread chance to complete */
1433 Sleep(100);
1434
1435 ret = pUnregisterWait(wait_handle);
1436 ok(ret, "UnregisterWait failed with error %ld\n", GetLastError());
1437
1438 /* test cancel case */
1439
1441
1443 ok(ret, "RegisterWaitForSingleObject failed with error %ld\n", GetLastError());
1444
1445 ret = pUnregisterWait(wait_handle);
1446 ok(ret, "UnregisterWait failed with error %ld\n", GetLastError());
1447
1448 /* test unregister while running */
1449
1452 ok(ret, "RegisterWaitForSingleObject failed with error %ld\n", GetLastError());
1453
1454 /* give worker thread chance to start */
1455 Sleep(50);
1456 ret = pUnregisterWait(wait_handle);
1457 ok(!ret, "UnregisterWait succeeded\n");
1458 ok(GetLastError() == ERROR_IO_PENDING, "UnregisterWait failed with error %ld\n", GetLastError());
1459
1460 /* give worker thread chance to complete */
1462 Sleep(50);
1463
1464 /* test timeout case */
1465
1467
1468 ret = pRegisterWaitForSingleObject(&wait_handle, handle, timeout_function, complete_event, 0, WT_EXECUTEONLYONCE);
1469 ok(ret, "RegisterWaitForSingleObject failed with error %ld\n", GetLastError());
1470
1472 /* give worker thread chance to complete */
1473 Sleep(100);
1474
1475 ret = pUnregisterWait(wait_handle);
1476 ok(ret, "UnregisterWait failed with error %ld\n", GetLastError());
1477
1478 SetLastError(0xdeadbeef);
1479 ret = pUnregisterWait(NULL);
1480 ok(!ret, "Expected UnregisterWait to fail\n");
1482 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1483
1484 /* test WT_EXECUTEINWAITTHREAD */
1485
1488 ok(ret, "RegisterWaitForSingleObject failed with error %ld\n", GetLastError());
1489
1491 /* give worker thread chance to complete */
1492 Sleep(100);
1493
1494 ret = pUnregisterWait(wait_handle);
1495 ok(ret, "UnregisterWait failed with error %ld\n", GetLastError());
1496
1497 /* the callback execution should be sequentially consistent with the wait handle return,
1498 even if the event is already set */
1499
1500 for (i = 0; i < 100; ++i)
1501 {
1503 unregister_param.complete_event = complete_event;
1504 unregister_param.wait_handle = INVALID_HANDLE_VALUE;
1505
1506 ret = pRegisterWaitForSingleObject(&unregister_param.wait_handle, handle, unregister_function, &unregister_param, INFINITE, WT_EXECUTEONLYONCE | WT_EXECUTEINWAITTHREAD);
1507 ok(ret, "RegisterWaitForSingleObject failed with error %ld\n", GetLastError());
1508
1510 }
1511
1512 /* test multiple waits with WT_EXECUTEINWAITTHREAD.
1513 * Windows puts multiple waits on the same wait thread, and using WT_EXECUTEINWAITTHREAD causes the callbacks to run serially.
1514 */
1515
1517 waitthread_trigger_event = CreateEventW(NULL, FALSE, FALSE, NULL);
1518 waitthread_wait_event = CreateEventW(NULL, FALSE, FALSE, NULL);
1519
1520 param.trigger_event = waitthread_trigger_event;
1521 param.wait_event = waitthread_wait_event;
1522 param.complete_event = complete_event;
1523
1524 ret = pRegisterWaitForSingleObject(&wait_handle2, waitthread_trigger_event, signaled_function, waitthread_wait_event,
1526 ok(ret, "RegisterWaitForSingleObject failed with error %ld\n", GetLastError());
1527
1529 ok(ret, "RegisterWaitForSingleObject failed with error %ld\n", GetLastError());
1530
1532 /* give worker thread chance to complete */
1533 Sleep(100);
1534
1535 ret = pUnregisterWait(wait_handle);
1536 ok(ret, "UnregisterWait failed with error %ld\n", GetLastError());
1537
1538 ret = pUnregisterWait(wait_handle2);
1539 ok(ret, "UnregisterWait failed with error %ld\n", GetLastError());
1540
1541 CloseHandle(waitthread_wait_event);
1542 CloseHandle(waitthread_trigger_event);
1545}
1546
1550
1551/* Function pointers to the FLS/TLS functions to test in LS_ThreadProc() */
1552static DWORD (WINAPI *LS_AllocFunc)(void);
1553static PVOID (WINAPI *LS_GetValueFunc)(DWORD);
1554static BOOL (WINAPI *LS_SetValueFunc)(DWORD, PVOID);
1555static BOOL (WINAPI *LS_FreeFunc)(DWORD);
1556
1557/* Names of the functions tested in LS_ThreadProc(), for error messages */
1558static const char* LS_AllocFuncName = "";
1559static const char* LS_GetValueFuncName = "";
1560static const char* LS_SetValueFuncName = "";
1561static const char* LS_FreeFuncName = "";
1562
1563/* FLS entry points, dynamically loaded in platforms that support them */
1564static DWORD (WINAPI *pFlsAlloc)(PFLS_CALLBACK_FUNCTION);
1565static BOOL (WINAPI *pFlsFree)(DWORD);
1566static PVOID (WINAPI *pFlsGetValue)(DWORD);
1567static BOOL (WINAPI *pFlsSetValue)(DWORD,PVOID);
1568
1569/* A thunk function to make FlsAlloc compatible with the signature of TlsAlloc */
1571{
1572 return pFlsAlloc(NULL);
1573}
1574
1576{
1577 /* We should NOT inherit the FLS/TLS values from our parent or from the
1578 main thread. */
1579 LPVOID val;
1580
1581 val = LS_GetValueFunc(LS_main);
1582 ok(val == NULL, "%s inheritance failed\n", LS_GetValueFuncName);
1583
1584 val = LS_GetValueFunc(LS_index0);
1585 ok(val == NULL, "%s inheritance failed\n", LS_GetValueFuncName);
1586
1587 val = LS_GetValueFunc(LS_index1);
1588 ok(val == NULL, "%s inheritance failed\n", LS_GetValueFuncName);
1589
1590 return 0;
1591}
1592
1593/* Basic FLS/TLS usage test. Make sure we can create slots and the values we
1594 store in them are separate among threads. Also test FLS/TLS value
1595 inheritance with LS_InheritanceProc. */
1597{
1598 LONG_PTR id = (LONG_PTR) p;
1599 LPVOID val;
1600 BOOL ret;
1601
1602 if (sync_threads_and_run_one(0, id))
1603 {
1604 LS_index0 = LS_AllocFunc();
1606 }
1608
1609 if (sync_threads_and_run_one(1, id))
1610 {
1611 LS_index1 = LS_AllocFunc();
1613
1614 /* Slot indices should be different even if created in different
1615 threads. */
1616 ok(LS_index0 != LS_index1, "%s failed\n", LS_AllocFuncName);
1617
1618 /* Both slots should be initialized to NULL */
1619 SetLastError(0xdeadbeef);
1620 val = LS_GetValueFunc(LS_index0);
1621 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1622 ok(val == NULL, "Slot not initialized correctly\n");
1623
1624 SetLastError(0xdeadbeef);
1625 val = LS_GetValueFunc(LS_index1);
1626 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1627 ok(val == NULL, "Slot not initialized correctly\n");
1628 }
1630
1631 if (sync_threads_and_run_one(0, id))
1632 {
1633 SetLastError(0xdeadbeef);
1634 val = LS_GetValueFunc(LS_index0);
1635 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1636 ok(val == NULL, "Slot not initialized correctly\n");
1637
1638 SetLastError(0xdeadbeef);
1639 val = LS_GetValueFunc(LS_index1);
1640 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1641 ok(val == NULL, "Slot not initialized correctly\n");
1642
1643 ret = LS_SetValueFunc(LS_index0, (LPVOID) 1);
1644 ok(ret, "%s failed\n", LS_SetValueFuncName);
1645
1646 ret = LS_SetValueFunc(LS_index1, (LPVOID) 2);
1647 ok(ret, "%s failed\n", LS_SetValueFuncName);
1648
1649 SetLastError(0xdeadbeef);
1650 val = LS_GetValueFunc(LS_index0);
1651 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1652 ok(val == (LPVOID) 1, "Slot not initialized correctly\n");
1653
1654 SetLastError(0xdeadbeef);
1655 val = LS_GetValueFunc(LS_index1);
1656 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1657 ok(val == (LPVOID) 2, "Slot not initialized correctly\n");
1658 }
1660
1661 if (sync_threads_and_run_one(1, id))
1662 {
1663 val = LS_GetValueFunc(LS_index0);
1664 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1665 ok(val == NULL, "Slot not initialized correctly\n");
1666
1667 val = LS_GetValueFunc(LS_index1);
1668 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1669 ok(val == NULL, "Slot not initialized correctly\n");
1670
1671 ret = LS_SetValueFunc(LS_index0, (LPVOID) 3);
1672 ok(ret, "%s failed\n", LS_SetValueFuncName);
1673
1674 ret = LS_SetValueFunc(LS_index1, (LPVOID) 4);
1675 ok(ret, "%s failed\n", LS_SetValueFuncName);
1676
1677 val = LS_GetValueFunc(LS_index0);
1678 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1679 ok(val == (LPVOID) 3, "Slot not initialized correctly\n");
1680
1681 val = LS_GetValueFunc(LS_index1);
1682 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1683 ok(val == (LPVOID) 4, "Slot not initialized correctly\n");
1684 }
1686
1687 if (sync_threads_and_run_one(0, id))
1688 {
1689 HANDLE thread;
1690 DWORD waitret, tid;
1691
1692 val = LS_GetValueFunc(LS_index0);
1693 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1694 ok(val == (LPVOID) 1, "Slot not initialized correctly\n");
1695
1696 val = LS_GetValueFunc(LS_index1);
1697 ok(GetLastError() == ERROR_SUCCESS, "%s failed\n", LS_GetValueFuncName);
1698 ok(val == (LPVOID) 2, "Slot not initialized correctly\n");
1699
1701 ok(thread != NULL, "CreateThread failed\n");
1702 waitret = WaitForSingleObject(thread, 60000);
1703 ok(waitret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
1705
1706 ret = LS_FreeFunc(LS_index0);
1707 ok(ret, "%s failed\n", LS_FreeFuncName);
1708 }
1710
1711 if (sync_threads_and_run_one(1, id))
1712 {
1713 ret = LS_FreeFunc(LS_index1);
1714 ok(ret, "%s failed\n", LS_FreeFuncName);
1715 }
1717
1718 return 0;
1719}
1720
1721static void run_LS_tests(void)
1722{
1723 HANDLE threads[2];
1724 LONG_PTR i;
1725 DWORD ret;
1726 BOOL suc;
1727
1729
1730 /* Allocate a slot in the main thread to test for inheritance. */
1731 LS_main = LS_AllocFunc();
1732 ok(LS_main != LS_OutOfIndexesValue, "%s failed\n", LS_AllocFuncName);
1733 suc = LS_SetValueFunc(LS_main, (LPVOID) 4114);
1734 ok(suc, "%s failed\n", LS_SetValueFuncName);
1735
1736 for (i = 0; i < 2; ++i)
1737 {
1738 DWORD tid;
1739
1741 ok(threads[i] != NULL, "CreateThread failed\n");
1742 }
1743
1744 ret = WaitForMultipleObjects(2, threads, TRUE, 60000);
1745 ok(ret == WAIT_OBJECT_0 || broken(ret == WAIT_OBJECT_0+1 /* nt4,w2k */), "WaitForAllObjects 2 threads %ld\n",ret);
1746
1747 for (i = 0; i < 2; ++i)
1749
1750 suc = LS_FreeFunc(LS_main);
1751 ok(suc, "%s failed\n", LS_FreeFuncName);
1753}
1754
1755static void test_TLS(void)
1756{
1758
1759 LS_AllocFunc = &TlsAlloc;
1760 LS_GetValueFunc = &TlsGetValue;
1761 LS_SetValueFunc = &TlsSetValue;
1762 LS_FreeFunc = &TlsFree;
1763
1764 LS_AllocFuncName = "TlsAlloc";
1765 LS_GetValueFuncName = "TlsGetValue";
1766 LS_SetValueFuncName = "TlsSetValue";
1767 LS_FreeFuncName = "TlsFree";
1768
1769 run_LS_tests();
1770}
1771
1772static void test_FLS(void)
1773{
1774 if (!pFlsAlloc || !pFlsFree || !pFlsGetValue || !pFlsSetValue)
1775 {
1776 win_skip("Fiber Local Storage not supported\n");
1777 return;
1778 }
1779
1781
1782 LS_AllocFunc = &FLS_AllocFuncThunk;
1783 LS_GetValueFunc = pFlsGetValue;
1784 LS_SetValueFunc = pFlsSetValue;
1785 LS_FreeFunc = pFlsFree;
1786
1787 LS_AllocFuncName = "FlsAlloc";
1788 LS_GetValueFuncName = "FlsGetValue";
1789 LS_SetValueFuncName = "FlsSetValue";
1790 LS_FreeFuncName = "FlsFree";
1791
1792 run_LS_tests();
1793}
1794
1795static void test_ThreadErrorMode(void)
1796{
1797 DWORD oldmode;
1798 DWORD mode;
1799 DWORD rtlmode;
1800 BOOL ret;
1801
1802 if (!pSetThreadErrorMode || !pGetThreadErrorMode)
1803 {
1804 win_skip("SetThreadErrorMode and/or GetThreadErrorMode unavailable (added in Windows 7)\n");
1805 return;
1806 }
1807
1808 if (!pRtlGetThreadErrorMode) {
1809 win_skip("RtlGetThreadErrorMode not available\n");
1810 return;
1811 }
1812
1813 oldmode = pGetThreadErrorMode();
1814
1815 ret = pSetThreadErrorMode(0, &mode);
1816 ok(ret, "SetThreadErrorMode failed\n");
1817 ok(mode == oldmode,
1818 "SetThreadErrorMode returned old mode 0x%lx, expected 0x%lx\n",
1819 mode, oldmode);
1820 mode = pGetThreadErrorMode();
1821 ok(mode == 0, "GetThreadErrorMode returned mode 0x%lx, expected 0\n", mode);
1822 rtlmode = pRtlGetThreadErrorMode();
1823 ok(rtlmode == 0,
1824 "RtlGetThreadErrorMode returned mode 0x%lx, expected 0\n", mode);
1825
1826 ret = pSetThreadErrorMode(SEM_FAILCRITICALERRORS, &mode);
1827 ok(ret, "SetThreadErrorMode failed\n");
1828 ok(mode == 0,
1829 "SetThreadErrorMode returned old mode 0x%lx, expected 0\n", mode);
1830 mode = pGetThreadErrorMode();
1832 "GetThreadErrorMode returned mode 0x%lx, expected SEM_FAILCRITICALERRORS\n",
1833 mode);
1834 rtlmode = pRtlGetThreadErrorMode();
1835 ok(rtlmode == 0x10,
1836 "RtlGetThreadErrorMode returned mode 0x%lx, expected 0x10\n", mode);
1837
1838 ret = pSetThreadErrorMode(SEM_NOGPFAULTERRORBOX, &mode);
1839 ok(ret, "SetThreadErrorMode failed\n");
1841 "SetThreadErrorMode returned old mode 0x%lx, expected SEM_FAILCRITICALERRORS\n",
1842 mode);
1843 mode = pGetThreadErrorMode();
1845 "GetThreadErrorMode returned mode 0x%lx, expected SEM_NOGPFAULTERRORBOX\n",
1846 mode);
1847 rtlmode = pRtlGetThreadErrorMode();
1848 ok(rtlmode == 0x20,
1849 "RtlGetThreadErrorMode returned mode 0x%lx, expected 0x20\n", mode);
1850
1851 ret = pSetThreadErrorMode(SEM_NOOPENFILEERRORBOX, NULL);
1852 ok(ret, "SetThreadErrorMode failed\n");
1853 mode = pGetThreadErrorMode();
1855 "GetThreadErrorMode returned mode 0x%lx, expected SEM_NOOPENFILEERRORBOX\n",
1856 mode);
1857 rtlmode = pRtlGetThreadErrorMode();
1858 ok(rtlmode == 0x40,
1859 "RtlGetThreadErrorMode returned mode 0x%lx, expected 0x40\n", rtlmode);
1860
1861 for (mode = 1; mode; mode <<= 1)
1862 {
1863 ret = pSetThreadErrorMode(mode, NULL);
1867 {
1868 ok(ret,
1869 "SetThreadErrorMode(0x%lx,NULL) failed with error %ld\n",
1870 mode, GetLastError());
1871 }
1872 else
1873 {
1875 ok(!ret,
1876 "SetThreadErrorMode(0x%lx,NULL) succeeded, expected failure\n",
1877 mode);
1879 "SetThreadErrorMode(0x%lx,NULL) failed with %ld, "
1880 "expected ERROR_INVALID_PARAMETER\n",
1881 mode, GLE);
1882 }
1883 }
1884
1885 pSetThreadErrorMode(oldmode, NULL);
1886}
1887
1889{
1890 unsigned int cw;
1891 unsigned long fpu_cw;
1893};
1894
1895static inline unsigned long get_fpu_cw(void)
1896{
1897#ifdef __arm64ec__
1898 extern NTSTATUS (*__os_arm64x_get_x64_information)(ULONG,void*,void*);
1899 unsigned int cw, sse;
1900 __os_arm64x_get_x64_information( 0, &sse, NULL );
1901 __os_arm64x_get_x64_information( 2, &cw, NULL );
1902 return MAKELONG( cw, sse );
1903#elif defined(__i386__) || defined(__x86_64__)
1904 WORD cw = 0;
1905 unsigned int sse = 0;
1906#ifdef _MSC_VER
1907#if defined(__REACTOS__) && defined (__x86_64__)
1908 extern void get_fpu_cw_raw(WORD *cw, unsigned int *sse);
1909 get_fpu_cw_raw(&cw, &sse);
1910#else
1911 __asm { fnstcw [cw] }
1912 __asm { stmxcsr [sse] }
1913#endif
1914#else
1915 __asm__ volatile ("fnstcw %0" : "=m" (cw));
1916 __asm__ volatile ("stmxcsr %0" : "=m" (sse));
1917#endif
1918 return MAKELONG( cw, sse );
1919#elif defined(__aarch64__)
1920 ULONG_PTR cw;
1921 __asm__ __volatile__( "mrs %0, fpcr" : "=r" (cw) );
1922 return cw;
1923#else
1924 return 0;
1925#endif
1926}
1927
1928static inline void fpu_invalid_operation(void)
1929{
1930 double d;
1931
1932#if defined(__i386__)
1933 unsigned int sse;
1934#ifdef _MSC_VER
1935 __asm { stmxcsr [sse] }
1936 sse |= 1; /* invalid operation flag */
1937 __asm { ldmxcsr [sse] }
1938#else
1939 __asm__ volatile ("stmxcsr %0" : "=m" (sse));
1940 sse |= 1;
1941 __asm__ volatile ("ldmxcsr %0" : : "m" (sse));
1942#endif
1943#endif
1944
1945 d = acos(2.0);
1946 ok(_isnan(d), "d = %lf\n", d);
1947 ok(_statusfp() & _SW_INVALID, "_statusfp() = %x\n", _statusfp());
1948}
1949
1951{
1952 struct fpu_thread_ctx *ctx = param;
1953 BOOL ret;
1954
1955 ctx->cw = _control87( 0, 0 );
1956 ctx->fpu_cw = get_fpu_cw();
1957
1958 ret = SetEvent(ctx->finished);
1959 ok(ret, "SetEvent failed, last error %#lx.\n", GetLastError());
1960
1961 return 0;
1962}
1963
1964static unsigned int get_thread_fpu_cw( unsigned long *fpu_cw )
1965{
1966 struct fpu_thread_ctx ctx;
1967 DWORD tid, res;
1968 HANDLE thread;
1969
1970 ctx.finished = CreateEventW(NULL, FALSE, FALSE, NULL);
1971 ok(!!ctx.finished, "Failed to create event, last error %#lx.\n", GetLastError());
1972
1973 thread = CreateThread(NULL, 0, fpu_thread, &ctx, 0, &tid);
1974 ok(!!thread, "Failed to create thread, last error %#lx.\n", GetLastError());
1975
1976 res = WaitForSingleObject(ctx.finished, INFINITE);
1977 ok(res == WAIT_OBJECT_0, "Wait failed (%#lx), last error %#lx.\n", res, GetLastError());
1978
1979 res = CloseHandle(ctx.finished);
1980 ok(!!res, "Failed to close event handle, last error %#lx.\n", GetLastError());
1981
1983 *fpu_cw = ctx.fpu_cw;
1984 return ctx.cw;
1985}
1986
1987static void test_thread_fpu_cw(void)
1988{
1989 static const struct {
1990 unsigned int cw; unsigned long fpu_cw; unsigned long fpu_cw_broken;
1991 } expected_cw[8] =
1992 {
1993#ifdef __i386__
1994 { _MCW_EM | _PC_53, MAKELONG( 0x27f, 0x1f80 ) },
1995 { _MCW_EM | _PC_53, MAKELONG( 0x27f, 0x1f80 ) },
1996 { _EM_INEXACT | _RC_CHOP | _PC_24, MAKELONG( 0xc60, 0x7000 ), MAKELONG( 0xc60, 0x1f80 ) },
1997 { _MCW_EM | _PC_53, MAKELONG( 0x27f, 0x1f80 ) },
1998 { _EM_INEXACT | _RC_CHOP | _PC_24, MAKELONG( 0xc60, 0x7000 ), MAKELONG( 0xc60, 0x1f80 ) },
1999 { _MCW_EM | _PC_53, MAKELONG( 0x27f, 0x1f80 ) },
2000 { _MCW_EM | _PC_53, MAKELONG( 0x27f, 0x1f81 ) },
2001 { _MCW_EM | _PC_53, MAKELONG( 0x27f, 0x1f81 ) }
2002#elif defined(__x86_64__)
2003 { _MCW_EM | _PC_64, MAKELONG( 0x27f, 0x1f80 ) },
2004 { _MCW_EM | _PC_64, MAKELONG( 0x27f, 0x1f80 ) },
2005 { _EM_INEXACT | _RC_CHOP | _PC_64, MAKELONG( 0x27f, 0x7000 ) },
2006 { _MCW_EM | _PC_64, MAKELONG( 0x27f, 0x1f80 ) },
2007 { _EM_INEXACT | _RC_CHOP | _PC_64, MAKELONG( 0x27f, 0x7000 ) },
2008 { _MCW_EM | _PC_64, MAKELONG( 0x27f, 0x1f80 ) },
2009 { _MCW_EM | _PC_64, MAKELONG( 0x27f, 0x1f81 ) },
2010 { _MCW_EM | _PC_64, MAKELONG( 0x27f, 0x1f81 ) }
2011#elif defined(__aarch64__)
2012 { _MCW_EM | _PC_64, 0 },
2013 { _MCW_EM | _PC_64, 0 },
2014 { _EM_INEXACT | _RC_CHOP | _PC_64, 0xc08f00 },
2015 { _MCW_EM | _PC_64, 0 },
2016 { _EM_INEXACT | _RC_CHOP | _PC_64, 0xc08f00 },
2017 { _MCW_EM | _PC_64, 0 },
2018 { _MCW_EM | _PC_64, 0 },
2019 { _MCW_EM | _PC_64, 0 }
2020#else
2021 { 0xdeadbeef, 0xdeadbeef }
2022#endif
2023 };
2024 unsigned int initial_cw, cw;
2025 unsigned long fpu_cw;
2026
2027 fpu_cw = get_fpu_cw();
2028 initial_cw = _control87( 0, 0 );
2029 ok(initial_cw == expected_cw[0].cw, "expected %#x got %#x\n", expected_cw[0].cw, initial_cw);
2030 ok(fpu_cw == expected_cw[0].fpu_cw, "expected %#lx got %#lx\n", expected_cw[0].fpu_cw, fpu_cw);
2031
2032 cw = get_thread_fpu_cw( &fpu_cw );
2033 ok(cw == expected_cw[1].cw, "expected %#x got %#x\n", expected_cw[1].cw, cw);
2034 ok(fpu_cw == expected_cw[1].fpu_cw, "expected %#lx got %#lx\n", expected_cw[1].fpu_cw, fpu_cw);
2035
2037 cw = _control87( 0, 0 );
2038 fpu_cw = get_fpu_cw();
2039 ok(cw == expected_cw[2].cw, "expected %#x got %#x\n", expected_cw[2].cw, cw);
2040 ok(fpu_cw == expected_cw[2].fpu_cw ||
2041 broken(expected_cw[2].fpu_cw_broken && fpu_cw == expected_cw[2].fpu_cw_broken),
2042 "expected %#lx got %#lx\n", expected_cw[2].fpu_cw, fpu_cw);
2043
2044 cw = get_thread_fpu_cw( &fpu_cw );
2045 ok(cw == expected_cw[3].cw, "expected %#x got %#x\n", expected_cw[3].cw, cw);
2046 ok(fpu_cw == expected_cw[3].fpu_cw, "expected %#lx got %#lx\n", expected_cw[3].fpu_cw, fpu_cw);
2047
2048 cw = _control87( 0, 0 );
2049 fpu_cw = get_fpu_cw();
2050 ok(cw == expected_cw[4].cw, "expected %#x got %#x\n", expected_cw[4].cw, cw);
2051 ok(fpu_cw == expected_cw[4].fpu_cw ||
2052 broken(expected_cw[4].fpu_cw_broken && fpu_cw == expected_cw[4].fpu_cw_broken),
2053 "expected %#lx got %#lx\n", expected_cw[4].fpu_cw, fpu_cw);
2054
2055 _control87( initial_cw, _MCW_EM | _MCW_RC | _MCW_PC );
2056 cw = _control87( 0, 0 );
2057 fpu_cw = get_fpu_cw();
2058 ok(cw == expected_cw[5].cw, "expected %#x got %#x\n", expected_cw[5].cw, cw);
2059 ok(fpu_cw == expected_cw[5].fpu_cw, "expected %#lx got %#lx\n", expected_cw[5].fpu_cw, fpu_cw);
2060
2062 cw = _control87( 0, 0 );
2063 fpu_cw = get_fpu_cw();
2064 ok(cw == expected_cw[6].cw, "expected %#x got %#x\n", expected_cw[6].cw, cw);
2065 ok(fpu_cw == expected_cw[6].fpu_cw, "expected %#lx got %#lx\n", expected_cw[6].fpu_cw, fpu_cw);
2066
2067 cw = _control87( initial_cw, _MCW_EM | _MCW_RC | _MCW_PC );
2068 fpu_cw = get_fpu_cw();
2069 ok(cw == expected_cw[7].cw, "expected %#x got %#x\n", expected_cw[6].cw, cw);
2070 ok(fpu_cw == expected_cw[7].fpu_cw, "expected %#lx got %#lx\n", expected_cw[6].fpu_cw, fpu_cw);
2071 _clearfp();
2072}
2073
2074static const char manifest_dep[] =
2075"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
2076"<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH "\"/>"
2077" <file name=\"testdep.dll\" />"
2078"</assembly>";
2079
2080static const char manifest_main[] =
2081"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
2082"<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />"
2083"<dependency>"
2084" <dependentAssembly>"
2085" <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH "\" />"
2086" </dependentAssembly>"
2087"</dependency>"
2088"</assembly>";
2089
2090static void create_manifest_file(const char *filename, const char *manifest)
2091{
2093 HANDLE file;
2094 DWORD size;
2095
2098 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %lu\n", GetLastError());
2101}
2102
2103static HANDLE test_create(const char *file)
2104{
2106 ACTCTXW actctx;
2107 HANDLE handle;
2108
2110 memset(&actctx, 0, sizeof(ACTCTXW));
2111 actctx.cbSize = sizeof(ACTCTXW);
2112 actctx.lpSource = path;
2113
2115 ok(handle != INVALID_HANDLE_VALUE, "failed to create context, error %lu\n", GetLastError());
2116
2117 ok(actctx.cbSize == sizeof(actctx), "cbSize=%ld\n", actctx.cbSize);
2118 ok(actctx.dwFlags == 0, "dwFlags=%ld\n", actctx.dwFlags);
2119 ok(actctx.lpSource == path, "lpSource=%p\n", actctx.lpSource);
2120 ok(actctx.wProcessorArchitecture == 0, "wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture);
2121 ok(actctx.wLangId == 0, "wLangId=%d\n", actctx.wLangId);
2122 ok(actctx.lpAssemblyDirectory == NULL, "lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory);
2123 ok(actctx.lpResourceName == NULL, "lpResourceName=%p\n", actctx.lpResourceName);
2124 ok(actctx.lpApplicationName == NULL, "lpApplicationName=%p\n", actctx.lpApplicationName);
2125 ok(actctx.hModule == NULL, "hModule=%p\n", actctx.hModule);
2126
2127 return handle;
2128}
2129
2130static void test_thread_actctx(void)
2131{
2135 DWORD tid, ret;
2136 BOOL b;
2137
2138 create_manifest_file("testdep1.manifest", manifest_dep);
2139 create_manifest_file("main.manifest", manifest_main);
2140
2141 context = test_create("main.manifest");
2142 DeleteFileA("testdep1.manifest");
2143 DeleteFileA("main.manifest");
2144
2145 handle = (void*)0xdeadbeef;
2147 ok(b, "GetCurrentActCtx failed: %lu\n", GetLastError());
2148 ok(handle == 0, "active context %p\n", handle);
2149
2150 /* without active context */
2151 param.thread_context = (void*)0xdeadbeef;
2152 param.handle = NULL;
2154 ok(thread != NULL, "failed, got %lu\n", GetLastError());
2155
2157 ok(ret == WAIT_OBJECT_0, "wait timeout\n");
2158 ok(param.thread_context == NULL, "got wrong thread context %p\n", param.thread_context);
2160
2162 ok(b, "activation failed: %lu\n", GetLastError());
2163
2164 handle = 0;
2166 ok(b, "GetCurrentActCtx failed: %lu\n", GetLastError());
2167 ok(handle != 0, "no active context\n");
2169
2170 param.handle = NULL;
2171 b = GetCurrentActCtx(&param.handle);
2172 ok(b && param.handle != NULL, "failed to get context, %lu\n", GetLastError());
2173
2174 param.thread_context = (void*)0xdeadbeef;
2176 ok(thread != NULL, "failed, got %lu\n", GetLastError());
2177
2179 ok(ret == WAIT_OBJECT_0, "wait timeout\n");
2180 ok(param.thread_context == context, "got wrong thread context %p, %p\n", param.thread_context, context);
2181 ReleaseActCtx(param.thread_context);
2183
2184 /* similar test for CreateRemoteThread() */
2185 param.thread_context = (void*)0xdeadbeef;
2187 ok(thread != NULL, "failed, got %lu\n", GetLastError());
2188
2190 ok(ret == WAIT_OBJECT_0, "wait timeout\n");
2191 ok(param.thread_context == context, "got wrong thread context %p, %p\n", param.thread_context, context);
2192 ReleaseActCtx(param.thread_context);
2194
2195 ReleaseActCtx(param.handle);
2196
2198 ok(b, "DeactivateActCtx failed: %lu\n", GetLastError());
2200}
2201
2203 int *foo = (int*)context;
2204
2205 (*foo)++;
2206}
2207
2208
2209static void test_threadpool(void)
2210{
2211 PTP_POOL pool;
2212 PTP_WORK work;
2213 int workcalled = 0;
2214
2215 if (!pCreateThreadpool) {
2216 win_skip("thread pool apis not supported.\n");
2217 return;
2218 }
2219
2220 work = pCreateThreadpoolWork(threadpool_workcallback, &workcalled, NULL);
2221 ok (work != NULL, "Error %ld in CreateThreadpoolWork\n", GetLastError());
2222 pSubmitThreadpoolWork(work);
2223 pWaitForThreadpoolWorkCallbacks(work, FALSE);
2224 pCloseThreadpoolWork(work);
2225
2226 ok (workcalled == 1, "expected work to be called once, got %d\n", workcalled);
2227
2228 pool = pCreateThreadpool(NULL);
2229 ok (pool != NULL, "CreateThreadpool failed\n");
2230 pCloseThreadpool(pool);
2231}
2232
2233static void test_reserved_tls(void)
2234{
2235 void *val;
2236 DWORD tls;
2237 BOOL ret;
2238
2239 /* This seems to be a WinXP SP2+ feature. */
2240 if(!pIsWow64Process) {
2241 win_skip("Skipping reserved TLS slot on too old Windows.\n");
2242 return;
2243 }
2244
2245 val = TlsGetValue(0);
2246 ok(!val, "TlsGetValue(0) = %p\n", val);
2247
2248 /* Also make sure that there is a TLS allocated. */
2249 tls = TlsAlloc();
2250 ok(tls && tls != TLS_OUT_OF_INDEXES, "tls = %lx\n", tls);
2251 TlsSetValue(tls, (void*)1);
2252
2253 val = TlsGetValue(0);
2254 ok(!val, "TlsGetValue(0) = %p\n", val);
2255
2256 TlsFree(tls);
2257
2258 /* The following is too ugly to be run by default */
2259 if(0) {
2260 /* Set TLS index 0 value and see that this works and doesn't cause problems
2261 * for remaining tests. */
2262 ret = TlsSetValue(0, (void*)1);
2263 ok(ret, "TlsSetValue(0, 1) failed: %lu\n", GetLastError());
2264
2265 val = TlsGetValue(0);
2266 ok(val == (void*)1, "TlsGetValue(0) = %p\n", val);
2267 }
2268}
2269
2270static void test_thread_info(void)
2271{
2272 char buf[4096];
2273 static const ULONG info_size[] =
2274 {
2275 sizeof(THREAD_BASIC_INFORMATION), /* ThreadBasicInformation */
2276 sizeof(KERNEL_USER_TIMES), /* ThreadTimes */
2277 sizeof(ULONG), /* ThreadPriority */
2278 sizeof(ULONG), /* ThreadBasePriority */
2279 sizeof(ULONG_PTR), /* ThreadAffinityMask */
2280 sizeof(HANDLE), /* ThreadImpersonationToken */
2281 sizeof(THREAD_DESCRIPTOR_INFORMATION), /* ThreadDescriptorTableEntry */
2282 sizeof(BOOLEAN), /* ThreadEnableAlignmentFaultFixup */
2283 0, /* ThreadEventPair_Reusable */
2284 sizeof(ULONG_PTR), /* ThreadQuerySetWin32StartAddress */
2285 sizeof(ULONG), /* ThreadZeroTlsCell */
2286 sizeof(LARGE_INTEGER), /* ThreadPerformanceCount */
2287 sizeof(ULONG), /* ThreadAmILastThread */
2288 sizeof(ULONG), /* ThreadIdealProcessor */
2289 sizeof(ULONG), /* ThreadPriorityBoost */
2290 sizeof(ULONG_PTR), /* ThreadSetTlsArrayAddress */
2291 sizeof(ULONG), /* ThreadIsIoPending */
2292 sizeof(BOOLEAN), /* ThreadHideFromDebugger */
2293 /* FIXME: Add remaining classes */
2294 };
2295 HANDLE thread;
2297
2298 if (!pOpenThread)
2299 {
2300 win_skip("OpenThread is not available on this platform\n");
2301 return;
2302 }
2303
2304 if (!pNtQueryInformationThread)
2305 {
2306 win_skip("NtQueryInformationThread is not available on this platform\n");
2307 return;
2308 }
2309
2311 if (!thread)
2312 {
2313 win_skip("THREAD_QUERY_LIMITED_INFORMATION is not supported on this platform\n");
2314 return;
2315 }
2316
2317 for (i = 0; i < ARRAY_SIZE(info_size); i++)
2318 {
2319 memset(buf, 0, sizeof(buf));
2320
2321#ifdef __i386__
2323 {
2324 CONTEXT ctx;
2325 THREAD_DESCRIPTOR_INFORMATION *tdi = (void *)buf;
2326
2327 ctx.ContextFlags = CONTEXT_SEGMENTS;
2329 tdi->Selector = ctx.SegDs;
2330 }
2331#endif
2332 ret_len = 0;
2333 status = pNtQueryInformationThread(thread, i, buf, info_size[i], &ret_len);
2334 if (status == STATUS_NOT_IMPLEMENTED) continue;
2335 if (status == STATUS_INVALID_INFO_CLASS) continue;
2336 if (status == STATUS_UNSUCCESSFUL) continue;
2337
2338 switch (i)
2339 {
2343#ifdef __REACTOS__
2344 ok(status == STATUS_SUCCESS || broken(status == STATUS_ACCESS_DENIED && (i == 0 || i == 14)) /* WS03 */, "for info %lu expected STATUS_SUCCESS, got %08lx (ret_len %lu)\n", i, status, ret_len);
2345#else
2346 ok(status == STATUS_SUCCESS, "for info %lu expected STATUS_SUCCESS, got %08lx (ret_len %lu)\n", i, status, ret_len);
2347#endif
2348 break;
2349
2350#ifdef __i386__
2352 ok(status == STATUS_SUCCESS || broken(status == STATUS_ACCESS_DENIED) /* testbot VM is broken */,
2353 "for info %lu expected STATUS_SUCCESS, got %08lx (ret_len %lu)\n", i, status, ret_len);
2354 break;
2355#endif
2356
2357 case ThreadTimes:
2358#ifdef __REACTOS__
2359 ok(status == STATUS_SUCCESS || broken(status == STATUS_ACCESS_DENIED) /* WS03 */, "for info %lu expected STATUS_SUCCESS, got %08lx (ret_len %lu)\n", i, status, ret_len);
2360#else
2361 ok(status == STATUS_SUCCESS, "for info %lu expected STATUS_SUCCESS, got %08lx (ret_len %lu)\n", i, status, ret_len);
2362#endif
2363 break;
2364
2365 case ThreadIsIoPending:
2366 todo_wine
2367 ok(status == STATUS_ACCESS_DENIED, "for info %lu expected STATUS_ACCESS_DENIED, got %08lx (ret_len %lu)\n", i, status, ret_len);
2368 break;
2369
2370 default:
2371 ok(status == STATUS_ACCESS_DENIED, "for info %lu expected STATUS_ACCESS_DENIED, got %08lx (ret_len %lu)\n", i, status, ret_len);
2372 break;
2373 }
2374 }
2375
2377}
2378
2380{
2381 DWORD dwType; /* Must be 0x1000. */
2382 LPCSTR szName; /* Pointer to name (in user addr space). */
2383 DWORD dwThreadID; /* Thread ID (-1 = caller thread). */
2384 DWORD dwFlags; /* Reserved for future use, must be zero. */
2386
2388{
2389 if (ExceptionInfo->ExceptionRecord != NULL &&
2390 ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_WINE_NAME_THREAD)
2392
2394}
2395
2397{
2398 THREAD_NAME_INFORMATION *thread_desc;
2399 static const WCHAR *desc = L"thread_desc";
2400 ULONG len, len2, desc_len;
2402 char buff[128];
2403 WCHAR *ptr;
2404 HRESULT hr;
2405 HANDLE thread;
2406 PVOID vectored_handler;
2408
2409 if (!pGetThreadDescription)
2410 {
2411 win_skip("Thread description API is not supported.\n");
2412 return;
2413 }
2414
2415 desc_len = lstrlenW(desc) * sizeof(*desc);
2416 thread_desc = (THREAD_NAME_INFORMATION *)buff;
2417
2418 /* Initial description. */
2419 ptr = NULL;
2420 hr = pGetThreadDescription(GetCurrentThread(), &ptr);
2421 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to get thread description, hr %#lx.\n", hr);
2422 ok(!lstrcmpW(ptr, L""), "Unexpected description %s.\n", wine_dbgstr_w(ptr));
2423 LocalFree(ptr);
2424
2425 len = 0;
2426 status = pNtQueryInformationThread(GetCurrentThread(), ThreadNameInformation, NULL, 0, &len);
2427 ok(status == STATUS_BUFFER_TOO_SMALL, "Unexpected status %#lx.\n", status);
2428 ok(len == sizeof(*thread_desc), "Unexpected structure length %lu.\n", len);
2429
2430 len2 = 0;
2431 thread_desc->ThreadName.Length = 1;
2432 thread_desc->ThreadName.MaximumLength = 0;
2433 thread_desc->ThreadName.Buffer = (WCHAR *)thread_desc;
2434 status = pNtQueryInformationThread(GetCurrentThread(), ThreadNameInformation, thread_desc, len, &len2);
2435 ok(!status, "Failed to get thread info, status %#lx.\n", status);
2436 ok(len2 == sizeof(*thread_desc), "Unexpected structure length %lu.\n", len);
2437 ok(!thread_desc->ThreadName.Length, "Unexpected description length %#x.\n", thread_desc->ThreadName.Length);
2438 ok(thread_desc->ThreadName.Buffer == (WCHAR *)(thread_desc + 1),
2439 "Unexpected description string pointer %p, %p.\n", thread_desc->ThreadName.Buffer, thread_desc);
2440
2441 hr = pSetThreadDescription(GetCurrentThread(), NULL);
2442 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to set thread description, hr %#lx.\n", hr);
2443
2444 hr = pSetThreadDescription(GetCurrentThread(), desc);
2445 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to set thread description, hr %#lx.\n", hr);
2446
2447 ptr = NULL;
2448 hr = pGetThreadDescription(GetCurrentThread(), &ptr);
2449 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to get thread description, hr %#lx.\n", hr);
2450 ok(!lstrcmpW(ptr, desc), "Unexpected description %s.\n", wine_dbgstr_w(ptr));
2451 LocalFree(ptr);
2452
2453 len = 0;
2454 status = pNtQueryInformationThread(GetCurrentThread(), ThreadNameInformation, NULL, 0, &len);
2455 ok(status == STATUS_BUFFER_TOO_SMALL, "Failed to get thread info, status %#lx.\n", status);
2456 ok(len == sizeof(*thread_desc) + desc_len, "Unexpected structure length %lu.\n", len);
2457
2458 len = 0;
2459 status = pNtQueryInformationThread(GetCurrentThread(), ThreadNameInformation, buff, sizeof(buff), &len);
2460 ok(!status, "Failed to get thread info.\n");
2461 ok(len == sizeof(*thread_desc) + desc_len, "Unexpected structure length %lu.\n", len);
2462
2463 ok(thread_desc->ThreadName.Length == desc_len && thread_desc->ThreadName.MaximumLength == desc_len,
2464 "Unexpected description length %u.\n", thread_desc->ThreadName.Length);
2465 ok(thread_desc->ThreadName.Buffer == (WCHAR *)(thread_desc + 1),
2466 "Unexpected description string pointer %p, %p.\n", thread_desc->ThreadName.Buffer, thread_desc);
2467 ok(!memcmp(thread_desc->ThreadName.Buffer, desc, desc_len), "Unexpected description string.\n");
2468
2469 /* Partial results. */
2470 len = 0;
2471 status = pNtQueryInformationThread(GetCurrentThread(), ThreadNameInformation, NULL, 0, &len);
2472 ok(status == STATUS_BUFFER_TOO_SMALL, "Unexpected status %#lx.\n", status);
2473 ok(len == sizeof(*thread_desc) + desc_len, "Unexpected structure length %lu.\n", len);
2474
2475 status = pNtQueryInformationThread(GetCurrentThread(), ThreadNameInformation, buff, len - sizeof(WCHAR), &len);
2476 ok(status == STATUS_BUFFER_TOO_SMALL, "Unexpected status %#lx.\n", status);
2477 ok(len == sizeof(*thread_desc) + desc_len, "Unexpected structure length %lu.\n", len);
2478
2479 /* Change description. */
2480 thread_desc->ThreadName.Length = thread_desc->ThreadName.MaximumLength = 8;
2481 lstrcpyW((WCHAR *)(thread_desc + 1), L"desc");
2482
2483 status = pNtSetInformationThread(GetCurrentThread(), ThreadNameInformation, thread_desc, sizeof(*thread_desc));
2484 ok(status == STATUS_SUCCESS, "Failed to set thread description, status %#lx.\n", status);
2485
2486 ptr = NULL;
2487 hr = pGetThreadDescription(GetCurrentThread(), &ptr);
2488 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to get thread description, hr %#lx.\n", hr);
2489 ok(!lstrcmpW(ptr, L"desc"), "Unexpected description %s.\n", wine_dbgstr_w(ptr));
2490 LocalFree(ptr);
2491
2492 status = pNtSetInformationThread(GetCurrentThread(), ThreadNameInformation, thread_desc, sizeof(*thread_desc) - 1);
2493 ok(status == STATUS_INFO_LENGTH_MISMATCH, "Unexpected status %#lx.\n", status);
2494
2496 ok(status == STATUS_ACCESS_VIOLATION, "Unexpected status %#lx.\n", status);
2497
2498 thread_desc->ThreadName.Buffer = NULL;
2499 status = pNtSetInformationThread(GetCurrentThread(), ThreadNameInformation, thread_desc, sizeof(*thread_desc));
2500 ok(status == STATUS_ACCESS_VIOLATION, "Unexpected status %#lx.\n", status);
2501
2502 hr = pSetThreadDescription(GetCurrentThread(), NULL);
2503 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to set thread description, hr %#lx.\n", hr);
2504
2505 ptr = NULL;
2506 hr = pGetThreadDescription(GetCurrentThread(), &ptr);
2507 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to get thread description, hr %#lx.\n", hr);
2508 ok(!lstrcmpW(ptr, L""), "Unexpected description %s.\n", wine_dbgstr_w(ptr));
2509 LocalFree(ptr);
2510
2511 /* Set with a string from RtlInitUnicodeString. */
2512 hr = pSetThreadDescription(GetCurrentThread(), L"123");
2513 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to set thread description, hr %#lx.\n", hr);
2514
2515 lstrcpyW((WCHAR *)(thread_desc + 1), L"desc");
2516 RtlInitUnicodeString(&thread_desc->ThreadName, (WCHAR *)(thread_desc + 1));
2517
2518 status = pNtSetInformationThread(GetCurrentThread(), ThreadNameInformation, thread_desc, sizeof(*thread_desc));
2519 ok(status == STATUS_SUCCESS, "Failed to set thread description, status %#lx.\n", status);
2520
2521 ptr = NULL;
2522 hr = pGetThreadDescription(GetCurrentThread(), &ptr);
2523 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to get thread description, hr %#lx.\n", hr);
2524 ok(!lstrcmpW(ptr, L"desc"), "Unexpected description %s.\n", wine_dbgstr_w(ptr));
2525 LocalFree(ptr);
2526
2527 /* Set with 0 length/NULL pointer. */
2528 hr = pSetThreadDescription(GetCurrentThread(), L"123");
2529 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to set thread description, hr %#lx.\n", hr);
2530
2531 memset(thread_desc, 0, sizeof(*thread_desc));
2532 status = pNtSetInformationThread(GetCurrentThread(), ThreadNameInformation, thread_desc, sizeof(*thread_desc));
2533 ok(!status, "Failed to set thread description, status %#lx.\n", status);
2534
2535 ptr = NULL;
2536 hr = pGetThreadDescription(GetCurrentThread(), &ptr);
2537 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to get thread description, hr %#lx.\n", hr);
2538 ok(!lstrcmpW(ptr, L""), "Unexpected description %s.\n", wine_dbgstr_w(ptr));
2539 LocalFree(ptr);
2540
2541 /* Get with only THREAD_QUERY_LIMITED_INFORMATION access. */
2543
2544 ptr = NULL;
2545 hr = pGetThreadDescription(thread, &ptr);
2546 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to get thread description, hr %#lx.\n", hr);
2547 ok(!lstrcmpW(ptr, L""), "Unexpected description %s.\n", wine_dbgstr_w(ptr));
2548 LocalFree(ptr);
2549
2550 len = 0;
2551 status = pNtQueryInformationThread(thread, ThreadNameInformation, NULL, 0, &len);
2552 ok(status == STATUS_BUFFER_TOO_SMALL, "Unexpected status %#lx.\n", status);
2553 ok(len == sizeof(*thread_desc), "Unexpected structure length %lu.\n", len);
2554
2556
2557 /* Set with only THREAD_SET_LIMITED_INFORMATION access. */
2559
2560 hr = pSetThreadDescription(thread, desc);
2561 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to set thread description, hr %#lx.\n", hr);
2562
2563 ptr = NULL;
2564 hr = pGetThreadDescription(GetCurrentThread(), &ptr);
2565 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to get thread description, hr %#lx.\n", hr);
2566 ok(!lstrcmpW(ptr, desc), "Unexpected description %s.\n", wine_dbgstr_w(ptr));
2567 LocalFree(ptr);
2568
2570
2571 /* The old exception-based thread name method should not affect GetThreadDescription. */
2572 hr = pSetThreadDescription(GetCurrentThread(), desc);
2573 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to set thread description, hr %#lx.\n", hr);
2574
2575 vectored_handler = pRtlAddVectoredExceptionHandler(FALSE, &msvc_threadname_vec_handler);
2576 ok(vectored_handler != 0, "RtlAddVectoredExceptionHandler failed\n");
2577
2578 info.dwType = 0x1000;
2579 info.szName = "123";
2580 info.dwThreadID = -1;
2581 info.dwFlags = 0;
2582 RaiseException(EXCEPTION_WINE_NAME_THREAD, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
2583
2584 pRtlRemoveVectoredExceptionHandler(vectored_handler);
2585
2586 ptr = NULL;
2587 hr = pGetThreadDescription(GetCurrentThread(), &ptr);
2588 ok(hr == HRESULT_FROM_NT(STATUS_SUCCESS), "Failed to get thread description, hr %#lx.\n", hr);
2589 ok(!lstrcmpW(ptr, desc), "Unexpected description %s.\n", wine_dbgstr_w(ptr));
2590 LocalFree(ptr);
2591}
2592
2593static void init_funcs(void)
2594{
2595 HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
2596 HMODULE ntdll = GetModuleHandleA("ntdll.dll");
2597
2598/* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
2599 so that the compile passes */
2600
2601#define X(f) p##f = (void*)GetProcAddress(hKernel32, #f)
2604 X(OpenThread);
2613
2620
2625
2626 X(FlsAlloc);
2627 X(FlsFree);
2628 X(FlsSetValue);
2629 X(FlsGetValue);
2630#undef X
2631
2632#define X(f) p##f = (void*)GetProcAddress(ntdll, #f)
2633 if (ntdll)
2634 {
2640 }
2641#undef X
2642}
2643
2645{
2646 int argc;
2647 char **argv;
2649
2650 init_funcs();
2651
2652 if (argc >= 3)
2653 {
2654 if (!strcmp(argv[2], "sleep"))
2655 {
2656 HANDLE hAddrEvents[2];
2657 create_function_addr_events(hAddrEvents);
2658 SetEvent(hAddrEvents[0]);
2659 SetEvent(hAddrEvents[1]);
2660 Sleep(5000); /* spawned process runs for at most 5 seconds */
2661 return;
2662 }
2663 while (1)
2664 {
2666 DWORD tid;
2668 ok(hThread != NULL, "CreateThread failed, error %lu\n",
2669 GetLastError());
2671 "Thread did not exit in time\n");
2672 if (hThread == NULL) break;
2674 }
2675 return;
2676 }
2677
2692#ifdef __i386__
2693 test_SetThreadContext();
2694 test_GetThreadSelectorEntry();
2695 test_GetThreadContext();
2696#endif
2699 test_TLS();
2700 test_FLS();
2705
2707}
unsigned char BOOLEAN
static int argc
Definition: ServiceArgs.c:12
#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 broken(x)
Definition: atltest.h:178
#define START_TEST(x)
Definition: atltest.h:75
LONG NTSTATUS
Definition: precomp.h:26
#define ARRAY_SIZE(A)
Definition: main.h:20
#define U(x)
Definition: wordpad.c:45
static HANDLE thread
Definition: service.c:33
#define ULongToPtr(ul)
Definition: basetsd.h:86
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
#define WAIT_TIMEOUT
Definition: dderror.h:14
#define ERROR_IO_PENDING
Definition: dderror.h:15
#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:19
#define CloseHandle
Definition: compat.h:739
#define ERROR_INVALID_ADDRESS
Definition: compat.h:106
#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
@ 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 lstrcpyW
Definition: compat.h:749
#define MultiByteToWideChar
Definition: compat.h:110
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
#define lstrlenW
Definition: compat.h:750
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
VOID WINAPI RaiseException(_In_ DWORD dwExceptionCode, _In_ DWORD dwExceptionFlags, _In_ DWORD nNumberOfArguments, _In_opt_ const ULONG_PTR *lpArguments)
Definition: except.c:700
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:4749
BOOL WINAPI TerminateProcess(IN HANDLE hProcess, IN UINT uExitCode)
Definition: proc.c:1534
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 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 SetThreadStackGuarantee(IN OUT PULONG StackSizeInBytes)
Definition: thread.c:1006
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
HANDLE WINAPI CreateActCtxW(PCACTCTXW pActCtx)
Definition: actctx.c:102
int WINAPI lstrcmpW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4246
ULONG WINAPI DECLSPEC_HOTPATCH GetTickCount(void)
Definition: sync.c:182
BOOL WINAPI DECLSPEC_HOTPATCH GetThreadGroupAffinity(HANDLE thread, GROUP_AFFINITY *affinity)
Definition: thread.c:212
PTP_POOL WINAPI DECLSPEC_HOTPATCH CreateThreadpool(void *reserved)
Definition: thread.c:1255
DWORD WINAPI DECLSPEC_HOTPATCH TlsAlloc(void)
Definition: thread.c:657
void WINAPI DECLSPEC_HOTPATCH GetCurrentThreadStackLimits(ULONG_PTR *low, ULONG_PTR *high)
Definition: thread.c:131
DWORD WINAPI DECLSPEC_HOTPATCH FlsAlloc(PFLS_CALLBACK_FUNCTION callback)
Definition: thread.c:1198
DWORD WINAPI DECLSPEC_HOTPATCH GetThreadErrorMode(void)
Definition: thread.c:203
BOOL WINAPI DECLSPEC_HOTPATCH FlsSetValue(DWORD index, PVOID data)
Definition: thread.c:1232
HRESULT WINAPI DECLSPEC_HOTPATCH GetThreadDescription(HANDLE thread, WCHAR **description)
Definition: thread.c:435
HRESULT WINAPI DECLSPEC_HOTPATCH SetThreadDescription(HANDLE thread, PCWSTR description)
Definition: thread.c:414
BOOL WINAPI SetThreadErrorMode(DWORD mode, DWORD *old)
Definition: thread.c:474
PTP_WORK WINAPI DECLSPEC_HOTPATCH CreateThreadpoolWork(PTP_WORK_CALLBACK callback, PVOID userdata, TP_CALLBACK_ENVIRON *environment)
Definition: thread.c:1325
BOOL WINAPI DECLSPEC_HOTPATCH SetThreadGroupAffinity(HANDLE thread, const GROUP_AFFINITY *new, GROUP_AFFINITY *old)
Definition: thread.c:498
PVOID WINAPI DECLSPEC_HOTPATCH FlsGetValue(DWORD index)
Definition: thread.c:1219
BOOL WINAPI DECLSPEC_HOTPATCH FlsFree(DWORD index)
Definition: thread.c:1210
#define assert(_expr)
Definition: assert.h:32
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2802
#define _MCW_EM
Definition: float.h:64
_ACRTIMP unsigned int __cdecl _statusfp(void)
Definition: math.c:1156
#define _PC_64
Definition: float.h:85
#define _MCW_PC
Definition: float.h:67
#define _MCW_RC
Definition: float.h:66
#define _EM_INEXACT
Definition: float.h:76
_ACRTIMP unsigned int __cdecl _clearfp(void)
Definition: math.c:1174
#define _PC_24
Definition: float.h:83
_ACRTIMP unsigned int __cdecl _control87(unsigned int, unsigned int)
Definition: math.c:1265
_ACRTIMP int __cdecl _isnan(double)
Definition: math.c:1660
#define _RC_CHOP
Definition: float.h:79
#define _SW_INVALID
Definition: float.h:97
#define _PC_53
Definition: float.h:84
_ACRTIMP double __cdecl acos(double)
Definition: acos.c:28
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3319
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
KAFFINITY affinity
Definition: wave.h:2
#define INFINITE
Definition: serial.h:102
#define ULONG_PTR
Definition: config.h:101
static unsigned char buff[32768]
Definition: fatten.c:17
#define MAXIMUM_PROCESSORS
Definition: rwlock.h:5
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
#define STATUS_ACCESS_VIOLATION
FxCollectionEntry * cur
struct _cl_event * event
Definition: glext.h:7739
GLuint res
Definition: glext.h:9613
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
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
GLenum GLsizei len
Definition: glext.h:6722
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
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1594
#define THREAD_QUERY_INFORMATION
Definition: pstypes.h:150
#define EXCEPTION_CONTINUE_SEARCH
Definition: excpt.h:91
#define EXCEPTION_CONTINUE_EXECUTION
Definition: excpt.h:92
NTSYSAPI ULONG WINAPI RtlRemoveVectoredExceptionHandler(PVOID)
NTSYSAPI DWORD WINAPI RtlGetThreadErrorMode(void)
Definition: error.c:217
@ ThreadNameInformation
Definition: winternl.h:2319
struct _THREAD_DESCRIPTOR_INFORMATION THREAD_DESCRIPTOR_INFORMATION
NTSYSAPI PVOID WINAPI RtlAddVectoredExceptionHandler(ULONG, PVECTORED_EXCEPTION_HANDLER)
#define THREAD_SUSPEND_RESUME
static TfClientId tid
const char * filename
Definition: ioapi.h:137
#define NtCurrentTeb
uint32_t entry
Definition: isohybrid.c:63
#define d
Definition: ke_i.h:81
#define b
Definition: ke_i.h:79
#define actctx
Definition: kernel32.h:8
#define wine_dbgstr_w
Definition: kernel32.h:34
BOOL is_wow64
Definition: main.c:38
int WINAPI lstrlenA(LPCSTR lpString)
Definition: lstring.c:145
_In_ BOOL _In_ HANDLE hProcess
Definition: mapping.h:71
#define win_skip
Definition: minitest.h:67
#define todo_wine_if(is_todo)
Definition: minitest.h:81
#define todo_wine
Definition: minitest.h:80
#define STILL_ACTIVE
Definition: minwinbase.h:43
PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE
Definition: minwinbase.h:124
#define error(str)
Definition: mkdosfs.c:1605
#define CREATE_ALWAYS
Definition: disk.h:72
static PVOID ptr
Definition: dispmode.c:27
#define sprintf
Definition: sprintf.c:45
HANDLE hKernel32
Definition: locale.c:13
HANDLE events[2]
Definition: event.c:4
static DWORD GLE
Definition: registry.c:38
#define THREAD_QUERY_LIMITED_INFORMATION
Definition: security.c:62
#define THREAD_SET_LIMITED_INFORMATION
Definition: security.c:61
static void test_create(void)
Definition: monthcal.c:1595
D3D11_SHADER_VARIABLE_DESC desc
Definition: reflection.c:1204
static HANDLE hEvent
Definition: comm.c:54
static HMODULE ntdll
Definition: debugger.c:59
static PROCESS_INFORMATION pi
Definition: debugger.c:2303
static JOBOBJECTINFOCLASS LPVOID DWORD LPDWORD ret_len
Definition: process.c:81
static HANDLE ULONG_PTR DWORD threads
Definition: process.c:83
static const char * LS_SetValueFuncName
Definition: thread.c:1560
static DWORD LS_index1
Definition: thread.c:1548
static DWORD WINAPI threadFunc1(LPVOID p)
Definition: thread.c:213
static const char * LS_AllocFuncName
Definition: thread.c:1558
static DWORD CALLBACK work_function(void *p)
Definition: thread.c:1311
static VOID test_GetThreadTimes(void)
Definition: thread.c:794
static WAITORTIMERCALLBACK
Definition: thread.c:84
static unsigned int get_thread_fpu_cw(unsigned long *fpu_cw)
Definition: thread.c:1964
static void test_thread_actctx(void)
Definition: thread.c:2130
static VOID test_CreateThread_stack(void)
Definition: thread.c:647
static void test_threadpool(void)
Definition: thread.c:2209
static VOID test_SuspendThread(void)
Definition: thread.c:555
static const char manifest_dep[]
Definition: thread.c:2074
static void create_function_addr_events(HANDLE events[2])
Definition: thread.c:317
static DWORD WINAPI threadFunc3(LPVOID p)
Definition: thread.c:246
static const char * LS_FreeFuncName
Definition: thread.c:1561
static DWORD LS_main
Definition: thread.c:1547
static void CALLBACK wait_complete_function(PVOID p, BOOLEAN TimerOrWaitFired)
Definition: thread.c:1355
static void cleanup_thread_sync_helpers(void)
Definition: thread.c:181
#define X(f)
static BOOL
Definition: thread.c:80
static void CALLBACK timeout_function(PVOID p, BOOLEAN TimerOrWaitFired)
Definition: thread.c:1364
static HANDLE
Definition: thread.c:84
static const WCHAR *static WCHAR **static PVECTORED_EXCEPTION_HANDLER
Definition: thread.c:102
static DWORD WINAPI LS_InheritanceProc(LPVOID p)
Definition: thread.c:1575
static unsigned long get_fpu_cw(void)
Definition: thread.c:1895
static VOID test_CreateThread_basic(void)
Definition: thread.c:419
static DWORD WINAPI threadFunc_SetEvent(LPVOID p)
Definition: thread.c:284
static VOID test_CreateThread_suspended(void)
Definition: thread.c:516
static void test_RegisterWaitForSingleObject(void)
Definition: thread.c:1406
static THREADINFOCLASS
Definition: thread.c:96
#define ARCH
Definition: thread.c:75
static void create_manifest_file(const char *filename, const char *manifest)
Definition: thread.c:2090
static HANDLE finish_event
Definition: thread.c:1308
static void test_SetThreadStackGuarantee(void)
Definition: thread.c:1025
static INT obeying_ars
Definition: thread.c:198
static DWORD WINAPI threadFunc_CloseHandle(LPVOID p)
Definition: thread.c:290
static HANDLE create_target_process(const char *arg)
Definition: thread.c:105
#define NUM_THREADS
Definition: thread.c:44
#define THREAD_ALL_ACCESS_NT4
Definition: thread.c:41
static void fpu_invalid_operation(void)
Definition: thread.c:1928
static VOID test_thread_processor(void)
Definition: thread.c:851
static VOID test_thread_priority(void)
Definition: thread.c:674
static VOID test_CreateRemoteThread(void)
Definition: thread.c:329
static DWORD
Definition: thread.c:80
static DWORD WINAPI threadFunc4(LPVOID p)
Definition: thread.c:254
static DWORD tlsIndex
Definition: thread.c:187
static PBOOL
Definition: thread.c:79
static void test_reserved_tls(void)
Definition: thread.c:2233
static void WINAPI threadpool_workcallback(PTP_CALLBACK_INSTANCE instance, void *context, PTP_WORK work)
Definition: thread.c:2202
#define obey_ar(x)
Definition: thread.c:199
static void CALLBACK signaled_function(PVOID p, BOOLEAN TimerOrWaitFired)
Definition: thread.c:1348
static HANDLE stop_event
Definition: thread.c:136
static ULONG
Definition: thread.c:81
static void test_thread_description(void)
Definition: thread.c:2396
struct tagTHREADNAME_INFO THREADNAME_INFO
static VOID test_GetCurrentThreadStackLimits(void)
Definition: thread.c:1002
static DWORD WINAPI threadFunc2(LPVOID p)
Definition: thread.c:241
static DWORD WINAPI thread_actctx_func(void *p)
Definition: thread.c:302
static PVOID
Definition: thread.c:81
static void resync_after_run(void)
Definition: thread.c:165
static GROUP_AFFINITY *static const GROUP_AFFINITY GROUP_AFFINITY *static LPCVOID
Definition: thread.c:99
static DWORD LS_index0
Definition: thread.c:1548
static void test_FLS(void)
Definition: thread.c:1772
static DWORD WINAPI fpu_thread(void *param)
Definition: thread.c:1950
static void run_LS_tests(void)
Definition: thread.c:1721
static HANDLE start_event
Definition: thread.c:136
static LONG CALLBACK msvc_threadname_vec_handler(EXCEPTION_POINTERS *ExceptionInfo)
Definition: thread.c:2387
static void test_thread_fpu_cw(void)
Definition: thread.c:1987
static DWORD WINAPI LS_ThreadProc(LPVOID p)
Definition: thread.c:1596
static VOID test_TerminateThread(void)
Definition: thread.c:610
static BOOL sync_threads_and_run_one(DWORD sync_id, DWORD my_id)
Definition: thread.c:148
static LONG num_synced
Definition: thread.c:137
static void init_funcs(void)
Definition: thread.c:2593
static void test_QueueUserWorkItem(void)
Definition: thread.c:1320
static DWORD WINAPI FLS_AllocFuncThunk(void)
Definition: thread.c:1570
static PDWORD
Definition: thread.c:87
static void CALLBACK unregister_function(PVOID p, BOOLEAN TimerOrWaitFired)
Definition: thread.c:1395
static PTP_CALLBACK_ENVIRON
Definition: thread.c:92
static void init_thread_sync_helpers(void)
Definition: thread.c:139
static void CALLBACK waitthread_test_function(PVOID p, BOOLEAN TimerOrWaitFired)
Definition: thread.c:1378
static void test_TLS(void)
Definition: thread.c:1755
static LONG times_executed
Definition: thread.c:1309
static void test_thread_info(void)
Definition: thread.c:2270
static PULONG_PTR
Definition: thread.c:78
static void test_ThreadErrorMode(void)
Definition: thread.c:1795
static PULONG
Definition: thread.c:96
static const char * LS_GetValueFuncName
Definition: thread.c:1559
static VOID test_GetThreadExitCode(void)
Definition: thread.c:1080
static DWORD LS_OutOfIndexesValue
Definition: thread.c:1549
static const char manifest_main[]
Definition: thread.c:2080
static SYSTEM_INFO si
Definition: virtual.c:39
static int test_value
Definition: signal.c:25
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_DEBUG_REGISTERS
Definition: nt_native.h:1376
#define CONTEXT_CONTROL
Definition: nt_native.h:1372
#define THREAD_TERMINATE
Definition: nt_native.h:1339
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define CONTEXT_SEGMENTS
Definition: nt_native.h:1374
#define CONTEXT_FULL
Definition: nt_native.h:1378
#define GENERIC_WRITE
Definition: nt_native.h:90
#define THREAD_SET_INFORMATION
Definition: nt_native.h:1340
NTSTATUS NTAPI NtQueryInformationThread(_In_ HANDLE ThreadHandle, _In_ THREADINFOCLASS ThreadInformationClass, _Out_writes_bytes_to_opt_(ThreadInformationLength, *ReturnLength) PVOID ThreadInformation, _In_ ULONG ThreadInformationLength, _Out_opt_ PULONG ReturnLength)
Definition: query.c:2881
NTSTATUS NTAPI NtSetInformationThread(_In_ HANDLE ThreadHandle, _In_ THREADINFOCLASS ThreadInformationClass, _In_reads_bytes_(ThreadInformationLength) PVOID ThreadInformation, _In_ ULONG ThreadInformationLength)
Definition: query.c:2268
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:333
@ sse
Definition: optimize.h:107
#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" "\tsub %rbp, %rax\n" "\tpush %rbp\n" "\t.seh_pushreg %rbp\n" "\tsub $32, %rsp\n" "\t.seh_stackalloc 32\n" "\t.seh_endprologue\n" "\tsub %rax, %rdx\n" "\tmov %rdx, %rbp\n" "\tjmp *%r8\n" "__seh2_global_filter_func_exit:\n" "\t.p2align 4\n" "\tadd $32, %rsp\n" "\tpop %rbp\n" "\tret\n" "\t.seh_endproc")
#define alloca
Definition: malloc.h:357
int winetest_get_mainargs(char ***pargv)
#define memset(x, y, z)
Definition: compat.h:39
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
HRESULT hr
Definition: shlfolder.c:183
static DWORD tls
Definition: sock.c:229
TCHAR * cmdline
Definition: stretchblt.cpp:32
PEXCEPTION_RECORD ExceptionRecord
Definition: rtltypes.h:200
DWORD ExceptionCode
Definition: compat.h:208
DWORD dwHighDateTime
Definition: mapidefs.h:66
DWORD dwLowDateTime
Definition: mapidefs.h:65
$USHORT Group
Definition: ntbasedef.h:673
KAFFINITY Mask
Definition: ntbasedef.h:672
Definition: compat.h:777
ULONG64 LdrData
Definition: winternl.h:1047
DWORD dwPageSize
Definition: winbase.h:898
DWORD dwNumberOfProcessors
Definition: winbase.h:902
ULONG64 Peb
Definition: winternl.h:1254
UNICODE_STRING ThreadName
Definition: pstypes.h:1090
USHORT MaximumLength
Definition: env_spec_w32.h:370
Definition: http.c:7252
Definition: cookie.c:34
Definition: fci.c:127
HANDLE finished
Definition: thread.c:1892
unsigned long fpu_cw
Definition: thread.c:1891
unsigned int cw
Definition: thread.c:1890
Definition: format.c:80
Definition: ps.c:97
int threadnum
Definition: thread.c:190
DWORD * threadmem
Definition: thread.c:192
HANDLE * event
Definition: thread.c:191
HANDLE thread_context
Definition: thread.c:298
HANDLE complete_event
Definition: thread.c:1392
HANDLE wait_handle
Definition: thread.c:1391
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
WINBASEAPI VOID WINAPI CloseThreadpoolWork(_Inout_ PTP_WORK pwk)
WINBASEAPI VOID WINAPI WaitForThreadpoolWorkCallbacks(_Inout_ PTP_WORK pwk, _In_ BOOL fCancelPendingCallbacks)
WINBASEAPI VOID WINAPI SubmitThreadpoolWork(_Inout_ PTP_WORK pwk)
WINBASEAPI VOID WINAPI CloseThreadpool(_Inout_ PTP_POOL ptpp)
#define LONG_PTR
Definition: treelist.c:79
#define DWORD_PTR
Definition: treelist.c:76
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
#define MAKELONG(a, b)
Definition: typedefs.h:249
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
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
static const CHAR manifest[]
Definition: v6util.h:41
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
HANDLE WINAPI GetCurrentThread(void)
Definition: proc.c:1148
#define FLS_OUT_OF_INDEXES
Definition: winbase.h:556
DWORD WINAPI GetCurrentThreadId(void)
Definition: thread.c:459
#define CREATE_SUSPENDED
Definition: winbase.h:182
VOID(WINAPI * PFLS_CALLBACK_FUNCTION)(PVOID)
Definition: winbase.h:1202
#define TLS_OUT_OF_INDEXES
Definition: winbase.h:529
#define WAIT_OBJECT_0
Definition: winbase.h:383
#define THREAD_PRIORITY_TIME_CRITICAL
Definition: winbase.h:305
#define THREAD_PRIORITY_ERROR_RETURN
Definition: winbase.h:306
#define THREAD_PRIORITY_NORMAL
Definition: winbase.h:304
#define THREAD_PRIORITY_IDLE
Definition: winbase.h:302
#define HRESULT
Definition: msvc.h:7
#define WINAPI
Definition: msvc.h:6
#define __EXCEPT(func)
Definition: exception.h:62
#define HRESULT_FROM_NT(x)
Definition: winerror.h:216
#define ERROR_INVALID_PRIORITY
Definition: winerror.h:1464
#define ERROR_INVALID_THREAD_ID
Definition: winerror.h:1270
#define ERROR_GEN_FAILURE
Definition: winerror.h:256
#define ERROR_NOACCESS
Definition: winerror.h:902
struct _TP_CALLBACK_INSTANCE * PTP_CALLBACK_INSTANCE
Definition: winnt_old.h:4651
#define WT_EXECUTEONLYONCE
Definition: winnt_old.h:1096
struct _TP_WORK * PTP_WORK
Definition: winnt_old.h:4650
#define WT_EXECUTEINWAITTHREAD
Definition: winnt_old.h:1095
VOID(NTAPI * PTP_WORK_CALLBACK)(_Inout_ PTP_CALLBACK_INSTANCE Instance, _Inout_opt_ PVOID Context, _Inout_ PTP_WORK Work)
Definition: winnt_old.h:4674
struct _TP_POOL * PTP_POOL
Definition: winnt_old.h:4649
#define WT_EXECUTEDEFAULT
Definition: winnt_old.h:1092
#define DUPLICATE_SAME_ACCESS
const char * LPCSTR
Definition: xmlstorage.h:183
__wchar_t WCHAR
Definition: xmlstorage.h:180