Moved all signal support to a new platform-specific file.
[wine] / scheduler / thread.c
1 /*
2  * Win32 threads
3  *
4  * Copyright 1996 Alexandre Julliard
5  */
6
7 #include "config.h"
8
9 #include <assert.h>
10 #include <fcntl.h>
11 #include <sys/types.h>
12 #include <sys/socket.h>
13 #ifdef HAVE_SYS_MMAN_H
14 #include <sys/mman.h>
15 #endif
16 #include <unistd.h>
17 #include "wine/winbase16.h"
18 #include "thread.h"
19 #include "process.h"
20 #include "task.h"
21 #include "module.h"
22 #include "user.h"
23 #include "winerror.h"
24 #include "heap.h"
25 #include "selectors.h"
26 #include "winnt.h"
27 #include "server.h"
28 #include "services.h"
29 #include "stackframe.h"
30 #include "builtin16.h"
31 #include "debugtools.h"
32 #include "queue.h"
33 #include "hook.h"
34
35 DEFAULT_DEBUG_CHANNEL(thread)
36
37 /* TEB of the initial thread */
38 static TEB initial_teb;
39
40 /* Global thread list (FIXME: not thread-safe) */
41 TEB *THREAD_First = &initial_teb;
42
43 /***********************************************************************
44  *           THREAD_IsWin16
45  */
46 BOOL THREAD_IsWin16( TEB *teb )
47 {
48     return !teb || !(teb->flags & TEBF_WIN32);
49 }
50
51 /***********************************************************************
52  *           THREAD_IdToTEB
53  *
54  * Convert a thread id to a TEB, making sure it is valid.
55  */
56 TEB *THREAD_IdToTEB( DWORD id )
57 {
58     TEB *teb = THREAD_First;
59
60     if (!id) return NtCurrentTeb();
61     while (teb)
62     {
63         if ((DWORD)teb->tid == id) return teb;
64         teb = teb->next;
65     }
66     /* Allow task handles to be used; convert to main thread */
67     if ( IsTask16( id ) )
68     {
69         TDB *pTask = (TDB *)GlobalLock16( id );
70         if (pTask) return pTask->teb;
71     }
72     SetLastError( ERROR_INVALID_PARAMETER );
73     return NULL;
74 }
75
76
77 /***********************************************************************
78  *           THREAD_InitTEB
79  *
80  * Initialization of a newly created TEB.
81  */
82 static BOOL THREAD_InitTEB( TEB *teb, DWORD stack_size, BOOL alloc_stack16,
83                             LPSECURITY_ATTRIBUTES sa )
84 {
85     DWORD old_prot;
86
87     /* Allocate the stack */
88
89     /* FIXME:
90      * If stacksize smaller than 1 MB, allocate 1MB 
91      * (one program wanted only 10 kB, which is recommendable, but some WINE
92      *  functions, noteably in the files subdir, push HUGE structures and
93      *  arrays on the stack. They probably shouldn't.)
94      * If stacksize larger than 16 MB, warn the user. (We could shrink the stack
95      * but this could give more or less unexplainable crashes.)
96      */
97     if (stack_size<1024*1024)
98         stack_size = 1024 * 1024;
99     if (stack_size >= 16*1024*1024)
100         WARN("Thread stack size is %ld MB.\n",stack_size/1024/1024);
101     teb->stack_base = VirtualAlloc(NULL, stack_size + SIGNAL_STACK_SIZE +
102                                    (alloc_stack16 ? 0x10000 : 0),
103                                    MEM_COMMIT, PAGE_EXECUTE_READWRITE );
104     if (!teb->stack_base) goto error;
105     /* Set a guard page at the bottom of the stack */
106     VirtualProtect( teb->stack_base, 1, PAGE_EXECUTE_READWRITE | PAGE_GUARD, &old_prot );
107     teb->stack_top    = (char *)teb->stack_base + stack_size;
108     teb->stack_low    = teb->stack_base;
109     teb->signal_stack = teb->stack_top;  /* start of signal stack */
110
111     /* Allocate the 16-bit stack selector */
112
113     if (alloc_stack16)
114     {
115         teb->stack_sel = SELECTOR_AllocBlock( teb->stack_top, 0x10000, SEGMENT_DATA,
116                                               FALSE, FALSE );
117         if (!teb->stack_sel) goto error;
118         teb->cur_stack = PTR_SEG_OFF_TO_SEGPTR( teb->stack_sel, 
119                                                 0x10000 - sizeof(STACK16FRAME) );
120         teb->signal_stack = (char *)teb->signal_stack + 0x10000;
121     }
122
123     /* Create the thread event */
124
125     if (!(teb->event = CreateEventA( NULL, FALSE, FALSE, NULL ))) goto error;
126     teb->event = ConvertToGlobalHandle( teb->event );
127     return TRUE;
128
129 error:
130     if (teb->event) CloseHandle( teb->event );
131     if (teb->stack_sel) SELECTOR_FreeBlock( teb->stack_sel, 1 );
132     if (teb->stack_base) VirtualFree( teb->stack_base, 0, MEM_RELEASE );
133     return FALSE;
134 }
135
136
137 /***********************************************************************
138  *           THREAD_FreeTEB
139  *
140  * Free data structures associated with a thread.
141  * Must be called from the context of another thread.
142  */
143 void CALLBACK THREAD_FreeTEB( ULONG_PTR arg )
144 {
145     TEB *teb = (TEB *)arg;
146     TEB **pptr = &THREAD_First;
147
148     TRACE("(%p) called\n", teb );
149     SERVICE_Delete( teb->cleanup );
150
151     PROCESS_CallUserSignalProc( USIG_THREAD_EXIT, 0 );
152     
153     CloseHandle( teb->event );
154     while (*pptr && (*pptr != teb)) pptr = &(*pptr)->next;
155     if (*pptr) *pptr = teb->next;
156
157     /* Free the associated memory */
158
159     if (teb->stack_sel) SELECTOR_FreeBlock( teb->stack_sel, 1 );
160     SELECTOR_FreeBlock( teb->teb_sel, 1 );
161     close( teb->socket );
162     if (teb->buffer) munmap( teb->buffer, teb->buffer_size );
163     VirtualFree( teb->stack_base, 0, MEM_RELEASE );
164     HeapFree( SystemHeap, 0, teb );
165 }
166
167
168 /***********************************************************************
169  *           THREAD_CreateInitialThread
170  *
171  * Create the initial thread.
172  */
173 TEB *THREAD_CreateInitialThread( PDB *pdb, int server_fd )
174 {
175     initial_teb.except      = (void *)-1;
176     initial_teb.self        = &initial_teb;
177     initial_teb.flags       = /* TEBF_WIN32 */ 0;
178     initial_teb.tls_ptr     = initial_teb.tls_array;
179     initial_teb.process     = pdb;
180     initial_teb.exit_code   = 0x103; /* STILL_ACTIVE */
181     initial_teb.socket      = server_fd;
182
183     /* Allocate the TEB selector (%fs register) */
184
185     if (!(initial_teb.teb_sel = SELECTOR_AllocBlock( &initial_teb, 0x1000,
186                                                      SEGMENT_DATA, TRUE, FALSE )))
187     {
188         MESSAGE("Could not allocate fs register for initial thread\n" );
189         return NULL;
190     }
191     SYSDEPS_SetCurThread( &initial_teb );
192
193     /* Now proceed with normal initialization */
194
195     if (CLIENT_InitThread()) return NULL;
196     if (!THREAD_InitTEB( &initial_teb, 0, TRUE, NULL )) return NULL;
197     return &initial_teb;
198 }
199
200
201 /***********************************************************************
202  *           THREAD_Create
203  */
204 TEB *THREAD_Create( PDB *pdb, DWORD flags, DWORD stack_size, BOOL alloc_stack16,
205                      LPSECURITY_ATTRIBUTES sa, int *server_handle )
206 {
207     struct new_thread_request *req = get_req_buffer();
208     int fd[2];
209     HANDLE cleanup_object;
210
211     TEB *teb = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(TEB) );
212     if (!teb) return NULL;
213     teb->except      = (void *)-1;
214     teb->htask16     = pdb->task;
215     teb->self        = teb;
216     teb->flags       = (pdb->flags & PDB32_WIN16_PROC)? 0 : TEBF_WIN32;
217     teb->tls_ptr     = teb->tls_array;
218     teb->process     = pdb;
219     teb->exit_code   = 0x103; /* STILL_ACTIVE */
220     teb->socket      = -1;
221
222     /* Allocate the TEB selector (%fs register) */
223
224     *server_handle = -1;
225     teb->teb_sel = SELECTOR_AllocBlock( teb, 0x1000, SEGMENT_DATA, TRUE, FALSE );
226     if (!teb->teb_sel) goto error;
227
228     /* Create the socket pair for server communication */
229
230     if (socketpair( AF_UNIX, SOCK_STREAM, 0, fd ) == -1)
231     {
232         SetLastError( ERROR_TOO_MANY_OPEN_FILES );  /* FIXME */
233         goto error;
234     }
235     teb->socket = fd[0];
236     fcntl( fd[0], F_SETFD, 1 ); /* set close on exec flag */
237
238     /* Create the thread on the server side */
239
240     req->pid     = teb->process->server_pid;
241     req->suspend = ((flags & CREATE_SUSPENDED) != 0);
242     req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
243     if (server_call_fd( REQ_NEW_THREAD, fd[1], NULL )) goto error;
244     teb->tid = req->tid;
245     *server_handle = req->handle;
246
247     /* Do the rest of the initialization */
248
249     if (!THREAD_InitTEB( teb, stack_size, alloc_stack16, sa )) goto error;
250     teb->next = THREAD_First;
251     THREAD_First = teb;
252
253     /* Install cleanup handler */
254     if ( !DuplicateHandle( GetCurrentProcess(), *server_handle, 
255                            GetCurrentProcess(), &cleanup_object, 
256                            0, FALSE, DUPLICATE_SAME_ACCESS ) ) goto error;
257     teb->cleanup = SERVICE_AddObject( cleanup_object, THREAD_FreeTEB, (ULONG_PTR)teb );
258
259     return teb;
260
261 error:
262     if (*server_handle != -1) CloseHandle( *server_handle );
263     if (teb->teb_sel) SELECTOR_FreeBlock( teb->teb_sel, 1 );
264     if (teb->socket != -1) close( teb->socket );
265     HeapFree( SystemHeap, 0, teb );
266     return NULL;
267 }
268
269
270 /***********************************************************************
271  *           THREAD_Start
272  *
273  * Start execution of a newly created thread. Does not return.
274  */
275 static void THREAD_Start(void)
276 {
277     LPTHREAD_START_ROUTINE func = (LPTHREAD_START_ROUTINE)NtCurrentTeb()->entry_point;
278     PROCESS_CallUserSignalProc( USIG_THREAD_INIT, 0 );
279     PE_InitTls();
280     MODULE_DllThreadAttach( NULL );
281
282     if (NtCurrentTeb()->process->flags & PDB32_DEBUGGED) DEBUG_SendCreateThreadEvent( func );
283
284     ExitThread( func( NtCurrentTeb()->entry_arg ) );
285 }
286
287
288 /***********************************************************************
289  *           CreateThread   (KERNEL32.63)
290  */
291 HANDLE WINAPI CreateThread( SECURITY_ATTRIBUTES *sa, DWORD stack,
292                             LPTHREAD_START_ROUTINE start, LPVOID param,
293                             DWORD flags, LPDWORD id )
294 {
295     int handle = -1;
296     TEB *teb = THREAD_Create( PROCESS_Current(), flags, stack, TRUE, sa, &handle );
297     if (!teb) return 0;
298     teb->flags      |= TEBF_WIN32;
299     teb->entry_point = start;
300     teb->entry_arg   = param;
301     teb->startup     = THREAD_Start;
302     if (SYSDEPS_SpawnThread( teb ) == -1)
303     {
304         CloseHandle( handle );
305         return 0;
306     }
307     if (id) *id = (DWORD)teb->tid;
308     return handle;
309 }
310
311 /***********************************************************************
312  *           CreateThread16   (KERNEL.441)
313  */
314 static DWORD CALLBACK THREAD_StartThread16( LPVOID threadArgs )
315 {
316     FARPROC16 start = ((FARPROC16 *)threadArgs)[0];
317     DWORD     param = ((DWORD *)threadArgs)[1];
318     HeapFree( GetProcessHeap(), 0, threadArgs );
319
320     ((LPDWORD)CURRENT_STACK16)[-1] = param;
321     return CallTo16Long( start, sizeof(DWORD) );
322 }
323 HANDLE WINAPI CreateThread16( SECURITY_ATTRIBUTES *sa, DWORD stack,
324                               FARPROC16 start, SEGPTR param,
325                               DWORD flags, LPDWORD id )
326 {
327     DWORD *threadArgs = HeapAlloc( GetProcessHeap(), 0, 2*sizeof(DWORD) );
328     if (!threadArgs) return INVALID_HANDLE_VALUE;
329     threadArgs[0] = (DWORD)start;
330     threadArgs[1] = (DWORD)param;
331
332     return CreateThread( sa, stack, THREAD_StartThread16, threadArgs, flags, id );
333 }
334
335
336 /***********************************************************************
337  * ExitThread [KERNEL32.215]  Ends a thread
338  *
339  * RETURNS
340  *    None
341  */
342 void WINAPI ExitThread( DWORD code ) /* [in] Exit code for this thread */
343 {
344     MODULE_DllThreadDetach( NULL );
345     TerminateThread( GetCurrentThread(), code );
346 }
347
348
349 /***********************************************************************
350  * GetCurrentThread [KERNEL32.200]  Gets pseudohandle for current thread
351  *
352  * RETURNS
353  *    Pseudohandle for the current thread
354  */
355 HANDLE WINAPI GetCurrentThread(void)
356 {
357     return CURRENT_THREAD_PSEUDOHANDLE;
358 }
359
360
361 /**********************************************************************
362  * GetLastError [KERNEL.148] [KERNEL32.227]  Returns last-error code.
363  *
364  * RETURNS
365  *     Calling thread's last error code value.
366  */
367 DWORD WINAPI GetLastError(void)
368 {
369     return NtCurrentTeb()->last_error;
370 }
371
372
373 /**********************************************************************
374  * SetLastErrorEx [USER32.485]  Sets the last-error code.
375  *
376  * RETURNS
377  *    None.
378  */
379 void WINAPI SetLastErrorEx(
380     DWORD error, /* [in] Per-thread error code */
381     DWORD type)  /* [in] Error type */
382 {
383     TRACE("(0x%08lx, 0x%08lx)\n", error,type);
384     switch(type) {
385         case 0:
386             break;
387         case SLE_ERROR:
388         case SLE_MINORERROR:
389         case SLE_WARNING:
390             /* Fall through for now */
391         default:
392             FIXME("(error=%08lx, type=%08lx): Unhandled type\n", error,type);
393             break;
394     }
395     SetLastError( error );
396 }
397
398
399 /**********************************************************************
400  * TlsAlloc [KERNEL32.530]  Allocates a TLS index.
401  *
402  * Allocates a thread local storage index
403  *
404  * RETURNS
405  *    Success: TLS Index
406  *    Failure: 0xFFFFFFFF
407  */
408 DWORD WINAPI TlsAlloc( void )
409 {
410     PDB *process = PROCESS_Current();
411     DWORD i, mask, ret = 0;
412     DWORD *bits = process->tls_bits;
413     EnterCriticalSection( &process->crit_section );
414     if (*bits == 0xffffffff)
415     {
416         bits++;
417         ret = 32;
418         if (*bits == 0xffffffff)
419         {
420             LeaveCriticalSection( &process->crit_section );
421             SetLastError( ERROR_NO_MORE_ITEMS );
422             return 0xffffffff;
423         }
424     }
425     for (i = 0, mask = 1; i < 32; i++, mask <<= 1) if (!(*bits & mask)) break;
426     *bits |= mask;
427     LeaveCriticalSection( &process->crit_section );
428     return ret + i;
429 }
430
431
432 /**********************************************************************
433  * TlsFree [KERNEL32.531]  Releases a TLS index.
434  *
435  * Releases a thread local storage index, making it available for reuse
436  * 
437  * RETURNS
438  *    Success: TRUE
439  *    Failure: FALSE
440  */
441 BOOL WINAPI TlsFree(
442     DWORD index) /* [in] TLS Index to free */
443 {
444     PDB *process = PROCESS_Current();
445     DWORD mask;
446     DWORD *bits = process->tls_bits;
447     if (index >= 64)
448     {
449         SetLastError( ERROR_INVALID_PARAMETER );
450         return FALSE;
451     }
452     EnterCriticalSection( &process->crit_section );
453     if (index >= 32) bits++;
454     mask = (1 << (index & 31));
455     if (!(*bits & mask))  /* already free? */
456     {
457         LeaveCriticalSection( &process->crit_section );
458         SetLastError( ERROR_INVALID_PARAMETER );
459         return FALSE;
460     }
461     *bits &= ~mask;
462     NtCurrentTeb()->tls_array[index] = 0;
463     /* FIXME: should zero all other thread values */
464     LeaveCriticalSection( &process->crit_section );
465     return TRUE;
466 }
467
468
469 /**********************************************************************
470  * TlsGetValue [KERNEL32.532]  Gets value in a thread's TLS slot
471  *
472  * RETURNS
473  *    Success: Value stored in calling thread's TLS slot for index
474  *    Failure: 0 and GetLastError returns NO_ERROR
475  */
476 LPVOID WINAPI TlsGetValue(
477     DWORD index) /* [in] TLS index to retrieve value for */
478 {
479     if (index >= 64)
480     {
481         SetLastError( ERROR_INVALID_PARAMETER );
482         return NULL;
483     }
484     SetLastError( ERROR_SUCCESS );
485     return NtCurrentTeb()->tls_array[index];
486 }
487
488
489 /**********************************************************************
490  * TlsSetValue [KERNEL32.533]  Stores a value in the thread's TLS slot.
491  *
492  * RETURNS
493  *    Success: TRUE
494  *    Failure: FALSE
495  */
496 BOOL WINAPI TlsSetValue(
497     DWORD index,  /* [in] TLS index to set value for */
498     LPVOID value) /* [in] Value to be stored */
499 {
500     if (index >= 64)
501     {
502         SetLastError( ERROR_INVALID_PARAMETER );
503         return FALSE;
504     }
505     NtCurrentTeb()->tls_array[index] = value;
506     return TRUE;
507 }
508
509
510 /***********************************************************************
511  * SetThreadContext [KERNEL32.670]  Sets context of thread.
512  *
513  * RETURNS
514  *    Success: TRUE
515  *    Failure: FALSE
516  */
517 BOOL WINAPI SetThreadContext(
518     HANDLE handle,  /* [in]  Handle to thread with context */
519     const CONTEXT *context) /* [out] Address of context structure */
520 {
521     FIXME("not implemented\n" );
522     return TRUE;
523 }
524
525 /***********************************************************************
526  * GetThreadContext [KERNEL32.294]  Retrieves context of thread.
527  *
528  * RETURNS
529  *    Success: TRUE
530  *    Failure: FALSE
531  */
532 BOOL WINAPI GetThreadContext(
533     HANDLE handle,  /* [in]  Handle to thread with context */
534     CONTEXT *context) /* [out] Address of context structure */
535 {
536 #ifdef __i386__
537     WORD cs, ds;
538
539     FIXME("returning dummy info\n" );
540
541     /* make up some plausible values for segment registers */
542     GET_CS(cs);
543     GET_DS(ds);
544     context->SegCs   = cs;
545     context->SegDs   = ds;
546     context->SegEs   = ds;
547     context->SegGs   = ds;
548     context->SegSs   = ds;
549     context->SegFs   = ds;
550 #endif
551     return TRUE;
552 }
553
554
555 /**********************************************************************
556  * GetThreadPriority [KERNEL32.296]  Returns priority for thread.
557  *
558  * RETURNS
559  *    Success: Thread's priority level.
560  *    Failure: THREAD_PRIORITY_ERROR_RETURN
561  */
562 INT WINAPI GetThreadPriority(
563     HANDLE hthread) /* [in] Handle to thread */
564 {
565     INT ret = THREAD_PRIORITY_ERROR_RETURN;
566     struct get_thread_info_request *req = get_req_buffer();
567     req->handle = hthread;
568     if (!server_call( REQ_GET_THREAD_INFO )) ret = req->priority;
569     return ret;
570 }
571
572
573 /**********************************************************************
574  * SetThreadPriority [KERNEL32.514]  Sets priority for thread.
575  *
576  * RETURNS
577  *    Success: TRUE
578  *    Failure: FALSE
579  */
580 BOOL WINAPI SetThreadPriority(
581     HANDLE hthread, /* [in] Handle to thread */
582     INT priority)   /* [in] Thread priority level */
583 {
584     struct set_thread_info_request *req = get_req_buffer();
585     req->handle   = hthread;
586     req->priority = priority;
587     req->mask     = SET_THREAD_INFO_PRIORITY;
588     return !server_call( REQ_SET_THREAD_INFO );
589 }
590
591
592 /**********************************************************************
593  *           SetThreadAffinityMask   (KERNEL32.669)
594  */
595 DWORD WINAPI SetThreadAffinityMask( HANDLE hThread, DWORD dwThreadAffinityMask )
596 {
597     struct set_thread_info_request *req = get_req_buffer();
598     req->handle   = hThread;
599     req->affinity = dwThreadAffinityMask;
600     req->mask     = SET_THREAD_INFO_AFFINITY;
601     if (server_call( REQ_SET_THREAD_INFO )) return 0;
602     return 1;  /* FIXME: should return previous value */
603 }
604
605
606 /**********************************************************************
607  * TerminateThread [KERNEL32.685]  Terminates a thread
608  *
609  * RETURNS
610  *    Success: TRUE
611  *    Failure: FALSE
612  */
613 BOOL WINAPI TerminateThread(
614     HANDLE handle, /* [in] Handle to thread */
615     DWORD exitcode)  /* [in] Exit code for thread */
616 {
617     struct terminate_thread_request *req = get_req_buffer();
618     req->handle    = handle;
619     req->exit_code = exitcode;
620     return !server_call( REQ_TERMINATE_THREAD );
621 }
622
623
624 /**********************************************************************
625  * GetExitCodeThread [KERNEL32.???]  Gets termination status of thread.
626  * 
627  * RETURNS
628  *    Success: TRUE
629  *    Failure: FALSE
630  */
631 BOOL WINAPI GetExitCodeThread(
632     HANDLE hthread, /* [in]  Handle to thread */
633     LPDWORD exitcode) /* [out] Address to receive termination status */
634 {
635     BOOL ret = FALSE;
636     struct get_thread_info_request *req = get_req_buffer();
637     req->handle = hthread;
638     if (!server_call( REQ_GET_THREAD_INFO ))
639     {
640         if (exitcode) *exitcode = req->exit_code;
641         ret = TRUE;
642     }
643     return ret;
644 }
645
646
647 /**********************************************************************
648  * ResumeThread [KERNEL32.587]  Resumes a thread.
649  *
650  * Decrements a thread's suspend count.  When count is zero, the
651  * execution of the thread is resumed.
652  *
653  * RETURNS
654  *    Success: Previous suspend count
655  *    Failure: 0xFFFFFFFF
656  *    Already running: 0
657  */
658 DWORD WINAPI ResumeThread(
659     HANDLE hthread) /* [in] Identifies thread to restart */
660 {
661     DWORD ret = 0xffffffff;
662     struct resume_thread_request *req = get_req_buffer();
663     req->handle = hthread;
664     if (!server_call( REQ_RESUME_THREAD )) ret = req->count;
665     return ret;
666 }
667
668
669 /**********************************************************************
670  * SuspendThread [KERNEL32.681]  Suspends a thread.
671  *
672  * RETURNS
673  *    Success: Previous suspend count
674  *    Failure: 0xFFFFFFFF
675  */
676 DWORD WINAPI SuspendThread(
677     HANDLE hthread) /* [in] Handle to the thread */
678 {
679     DWORD ret = 0xffffffff;
680     struct suspend_thread_request *req = get_req_buffer();
681     req->handle = hthread;
682     if (!server_call( REQ_SUSPEND_THREAD )) ret = req->count;
683     return ret;
684 }
685
686
687 /***********************************************************************
688  *              QueueUserAPC  (KERNEL32.566)
689  */
690 DWORD WINAPI QueueUserAPC( PAPCFUNC func, HANDLE hthread, ULONG_PTR data )
691 {
692     struct queue_apc_request *req = get_req_buffer();
693     req->handle = hthread;
694     req->func   = func;
695     req->param  = (void *)data;
696     return !server_call( REQ_QUEUE_APC );
697 }
698
699
700 /**********************************************************************
701  * GetThreadTimes [KERNEL32.???]  Obtains timing information.
702  *
703  * NOTES
704  *    What are the fields where these values are stored?
705  *
706  * RETURNS
707  *    Success: TRUE
708  *    Failure: FALSE
709  */
710 BOOL WINAPI GetThreadTimes( 
711     HANDLE thread,         /* [in]  Specifies the thread of interest */
712     LPFILETIME creationtime, /* [out] When the thread was created */
713     LPFILETIME exittime,     /* [out] When the thread was destroyed */
714     LPFILETIME kerneltime,   /* [out] Time thread spent in kernel mode */
715     LPFILETIME usertime)     /* [out] Time thread spent in user mode */
716 {
717     FIXME("(0x%08x): stub\n",thread);
718     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
719     return FALSE;
720 }
721
722
723 /**********************************************************************
724  * AttachThreadInput [KERNEL32.8]  Attaches input of 1 thread to other
725  *
726  * Attaches the input processing mechanism of one thread to that of
727  * another thread.
728  *
729  * RETURNS
730  *    Success: TRUE
731  *    Failure: FALSE
732  *
733  * TODO:
734  *    1. Reset the Key State (currenly per thread key state is not maintained)
735  */
736 BOOL WINAPI AttachThreadInput( 
737     DWORD idAttach,   /* [in] Thread to attach */
738     DWORD idAttachTo, /* [in] Thread to attach to */
739     BOOL fAttach)   /* [in] Attach or detach */
740 {
741     MESSAGEQUEUE *pSrcMsgQ = 0, *pTgtMsgQ = 0;
742     BOOL16 bRet = 0;
743
744     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
745
746     /* A thread cannot attach to itself */
747     if ( idAttach == idAttachTo )
748         goto CLEANUP;
749
750     /* According to the docs this method should fail if a
751      * "Journal record" hook is installed. (attaches all input queues together)
752      */
753     if ( HOOK_IsHooked( WH_JOURNALRECORD ) )
754         goto CLEANUP;
755         
756     /* Retrieve message queues corresponding to the thread id's */
757     pTgtMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetThreadQueue16( idAttach ) );
758     pSrcMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetThreadQueue16( idAttachTo ) );
759
760     /* Ensure we have message queues and that Src and Tgt threads
761      * are not system threads.
762      */
763     if ( !pSrcMsgQ || !pTgtMsgQ || !pSrcMsgQ->pQData || !pTgtMsgQ->pQData )
764         goto CLEANUP;
765
766     if (fAttach)   /* Attach threads */
767     {
768         /* Only attach if currently detached  */
769         if ( pTgtMsgQ->pQData != pSrcMsgQ->pQData )
770         {
771             /* First release the target threads perQData */
772             PERQDATA_Release( pTgtMsgQ->pQData );
773         
774             /* Share a reference to the source threads perQDATA */
775             PERQDATA_Addref( pSrcMsgQ->pQData );
776             pTgtMsgQ->pQData = pSrcMsgQ->pQData;
777         }
778     }
779     else    /* Detach threads */
780     {
781         /* Only detach if currently attached */
782         if ( pTgtMsgQ->pQData == pSrcMsgQ->pQData )
783         {
784             /* First release the target threads perQData */
785             PERQDATA_Release( pTgtMsgQ->pQData );
786         
787             /* Give the target thread its own private perQDATA once more */
788             pTgtMsgQ->pQData = PERQDATA_CreateInstance();
789         }
790     }
791
792     /* TODO: Reset the Key State */
793
794     bRet = 1;      /* Success */
795     
796 CLEANUP:
797
798     /* Unlock the queues before returning */
799     if ( pSrcMsgQ )
800         QUEUE_Unlock( pSrcMsgQ );
801     if ( pTgtMsgQ )
802         QUEUE_Unlock( pTgtMsgQ );
803     
804     return bRet;
805 }
806
807 /**********************************************************************
808  * VWin32_BoostThreadGroup [KERNEL.535]
809  */
810 VOID WINAPI VWin32_BoostThreadGroup( DWORD threadId, INT boost )
811 {
812     FIXME("(0x%08lx,%d): stub\n", threadId, boost);
813 }
814
815 /**********************************************************************
816  * VWin32_BoostThreadStatic [KERNEL.536]
817  */
818 VOID WINAPI VWin32_BoostThreadStatic( DWORD threadId, INT boost )
819 {
820     FIXME("(0x%08lx,%d): stub\n", threadId, boost);
821 }
822
823 /**********************************************************************
824  * SetThreadLocale [KERNEL32.671]  Sets the calling threads current locale.
825  *
826  * RETURNS
827  *    Success: TRUE
828  *    Failure: FALSE
829  *
830  * NOTES
831  *  Implemented in NT only (3.1 and above according to MS
832  */
833 BOOL WINAPI SetThreadLocale(
834     LCID lcid)     /* [in] Locale identifier */
835 {
836     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
837     return FALSE;
838 }
839
840
841 /**********************************************************************
842  * SetLastError [KERNEL.147] [KERNEL32.497]  Sets the last-error code.
843  *
844  * RETURNS
845  *    None.
846  */
847 #undef SetLastError
848 void WINAPI SetLastError( DWORD error ) /* [in] Per-thread error code */
849 {
850     NtCurrentTeb()->last_error = error;
851 }
852
853
854 /***********************************************************************
855  * GetCurrentThreadId [KERNEL32.201]  Returns thread identifier.
856  *
857  * RETURNS
858  *    Thread identifier of calling thread
859  */
860 #undef GetCurrentThreadId
861 DWORD WINAPI GetCurrentThreadId(void)
862 {
863     return (DWORD)NtCurrentTeb()->tid;
864 }