Fixed some issues found by winapi_check.
[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 <sys/types.h>
27 #ifdef HAVE_SYS_TIMES_H
28 #include <sys/times.h>
29 #endif
30 #ifdef HAVE_UNISTD_H
31 # include <unistd.h>
32 #endif
33
34 #include "winbase.h"
35 #include "winerror.h"
36 #include "winnls.h"
37 #include "thread.h"
38 #include "wine/server.h"
39 #include "wine/debug.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(thread);
42
43
44 /***********************************************************************
45  * SetThreadContext [KERNEL32.@]  Sets context of thread.
46  *
47  * RETURNS
48  *    Success: TRUE
49  *    Failure: FALSE
50  */
51 BOOL WINAPI SetThreadContext( HANDLE handle,           /* [in]  Handle to thread with context */
52                               const CONTEXT *context ) /* [in] Address of context structure */
53 {
54     NTSTATUS status = NtSetContextThread( handle, context );
55     if (status) SetLastError( RtlNtStatusToDosError(status) );
56     return !status;
57 }
58
59
60 /***********************************************************************
61  * GetThreadContext [KERNEL32.@]  Retrieves context of thread.
62  *
63  * RETURNS
64  *    Success: TRUE
65  *    Failure: FALSE
66  */
67 BOOL WINAPI GetThreadContext( HANDLE handle,     /* [in]  Handle to thread with context */
68                               CONTEXT *context ) /* [out] Address of context structure */
69 {
70     NTSTATUS status = NtGetContextThread( handle, context );
71     if (status) SetLastError( RtlNtStatusToDosError(status) );
72     return !status;
73 }
74
75
76 /**********************************************************************
77  * SuspendThread [KERNEL32.@]  Suspends a thread.
78  *
79  * RETURNS
80  *    Success: Previous suspend count
81  *    Failure: 0xFFFFFFFF
82  */
83 DWORD WINAPI SuspendThread( HANDLE hthread ) /* [in] Handle to the thread */
84 {
85     DWORD ret;
86     NTSTATUS status = NtSuspendThread( hthread, &ret );
87
88     if (status)
89     {
90         ret = ~0U;
91         SetLastError( RtlNtStatusToDosError(status) );
92     }
93     return ret;
94 }
95
96
97 /**********************************************************************
98  * ResumeThread [KERNEL32.@]  Resumes a thread.
99  *
100  * Decrements a thread's suspend count.  When count is zero, the
101  * execution of the thread is resumed.
102  *
103  * RETURNS
104  *    Success: Previous suspend count
105  *    Failure: 0xFFFFFFFF
106  *    Already running: 0
107  */
108 DWORD WINAPI ResumeThread( HANDLE hthread ) /* [in] Identifies thread to restart */
109 {
110     DWORD ret;
111     NTSTATUS status = NtResumeThread( hthread, &ret );
112
113     if (status)
114     {
115         ret = ~0U;
116         SetLastError( RtlNtStatusToDosError(status) );
117     }
118     return ret;
119 }
120
121
122 /**********************************************************************
123  * GetThreadPriority [KERNEL32.@]  Returns priority for thread.
124  *
125  * RETURNS
126  *    Success: Thread's priority level.
127  *    Failure: THREAD_PRIORITY_ERROR_RETURN
128  */
129 INT WINAPI GetThreadPriority(
130     HANDLE hthread) /* [in] Handle to thread */
131 {
132     THREAD_BASIC_INFORMATION info;
133     NTSTATUS status = NtQueryInformationThread( hthread, ThreadBasicInformation,
134                                                 &info, sizeof(info), NULL );
135
136     if (status)
137     {
138         SetLastError( RtlNtStatusToDosError(status) );
139         return THREAD_PRIORITY_ERROR_RETURN;
140     }
141     return info.Priority;
142 }
143
144
145 /**********************************************************************
146  * SetThreadPriority [KERNEL32.@]  Sets priority for thread.
147  *
148  * RETURNS
149  *    Success: TRUE
150  *    Failure: FALSE
151  */
152 BOOL WINAPI SetThreadPriority(
153     HANDLE hthread, /* [in] Handle to thread */
154     INT priority)   /* [in] Thread priority level */
155 {
156     BOOL ret;
157     SERVER_START_REQ( set_thread_info )
158     {
159         req->handle   = hthread;
160         req->priority = priority;
161         req->mask     = SET_THREAD_INFO_PRIORITY;
162         ret = !wine_server_call_err( req );
163     }
164     SERVER_END_REQ;
165     return ret;
166 }
167
168
169 /**********************************************************************
170  * GetThreadPriorityBoost [KERNEL32.@]  Returns priority boost for thread.
171  *
172  * Always reports that priority boost is disabled.
173  *
174  * RETURNS
175  *    Success: TRUE.
176  *    Failure: FALSE
177  */
178 BOOL WINAPI GetThreadPriorityBoost(
179     HANDLE hthread, /* [in] Handle to thread */
180     PBOOL pstate)   /* [out] pointer to var that receives the boost state */
181 {
182     if (pstate) *pstate = FALSE;
183     return NO_ERROR;
184 }
185
186
187 /**********************************************************************
188  * SetThreadPriorityBoost [KERNEL32.@]  Sets priority boost for thread.
189  *
190  * Priority boost is not implemented. Thsi function always returns
191  * FALSE and sets last error to ERROR_CALL_NOT_IMPLEMENTED
192  *
193  * RETURNS
194  *    Always returns FALSE to indicate a failure
195  */
196 BOOL WINAPI SetThreadPriorityBoost(
197     HANDLE hthread, /* [in] Handle to thread */
198     BOOL disable)   /* [in] TRUE to disable priority boost */
199 {
200     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
201     return FALSE;
202 }
203
204
205 /**********************************************************************
206  *           SetThreadAffinityMask   (KERNEL32.@)
207  */
208 DWORD WINAPI SetThreadAffinityMask( HANDLE hThread, DWORD dwThreadAffinityMask )
209 {
210     DWORD ret;
211     SERVER_START_REQ( set_thread_info )
212     {
213         req->handle   = hThread;
214         req->affinity = dwThreadAffinityMask;
215         req->mask     = SET_THREAD_INFO_AFFINITY;
216         ret = !wine_server_call_err( req );
217         /* FIXME: should return previous value */
218     }
219     SERVER_END_REQ;
220     return ret;
221 }
222
223
224 /**********************************************************************
225  * SetThreadIdealProcessor [KERNEL32.@]  Obtains timing information.
226  *
227  * RETURNS
228  *    Success: Value of last call to SetThreadIdealProcessor
229  *    Failure: -1
230  */
231 DWORD WINAPI SetThreadIdealProcessor(
232     HANDLE hThread,          /* [in] Specifies the thread of interest */
233     DWORD dwIdealProcessor)  /* [in] Specifies the new preferred processor */
234 {
235     FIXME("(%p): stub\n",hThread);
236     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
237     return -1L;
238 }
239
240
241 /***********************************************************************
242  * SetThreadExecutionState (KERNEL32.@)
243  *
244  * Informs the system that activity is taking place for
245  * power management purposes.
246  */
247 EXECUTION_STATE WINAPI SetThreadExecutionState(EXECUTION_STATE flags)
248 {
249     static EXECUTION_STATE current =
250         ES_SYSTEM_REQUIRED|ES_DISPLAY_REQUIRED|ES_USER_PRESENT;
251     EXECUTION_STATE old = current;
252
253     if (!(current & ES_CONTINUOUS) || (flags & ES_CONTINUOUS))
254         current = flags;
255     FIXME("(0x%lx): stub, harmless (power management).\n", flags);
256     return old;
257 }
258
259
260 /* callback for QueueUserAPC */
261 static void CALLBACK call_user_apc( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3 )
262 {
263     PAPCFUNC func = (PAPCFUNC)arg1;
264     func( arg2 );
265 }
266
267 /***********************************************************************
268  *              QueueUserAPC  (KERNEL32.@)
269  */
270 DWORD WINAPI QueueUserAPC( PAPCFUNC func, HANDLE hthread, ULONG_PTR data )
271 {
272     NTSTATUS status = NtQueueApcThread( hthread, call_user_apc, (ULONG_PTR)func, data, 0 );
273
274     if (status) SetLastError( RtlNtStatusToDosError(status) );
275     return !status;
276 }
277
278
279 /**********************************************************************
280  * GetThreadTimes [KERNEL32.@]  Obtains timing information.
281  *
282  * RETURNS
283  *    Success: TRUE
284  *    Failure: FALSE
285  */
286 BOOL WINAPI GetThreadTimes(
287     HANDLE thread,         /* [in]  Specifies the thread of interest */
288     LPFILETIME creationtime, /* [out] When the thread was created */
289     LPFILETIME exittime,     /* [out] When the thread was destroyed */
290     LPFILETIME kerneltime,   /* [out] Time thread spent in kernel mode */
291     LPFILETIME usertime)     /* [out] Time thread spent in user mode */
292 {
293     BOOL ret = TRUE;
294
295     if (creationtime || exittime)
296     {
297         /* We need to do a server call to get the creation time or exit time */
298         /* This works on any thread */
299
300         SERVER_START_REQ( get_thread_info )
301         {
302             req->handle = thread;
303             req->tid_in = 0;
304             if ((ret = !wine_server_call_err( req )))
305             {
306                 if (creationtime)
307                     RtlSecondsSince1970ToTime( reply->creation_time, (LARGE_INTEGER*)creationtime );
308                 if (exittime)
309                     RtlSecondsSince1970ToTime( reply->exit_time, (LARGE_INTEGER*)exittime );
310             }
311         }
312         SERVER_END_REQ;
313     }
314     if (ret && (kerneltime || usertime))
315     {
316         /* We call times(2) for kernel time or user time */
317         /* We can only (portably) do this for the current thread */
318         if (thread == GetCurrentThread())
319         {
320             ULONGLONG time;
321             struct tms time_buf;
322             long clocks_per_sec = sysconf(_SC_CLK_TCK);
323
324             times(&time_buf);
325             if (kerneltime)
326             {
327                 time = (ULONGLONG)time_buf.tms_stime * 10000000 / clocks_per_sec;
328                 kerneltime->dwHighDateTime = time >> 32;
329                 kerneltime->dwLowDateTime = (DWORD)time;
330             }
331             if (usertime)
332             {
333                 time = (ULONGLONG)time_buf.tms_utime * 10000000 / clocks_per_sec;
334                 usertime->dwHighDateTime = time >> 32;
335                 usertime->dwLowDateTime = (DWORD)time;
336             }
337         }
338         else
339         {
340             if (kerneltime) kerneltime->dwHighDateTime = kerneltime->dwLowDateTime = 0;
341             if (usertime) usertime->dwHighDateTime = usertime->dwLowDateTime = 0;
342             FIXME("Cannot get kerneltime or usertime of other threads\n");
343         }
344     }
345     return ret;
346 }
347
348
349 /**********************************************************************
350  * VWin32_BoostThreadGroup [KERNEL.535]
351  */
352 VOID WINAPI VWin32_BoostThreadGroup( DWORD threadId, INT boost )
353 {
354     FIXME("(0x%08lx,%d): stub\n", threadId, boost);
355 }
356
357
358 /**********************************************************************
359  * VWin32_BoostThreadStatic [KERNEL.536]
360  */
361 VOID WINAPI VWin32_BoostThreadStatic( DWORD threadId, INT boost )
362 {
363     FIXME("(0x%08lx,%d): stub\n", threadId, boost);
364 }
365
366
367 /***********************************************************************
368  * GetCurrentThread [KERNEL32.@]  Gets pseudohandle for current thread
369  *
370  * RETURNS
371  *    Pseudohandle for the current thread
372  */
373 #undef GetCurrentThread
374 HANDLE WINAPI GetCurrentThread(void)
375 {
376     return (HANDLE)0xfffffffe;
377 }