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