kernel32: GlobalMemoryStatusEx: return the size of physical memory + swapsize in...
[wine] / dlls / kernel32 / 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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_UNISTD_H
29 # include <unistd.h>
30 #endif
31
32 #include "ntstatus.h"
33 #define WIN32_NO_STATUS
34 #include "windef.h"
35 #include "winbase.h"
36 #include "winerror.h"
37 #include "winnls.h"
38 #include "thread.h"
39 #include "wine/winbase16.h"
40 #include "wine/exception.h"
41 #include "wine/library.h"
42 #include "wine/server.h"
43 #include "wine/debug.h"
44
45 #include "kernel_private.h"
46
47 WINE_DEFAULT_DEBUG_CHANNEL(thread);
48
49
50 /***********************************************************************
51  *           CreateThread   (KERNEL32.@)
52  */
53 HANDLE WINAPI CreateThread( SECURITY_ATTRIBUTES *sa, SIZE_T stack,
54                             LPTHREAD_START_ROUTINE start, LPVOID param,
55                             DWORD flags, LPDWORD id )
56 {
57      return CreateRemoteThread( GetCurrentProcess(),
58                                 sa, stack, start, param, flags, id );
59 }
60
61
62 /***************************************************************************
63  *                  CreateRemoteThread   (KERNEL32.@)
64  *
65  * Creates a thread that runs in the address space of another process
66  *
67  * PARAMS
68  *
69  * RETURNS
70  *   Success: Handle to the new thread.
71  *   Failure: NULL. Use GetLastError() to find the error cause.
72  *
73  * BUGS
74  *   Improper memory allocation: there's no ability to free new_thread_info
75  *   in other process.
76  *   Bad start address for RtlCreateUserThread because the library
77  *   may be loaded at different address in other process.
78  */
79 HANDLE WINAPI CreateRemoteThread( HANDLE hProcess, SECURITY_ATTRIBUTES *sa, SIZE_T stack,
80                                   LPTHREAD_START_ROUTINE start, LPVOID param,
81                                   DWORD flags, LPDWORD id )
82 {
83     HANDLE handle;
84     CLIENT_ID client_id;
85     NTSTATUS status;
86     SIZE_T stack_reserve = 0, stack_commit = 0;
87
88     if (flags & STACK_SIZE_PARAM_IS_A_RESERVATION) stack_reserve = stack;
89     else stack_commit = stack;
90
91     status = RtlCreateUserThread( hProcess, NULL, TRUE,
92                                   NULL, stack_reserve, stack_commit,
93                                   (PRTL_THREAD_START_ROUTINE)start, param, &handle, &client_id );
94     if (status == STATUS_SUCCESS)
95     {
96         if (id) *id = (DWORD)client_id.UniqueThread;
97         if (sa && (sa->nLength >= sizeof(*sa)) && sa->bInheritHandle)
98             SetHandleInformation( handle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT );
99         if (!(flags & CREATE_SUSPENDED))
100         {
101             ULONG ret;
102             if (NtResumeThread( handle, &ret ))
103             {
104                 NtClose( handle );
105                 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
106                 handle = 0;
107             }
108         }
109     }
110     else
111     {
112         SetLastError( RtlNtStatusToDosError(status) );
113         handle = 0;
114     }
115     return handle;
116 }
117
118
119 /***********************************************************************
120  * OpenThread  [KERNEL32.@]   Retrieves a handle to a thread from its thread id
121  */
122 HANDLE WINAPI OpenThread( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId )
123 {
124     NTSTATUS status;
125     HANDLE handle;
126     OBJECT_ATTRIBUTES attr;
127     CLIENT_ID cid;
128
129     attr.Length = sizeof(attr);
130     attr.RootDirectory = 0;
131     attr.Attributes = bInheritHandle ? OBJ_INHERIT : 0;
132     attr.ObjectName = NULL;
133     attr.SecurityDescriptor = NULL;
134     attr.SecurityQualityOfService = NULL;
135
136     cid.UniqueProcess = 0; /* FIXME */
137     cid.UniqueThread = (HANDLE)dwThreadId;
138     status = NtOpenThread( &handle, dwDesiredAccess, &attr, &cid );
139     if (status)
140     {
141         SetLastError( RtlNtStatusToDosError(status) );
142         handle = 0;
143     }
144     return handle;
145 }
146
147
148 /***********************************************************************
149  * ExitThread [KERNEL32.@]  Ends a thread
150  *
151  * RETURNS
152  *    None
153  */
154 void WINAPI ExitThread( DWORD code ) /* [in] Exit code for this thread */
155 {
156     BOOL last;
157     SERVER_START_REQ( terminate_thread )
158     {
159         /* send the exit code to the server */
160         req->handle    = GetCurrentThread();
161         req->exit_code = code;
162         wine_server_call( req );
163         last = reply->last;
164     }
165     SERVER_END_REQ;
166
167     if (last)
168     {
169         LdrShutdownProcess();
170         exit( code );
171     }
172     else RtlExitUserThread( code );
173 }
174
175
176 /**********************************************************************
177  * TerminateThread [KERNEL32.@]  Terminates a thread
178  *
179  * RETURNS
180  *    Success: TRUE
181  *    Failure: FALSE
182  */
183 BOOL WINAPI TerminateThread( HANDLE handle,    /* [in] Handle to thread */
184                              DWORD exit_code)  /* [in] Exit code for thread */
185 {
186     NTSTATUS status = NtTerminateThread( handle, exit_code );
187     if (status) SetLastError( RtlNtStatusToDosError(status) );
188     return !status;
189 }
190
191
192 /***********************************************************************
193  *           FreeLibraryAndExitThread (KERNEL32.@)
194  */
195 void WINAPI FreeLibraryAndExitThread(HINSTANCE hLibModule, DWORD dwExitCode)
196 {
197     FreeLibrary(hLibModule);
198     ExitThread(dwExitCode);
199 }
200
201
202 /**********************************************************************
203  *              GetExitCodeThread (KERNEL32.@)
204  *
205  * Gets termination status of thread.
206  *
207  * RETURNS
208  *    Success: TRUE
209  *    Failure: FALSE
210  */
211 BOOL WINAPI GetExitCodeThread(
212     HANDLE hthread, /* [in]  Handle to thread */
213     LPDWORD exitcode) /* [out] Address to receive termination status */
214 {
215     THREAD_BASIC_INFORMATION info;
216     NTSTATUS status = NtQueryInformationThread( hthread, ThreadBasicInformation,
217                                                 &info, sizeof(info), NULL );
218
219     if (status)
220     {
221         SetLastError( RtlNtStatusToDosError(status) );
222         return FALSE;
223     }
224     if (exitcode) *exitcode = info.ExitStatus;
225     return TRUE;
226 }
227
228
229 /***********************************************************************
230  * SetThreadContext [KERNEL32.@]  Sets context of thread.
231  *
232  * RETURNS
233  *    Success: TRUE
234  *    Failure: FALSE
235  */
236 BOOL WINAPI SetThreadContext( HANDLE handle,           /* [in]  Handle to thread with context */
237                               const CONTEXT *context ) /* [in] Address of context structure */
238 {
239     NTSTATUS status = NtSetContextThread( handle, context );
240     if (status) SetLastError( RtlNtStatusToDosError(status) );
241     return !status;
242 }
243
244
245 /***********************************************************************
246  * GetThreadContext [KERNEL32.@]  Retrieves context of thread.
247  *
248  * RETURNS
249  *    Success: TRUE
250  *    Failure: FALSE
251  */
252 BOOL WINAPI GetThreadContext( HANDLE handle,     /* [in]  Handle to thread with context */
253                               CONTEXT *context ) /* [out] Address of context structure */
254 {
255     NTSTATUS status = NtGetContextThread( handle, context );
256     if (status) SetLastError( RtlNtStatusToDosError(status) );
257     return !status;
258 }
259
260
261 /**********************************************************************
262  * SuspendThread [KERNEL32.@]  Suspends a thread.
263  *
264  * RETURNS
265  *    Success: Previous suspend count
266  *    Failure: 0xFFFFFFFF
267  */
268 DWORD WINAPI SuspendThread( HANDLE hthread ) /* [in] Handle to the thread */
269 {
270     DWORD ret;
271     NTSTATUS status = NtSuspendThread( hthread, &ret );
272
273     if (status)
274     {
275         ret = ~0U;
276         SetLastError( RtlNtStatusToDosError(status) );
277     }
278     return ret;
279 }
280
281
282 /**********************************************************************
283  * ResumeThread [KERNEL32.@]  Resumes a thread.
284  *
285  * Decrements a thread's suspend count.  When count is zero, the
286  * execution of the thread is resumed.
287  *
288  * RETURNS
289  *    Success: Previous suspend count
290  *    Failure: 0xFFFFFFFF
291  *    Already running: 0
292  */
293 DWORD WINAPI ResumeThread( HANDLE hthread ) /* [in] Identifies thread to restart */
294 {
295     DWORD ret;
296     NTSTATUS status = NtResumeThread( hthread, &ret );
297
298     if (status)
299     {
300         ret = ~0U;
301         SetLastError( RtlNtStatusToDosError(status) );
302     }
303     return ret;
304 }
305
306
307 /**********************************************************************
308  * GetThreadPriority [KERNEL32.@]  Returns priority for thread.
309  *
310  * RETURNS
311  *    Success: Thread's priority level.
312  *    Failure: THREAD_PRIORITY_ERROR_RETURN
313  */
314 INT WINAPI GetThreadPriority(
315     HANDLE hthread) /* [in] Handle to thread */
316 {
317     THREAD_BASIC_INFORMATION info;
318     NTSTATUS status = NtQueryInformationThread( hthread, ThreadBasicInformation,
319                                                 &info, sizeof(info), NULL );
320
321     if (status)
322     {
323         SetLastError( RtlNtStatusToDosError(status) );
324         return THREAD_PRIORITY_ERROR_RETURN;
325     }
326     return info.Priority;
327 }
328
329
330 /**********************************************************************
331  * SetThreadPriority [KERNEL32.@]  Sets priority for thread.
332  *
333  * RETURNS
334  *    Success: TRUE
335  *    Failure: FALSE
336  */
337 BOOL WINAPI SetThreadPriority(
338     HANDLE hthread, /* [in] Handle to thread */
339     INT priority)   /* [in] Thread priority level */
340 {
341     DWORD       prio = priority;
342     NTSTATUS    status;
343
344     status = NtSetInformationThread(hthread, ThreadBasePriority,
345                                     &prio, sizeof(prio));
346
347     if (status)
348     {
349         SetLastError( RtlNtStatusToDosError(status) );
350         return FALSE;
351     }
352
353     return TRUE;
354 }
355
356
357 /**********************************************************************
358  * GetThreadPriorityBoost [KERNEL32.@]  Returns priority boost for thread.
359  *
360  * Always reports that priority boost is disabled.
361  *
362  * RETURNS
363  *    Success: TRUE.
364  *    Failure: FALSE
365  */
366 BOOL WINAPI GetThreadPriorityBoost(
367     HANDLE hthread, /* [in] Handle to thread */
368     PBOOL pstate)   /* [out] pointer to var that receives the boost state */
369 {
370     if (pstate) *pstate = FALSE;
371     return NO_ERROR;
372 }
373
374
375 /**********************************************************************
376  * SetThreadPriorityBoost [KERNEL32.@]  Sets priority boost for thread.
377  *
378  * Priority boost is not implemented. Thsi function always returns
379  * FALSE and sets last error to ERROR_CALL_NOT_IMPLEMENTED
380  *
381  * RETURNS
382  *    Always returns FALSE to indicate a failure
383  */
384 BOOL WINAPI SetThreadPriorityBoost(
385     HANDLE hthread, /* [in] Handle to thread */
386     BOOL disable)   /* [in] TRUE to disable priority boost */
387 {
388     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
389     return FALSE;
390 }
391
392
393 /**********************************************************************
394  *           SetThreadAffinityMask   (KERNEL32.@)
395  */
396 DWORD WINAPI SetThreadAffinityMask( HANDLE hThread, DWORD dwThreadAffinityMask )
397 {
398     NTSTATUS                    status;
399     THREAD_BASIC_INFORMATION    tbi;
400
401     status = NtQueryInformationThread( hThread, ThreadBasicInformation, 
402                                        &tbi, sizeof(tbi), NULL );
403     if (status)
404     {
405         SetLastError( RtlNtStatusToDosError(status) );
406         return 0;
407     }
408     status = NtSetInformationThread( hThread, ThreadAffinityMask, 
409                                      &dwThreadAffinityMask,
410                                      sizeof(dwThreadAffinityMask));
411     if (status)
412     {
413         SetLastError( RtlNtStatusToDosError(status) );
414         return 0;
415     }
416     return tbi.AffinityMask;
417 }
418
419
420 /**********************************************************************
421  * SetThreadIdealProcessor [KERNEL32.@]  Obtains timing information.
422  *
423  * RETURNS
424  *    Success: Value of last call to SetThreadIdealProcessor
425  *    Failure: -1
426  */
427 DWORD WINAPI SetThreadIdealProcessor(
428     HANDLE hThread,          /* [in] Specifies the thread of interest */
429     DWORD dwIdealProcessor)  /* [in] Specifies the new preferred processor */
430 {
431     FIXME("(%p): stub\n",hThread);
432     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
433     return -1L;
434 }
435
436
437 /* callback for QueueUserAPC */
438 static void CALLBACK call_user_apc( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3 )
439 {
440     PAPCFUNC func = (PAPCFUNC)arg1;
441     func( arg2 );
442 }
443
444 /***********************************************************************
445  *              QueueUserAPC  (KERNEL32.@)
446  */
447 DWORD WINAPI QueueUserAPC( PAPCFUNC func, HANDLE hthread, ULONG_PTR data )
448 {
449     NTSTATUS status = NtQueueApcThread( hthread, call_user_apc, (ULONG_PTR)func, data, 0 );
450
451     if (status) SetLastError( RtlNtStatusToDosError(status) );
452     return !status;
453 }
454
455 /***********************************************************************
456  *              QueueUserWorkItem  (KERNEL32.@)
457  */
458 BOOL WINAPI QueueUserWorkItem( LPTHREAD_START_ROUTINE Function, PVOID Context, ULONG Flags )
459 {
460     NTSTATUS status;
461
462     TRACE("(%p,%p,0x%08x)\n", Function, Context, Flags);
463
464     status = RtlQueueWorkItem( Function, Context, Flags );
465
466     if (status) SetLastError( RtlNtStatusToDosError(status) );
467     return !status;
468 }
469
470 /**********************************************************************
471  * GetThreadTimes [KERNEL32.@]  Obtains timing information.
472  *
473  * RETURNS
474  *    Success: TRUE
475  *    Failure: FALSE
476  */
477 BOOL WINAPI GetThreadTimes(
478     HANDLE thread,         /* [in]  Specifies the thread of interest */
479     LPFILETIME creationtime, /* [out] When the thread was created */
480     LPFILETIME exittime,     /* [out] When the thread was destroyed */
481     LPFILETIME kerneltime,   /* [out] Time thread spent in kernel mode */
482     LPFILETIME usertime)     /* [out] Time thread spent in user mode */
483 {
484     KERNEL_USER_TIMES   kusrt;
485     NTSTATUS            status;
486
487     status = NtQueryInformationThread(thread, ThreadTimes, &kusrt,
488                                       sizeof(kusrt), NULL);
489     if (status)
490     {
491         SetLastError( RtlNtStatusToDosError(status) );
492         return FALSE;
493     }
494     if (creationtime)
495     {
496         creationtime->dwLowDateTime = kusrt.CreateTime.u.LowPart;
497         creationtime->dwHighDateTime = kusrt.CreateTime.u.HighPart;
498     }
499     if (exittime)
500     {
501         exittime->dwLowDateTime = kusrt.ExitTime.u.LowPart;
502         exittime->dwHighDateTime = kusrt.ExitTime.u.HighPart;
503     }
504     if (kerneltime)
505     {
506         kerneltime->dwLowDateTime = kusrt.KernelTime.u.LowPart;
507         kerneltime->dwHighDateTime = kusrt.KernelTime.u.HighPart;
508     }
509     if (usertime)
510     {
511         usertime->dwLowDateTime = kusrt.UserTime.u.LowPart;
512         usertime->dwHighDateTime = kusrt.UserTime.u.HighPart;
513     }
514     
515     return TRUE;
516 }
517
518
519 /**********************************************************************
520  * VWin32_BoostThreadGroup [KERNEL.535]
521  */
522 VOID WINAPI VWin32_BoostThreadGroup( DWORD threadId, INT boost )
523 {
524     FIXME("(0x%08x,%d): stub\n", threadId, boost);
525 }
526
527
528 /**********************************************************************
529  * VWin32_BoostThreadStatic [KERNEL.536]
530  */
531 VOID WINAPI VWin32_BoostThreadStatic( DWORD threadId, INT boost )
532 {
533     FIXME("(0x%08x,%d): stub\n", threadId, boost);
534 }
535
536
537 /***********************************************************************
538  * GetCurrentThread [KERNEL32.@]  Gets pseudohandle for current thread
539  *
540  * RETURNS
541  *    Pseudohandle for the current thread
542  */
543 #undef GetCurrentThread
544 HANDLE WINAPI GetCurrentThread(void)
545 {
546     return (HANDLE)0xfffffffe;
547 }
548
549
550 #ifdef __i386__
551
552 /***********************************************************************
553  *              SetLastError (KERNEL.147)
554  *              SetLastError (KERNEL32.@)
555  */
556 /* void WINAPI SetLastError( DWORD error ); */
557 __ASM_GLOBAL_FUNC( SetLastError,
558                    "movl 4(%esp),%eax\n\t"
559                    ".byte 0x64\n\t"
560                    "movl %eax,0x34\n\t"
561                    "ret $4" )
562
563 /***********************************************************************
564  *              GetLastError (KERNEL.148)
565  *              GetLastError (KERNEL32.@)
566  */
567 /* DWORD WINAPI GetLastError(void); */
568 __ASM_GLOBAL_FUNC( GetLastError, ".byte 0x64\n\tmovl 0x34,%eax\n\tret" )
569
570 /***********************************************************************
571  *              GetCurrentProcessId (KERNEL.471)
572  *              GetCurrentProcessId (KERNEL32.@)
573  */
574 /* DWORD WINAPI GetCurrentProcessId(void) */
575 __ASM_GLOBAL_FUNC( GetCurrentProcessId, ".byte 0x64\n\tmovl 0x20,%eax\n\tret" )
576
577 /***********************************************************************
578  *              GetCurrentThreadId (KERNEL.462)
579  *              GetCurrentThreadId (KERNEL32.@)
580  */
581 /* DWORD WINAPI GetCurrentThreadId(void) */
582 __ASM_GLOBAL_FUNC( GetCurrentThreadId, ".byte 0x64\n\tmovl 0x24,%eax\n\tret" )
583
584 #else  /* __i386__ */
585
586 /**********************************************************************
587  *              SetLastError (KERNEL.147)
588  *              SetLastError (KERNEL32.@)
589  *
590  * Sets the last-error code.
591  *
592  * RETURNS
593  * Nothing.
594  */
595 void WINAPI SetLastError( DWORD error ) /* [in] Per-thread error code */
596 {
597     NtCurrentTeb()->LastErrorValue = error;
598 }
599
600 /**********************************************************************
601  *              GetLastError (KERNEL.148)
602  *              GetLastError (KERNEL32.@)
603  *
604  * Get the last-error code.
605  *
606  * RETURNS
607  *  last-error code.
608  */
609 DWORD WINAPI GetLastError(void)
610 {
611     return NtCurrentTeb()->LastErrorValue;
612 }
613
614 /***********************************************************************
615  *              GetCurrentProcessId (KERNEL.471)
616  *              GetCurrentProcessId (KERNEL32.@)
617  *
618  * Get the current process identifier.
619  *
620  * RETURNS
621  *  current process identifier
622  */
623 DWORD WINAPI GetCurrentProcessId(void)
624 {
625     return (DWORD)NtCurrentTeb()->ClientId.UniqueProcess;
626 }
627
628 /***********************************************************************
629  *              GetCurrentThreadId (KERNEL.462)
630  *              GetCurrentThreadId (KERNEL32.@)
631  *
632  * Get the current thread identifier.
633  *
634  * RETURNS
635  *  current thread identifier
636  */
637 DWORD WINAPI GetCurrentThreadId(void)
638 {
639     return (DWORD)NtCurrentTeb()->ClientId.UniqueThread;
640 }
641
642 #endif  /* __i386__ */