branch update for HEAD-2003050101
[reactos.git] / ntoskrnl / ps / tinfo.c
1 /* $Id$
2  *
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PROJECT:         ReactOS kernel
5  * FILE:            ntoskrnl/ps/tinfo.c
6  * PURPOSE:         Getting/setting thread information
7  * PROGRAMMER:      David Welch (welch@mcmail.com)
8  * UPDATE HISTORY:
9  *                  Created 22/05/98
10  */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <internal/ps.h>
16 #include <internal/safe.h>
17
18 #include <internal/debug.h>
19
20 /* FUNCTIONS *****************************************************************/
21
22 NTSTATUS STDCALL 
23 NtSetInformationThread(HANDLE           ThreadHandle,
24                        THREADINFOCLASS  ThreadInformationClass,
25                        PVOID            ThreadInformation,
26                        ULONG ThreadInformationLength)
27 {
28    PETHREAD                     Thread;
29    NTSTATUS                     Status;
30    
31    Status = ObReferenceObjectByHandle(ThreadHandle,
32                                       THREAD_SET_INFORMATION,
33                                       PsThreadType,
34                                       ExGetPreviousMode(),
35                                       (PVOID*)&Thread,
36                                       NULL);
37    if (!NT_SUCCESS(Status))
38      {
39         return Status;
40      }
41    
42    switch (ThreadInformationClass)
43      {
44       case ThreadBasicInformation:
45         /* Can only be queried */
46         Status = STATUS_INVALID_INFO_CLASS;
47         break;
48         
49       case ThreadTimes:
50         /* Can only be queried */
51         Status = STATUS_INVALID_INFO_CLASS;
52         break;
53         
54       case ThreadPriority:
55           {
56             KPRIORITY Priority;
57             
58             if (ThreadInformationLength != sizeof(KPRIORITY))
59               {
60                 Status = STATUS_INFO_LENGTH_MISMATCH;
61                 break;
62               }
63             Priority = *(KPRIORITY*)ThreadInformation;
64             if (Priority < LOW_PRIORITY || Priority >= MAXIMUM_PRIORITY)
65               {
66                 Status = STATUS_INVALID_PARAMETER;
67                 break;
68               }
69             KeSetPriorityThread(&Thread->Tcb, Priority);
70             Status = STATUS_SUCCESS;
71             break;
72           }
73         
74       case ThreadBasePriority:
75         if (ThreadInformationLength != sizeof(ULONG))
76           {
77             Status = STATUS_INFO_LENGTH_MISMATCH;
78             break;
79           }
80         Status = MmCopyFromCaller(&(Thread->Tcb.BasePriority),
81                                   ThreadInformation,
82                                   sizeof(ULONG));
83         break;
84         
85       case ThreadAffinityMask:
86         Thread->Tcb.UserAffinity = *((PULONG)ThreadInformation);
87         break;
88         
89       case ThreadImpersonationToken:
90         {
91           HANDLE TokenHandle;
92
93           if (ThreadInformationLength != sizeof(HANDLE))
94             {
95               Status = STATUS_INFO_LENGTH_MISMATCH;
96               break;
97             }
98           TokenHandle = *((PHANDLE)ThreadInformation);
99           Status = PsAssignImpersonationToken(Thread, TokenHandle);
100           break;
101         }
102         
103       case ThreadDescriptorTableEntry:
104         /* Can only be queried */
105         Status = STATUS_INVALID_INFO_CLASS;
106         break;
107         
108       case ThreadEventPair:
109         Status = STATUS_NOT_IMPLEMENTED;
110         break;
111         
112       case ThreadQuerySetWin32StartAddress:
113         if (ThreadInformationLength != sizeof(ULONG))
114           {
115             Status = STATUS_INFO_LENGTH_MISMATCH;
116             break;
117           }
118         Thread->u2.Win32StartAddress = (PVOID)*((PULONG)ThreadInformation);
119         Status = STATUS_SUCCESS;
120         break;
121                 
122       case ThreadZeroTlsCell:
123         {
124           Status = STATUS_NOT_IMPLEMENTED;
125           break;
126         }
127         
128       case ThreadPerformanceCount:
129         /* Can only be queried */
130         Status = STATUS_INVALID_INFO_CLASS;
131         break;
132         
133       case ThreadAmILastThread:
134         /* Can only be queried */
135         Status = STATUS_INVALID_INFO_CLASS;
136         break;
137         
138      case ThreadIdealProcessor:
139        Status = STATUS_NOT_IMPLEMENTED;
140        break;
141        
142      case ThreadPriorityBoost:
143        Status = STATUS_NOT_IMPLEMENTED;
144        break;
145         
146      case ThreadSetTlsArrayAddress:
147        Status = STATUS_NOT_IMPLEMENTED;
148        break;
149
150      case ThreadIsIoPending:
151        /* Can only be queried */
152        Status = STATUS_INVALID_INFO_CLASS;
153        break;
154
155      case ThreadHideFromDebugger:
156        Status = STATUS_NOT_IMPLEMENTED;
157        break;
158
159       default:
160         Status = STATUS_UNSUCCESSFUL;
161      }
162    ObDereferenceObject(Thread);
163    return Status;
164 }
165
166
167 NTSTATUS STDCALL
168 NtQueryInformationThread (IN    HANDLE          ThreadHandle,
169                           IN    THREADINFOCLASS ThreadInformationClass,
170                           OUT   PVOID           ThreadInformation,
171                           IN    ULONG           ThreadInformationLength,
172                           OUT   PULONG          ReturnLength)
173 {
174    PETHREAD Thread;
175    NTSTATUS Status;
176
177    Status = ObReferenceObjectByHandle(ThreadHandle,
178                                       THREAD_QUERY_INFORMATION,
179                                       PsThreadType,
180                                       ExGetPreviousMode(),
181                                       (PVOID*)&Thread,
182                                       NULL);
183    if (!NT_SUCCESS(Status))
184      {
185         return Status;
186      }
187
188    switch (ThreadInformationClass)
189      {
190      case ThreadBasicInformation:
191        {
192          PTHREAD_BASIC_INFORMATION TBI;
193          
194          TBI = (PTHREAD_BASIC_INFORMATION)ThreadInformation;
195          
196          if (ThreadInformationLength != sizeof(THREAD_BASIC_INFORMATION))
197            {
198              Status = STATUS_INFO_LENGTH_MISMATCH;
199              break;
200            }
201          
202          TBI->ExitStatus = Thread->ExitStatus;
203          TBI->TebBaseAddress = Thread->Tcb.Teb;
204          TBI->ClientId = Thread->Cid;
205          TBI->AffinityMask = Thread->Tcb.Affinity;
206          TBI->Priority = Thread->Tcb.Priority;
207          TBI->BasePriority = Thread->Tcb.BasePriority;
208          Status = STATUS_SUCCESS;
209          break;
210        }
211        
212      case ThreadTimes:
213        Status = STATUS_NOT_IMPLEMENTED;
214        break;
215        
216      case ThreadPriority:
217        /* Can be set only */
218        Status = STATUS_INVALID_INFO_CLASS;
219        break;
220        
221      case ThreadBasePriority:
222        /* Can be set only */
223        Status = STATUS_INVALID_INFO_CLASS;
224        break;
225        
226      case ThreadAffinityMask:
227        /* Can be set only */
228        Status = STATUS_INVALID_INFO_CLASS;
229        break;
230
231      case ThreadImpersonationToken:
232        /* Can be set only */
233        Status = STATUS_INVALID_INFO_CLASS;
234        break;
235        
236      case ThreadDescriptorTableEntry:
237        /* Nebbett says nothing about this */
238        Status = STATUS_NOT_IMPLEMENTED;
239        break;
240
241      case ThreadEnableAlignmentFaultFixup:
242        /* Can be set only */
243        Status = STATUS_INVALID_INFO_CLASS;
244        break;
245        
246      case ThreadEventPair:
247        /* Can be set only */
248        Status = STATUS_INVALID_INFO_CLASS;
249        break;
250
251      case ThreadQuerySetWin32StartAddress:
252        if (ThreadInformationLength != sizeof(PVOID))
253          {
254            Status = STATUS_INFO_LENGTH_MISMATCH;
255            break;
256          }
257        *((PVOID*)ThreadInformation) = Thread->u2.Win32StartAddress;
258        Status = STATUS_SUCCESS;
259        break;
260
261      case ThreadZeroTlsCell:
262        /* Can only be set */
263        Status = STATUS_INVALID_INFO_CLASS;
264        break;
265
266      case ThreadPerformanceCount:
267        /* Nebbett says this class is always zero */
268        if (ThreadInformationLength != sizeof(LARGE_INTEGER))
269          {
270            Status = STATUS_INFO_LENGTH_MISMATCH;
271            break;
272          }
273        ((PLARGE_INTEGER)ThreadInformation)->QuadPart = 0;
274        Status = STATUS_SUCCESS;
275        break;
276
277      case ThreadAmILastThread:
278        {
279          if (ThreadInformationLength != sizeof(BOOLEAN))
280            {
281              Status = STATUS_INFO_LENGTH_MISMATCH;
282              break;
283            }
284          if (Thread->ThreadsProcess->ThreadListHead.Flink->Flink ==
285              &Thread->ThreadsProcess->ThreadListHead)
286            {
287              *((PBOOLEAN)ThreadInformation) = TRUE;
288            }
289          else
290            {
291              *((PBOOLEAN)ThreadInformation) = FALSE;
292            }
293          Status = STATUS_SUCCESS;
294          break;
295        }
296
297      case ThreadIdealProcessor:
298        /* Can only be set */
299        Status = STATUS_INFO_LENGTH_MISMATCH;
300        break;
301
302      case ThreadPriorityBoost:
303        Status = STATUS_NOT_IMPLEMENTED;
304        break;
305
306      case ThreadSetTlsArrayAddress:
307        /* Can only be set */
308        Status = STATUS_INVALID_INFO_CLASS;
309        break;
310
311      case ThreadIsIoPending:
312        Status = STATUS_NOT_IMPLEMENTED;
313        break;
314        
315      case ThreadHideFromDebugger:
316        /* Can only be set */
317        Status = STATUS_INVALID_INFO_CLASS;
318        break;
319
320       default:
321         Status = STATUS_INVALID_INFO_CLASS;
322      }
323    ObDereferenceObject(Thread);
324    return(Status);
325 }
326
327 VOID KeSetPreviousMode(ULONG Mode)
328 {
329    PsGetCurrentThread()->Tcb.PreviousMode = Mode;
330 }
331
332 ULONG STDCALL
333 KeGetPreviousMode (VOID)
334 {
335    return (ULONG)PsGetCurrentThread()->Tcb.PreviousMode;
336 }
337
338 ULONG STDCALL
339 ExGetPreviousMode (VOID)
340 {
341    return (ULONG)PsGetCurrentThread()->Tcb.PreviousMode;
342 }
343
344 /* EOF */