Created separate libraries for dplay, shfolder, shlwapi, wow32 and
[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 "winerror.h"
23 #include "heap.h"
24 #include "selectors.h"
25 #include "winnt.h"
26 #include "server.h"
27 #include "services.h"
28 #include "stackframe.h"
29 #include "builtin16.h"
30 #include "debugtools.h"
31 #include "queue.h"
32 #include "hook.h"
33 #include "winnls.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     teb->CurrentLocale = GetUserDefaultLCID(); /* for threads in user context */
301     if (id) *id = (DWORD)tid;
302     if (SYSDEPS_SpawnThread( teb ) == -1)
303     {
304         CloseHandle( handle );
305         return 0;
306     }
307     return handle;
308 }
309
310 /***********************************************************************
311  *           CreateThread16   (KERNEL.441)
312  */
313 static DWORD CALLBACK THREAD_StartThread16( LPVOID threadArgs )
314 {
315     FARPROC16 start = ((FARPROC16 *)threadArgs)[0];
316     DWORD     param = ((DWORD *)threadArgs)[1];
317     HeapFree( GetProcessHeap(), 0, threadArgs );
318
319     ((LPDWORD)CURRENT_STACK16)[-1] = param;
320     return CallTo16Long( start, sizeof(DWORD) );
321 }
322 HANDLE WINAPI CreateThread16( SECURITY_ATTRIBUTES *sa, DWORD stack,
323                               FARPROC16 start, SEGPTR param,
324                               DWORD flags, LPDWORD id )
325 {
326     DWORD *threadArgs = HeapAlloc( GetProcessHeap(), 0, 2*sizeof(DWORD) );
327     if (!threadArgs) return INVALID_HANDLE_VALUE;
328     threadArgs[0] = (DWORD)start;
329     threadArgs[1] = (DWORD)param;
330
331     return CreateThread( sa, stack, THREAD_StartThread16, threadArgs, flags, id );
332 }
333
334
335 /***********************************************************************
336  * ExitThread [KERNEL32.215]  Ends a thread
337  *
338  * RETURNS
339  *    None
340  */
341 void WINAPI ExitThread( DWORD code ) /* [in] Exit code for this thread */
342 {
343     struct terminate_thread_request *req = get_req_buffer();
344
345      /* send the exit code to the server */
346     req->handle    = GetCurrentThread();
347     req->exit_code = code;
348     server_call( REQ_TERMINATE_THREAD );
349     if (req->last)
350     {
351         MODULE_DllProcessDetach( TRUE, (LPVOID)1 );
352         exit( code );
353     }
354     else
355     {
356         MODULE_DllThreadDetach( NULL );
357         if (!(NtCurrentTeb()->tibflags & TEBF_WIN32)) TASK_KillTask( 0 );
358         SYSDEPS_ExitThread( code );
359     }
360 }
361
362
363 /**********************************************************************
364  * SetLastErrorEx [USER32.485]  Sets the last-error code.
365  *
366  * RETURNS
367  *    None.
368  */
369 void WINAPI SetLastErrorEx(
370     DWORD error, /* [in] Per-thread error code */
371     DWORD type)  /* [in] Error type */
372 {
373     TRACE("(0x%08lx, 0x%08lx)\n", error,type);
374     switch(type) {
375         case 0:
376             break;
377         case SLE_ERROR:
378         case SLE_MINORERROR:
379         case SLE_WARNING:
380             /* Fall through for now */
381         default:
382             FIXME("(error=%08lx, type=%08lx): Unhandled type\n", error,type);
383             break;
384     }
385     SetLastError( error );
386 }
387
388
389 /**********************************************************************
390  * TlsAlloc [KERNEL32.530]  Allocates a TLS index.
391  *
392  * Allocates a thread local storage index
393  *
394  * RETURNS
395  *    Success: TLS Index
396  *    Failure: 0xFFFFFFFF
397  */
398 DWORD WINAPI TlsAlloc( void )
399 {
400     PDB *process = PROCESS_Current();
401     DWORD i, mask, ret = 0;
402     DWORD *bits = process->tls_bits;
403     EnterCriticalSection( &process->crit_section );
404     if (*bits == 0xffffffff)
405     {
406         bits++;
407         ret = 32;
408         if (*bits == 0xffffffff)
409         {
410             LeaveCriticalSection( &process->crit_section );
411             SetLastError( ERROR_NO_MORE_ITEMS );
412             return 0xffffffff;
413         }
414     }
415     for (i = 0, mask = 1; i < 32; i++, mask <<= 1) if (!(*bits & mask)) break;
416     *bits |= mask;
417     LeaveCriticalSection( &process->crit_section );
418     return ret + i;
419 }
420
421
422 /**********************************************************************
423  * TlsFree [KERNEL32.531]  Releases a TLS index.
424  *
425  * Releases a thread local storage index, making it available for reuse
426  * 
427  * RETURNS
428  *    Success: TRUE
429  *    Failure: FALSE
430  */
431 BOOL WINAPI TlsFree(
432     DWORD index) /* [in] TLS Index to free */
433 {
434     PDB *process = PROCESS_Current();
435     DWORD mask;
436     DWORD *bits = process->tls_bits;
437     if (index >= 64)
438     {
439         SetLastError( ERROR_INVALID_PARAMETER );
440         return FALSE;
441     }
442     EnterCriticalSection( &process->crit_section );
443     if (index >= 32) bits++;
444     mask = (1 << (index & 31));
445     if (!(*bits & mask))  /* already free? */
446     {
447         LeaveCriticalSection( &process->crit_section );
448         SetLastError( ERROR_INVALID_PARAMETER );
449         return FALSE;
450     }
451     *bits &= ~mask;
452     NtCurrentTeb()->tls_array[index] = 0;
453     /* FIXME: should zero all other thread values */
454     LeaveCriticalSection( &process->crit_section );
455     return TRUE;
456 }
457
458
459 /**********************************************************************
460  * TlsGetValue [KERNEL32.532]  Gets value in a thread's TLS slot
461  *
462  * RETURNS
463  *    Success: Value stored in calling thread's TLS slot for index
464  *    Failure: 0 and GetLastError returns NO_ERROR
465  */
466 LPVOID WINAPI TlsGetValue(
467     DWORD index) /* [in] TLS index to retrieve value for */
468 {
469     if (index >= 64)
470     {
471         SetLastError( ERROR_INVALID_PARAMETER );
472         return NULL;
473     }
474     SetLastError( ERROR_SUCCESS );
475     return NtCurrentTeb()->tls_array[index];
476 }
477
478
479 /**********************************************************************
480  * TlsSetValue [KERNEL32.533]  Stores a value in the thread's TLS slot.
481  *
482  * RETURNS
483  *    Success: TRUE
484  *    Failure: FALSE
485  */
486 BOOL WINAPI TlsSetValue(
487     DWORD index,  /* [in] TLS index to set value for */
488     LPVOID value) /* [in] Value to be stored */
489 {
490     if (index >= 64)
491     {
492         SetLastError( ERROR_INVALID_PARAMETER );
493         return FALSE;
494     }
495     NtCurrentTeb()->tls_array[index] = value;
496     return TRUE;
497 }
498
499
500 /***********************************************************************
501  * SetThreadContext [KERNEL32.670]  Sets context of thread.
502  *
503  * RETURNS
504  *    Success: TRUE
505  *    Failure: FALSE
506  */
507 BOOL WINAPI SetThreadContext( HANDLE handle,           /* [in]  Handle to thread with context */
508                               const CONTEXT *context ) /* [in] Address of context structure */
509 {
510     struct set_thread_context_request *req = get_req_buffer();
511     req->handle = handle;
512     req->flags = context->ContextFlags;
513     memcpy( &req->context, context, sizeof(*context) );
514     return !server_call( REQ_SET_THREAD_CONTEXT );
515 }
516
517
518 /***********************************************************************
519  * GetThreadContext [KERNEL32.294]  Retrieves context of thread.
520  *
521  * RETURNS
522  *    Success: TRUE
523  *    Failure: FALSE
524  */
525 BOOL WINAPI GetThreadContext( HANDLE handle,     /* [in]  Handle to thread with context */
526                               CONTEXT *context ) /* [out] Address of context structure */
527 {
528     struct get_thread_context_request *req = get_req_buffer();
529     req->handle = handle;
530     req->flags = context->ContextFlags;
531     memcpy( &req->context, context, sizeof(*context) );
532     if (server_call( REQ_GET_THREAD_CONTEXT )) return FALSE;
533     memcpy( context, &req->context, sizeof(*context) );
534     return TRUE;
535 }
536
537
538 /**********************************************************************
539  * GetThreadPriority [KERNEL32.296]  Returns priority for thread.
540  *
541  * RETURNS
542  *    Success: Thread's priority level.
543  *    Failure: THREAD_PRIORITY_ERROR_RETURN
544  */
545 INT WINAPI GetThreadPriority(
546     HANDLE hthread) /* [in] Handle to thread */
547 {
548     INT ret = THREAD_PRIORITY_ERROR_RETURN;
549     struct get_thread_info_request *req = get_req_buffer();
550     req->handle = hthread;
551     req->tid_in = 0;
552     if (!server_call( REQ_GET_THREAD_INFO )) ret = req->priority;
553     return ret;
554 }
555
556
557 /**********************************************************************
558  * SetThreadPriority [KERNEL32.514]  Sets priority for thread.
559  *
560  * RETURNS
561  *    Success: TRUE
562  *    Failure: FALSE
563  */
564 BOOL WINAPI SetThreadPriority(
565     HANDLE hthread, /* [in] Handle to thread */
566     INT priority)   /* [in] Thread priority level */
567 {
568     struct set_thread_info_request *req = get_req_buffer();
569     req->handle   = hthread;
570     req->priority = priority;
571     req->mask     = SET_THREAD_INFO_PRIORITY;
572     return !server_call( REQ_SET_THREAD_INFO );
573 }
574
575
576 /**********************************************************************
577  * GetThreadPriorityBoost [KERNEL32.877]  Returns priority boost for thread.
578  *
579  * Always reports that priority boost is disabled.
580  *
581  * RETURNS
582  *    Success: TRUE.
583  *    Failure: FALSE
584  */
585 BOOL WINAPI GetThreadPriorityBoost(
586     HANDLE hthread, /* [in] Handle to thread */
587     PBOOL pstate)   /* [out] pointer to var that receives the boost state */
588 {
589     if (pstate) *pstate = FALSE;
590     return NO_ERROR;
591 }
592
593
594 /**********************************************************************
595  * SetThreadPriorityBoost [KERNEL32.893]  Sets priority boost for thread.
596  *
597  * Priority boost is not implemented. Thsi function always returns 
598  * FALSE and sets last error to ERROR_CALL_NOT_IMPLEMENTED
599  *
600  * RETURNS
601  *    Always returns FALSE to indicate a failure 
602  */
603 BOOL WINAPI SetThreadPriorityBoost(
604     HANDLE hthread, /* [in] Handle to thread */
605     BOOL disable)   /* [in] TRUE to disable priority boost */
606 {
607     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
608     return FALSE;
609 }
610
611
612 /**********************************************************************
613  *           SetThreadAffinityMask   (KERNEL32.669)
614  */
615 DWORD WINAPI SetThreadAffinityMask( HANDLE hThread, DWORD dwThreadAffinityMask )
616 {
617     struct set_thread_info_request *req = get_req_buffer();
618     req->handle   = hThread;
619     req->affinity = dwThreadAffinityMask;
620     req->mask     = SET_THREAD_INFO_AFFINITY;
621     if (server_call( REQ_SET_THREAD_INFO )) return 0;
622     return 1;  /* FIXME: should return previous value */
623 }
624
625
626 /**********************************************************************
627  * TerminateThread [KERNEL32.685]  Terminates a thread
628  *
629  * RETURNS
630  *    Success: TRUE
631  *    Failure: FALSE
632  */
633 BOOL WINAPI TerminateThread(
634     HANDLE handle, /* [in] Handle to thread */
635     DWORD exitcode)  /* [in] Exit code for thread */
636 {
637     BOOL ret;
638     struct terminate_thread_request *req = get_req_buffer();
639     req->handle    = handle;
640     req->exit_code = exitcode;
641     if ((ret = !server_call( REQ_TERMINATE_THREAD )) && req->self)
642     {
643         PROCESS_CallUserSignalProc( USIG_THREAD_EXIT, 0 );
644         if (req->last) exit( exitcode );
645         else SYSDEPS_ExitThread( exitcode );
646     }
647     return ret;
648 }
649
650
651 /**********************************************************************
652  * GetExitCodeThread [KERNEL32.???]  Gets termination status of thread.
653  * 
654  * RETURNS
655  *    Success: TRUE
656  *    Failure: FALSE
657  */
658 BOOL WINAPI GetExitCodeThread(
659     HANDLE hthread, /* [in]  Handle to thread */
660     LPDWORD exitcode) /* [out] Address to receive termination status */
661 {
662     BOOL ret = FALSE;
663     struct get_thread_info_request *req = get_req_buffer();
664     req->handle = hthread;
665     req->tid_in = 0;
666     if (!server_call( REQ_GET_THREAD_INFO ))
667     {
668         if (exitcode) *exitcode = req->exit_code;
669         ret = TRUE;
670     }
671     return ret;
672 }
673
674
675 /**********************************************************************
676  * ResumeThread [KERNEL32.587]  Resumes a thread.
677  *
678  * Decrements a thread's suspend count.  When count is zero, the
679  * execution of the thread is resumed.
680  *
681  * RETURNS
682  *    Success: Previous suspend count
683  *    Failure: 0xFFFFFFFF
684  *    Already running: 0
685  */
686 DWORD WINAPI ResumeThread(
687     HANDLE hthread) /* [in] Identifies thread to restart */
688 {
689     DWORD ret = 0xffffffff;
690     struct resume_thread_request *req = get_req_buffer();
691     req->handle = hthread;
692     if (!server_call( REQ_RESUME_THREAD )) ret = req->count;
693     return ret;
694 }
695
696
697 /**********************************************************************
698  * SuspendThread [KERNEL32.681]  Suspends a thread.
699  *
700  * RETURNS
701  *    Success: Previous suspend count
702  *    Failure: 0xFFFFFFFF
703  */
704 DWORD WINAPI SuspendThread(
705     HANDLE hthread) /* [in] Handle to the thread */
706 {
707     DWORD ret = 0xffffffff;
708     struct suspend_thread_request *req = get_req_buffer();
709     req->handle = hthread;
710     if (!server_call( REQ_SUSPEND_THREAD )) ret = req->count;
711     return ret;
712 }
713
714
715 /***********************************************************************
716  *              QueueUserAPC  (KERNEL32.566)
717  */
718 DWORD WINAPI QueueUserAPC( PAPCFUNC func, HANDLE hthread, ULONG_PTR data )
719 {
720     struct queue_apc_request *req = get_req_buffer();
721     req->handle = hthread;
722     req->func   = func;
723     req->param  = (void *)data;
724     return !server_call( REQ_QUEUE_APC );
725 }
726
727
728 /**********************************************************************
729  * GetThreadTimes [KERNEL32.???]  Obtains timing information.
730  *
731  * NOTES
732  *    What are the fields where these values are stored?
733  *
734  * RETURNS
735  *    Success: TRUE
736  *    Failure: FALSE
737  */
738 BOOL WINAPI GetThreadTimes( 
739     HANDLE thread,         /* [in]  Specifies the thread of interest */
740     LPFILETIME creationtime, /* [out] When the thread was created */
741     LPFILETIME exittime,     /* [out] When the thread was destroyed */
742     LPFILETIME kerneltime,   /* [out] Time thread spent in kernel mode */
743     LPFILETIME usertime)     /* [out] Time thread spent in user mode */
744 {
745     FIXME("(0x%08x): stub\n",thread);
746     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
747     return FALSE;
748 }
749
750
751 /**********************************************************************
752  * AttachThreadInput [KERNEL32.8]  Attaches input of 1 thread to other
753  *
754  * Attaches the input processing mechanism of one thread to that of
755  * another thread.
756  *
757  * RETURNS
758  *    Success: TRUE
759  *    Failure: FALSE
760  *
761  * TODO:
762  *    1. Reset the Key State (currenly per thread key state is not maintained)
763  */
764 BOOL WINAPI AttachThreadInput( 
765     DWORD idAttach,   /* [in] Thread to attach */
766     DWORD idAttachTo, /* [in] Thread to attach to */
767     BOOL fAttach)   /* [in] Attach or detach */
768 {
769     MESSAGEQUEUE *pSrcMsgQ = 0, *pTgtMsgQ = 0;
770     BOOL16 bRet = 0;
771
772     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
773
774     /* A thread cannot attach to itself */
775     if ( idAttach == idAttachTo )
776         goto CLEANUP;
777
778     /* According to the docs this method should fail if a
779      * "Journal record" hook is installed. (attaches all input queues together)
780      */
781     if ( HOOK_IsHooked( WH_JOURNALRECORD ) )
782         goto CLEANUP;
783         
784     /* Retrieve message queues corresponding to the thread id's */
785     pTgtMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetThreadQueue16( idAttach ) );
786     pSrcMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetThreadQueue16( idAttachTo ) );
787
788     /* Ensure we have message queues and that Src and Tgt threads
789      * are not system threads.
790      */
791     if ( !pSrcMsgQ || !pTgtMsgQ || !pSrcMsgQ->pQData || !pTgtMsgQ->pQData )
792         goto CLEANUP;
793
794     if (fAttach)   /* Attach threads */
795     {
796         /* Only attach if currently detached  */
797         if ( pTgtMsgQ->pQData != pSrcMsgQ->pQData )
798         {
799             /* First release the target threads perQData */
800             PERQDATA_Release( pTgtMsgQ->pQData );
801         
802             /* Share a reference to the source threads perQDATA */
803             PERQDATA_Addref( pSrcMsgQ->pQData );
804             pTgtMsgQ->pQData = pSrcMsgQ->pQData;
805         }
806     }
807     else    /* Detach threads */
808     {
809         /* Only detach if currently attached */
810         if ( pTgtMsgQ->pQData == pSrcMsgQ->pQData )
811         {
812             /* First release the target threads perQData */
813             PERQDATA_Release( pTgtMsgQ->pQData );
814         
815             /* Give the target thread its own private perQDATA once more */
816             pTgtMsgQ->pQData = PERQDATA_CreateInstance();
817         }
818     }
819
820     /* TODO: Reset the Key State */
821
822     bRet = 1;      /* Success */
823     
824 CLEANUP:
825
826     /* Unlock the queues before returning */
827     if ( pSrcMsgQ )
828         QUEUE_Unlock( pSrcMsgQ );
829     if ( pTgtMsgQ )
830         QUEUE_Unlock( pTgtMsgQ );
831     
832     return bRet;
833 }
834
835 /**********************************************************************
836  * VWin32_BoostThreadGroup [KERNEL.535]
837  */
838 VOID WINAPI VWin32_BoostThreadGroup( DWORD threadId, INT boost )
839 {
840     FIXME("(0x%08lx,%d): stub\n", threadId, boost);
841 }
842
843 /**********************************************************************
844  * VWin32_BoostThreadStatic [KERNEL.536]
845  */
846 VOID WINAPI VWin32_BoostThreadStatic( DWORD threadId, INT boost )
847 {
848     FIXME("(0x%08lx,%d): stub\n", threadId, boost);
849 }
850
851
852 /***********************************************************************
853  *           GetThreadLocale    (KERNEL32.295)
854  */
855 LCID WINAPI GetThreadLocale(void)
856 {
857     return NtCurrentTeb()->CurrentLocale;
858 }
859
860
861 /**********************************************************************
862  * SetThreadLocale [KERNEL32.671]  Sets the calling threads current locale.
863  *
864  * RETURNS
865  *    Success: TRUE
866  *    Failure: FALSE
867  *
868  * FIXME
869  *  check if lcid is a valid cp
870  */
871 BOOL WINAPI SetThreadLocale(
872     LCID lcid)     /* [in] Locale identifier */
873 {
874     switch (lcid)
875     {
876       case LOCALE_SYSTEM_DEFAULT:
877         lcid = GetSystemDefaultLCID();
878         break;
879       case LOCALE_USER_DEFAULT:
880       case LOCALE_NEUTRAL:
881         lcid = GetUserDefaultLCID();
882         break;
883     }
884     NtCurrentTeb()->CurrentLocale = lcid;
885     return TRUE;
886 }
887
888
889 /***********************************************************************
890  * GetCurrentThread [KERNEL32.200]  Gets pseudohandle for current thread
891  *
892  * RETURNS
893  *    Pseudohandle for the current thread
894  */
895 #undef GetCurrentThread
896 HANDLE WINAPI GetCurrentThread(void)
897 {
898     return 0xfffffffe;
899 }
900
901
902 #ifdef __i386__
903
904 /* void WINAPI SetLastError( DWORD error ); */
905 __ASM_GLOBAL_FUNC( SetLastError,
906                    "movl 4(%esp),%eax\n\t"
907                    ".byte 0x64\n\t"
908                    "movl %eax,0x60\n\t"
909                    "ret $4" );
910
911 /* DWORD WINAPI GetLastError(void); */
912 __ASM_GLOBAL_FUNC( GetLastError, ".byte 0x64\n\tmovl 0x60,%eax\n\tret" );
913
914 /* DWORD WINAPI GetCurrentProcessId(void) */
915 __ASM_GLOBAL_FUNC( GetCurrentProcessId, ".byte 0x64\n\tmovl 0x20,%eax\n\tret" );
916                    
917 /* DWORD WINAPI GetCurrentThreadId(void) */
918 __ASM_GLOBAL_FUNC( GetCurrentThreadId, ".byte 0x64\n\tmovl 0x24,%eax\n\tret" );
919                    
920 #else  /* __i386__ */
921
922 /**********************************************************************
923  * SetLastError [KERNEL.147] [KERNEL32.497]  Sets the last-error code.
924  */
925 void WINAPI SetLastError( DWORD error ) /* [in] Per-thread error code */
926 {
927     NtCurrentTeb()->last_error = error;
928 }
929
930 /**********************************************************************
931  * GetLastError [KERNEL.148] [KERNEL32.227]  Returns last-error code.
932  */
933 DWORD WINAPI GetLastError(void)
934 {
935     return NtCurrentTeb()->last_error;
936 }
937
938 /***********************************************************************
939  * GetCurrentProcessId [KERNEL32.199]  Returns process identifier.
940  */
941 DWORD WINAPI GetCurrentProcessId(void)
942 {
943     return (DWORD)NtCurrentTeb()->pid;
944 }
945
946 /***********************************************************************
947  * GetCurrentThreadId [KERNEL32.201]  Returns thread identifier.
948  */
949 DWORD WINAPI GetCurrentThreadId(void)
950 {
951     return (DWORD)NtCurrentTeb()->tid;
952 }
953
954 #endif  /* __i386__ */