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