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