EnumThemeColors() and EnumThemeSizes() actually do not return a single
[wine] / dlls / kernel / thread.c
1 /*
2  * Win32 threads
3  *
4  * Copyright 1996 Alexandre Julliard
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <assert.h>
25 #include <fcntl.h>
26 #include <stdarg.h>
27 #include <sys/types.h>
28 #ifdef HAVE_SYS_TIMES_H
29 #include <sys/times.h>
30 #endif
31 #ifdef HAVE_UNISTD_H
32 # include <unistd.h>
33 #endif
34
35 #include "ntstatus.h"
36 #include "windef.h"
37 #include "winbase.h"
38 #include "winerror.h"
39 #include "winnls.h"
40 #include "thread.h"
41 #include "module.h"
42 #include "wine/winbase16.h"
43 #include "wine/exception.h"
44 #include "wine/library.h"
45 #include "wine/pthread.h"
46 #include "wine/server.h"
47 #include "wine/debug.h"
48
49 #include "kernel_private.h"
50
51 WINE_DEFAULT_DEBUG_CHANNEL(thread);
52 WINE_DECLARE_DEBUG_CHANNEL(relay);
53
54
55 /***********************************************************************
56  *           THREAD_InitStack
57  *
58  * Allocate the stack of a thread.
59  */
60 TEB *THREAD_InitStack( TEB *teb, DWORD stack_size )
61 {
62     DWORD old_prot;
63     DWORD page_size = getpagesize();
64     void *base;
65
66     stack_size = (stack_size + (page_size - 1)) & ~(page_size - 1);
67     if (stack_size < 1024 * 1024) stack_size = 1024 * 1024;  /* Xlib needs a large stack */
68
69     if (!(base = VirtualAlloc( NULL, stack_size, MEM_COMMIT, PAGE_READWRITE )))
70         return NULL;
71
72     teb->DeallocationStack = base;
73     teb->Tib.StackBase     = (char *)base + stack_size;
74     teb->Tib.StackLimit    = base;  /* note: limit is lower than base since the stack grows down */
75
76     /* Setup guard pages */
77
78     VirtualProtect( base, 1, PAGE_READWRITE | PAGE_GUARD, &old_prot );
79     return teb;
80 }
81
82
83 struct new_thread_info
84 {
85     LPTHREAD_START_ROUTINE func;
86     void                  *arg;
87 };
88
89 /***********************************************************************
90  *           THREAD_Start
91  *
92  * Start execution of a newly created thread. Does not return.
93  */
94 static void CALLBACK THREAD_Start( void *ptr )
95 {
96     struct new_thread_info *info = ptr;
97     LPTHREAD_START_ROUTINE func = info->func;
98     void *arg = info->arg;
99
100     RtlFreeHeap( GetProcessHeap(), 0, info );
101
102     if (TRACE_ON(relay))
103         DPRINTF("%04lx:Starting thread (entryproc=%p)\n", GetCurrentThreadId(), func );
104
105     __TRY
106     {
107         MODULE_DllThreadAttach( NULL );
108         ExitThread( func( arg ) );
109     }
110     __EXCEPT(UnhandledExceptionFilter)
111     {
112         TerminateThread( GetCurrentThread(), GetExceptionCode() );
113     }
114     __ENDTRY
115 }
116
117
118 /***********************************************************************
119  *           CreateThread   (KERNEL32.@)
120  */
121 HANDLE WINAPI CreateThread( SECURITY_ATTRIBUTES *sa, SIZE_T stack,
122                             LPTHREAD_START_ROUTINE start, LPVOID param,
123                             DWORD flags, LPDWORD id )
124 {
125      return CreateRemoteThread( GetCurrentProcess(),
126                                 sa, stack, start, param, flags, id );
127 }
128
129
130 /***************************************************************************
131  *                  CreateRemoteThread   (KERNEL32.@)
132  *
133  * Creates a thread that runs in the address space of another process
134  *
135  * PARAMS
136  *
137  * RETURNS
138  *   Success: Handle to the new thread.
139  *   Failure: NULL. Use GetLastError() to find the error cause.
140  *
141  * BUGS
142  *   Improper memory allocation: there's no ability to free new_thread_info
143  *   in other process.
144  *   Bad start address for RtlCreateUserThread because the library
145  *   may be loaded at different address in other process.
146  */
147 HANDLE WINAPI CreateRemoteThread( HANDLE hProcess, SECURITY_ATTRIBUTES *sa, SIZE_T stack,
148                                   LPTHREAD_START_ROUTINE start, LPVOID param,
149                                   DWORD flags, LPDWORD id )
150 {
151     HANDLE handle;
152     CLIENT_ID client_id;
153     NTSTATUS status;
154     SIZE_T stack_reserve = 0, stack_commit = 0;
155     struct new_thread_info *info;
156
157     if (!(info = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*info) )))
158     {
159         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
160         return 0;
161     }
162     info->func = start;
163     info->arg  = param;
164
165     if (flags & STACK_SIZE_PARAM_IS_A_RESERVATION) stack_reserve = stack;
166     else stack_commit = stack;
167
168     status = RtlCreateUserThread( hProcess, NULL, TRUE,
169                                   NULL, stack_reserve, stack_commit,
170                                   THREAD_Start, info, &handle, &client_id );
171     if (status == STATUS_SUCCESS)
172     {
173         if (id) *id = (DWORD)client_id.UniqueThread;
174         if (sa && (sa->nLength >= sizeof(*sa)) && sa->bInheritHandle)
175             SetHandleInformation( handle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT );
176         if (!(flags & CREATE_SUSPENDED))
177         {
178             ULONG ret;
179             if (NtResumeThread( handle, &ret ))
180             {
181                 NtClose( handle );
182                 RtlFreeHeap( GetProcessHeap(), 0, info );
183                 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
184                 handle = 0;
185             }
186         }
187     }
188     else
189     {
190         RtlFreeHeap( GetProcessHeap(), 0, info );
191         SetLastError( RtlNtStatusToDosError(status) );
192         handle = 0;
193     }
194     return handle;
195 }
196
197
198 /***********************************************************************
199  * OpenThread  [KERNEL32.@]   Retrieves a handle to a thread from its thread id
200  */
201 HANDLE WINAPI OpenThread( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId )
202 {
203     NTSTATUS status;
204     HANDLE handle;
205     OBJECT_ATTRIBUTES attr;
206     CLIENT_ID cid;
207
208     attr.Length = sizeof(attr);
209     attr.RootDirectory = 0;
210     attr.Attributes = bInheritHandle ? OBJ_INHERIT : 0;
211     attr.ObjectName = NULL;
212     attr.SecurityDescriptor = NULL;
213     attr.SecurityQualityOfService = NULL;
214
215     cid.UniqueProcess = 0; /* FIXME */
216     cid.UniqueThread = (HANDLE)dwThreadId;
217     status = NtOpenThread( &handle, dwDesiredAccess, &attr, &cid );
218     if (status)
219     {
220         SetLastError( RtlNtStatusToDosError(status) );
221         handle = 0;
222     }
223     return handle;
224 }
225
226
227 /***********************************************************************
228  * ExitThread [KERNEL32.@]  Ends a thread
229  *
230  * RETURNS
231  *    None
232  */
233 void WINAPI ExitThread( DWORD code ) /* [in] Exit code for this thread */
234 {
235     BOOL last;
236     SERVER_START_REQ( terminate_thread )
237     {
238         /* send the exit code to the server */
239         req->handle    = GetCurrentThread();
240         req->exit_code = code;
241         wine_server_call( req );
242         last = reply->last;
243     }
244     SERVER_END_REQ;
245
246     if (last)
247     {
248         LdrShutdownProcess();
249         exit( code );
250     }
251     else RtlExitUserThread( code );
252 }
253
254
255 /**********************************************************************
256  * TerminateThread [KERNEL32.@]  Terminates a thread
257  *
258  * RETURNS
259  *    Success: TRUE
260  *    Failure: FALSE
261  */
262 BOOL WINAPI TerminateThread( HANDLE handle,    /* [in] Handle to thread */
263                              DWORD exit_code)  /* [in] Exit code for thread */
264 {
265     NTSTATUS status = NtTerminateThread( handle, exit_code );
266     if (status) SetLastError( RtlNtStatusToDosError(status) );
267     return !status;
268 }
269
270
271 /***********************************************************************
272  *           FreeLibraryAndExitThread (KERNEL32.@)
273  */
274 void WINAPI FreeLibraryAndExitThread(HINSTANCE hLibModule, DWORD dwExitCode)
275 {
276     FreeLibrary(hLibModule);
277     ExitThread(dwExitCode);
278 }
279
280
281 /**********************************************************************
282  *              GetExitCodeThread (KERNEL32.@)
283  *
284  * Gets termination status of thread.
285  *
286  * RETURNS
287  *    Success: TRUE
288  *    Failure: FALSE
289  */
290 BOOL WINAPI GetExitCodeThread(
291     HANDLE hthread, /* [in]  Handle to thread */
292     LPDWORD exitcode) /* [out] Address to receive termination status */
293 {
294     THREAD_BASIC_INFORMATION info;
295     NTSTATUS status = NtQueryInformationThread( hthread, ThreadBasicInformation,
296                                                 &info, sizeof(info), NULL );
297
298     if (status)
299     {
300         SetLastError( RtlNtStatusToDosError(status) );
301         return FALSE;
302     }
303     if (exitcode) *exitcode = info.ExitStatus;
304     return TRUE;
305 }
306
307
308 /***********************************************************************
309  * SetThreadContext [KERNEL32.@]  Sets context of thread.
310  *
311  * RETURNS
312  *    Success: TRUE
313  *    Failure: FALSE
314  */
315 BOOL WINAPI SetThreadContext( HANDLE handle,           /* [in]  Handle to thread with context */
316                               const CONTEXT *context ) /* [in] Address of context structure */
317 {
318     NTSTATUS status = NtSetContextThread( handle, context );
319     if (status) SetLastError( RtlNtStatusToDosError(status) );
320     return !status;
321 }
322
323
324 /***********************************************************************
325  * GetThreadContext [KERNEL32.@]  Retrieves context of thread.
326  *
327  * RETURNS
328  *    Success: TRUE
329  *    Failure: FALSE
330  */
331 BOOL WINAPI GetThreadContext( HANDLE handle,     /* [in]  Handle to thread with context */
332                               CONTEXT *context ) /* [out] Address of context structure */
333 {
334     NTSTATUS status = NtGetContextThread( handle, context );
335     if (status) SetLastError( RtlNtStatusToDosError(status) );
336     return !status;
337 }
338
339
340 /**********************************************************************
341  * SuspendThread [KERNEL32.@]  Suspends a thread.
342  *
343  * RETURNS
344  *    Success: Previous suspend count
345  *    Failure: 0xFFFFFFFF
346  */
347 DWORD WINAPI SuspendThread( HANDLE hthread ) /* [in] Handle to the thread */
348 {
349     DWORD ret;
350     NTSTATUS status = NtSuspendThread( hthread, &ret );
351
352     if (status)
353     {
354         ret = ~0U;
355         SetLastError( RtlNtStatusToDosError(status) );
356     }
357     return ret;
358 }
359
360
361 /**********************************************************************
362  * ResumeThread [KERNEL32.@]  Resumes a thread.
363  *
364  * Decrements a thread's suspend count.  When count is zero, the
365  * execution of the thread is resumed.
366  *
367  * RETURNS
368  *    Success: Previous suspend count
369  *    Failure: 0xFFFFFFFF
370  *    Already running: 0
371  */
372 DWORD WINAPI ResumeThread( HANDLE hthread ) /* [in] Identifies thread to restart */
373 {
374     DWORD ret;
375     NTSTATUS status = NtResumeThread( hthread, &ret );
376
377     if (status)
378     {
379         ret = ~0U;
380         SetLastError( RtlNtStatusToDosError(status) );
381     }
382     return ret;
383 }
384
385
386 /**********************************************************************
387  * GetThreadPriority [KERNEL32.@]  Returns priority for thread.
388  *
389  * RETURNS
390  *    Success: Thread's priority level.
391  *    Failure: THREAD_PRIORITY_ERROR_RETURN
392  */
393 INT WINAPI GetThreadPriority(
394     HANDLE hthread) /* [in] Handle to thread */
395 {
396     THREAD_BASIC_INFORMATION info;
397     NTSTATUS status = NtQueryInformationThread( hthread, ThreadBasicInformation,
398                                                 &info, sizeof(info), NULL );
399
400     if (status)
401     {
402         SetLastError( RtlNtStatusToDosError(status) );
403         return THREAD_PRIORITY_ERROR_RETURN;
404     }
405     return info.Priority;
406 }
407
408
409 /**********************************************************************
410  * SetThreadPriority [KERNEL32.@]  Sets priority for thread.
411  *
412  * RETURNS
413  *    Success: TRUE
414  *    Failure: FALSE
415  */
416 BOOL WINAPI SetThreadPriority(
417     HANDLE hthread, /* [in] Handle to thread */
418     INT priority)   /* [in] Thread priority level */
419 {
420     BOOL ret;
421     SERVER_START_REQ( set_thread_info )
422     {
423         req->handle   = hthread;
424         req->priority = priority;
425         req->mask     = SET_THREAD_INFO_PRIORITY;
426         ret = !wine_server_call_err( req );
427     }
428     SERVER_END_REQ;
429     return ret;
430 }
431
432
433 /**********************************************************************
434  * GetThreadPriorityBoost [KERNEL32.@]  Returns priority boost for thread.
435  *
436  * Always reports that priority boost is disabled.
437  *
438  * RETURNS
439  *    Success: TRUE.
440  *    Failure: FALSE
441  */
442 BOOL WINAPI GetThreadPriorityBoost(
443     HANDLE hthread, /* [in] Handle to thread */
444     PBOOL pstate)   /* [out] pointer to var that receives the boost state */
445 {
446     if (pstate) *pstate = FALSE;
447     return NO_ERROR;
448 }
449
450
451 /**********************************************************************
452  * SetThreadPriorityBoost [KERNEL32.@]  Sets priority boost for thread.
453  *
454  * Priority boost is not implemented. Thsi function always returns
455  * FALSE and sets last error to ERROR_CALL_NOT_IMPLEMENTED
456  *
457  * RETURNS
458  *    Always returns FALSE to indicate a failure
459  */
460 BOOL WINAPI SetThreadPriorityBoost(
461     HANDLE hthread, /* [in] Handle to thread */
462     BOOL disable)   /* [in] TRUE to disable priority boost */
463 {
464     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
465     return FALSE;
466 }
467
468
469 /**********************************************************************
470  *           SetThreadAffinityMask   (KERNEL32.@)
471  */
472 DWORD WINAPI SetThreadAffinityMask( HANDLE hThread, DWORD dwThreadAffinityMask )
473 {
474     DWORD ret;
475     SERVER_START_REQ( set_thread_info )
476     {
477         req->handle   = hThread;
478         req->affinity = dwThreadAffinityMask;
479         req->mask     = SET_THREAD_INFO_AFFINITY;
480         ret = !wine_server_call_err( req );
481         /* FIXME: should return previous value */
482     }
483     SERVER_END_REQ;
484     return ret;
485 }
486
487
488 /**********************************************************************
489  * SetThreadIdealProcessor [KERNEL32.@]  Obtains timing information.
490  *
491  * RETURNS
492  *    Success: Value of last call to SetThreadIdealProcessor
493  *    Failure: -1
494  */
495 DWORD WINAPI SetThreadIdealProcessor(
496     HANDLE hThread,          /* [in] Specifies the thread of interest */
497     DWORD dwIdealProcessor)  /* [in] Specifies the new preferred processor */
498 {
499     FIXME("(%p): stub\n",hThread);
500     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
501     return -1L;
502 }
503
504
505 /* callback for QueueUserAPC */
506 static void CALLBACK call_user_apc( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3 )
507 {
508     PAPCFUNC func = (PAPCFUNC)arg1;
509     func( arg2 );
510 }
511
512 /***********************************************************************
513  *              QueueUserAPC  (KERNEL32.@)
514  */
515 DWORD WINAPI QueueUserAPC( PAPCFUNC func, HANDLE hthread, ULONG_PTR data )
516 {
517     NTSTATUS status = NtQueueApcThread( hthread, call_user_apc, (ULONG_PTR)func, data, 0 );
518
519     if (status) SetLastError( RtlNtStatusToDosError(status) );
520     return !status;
521 }
522
523 /***********************************************************************
524  *              QueueUserWorkItem  (KERNEL32.@)
525  */
526 BOOL WINAPI QueueUserWorkItem( LPTHREAD_START_ROUTINE Function, PVOID Context, ULONG Flags )
527 {
528     FIXME("(%p,%p,0x%08lx): stub\n", Function, Context, Flags);
529     return FALSE;
530 }
531
532 /**********************************************************************
533  * GetThreadTimes [KERNEL32.@]  Obtains timing information.
534  *
535  * RETURNS
536  *    Success: TRUE
537  *    Failure: FALSE
538  */
539 BOOL WINAPI GetThreadTimes(
540     HANDLE thread,         /* [in]  Specifies the thread of interest */
541     LPFILETIME creationtime, /* [out] When the thread was created */
542     LPFILETIME exittime,     /* [out] When the thread was destroyed */
543     LPFILETIME kerneltime,   /* [out] Time thread spent in kernel mode */
544     LPFILETIME usertime)     /* [out] Time thread spent in user mode */
545 {
546     BOOL ret = TRUE;
547
548     if (creationtime || exittime)
549     {
550         /* We need to do a server call to get the creation time or exit time */
551         /* This works on any thread */
552
553         SERVER_START_REQ( get_thread_info )
554         {
555             req->handle = thread;
556             req->tid_in = 0;
557             if ((ret = !wine_server_call_err( req )))
558             {
559                 if (creationtime)
560                     RtlSecondsSince1970ToTime( reply->creation_time, (LARGE_INTEGER*)creationtime );
561                 if (exittime)
562                     RtlSecondsSince1970ToTime( reply->exit_time, (LARGE_INTEGER*)exittime );
563             }
564         }
565         SERVER_END_REQ;
566     }
567     if (ret && (kerneltime || usertime))
568     {
569         /* We call times(2) for kernel time or user time */
570         /* We can only (portably) do this for the current thread */
571         if (thread == GetCurrentThread())
572         {
573             ULONGLONG time;
574             struct tms time_buf;
575             long clocks_per_sec = sysconf(_SC_CLK_TCK);
576
577             times(&time_buf);
578             if (kerneltime)
579             {
580                 time = (ULONGLONG)time_buf.tms_stime * 10000000 / clocks_per_sec;
581                 kerneltime->dwHighDateTime = time >> 32;
582                 kerneltime->dwLowDateTime = (DWORD)time;
583             }
584             if (usertime)
585             {
586                 time = (ULONGLONG)time_buf.tms_utime * 10000000 / clocks_per_sec;
587                 usertime->dwHighDateTime = time >> 32;
588                 usertime->dwLowDateTime = (DWORD)time;
589             }
590         }
591         else
592         {
593             if (kerneltime) kerneltime->dwHighDateTime = kerneltime->dwLowDateTime = 0;
594             if (usertime) usertime->dwHighDateTime = usertime->dwLowDateTime = 0;
595             FIXME("Cannot get kerneltime or usertime of other threads\n");
596         }
597     }
598     return ret;
599 }
600
601
602 /**********************************************************************
603  * VWin32_BoostThreadGroup [KERNEL.535]
604  */
605 VOID WINAPI VWin32_BoostThreadGroup( DWORD threadId, INT boost )
606 {
607     FIXME("(0x%08lx,%d): stub\n", threadId, boost);
608 }
609
610
611 /**********************************************************************
612  * VWin32_BoostThreadStatic [KERNEL.536]
613  */
614 VOID WINAPI VWin32_BoostThreadStatic( DWORD threadId, INT boost )
615 {
616     FIXME("(0x%08lx,%d): stub\n", threadId, boost);
617 }
618
619
620 /***********************************************************************
621  * GetCurrentThread [KERNEL32.@]  Gets pseudohandle for current thread
622  *
623  * RETURNS
624  *    Pseudohandle for the current thread
625  */
626 #undef GetCurrentThread
627 HANDLE WINAPI GetCurrentThread(void)
628 {
629     return (HANDLE)0xfffffffe;
630 }
631
632
633 #ifdef __i386__
634
635 /***********************************************************************
636  *              SetLastError (KERNEL.147)
637  *              SetLastError (KERNEL32.@)
638  */
639 /* void WINAPI SetLastError( DWORD error ); */
640 __ASM_GLOBAL_FUNC( SetLastError,
641                    "movl 4(%esp),%eax\n\t"
642                    ".byte 0x64\n\t"
643                    "movl %eax,0x34\n\t"
644                    "ret $4" )
645
646 /***********************************************************************
647  *              GetLastError (KERNEL.148)
648  *              GetLastError (KERNEL32.@)
649  */
650 /* DWORD WINAPI GetLastError(void); */
651 __ASM_GLOBAL_FUNC( GetLastError, ".byte 0x64\n\tmovl 0x34,%eax\n\tret" )
652
653 /***********************************************************************
654  *              GetCurrentProcessId (KERNEL.471)
655  *              GetCurrentProcessId (KERNEL32.@)
656  */
657 /* DWORD WINAPI GetCurrentProcessId(void) */
658 __ASM_GLOBAL_FUNC( GetCurrentProcessId, ".byte 0x64\n\tmovl 0x20,%eax\n\tret" )
659
660 /***********************************************************************
661  *              GetCurrentThreadId (KERNEL.462)
662  *              GetCurrentThreadId (KERNEL32.@)
663  */
664 /* DWORD WINAPI GetCurrentThreadId(void) */
665 __ASM_GLOBAL_FUNC( GetCurrentThreadId, ".byte 0x64\n\tmovl 0x24,%eax\n\tret" )
666
667 #else  /* __i386__ */
668
669 /**********************************************************************
670  *              SetLastError (KERNEL.147)
671  *              SetLastError (KERNEL32.@)
672  *
673  * Sets the last-error code.
674  */
675 void WINAPI SetLastError( DWORD error ) /* [in] Per-thread error code */
676 {
677     NtCurrentTeb()->LastErrorValue = error;
678 }
679
680 /**********************************************************************
681  *              GetLastError (KERNEL.148)
682  *              GetLastError (KERNEL32.@)
683  *
684  * Returns last-error code.
685  */
686 DWORD WINAPI GetLastError(void)
687 {
688     return NtCurrentTeb()->LastErrorValue;
689 }
690
691 /***********************************************************************
692  *              GetCurrentProcessId (KERNEL.471)
693  *              GetCurrentProcessId (KERNEL32.@)
694  *
695  * Returns process identifier.
696  */
697 DWORD WINAPI GetCurrentProcessId(void)
698 {
699     return (DWORD)NtCurrentTeb()->ClientId.UniqueProcess;
700 }
701
702 /***********************************************************************
703  *              GetCurrentThreadId (KERNEL.462)
704  *              GetCurrentThreadId (KERNEL32.@)
705  *
706  * Returns thread identifier.
707  */
708 DWORD WINAPI GetCurrentThreadId(void)
709 {
710     return (DWORD)NtCurrentTeb()->ClientId.UniqueThread;
711 }
712
713 #endif  /* __i386__ */