Move named pipe objects into directory name space.
[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 /***********************************************************************
53  *           THREAD_InitStack
54  *
55  * Allocate the stack of a thread.
56  */
57 TEB *THREAD_InitStack( TEB *teb, DWORD stack_size )
58 {
59     DWORD old_prot;
60     DWORD page_size = getpagesize();
61     void *base;
62
63     stack_size = (stack_size + (page_size - 1)) & ~(page_size - 1);
64     if (stack_size < 1024 * 1024) stack_size = 1024 * 1024;  /* Xlib needs a large stack */
65
66     if (!(base = VirtualAlloc( NULL, stack_size, MEM_COMMIT, PAGE_READWRITE )))
67         return NULL;
68
69     teb->DeallocationStack = base;
70     teb->Tib.StackBase     = (char *)base + stack_size;
71     teb->Tib.StackLimit    = base;  /* note: limit is lower than base since the stack grows down */
72
73     /* Setup guard pages */
74
75     VirtualProtect( base, 1, PAGE_READWRITE | PAGE_GUARD, &old_prot );
76     return teb;
77 }
78
79
80 struct new_thread_info
81 {
82     LPTHREAD_START_ROUTINE func;
83     void                  *arg;
84 };
85
86 /***********************************************************************
87  *           THREAD_Start
88  *
89  * Start execution of a newly created thread. Does not return.
90  */
91 static void CALLBACK THREAD_Start( void *ptr )
92 {
93     struct new_thread_info *info = ptr;
94     LPTHREAD_START_ROUTINE func = info->func;
95     void *arg = info->arg;
96
97     RtlFreeHeap( GetProcessHeap(), 0, info );
98
99     if (TRACE_ON(relay))
100         DPRINTF("%04lx:Starting thread (entryproc=%p)\n", GetCurrentThreadId(), func );
101
102     __TRY
103     {
104         MODULE_DllThreadAttach( NULL );
105         ExitThread( func( arg ) );
106     }
107     __EXCEPT(UnhandledExceptionFilter)
108     {
109         TerminateThread( GetCurrentThread(), GetExceptionCode() );
110     }
111     __ENDTRY
112 }
113
114
115 /***********************************************************************
116  *           CreateThread   (KERNEL32.@)
117  */
118 HANDLE WINAPI CreateThread( SECURITY_ATTRIBUTES *sa, SIZE_T stack,
119                             LPTHREAD_START_ROUTINE start, LPVOID param,
120                             DWORD flags, LPDWORD id )
121 {
122      return CreateRemoteThread( GetCurrentProcess(),
123                                 sa, stack, start, param, flags, id );
124 }
125
126
127 /***************************************************************************
128  *                  CreateRemoteThread   (KERNEL32.@)
129  *
130  * Creates a thread that runs in the address space of another process
131  *
132  * PARAMS
133  *
134  * RETURNS
135  *   Success: Handle to the new thread.
136  *   Failure: NULL. Use GetLastError() to find the error cause.
137  *
138  * BUGS
139  *   Improper memory allocation: there's no ability to free new_thread_info
140  *   in other process.
141  *   Bad start address for RtlCreateUserThread because the library
142  *   may be loaded at different address in other process.
143  */
144 HANDLE WINAPI CreateRemoteThread( HANDLE hProcess, SECURITY_ATTRIBUTES *sa, SIZE_T stack,
145                                   LPTHREAD_START_ROUTINE start, LPVOID param,
146                                   DWORD flags, LPDWORD id )
147 {
148     HANDLE handle;
149     CLIENT_ID client_id;
150     NTSTATUS status;
151     SIZE_T stack_reserve = 0, stack_commit = 0;
152     struct new_thread_info *info;
153
154     if (!(info = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*info) )))
155     {
156         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
157         return 0;
158     }
159     info->func = start;
160     info->arg  = param;
161
162     if (flags & STACK_SIZE_PARAM_IS_A_RESERVATION) stack_reserve = stack;
163     else stack_commit = stack;
164
165     status = RtlCreateUserThread( hProcess, NULL, TRUE,
166                                   NULL, stack_reserve, stack_commit,
167                                   THREAD_Start, info, &handle, &client_id );
168     if (status == STATUS_SUCCESS)
169     {
170         if (id) *id = (DWORD)client_id.UniqueThread;
171         if (sa && (sa->nLength >= sizeof(*sa)) && sa->bInheritHandle)
172             SetHandleInformation( handle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT );
173         if (!(flags & CREATE_SUSPENDED))
174         {
175             ULONG ret;
176             if (NtResumeThread( handle, &ret ))
177             {
178                 NtClose( handle );
179                 RtlFreeHeap( GetProcessHeap(), 0, info );
180                 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
181                 handle = 0;
182             }
183         }
184     }
185     else
186     {
187         RtlFreeHeap( GetProcessHeap(), 0, info );
188         SetLastError( RtlNtStatusToDosError(status) );
189         handle = 0;
190     }
191     return handle;
192 }
193
194
195 /***********************************************************************
196  * OpenThread  [KERNEL32.@]   Retrieves a handle to a thread from its thread id
197  */
198 HANDLE WINAPI OpenThread( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId )
199 {
200     NTSTATUS status;
201     HANDLE handle;
202     OBJECT_ATTRIBUTES attr;
203     CLIENT_ID cid;
204
205     attr.Length = sizeof(attr);
206     attr.RootDirectory = 0;
207     attr.Attributes = bInheritHandle ? OBJ_INHERIT : 0;
208     attr.ObjectName = NULL;
209     attr.SecurityDescriptor = NULL;
210     attr.SecurityQualityOfService = NULL;
211
212     cid.UniqueProcess = 0; /* FIXME */
213     cid.UniqueThread = (HANDLE)dwThreadId;
214     status = NtOpenThread( &handle, dwDesiredAccess, &attr, &cid );
215     if (status)
216     {
217         SetLastError( RtlNtStatusToDosError(status) );
218         handle = 0;
219     }
220     return handle;
221 }
222
223
224 /***********************************************************************
225  * ExitThread [KERNEL32.@]  Ends a thread
226  *
227  * RETURNS
228  *    None
229  */
230 void WINAPI ExitThread( DWORD code ) /* [in] Exit code for this thread */
231 {
232     BOOL last;
233     SERVER_START_REQ( terminate_thread )
234     {
235         /* send the exit code to the server */
236         req->handle    = GetCurrentThread();
237         req->exit_code = code;
238         wine_server_call( req );
239         last = reply->last;
240     }
241     SERVER_END_REQ;
242
243     if (last)
244     {
245         LdrShutdownProcess();
246         exit( code );
247     }
248     else RtlExitUserThread( code );
249 }
250
251
252 /**********************************************************************
253  * TerminateThread [KERNEL32.@]  Terminates a thread
254  *
255  * RETURNS
256  *    Success: TRUE
257  *    Failure: FALSE
258  */
259 BOOL WINAPI TerminateThread( HANDLE handle,    /* [in] Handle to thread */
260                              DWORD exit_code)  /* [in] Exit code for thread */
261 {
262     NTSTATUS status = NtTerminateThread( handle, exit_code );
263     if (status) SetLastError( RtlNtStatusToDosError(status) );
264     return !status;
265 }
266
267
268 /***********************************************************************
269  *           FreeLibraryAndExitThread (KERNEL32.@)
270  */
271 void WINAPI FreeLibraryAndExitThread(HINSTANCE hLibModule, DWORD dwExitCode)
272 {
273     FreeLibrary(hLibModule);
274     ExitThread(dwExitCode);
275 }
276
277
278 /**********************************************************************
279  *              GetExitCodeThread (KERNEL32.@)
280  *
281  * Gets termination status of thread.
282  *
283  * RETURNS
284  *    Success: TRUE
285  *    Failure: FALSE
286  */
287 BOOL WINAPI GetExitCodeThread(
288     HANDLE hthread, /* [in]  Handle to thread */
289     LPDWORD exitcode) /* [out] Address to receive termination status */
290 {
291     THREAD_BASIC_INFORMATION info;
292     NTSTATUS status = NtQueryInformationThread( hthread, ThreadBasicInformation,
293                                                 &info, sizeof(info), NULL );
294
295     if (status)
296     {
297         SetLastError( RtlNtStatusToDosError(status) );
298         return FALSE;
299     }
300     if (exitcode) *exitcode = info.ExitStatus;
301     return TRUE;
302 }
303
304
305 /***********************************************************************
306  * SetThreadContext [KERNEL32.@]  Sets context of thread.
307  *
308  * RETURNS
309  *    Success: TRUE
310  *    Failure: FALSE
311  */
312 BOOL WINAPI SetThreadContext( HANDLE handle,           /* [in]  Handle to thread with context */
313                               const CONTEXT *context ) /* [in] Address of context structure */
314 {
315     NTSTATUS status = NtSetContextThread( handle, context );
316     if (status) SetLastError( RtlNtStatusToDosError(status) );
317     return !status;
318 }
319
320
321 /***********************************************************************
322  * GetThreadContext [KERNEL32.@]  Retrieves context of thread.
323  *
324  * RETURNS
325  *    Success: TRUE
326  *    Failure: FALSE
327  */
328 BOOL WINAPI GetThreadContext( HANDLE handle,     /* [in]  Handle to thread with context */
329                               CONTEXT *context ) /* [out] Address of context structure */
330 {
331     NTSTATUS status = NtGetContextThread( handle, context );
332     if (status) SetLastError( RtlNtStatusToDosError(status) );
333     return !status;
334 }
335
336
337 /**********************************************************************
338  * SuspendThread [KERNEL32.@]  Suspends a thread.
339  *
340  * RETURNS
341  *    Success: Previous suspend count
342  *    Failure: 0xFFFFFFFF
343  */
344 DWORD WINAPI SuspendThread( HANDLE hthread ) /* [in] Handle to the thread */
345 {
346     DWORD ret;
347     NTSTATUS status = NtSuspendThread( hthread, &ret );
348
349     if (status)
350     {
351         ret = ~0U;
352         SetLastError( RtlNtStatusToDosError(status) );
353     }
354     return ret;
355 }
356
357
358 /**********************************************************************
359  * ResumeThread [KERNEL32.@]  Resumes a thread.
360  *
361  * Decrements a thread's suspend count.  When count is zero, the
362  * execution of the thread is resumed.
363  *
364  * RETURNS
365  *    Success: Previous suspend count
366  *    Failure: 0xFFFFFFFF
367  *    Already running: 0
368  */
369 DWORD WINAPI ResumeThread( HANDLE hthread ) /* [in] Identifies thread to restart */
370 {
371     DWORD ret;
372     NTSTATUS status = NtResumeThread( hthread, &ret );
373
374     if (status)
375     {
376         ret = ~0U;
377         SetLastError( RtlNtStatusToDosError(status) );
378     }
379     return ret;
380 }
381
382
383 /**********************************************************************
384  * GetThreadPriority [KERNEL32.@]  Returns priority for thread.
385  *
386  * RETURNS
387  *    Success: Thread's priority level.
388  *    Failure: THREAD_PRIORITY_ERROR_RETURN
389  */
390 INT WINAPI GetThreadPriority(
391     HANDLE hthread) /* [in] Handle to thread */
392 {
393     THREAD_BASIC_INFORMATION info;
394     NTSTATUS status = NtQueryInformationThread( hthread, ThreadBasicInformation,
395                                                 &info, sizeof(info), NULL );
396
397     if (status)
398     {
399         SetLastError( RtlNtStatusToDosError(status) );
400         return THREAD_PRIORITY_ERROR_RETURN;
401     }
402     return info.Priority;
403 }
404
405
406 /**********************************************************************
407  * SetThreadPriority [KERNEL32.@]  Sets priority for thread.
408  *
409  * RETURNS
410  *    Success: TRUE
411  *    Failure: FALSE
412  */
413 BOOL WINAPI SetThreadPriority(
414     HANDLE hthread, /* [in] Handle to thread */
415     INT priority)   /* [in] Thread priority level */
416 {
417     DWORD       prio = priority;
418     NTSTATUS    status;
419
420     status = NtSetInformationThread(hthread, ThreadBasePriority,
421                                     &prio, sizeof(prio));
422
423     if (status)
424     {
425         SetLastError( RtlNtStatusToDosError(status) );
426         return FALSE;
427     }
428
429     return TRUE;
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     KERNEL_USER_TIMES   kusrt;
547     NTSTATUS            status;
548
549     status = NtQueryInformationThread(thread, ThreadTimes, &kusrt,
550                                       sizeof(kusrt), NULL);
551     if (status)
552     {
553         SetLastError( RtlNtStatusToDosError(status) );
554         return FALSE;
555     }
556     if (creationtime)
557     {
558         creationtime->dwLowDateTime = kusrt.CreateTime.u.LowPart;
559         creationtime->dwHighDateTime = kusrt.CreateTime.u.HighPart;
560     }
561     if (exittime)
562     {
563         exittime->dwLowDateTime = kusrt.ExitTime.u.LowPart;
564         exittime->dwHighDateTime = kusrt.ExitTime.u.HighPart;
565     }
566     if (kerneltime)
567     {
568         kerneltime->dwLowDateTime = kusrt.KernelTime.u.LowPart;
569         kerneltime->dwHighDateTime = kusrt.KernelTime.u.HighPart;
570     }
571     if (usertime)
572     {
573         usertime->dwLowDateTime = kusrt.UserTime.u.LowPart;
574         usertime->dwHighDateTime = kusrt.UserTime.u.HighPart;
575     }
576     
577     return TRUE;
578 }
579
580
581 /**********************************************************************
582  * VWin32_BoostThreadGroup [KERNEL.535]
583  */
584 VOID WINAPI VWin32_BoostThreadGroup( DWORD threadId, INT boost )
585 {
586     FIXME("(0x%08lx,%d): stub\n", threadId, boost);
587 }
588
589
590 /**********************************************************************
591  * VWin32_BoostThreadStatic [KERNEL.536]
592  */
593 VOID WINAPI VWin32_BoostThreadStatic( DWORD threadId, INT boost )
594 {
595     FIXME("(0x%08lx,%d): stub\n", threadId, boost);
596 }
597
598
599 /***********************************************************************
600  * GetCurrentThread [KERNEL32.@]  Gets pseudohandle for current thread
601  *
602  * RETURNS
603  *    Pseudohandle for the current thread
604  */
605 #undef GetCurrentThread
606 HANDLE WINAPI GetCurrentThread(void)
607 {
608     return (HANDLE)0xfffffffe;
609 }
610
611
612 #ifdef __i386__
613
614 /***********************************************************************
615  *              SetLastError (KERNEL.147)
616  *              SetLastError (KERNEL32.@)
617  */
618 /* void WINAPI SetLastError( DWORD error ); */
619 __ASM_GLOBAL_FUNC( SetLastError,
620                    "movl 4(%esp),%eax\n\t"
621                    ".byte 0x64\n\t"
622                    "movl %eax,0x34\n\t"
623                    "ret $4" )
624
625 /***********************************************************************
626  *              GetLastError (KERNEL.148)
627  *              GetLastError (KERNEL32.@)
628  */
629 /* DWORD WINAPI GetLastError(void); */
630 __ASM_GLOBAL_FUNC( GetLastError, ".byte 0x64\n\tmovl 0x34,%eax\n\tret" )
631
632 /***********************************************************************
633  *              GetCurrentProcessId (KERNEL.471)
634  *              GetCurrentProcessId (KERNEL32.@)
635  */
636 /* DWORD WINAPI GetCurrentProcessId(void) */
637 __ASM_GLOBAL_FUNC( GetCurrentProcessId, ".byte 0x64\n\tmovl 0x20,%eax\n\tret" )
638
639 /***********************************************************************
640  *              GetCurrentThreadId (KERNEL.462)
641  *              GetCurrentThreadId (KERNEL32.@)
642  */
643 /* DWORD WINAPI GetCurrentThreadId(void) */
644 __ASM_GLOBAL_FUNC( GetCurrentThreadId, ".byte 0x64\n\tmovl 0x24,%eax\n\tret" )
645
646 #else  /* __i386__ */
647
648 /**********************************************************************
649  *              SetLastError (KERNEL.147)
650  *              SetLastError (KERNEL32.@)
651  *
652  * Sets the last-error code.
653  *
654  * RETURNS
655  * Nothing.
656  */
657 void WINAPI SetLastError( DWORD error ) /* [in] Per-thread error code */
658 {
659     NtCurrentTeb()->LastErrorValue = error;
660 }
661
662 /**********************************************************************
663  *              GetLastError (KERNEL.148)
664  *              GetLastError (KERNEL32.@)
665  *
666  * Get the last-error code.
667  *
668  * RETURNS
669  *  last-error code.
670  */
671 DWORD WINAPI GetLastError(void)
672 {
673     return NtCurrentTeb()->LastErrorValue;
674 }
675
676 /***********************************************************************
677  *              GetCurrentProcessId (KERNEL.471)
678  *              GetCurrentProcessId (KERNEL32.@)
679  *
680  * Get the current process identifier.
681  *
682  * RETURNS
683  *  current process identifier
684  */
685 DWORD WINAPI GetCurrentProcessId(void)
686 {
687     return (DWORD)NtCurrentTeb()->ClientId.UniqueProcess;
688 }
689
690 /***********************************************************************
691  *              GetCurrentThreadId (KERNEL.462)
692  *              GetCurrentThreadId (KERNEL32.@)
693  *
694  * Get the current thread identifier.
695  *
696  * RETURNS
697  *  current thread identifier
698  */
699 DWORD WINAPI GetCurrentThreadId(void)
700 {
701     return (DWORD)NtCurrentTeb()->ClientId.UniqueThread;
702 }
703
704 #endif  /* __i386__ */