Moved a few more functions to the dlls/kernel directory.
[wine] / dlls / ntdll / thread.c
1 /*
2  * NT threads support
3  *
4  * Copyright 1996, 2003 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "ntstatus.h"
22 #include "thread.h"
23 #include "winternl.h"
24 #include "wine/server.h"
25 #include "wine/debug.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(thread);
28
29
30 /***********************************************************************
31  *              NtOpenThread   (NTDLL.@)
32  *              ZwOpenThread   (NTDLL.@)
33  */
34 NTSTATUS WINAPI NtOpenThread( HANDLE *handle, ACCESS_MASK access,
35                               const OBJECT_ATTRIBUTES *attr, const CLIENT_ID *id )
36 {
37     NTSTATUS ret;
38
39     SERVER_START_REQ( open_thread )
40     {
41         req->tid     = (thread_id_t)id->UniqueThread;
42         req->access  = access;
43         req->inherit = attr && (attr->Attributes & OBJ_INHERIT);
44         ret = wine_server_call( req );
45         *handle = reply->handle;
46     }
47     SERVER_END_REQ;
48     return ret;
49 }
50
51
52 /******************************************************************************
53  *              NtSuspendThread   (NTDLL.@)
54  *              ZwSuspendThread   (NTDLL.@)
55  */
56 NTSTATUS WINAPI NtSuspendThread( HANDLE handle, PULONG count )
57 {
58     NTSTATUS ret;
59
60     SERVER_START_REQ( suspend_thread )
61     {
62         req->handle = handle;
63         if (!(ret = wine_server_call( req ))) *count = reply->count;
64     }
65     SERVER_END_REQ;
66     return ret;
67 }
68
69
70 /******************************************************************************
71  *              NtResumeThread   (NTDLL.@)
72  *              ZwResumeThread   (NTDLL.@)
73  */
74 NTSTATUS WINAPI NtResumeThread( HANDLE handle, PULONG count )
75 {
76     NTSTATUS ret;
77
78     SERVER_START_REQ( resume_thread )
79     {
80         req->handle = handle;
81         if (!(ret = wine_server_call( req ))) *count = reply->count;
82     }
83     SERVER_END_REQ;
84     return ret;
85 }
86
87
88 /******************************************************************************
89  *              NtTerminateThread  (NTDLL.@)
90  *              ZwTerminateThread  (NTDLL.@)
91  */
92 NTSTATUS WINAPI NtTerminateThread( HANDLE handle, LONG exit_code )
93 {
94     NTSTATUS ret;
95     BOOL self, last;
96
97     SERVER_START_REQ( terminate_thread )
98     {
99         req->handle    = handle;
100         req->exit_code = exit_code;
101         ret = wine_server_call( req );
102         self = !ret && reply->self;
103         last = reply->last;
104     }
105     SERVER_END_REQ;
106
107     if (self)
108     {
109         if (last) exit( exit_code );
110         else
111         {
112             RtlAcquirePebLock();
113             RemoveEntryList( &NtCurrentTeb()->TlsLinks );
114             RtlReleasePebLock();
115             SYSDEPS_ExitThread( exit_code );
116         }
117     }
118     return ret;
119 }
120
121
122 /******************************************************************************
123  *              NtQueueApcThread  (NTDLL.@)
124  */
125 NTSTATUS WINAPI NtQueueApcThread( HANDLE handle, PNTAPCFUNC func, ULONG_PTR arg1,
126                                   ULONG_PTR arg2, ULONG_PTR arg3 )
127 {
128     NTSTATUS ret;
129     SERVER_START_REQ( queue_apc )
130     {
131         req->handle = handle;
132         req->user   = 1;
133         req->func   = func;
134         req->arg1   = (void *)arg1;
135         req->arg2   = (void *)arg2;
136         req->arg3   = (void *)arg3;
137         ret = wine_server_call( req );
138     }
139     SERVER_END_REQ;
140     return ret;
141 }
142
143
144 /***********************************************************************
145  *              NtSetContextThread  (NTDLL.@)
146  *              ZwSetContextThread  (NTDLL.@)
147  */
148 NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
149 {
150     NTSTATUS ret;
151
152     SERVER_START_REQ( set_thread_context )
153     {
154         req->handle = handle;
155         req->flags  = context->ContextFlags;
156         wine_server_add_data( req, context, sizeof(*context) );
157         ret = wine_server_call( req );
158     }
159     SERVER_END_REQ;
160     return ret;
161 }
162
163
164 /***********************************************************************
165  *              NtGetContextThread  (NTDLL.@)
166  *              ZwGetContextThread  (NTDLL.@)
167  */
168 NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
169 {
170     NTSTATUS ret;
171
172     SERVER_START_REQ( get_thread_context )
173     {
174         req->handle = handle;
175         req->flags = context->ContextFlags;
176         wine_server_add_data( req, context, sizeof(*context) );
177         wine_server_set_reply( req, context, sizeof(*context) );
178         ret = wine_server_call( req );
179     }
180     SERVER_END_REQ;
181     return ret;
182 }
183
184
185 /******************************************************************************
186  *              NtQueryInformationThread  (NTDLL.@)
187  *              ZwQueryInformationThread  (NTDLL.@)
188  */
189 NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class,
190                                           void *data, ULONG length, ULONG *ret_len )
191 {
192     NTSTATUS status;
193
194     switch(class)
195     {
196     case ThreadBasicInformation:
197         {
198             THREAD_BASIC_INFORMATION info;
199
200             SERVER_START_REQ( get_thread_info )
201             {
202                 req->handle = handle;
203                 req->tid_in = 0;
204                 if (!(status = wine_server_call( req )))
205                 {
206                     info.ExitStatus             = reply->exit_code;
207                     info.TebBaseAddress         = reply->teb;
208                     info.ClientId.UniqueProcess = (HANDLE)reply->pid;
209                     info.ClientId.UniqueThread  = (HANDLE)reply->tid;
210                     info.AffinityMask           = reply->affinity;
211                     info.Priority               = reply->priority;
212                     info.BasePriority           = reply->priority;  /* FIXME */
213                 }
214             }
215             SERVER_END_REQ;
216             if (status == STATUS_SUCCESS)
217             {
218                 if (data) memcpy( data, &info, min( length, sizeof(info) ));
219                 if (ret_len) *ret_len = min( length, sizeof(info) );
220             }
221         }
222         return status;
223     case ThreadTimes:
224     case ThreadPriority:
225     case ThreadBasePriority:
226     case ThreadAffinityMask:
227     case ThreadImpersonationToken:
228     case ThreadDescriptorTableEntry:
229     case ThreadEnableAlignmentFaultFixup:
230     case ThreadEventPair_Reusable:
231     case ThreadQuerySetWin32StartAddress:
232     case ThreadZeroTlsCell:
233     case ThreadPerformanceCount:
234     case ThreadAmILastThread:
235     case ThreadIdealProcessor:
236     case ThreadPriorityBoost:
237     case ThreadSetTlsArrayAddress:
238     case ThreadIsIoPending:
239     default:
240         FIXME( "info class %d not supported yet\n", class );
241         return STATUS_NOT_IMPLEMENTED;
242     }
243 }
244
245
246 /******************************************************************************
247  *              NtSetInformationThread  (NTDLL.@)
248  *              ZwSetInformationThread  (NTDLL.@)
249  */
250 NTSTATUS WINAPI NtSetInformationThread( HANDLE handle, THREADINFOCLASS class,
251                                         LPCVOID data, ULONG length )
252 {
253     switch(class)
254     {
255     case ThreadZeroTlsCell:
256         if (handle == GetCurrentThread())
257         {
258             LIST_ENTRY *entry = &NtCurrentTeb()->TlsLinks;
259             DWORD index;
260
261             if (length != sizeof(DWORD)) return STATUS_INVALID_PARAMETER;
262             index = *(DWORD *)data;
263             if (index >= 64) return STATUS_INVALID_PARAMETER;
264             RtlAcquirePebLock();
265             do
266             {
267                 TEB *teb = CONTAINING_RECORD(entry, TEB, TlsLinks);
268                 teb->TlsSlots[index] = 0;
269                 entry = entry->Flink;
270             } while (entry != &NtCurrentTeb()->TlsLinks);
271             RtlReleasePebLock();
272             return STATUS_SUCCESS;
273         }
274         FIXME( "ZeroTlsCell not supported on other threads\n" );
275         return STATUS_NOT_IMPLEMENTED;
276
277     case ThreadBasicInformation:
278     case ThreadTimes:
279     case ThreadPriority:
280     case ThreadBasePriority:
281     case ThreadAffinityMask:
282     case ThreadImpersonationToken:
283     case ThreadDescriptorTableEntry:
284     case ThreadEnableAlignmentFaultFixup:
285     case ThreadEventPair_Reusable:
286     case ThreadQuerySetWin32StartAddress:
287     case ThreadPerformanceCount:
288     case ThreadAmILastThread:
289     case ThreadIdealProcessor:
290     case ThreadPriorityBoost:
291     case ThreadSetTlsArrayAddress:
292     case ThreadIsIoPending:
293     default:
294         FIXME( "info class %d not supported yet\n", class );
295         return STATUS_NOT_IMPLEMENTED;
296     }
297 }