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