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