2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ps/query.c
5 * PURPOSE: Process Manager: Thread/Process Query/Set Information
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 * Thomas Weidenmueller (w3seek@reactos.org)
10 /* INCLUDES ******************************************************************/
16 /* Include Information Class Tables */
17 #include "internal/ps_i.h"
20 ULONG PspTraceLevel
= 0;
22 /* PRIVATE FUNCTIONS *********************************************************/
26 PsReferenceProcessFilePointer(IN PEPROCESS Process
,
27 OUT PFILE_OBJECT
*FileObject
)
32 /* Lock the process */
33 ExAcquireRundownProtection(&Process
->RundownProtect
);
36 Section
= Process
->SectionObject
;
39 /* Get the file object and reference it */
40 *FileObject
= MmGetFileObjectForSection((PVOID
)Section
);
41 ObReferenceObject(*FileObject
);
44 /* Release the protection */
45 ExReleaseRundownProtection(&Process
->RundownProtect
);
48 return Section
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
;
51 /* PUBLIC FUNCTIONS **********************************************************/
58 NtQueryInformationProcess(IN HANDLE ProcessHandle
,
59 IN PROCESSINFOCLASS ProcessInformationClass
,
60 OUT PVOID ProcessInformation
,
61 IN ULONG ProcessInformationLength
,
62 OUT PULONG ReturnLength OPTIONAL
)
65 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
66 NTSTATUS Status
= STATUS_SUCCESS
;
68 PPROCESS_BASIC_INFORMATION ProcessBasicInfo
=
69 (PPROCESS_BASIC_INFORMATION
)ProcessInformation
;
70 PKERNEL_USER_TIMES ProcessTime
= (PKERNEL_USER_TIMES
)ProcessInformation
;
71 PPROCESS_PRIORITY_CLASS PsPriorityClass
= (PPROCESS_PRIORITY_CLASS
)ProcessInformation
;
73 PPROCESS_SESSION_INFORMATION SessionInfo
=
74 (PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
75 PVM_COUNTERS VmCounters
= (PVM_COUNTERS
)ProcessInformation
;
76 PIO_COUNTERS IoCounters
= (PIO_COUNTERS
)ProcessInformation
;
77 PQUOTA_LIMITS QuotaLimits
= (PQUOTA_LIMITS
)ProcessInformation
;
78 PROCESS_DEVICEMAP_INFORMATION DeviceMap
;
79 PUNICODE_STRING ImageName
;
83 /* Check for user-mode caller */
84 if (PreviousMode
!= KernelMode
)
86 /* Prepare to probe parameters */
89 ProbeForWrite(ProcessInformation
,
90 ProcessInformationLength
,
92 if (ReturnLength
) ProbeForWriteUlong(ReturnLength
);
94 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
96 /* Get the error code */
97 Status
= _SEH2_GetExceptionCode();
100 if(!NT_SUCCESS(Status
)) return Status
;
103 if((ProcessInformationClass
== ProcessCookie
) &&
104 (ProcessHandle
!= NtCurrentProcess()))
107 * Retreiving the process cookie is only allowed for the calling process
108 * itself! XP only allowes NtCurrentProcess() as process handles even if
109 * a real handle actually represents the current process.
111 return STATUS_INVALID_PARAMETER
;
114 /* Check the information class */
115 switch (ProcessInformationClass
)
117 /* Basic process information */
118 case ProcessBasicInformation
:
120 /* Set return length */
121 Length
= sizeof(PROCESS_BASIC_INFORMATION
);
123 if (ProcessInformationLength
!= Length
)
125 Status
= STATUS_INFO_LENGTH_MISMATCH
;
129 /* Reference the process */
130 Status
= ObReferenceObjectByHandle(ProcessHandle
,
131 PROCESS_QUERY_INFORMATION
,
136 if (!NT_SUCCESS(Status
)) break;
138 /* Protect writes with SEH */
141 /* Write all the information from the EPROCESS/KPROCESS */
142 ProcessBasicInfo
->ExitStatus
= Process
->ExitStatus
;
143 ProcessBasicInfo
->PebBaseAddress
= Process
->Peb
;
144 ProcessBasicInfo
->AffinityMask
= Process
->Pcb
.Affinity
;
145 ProcessBasicInfo
->UniqueProcessId
= (ULONG_PTR
)Process
->
147 ProcessBasicInfo
->InheritedFromUniqueProcessId
=
148 (ULONG
)Process
->InheritedFromUniqueProcessId
;
149 ProcessBasicInfo
->BasePriority
= Process
->Pcb
.BasePriority
;
152 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
154 /* Get exception code */
155 Status
= _SEH2_GetExceptionCode();
159 /* Dereference the process */
160 ObDereferenceObject(Process
);
163 /* Process quota limits */
164 case ProcessQuotaLimits
:
166 Length
= sizeof(QUOTA_LIMITS
);
167 if (ProcessInformationLength
!= Length
)
169 Status
= STATUS_INFO_LENGTH_MISMATCH
;
173 /* Reference the process */
174 Status
= ObReferenceObjectByHandle(ProcessHandle
,
175 PROCESS_QUERY_INFORMATION
,
180 if (!NT_SUCCESS(Status
)) break;
182 /* Indicate success */
183 Status
= STATUS_SUCCESS
;
187 /* Set max/min working set sizes */
188 QuotaLimits
->MaximumWorkingSetSize
=
189 Process
->Vm
.MaximumWorkingSetSize
<< PAGE_SHIFT
;
190 QuotaLimits
->MinimumWorkingSetSize
=
191 Process
->Vm
.MinimumWorkingSetSize
<< PAGE_SHIFT
;
193 /* Set default time limits */
194 QuotaLimits
->TimeLimit
.LowPart
= (ULONG
)-1;
195 QuotaLimits
->TimeLimit
.HighPart
= (ULONG
)-1;
197 /* Is quota block a default one? */
198 if (Process
->QuotaBlock
== &PspDefaultQuotaBlock
)
200 /* Set default pools and pagefile limits */
201 QuotaLimits
->PagedPoolLimit
= (SIZE_T
)-1;
202 QuotaLimits
->NonPagedPoolLimit
= (SIZE_T
)-1;
203 QuotaLimits
->PagefileLimit
= (SIZE_T
)-1;
207 /* Get limits from non-default quota block */
208 QuotaLimits
->PagedPoolLimit
=
209 Process
->QuotaBlock
->QuotaEntry
[PagedPool
].Limit
;
210 QuotaLimits
->NonPagedPoolLimit
=
211 Process
->QuotaBlock
->QuotaEntry
[NonPagedPool
].Limit
;
212 QuotaLimits
->PagefileLimit
=
213 Process
->QuotaBlock
->QuotaEntry
[2].Limit
;
216 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
218 /* Get exception code */
219 Status
= _SEH2_GetExceptionCode();
223 /* Dereference the process */
224 ObDereferenceObject(Process
);
227 case ProcessIoCounters
:
229 Length
= sizeof(IO_COUNTERS
);
230 if (ProcessInformationLength
!= Length
)
232 Status
= STATUS_INFO_LENGTH_MISMATCH
;
236 /* Reference the process */
237 Status
= ObReferenceObjectByHandle(ProcessHandle
,
238 PROCESS_QUERY_INFORMATION
,
243 if (!NT_SUCCESS(Status
)) break;
247 IoCounters
->ReadOperationCount
= Process
->ReadOperationCount
.QuadPart
;
248 IoCounters
->ReadTransferCount
= Process
->ReadTransferCount
.QuadPart
;
249 IoCounters
->WriteOperationCount
= Process
->WriteOperationCount
.QuadPart
;
250 IoCounters
->WriteTransferCount
= Process
->WriteTransferCount
.QuadPart
;
251 IoCounters
->OtherOperationCount
= Process
->OtherOperationCount
.QuadPart
;
252 IoCounters
->OtherTransferCount
= Process
->OtherTransferCount
.QuadPart
;
254 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
256 /* Ignore exception */
260 /* Set status to success in any case */
261 Status
= STATUS_SUCCESS
;
263 /* Dereference the process */
264 ObDereferenceObject(Process
);
270 /* Set the return length */
271 Length
= sizeof(KERNEL_USER_TIMES
);
273 if (ProcessInformationLength
!= Length
)
275 Status
= STATUS_INFO_LENGTH_MISMATCH
;
279 /* Reference the process */
280 Status
= ObReferenceObjectByHandle(ProcessHandle
,
281 PROCESS_QUERY_INFORMATION
,
286 if (!NT_SUCCESS(Status
)) break;
288 /* Protect writes with SEH */
291 /* Copy time information from EPROCESS/KPROCESS */
292 ProcessTime
->CreateTime
= Process
->CreateTime
;
293 ProcessTime
->UserTime
.QuadPart
= Process
->Pcb
.UserTime
*
295 ProcessTime
->KernelTime
.QuadPart
= Process
->Pcb
.KernelTime
*
297 ProcessTime
->ExitTime
= Process
->ExitTime
;
299 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
301 /* Get exception code */
302 Status
= _SEH2_GetExceptionCode();
306 /* Dereference the process */
307 ObDereferenceObject(Process
);
310 /* Process Debug Port */
311 case ProcessDebugPort
:
313 /* Set return length */
314 Length
= sizeof(HANDLE
);
316 if (ProcessInformationLength
!= Length
)
318 Status
= STATUS_INFO_LENGTH_MISMATCH
;
322 /* Reference the process */
323 Status
= ObReferenceObjectByHandle(ProcessHandle
,
324 PROCESS_QUERY_INFORMATION
,
329 if (!NT_SUCCESS(Status
)) break;
331 /* Protect write with SEH */
334 /* Return whether or not we have a debug port */
335 *(PHANDLE
)ProcessInformation
= (Process
->DebugPort
?
338 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
340 /* Get exception code */
341 Status
= _SEH2_GetExceptionCode();
345 /* Dereference the process */
346 ObDereferenceObject(Process
);
349 /* LDT, WS and VDM Information: not implemented */
350 case ProcessLdtInformation
:
351 case ProcessWorkingSetWatch
:
352 case ProcessWx86Information
:
354 /* Reference the process */
355 Status
= ObReferenceObjectByHandle(ProcessHandle
,
356 PROCESS_QUERY_INFORMATION
,
361 if (!NT_SUCCESS(Status
)) break;
363 DPRINT1("Not implemented: %lx\n", ProcessInformationClass
);
365 /* Dereference the process */
366 ObDereferenceObject(Process
);
367 Status
= STATUS_NOT_IMPLEMENTED
;
370 case ProcessHandleCount
:
372 /* Set the return length*/
373 Length
= sizeof(ULONG
);
375 if (ProcessInformationLength
!= Length
)
377 Status
= STATUS_INFO_LENGTH_MISMATCH
;
381 /* Reference the process */
382 Status
= ObReferenceObjectByHandle(ProcessHandle
,
383 PROCESS_QUERY_INFORMATION
,
388 if (!NT_SUCCESS(Status
)) break;
390 /* Count the number of handles this process has */
391 HandleCount
= ObGetProcessHandleCount(Process
);
393 /* Protect write in SEH */
396 /* Return the count of handles */
397 *(PULONG
)ProcessInformation
= HandleCount
;
399 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
401 /* Get the exception code */
402 Status
= _SEH2_GetExceptionCode();
406 /* Dereference the process */
407 ObDereferenceObject(Process
);
410 /* Session ID for the process */
411 case ProcessSessionInformation
:
413 /* Set the return length*/
414 Length
= sizeof(PROCESS_SESSION_INFORMATION
);
416 if (ProcessInformationLength
!= Length
)
418 Status
= STATUS_INFO_LENGTH_MISMATCH
;
422 /* Reference the process */
423 Status
= ObReferenceObjectByHandle(ProcessHandle
,
424 PROCESS_QUERY_INFORMATION
,
429 if (!NT_SUCCESS(Status
)) break;
431 /* Enter SEH for write safety */
434 /* Write back the Session ID */
435 SessionInfo
->SessionId
= Process
->Session
;
437 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
439 /* Get the exception code */
440 Status
= _SEH2_GetExceptionCode();
444 /* Dereference the process */
445 ObDereferenceObject(Process
);
448 /* WOW64: Not implemented */
449 case ProcessWow64Information
:
450 Status
= STATUS_NOT_IMPLEMENTED
;
453 /* Virtual Memory Statistics */
454 case ProcessVmCounters
:
456 /* Set the return length */
457 Length
= sizeof(VM_COUNTERS
);
459 if (ProcessInformationLength
!= Length
)
461 Status
= STATUS_INFO_LENGTH_MISMATCH
;
465 /* Reference the process */
466 Status
= ObReferenceObjectByHandle(ProcessHandle
,
467 PROCESS_QUERY_INFORMATION
,
472 if (!NT_SUCCESS(Status
)) break;
474 /* Enter SEH for write safety */
477 /* Return data from EPROCESS */
478 VmCounters
->PeakVirtualSize
= Process
->PeakVirtualSize
;
479 VmCounters
->VirtualSize
= Process
->VirtualSize
;
480 VmCounters
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
481 VmCounters
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
482 VmCounters
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
483 VmCounters
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeak
[0];
484 VmCounters
->QuotaPagedPoolUsage
= Process
->QuotaUsage
[0];
485 VmCounters
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeak
[1];
486 VmCounters
->QuotaNonPagedPoolUsage
= Process
->QuotaUsage
[1];
487 VmCounters
->PagefileUsage
= Process
->QuotaUsage
[2];
488 VmCounters
->PeakPagefileUsage
= Process
->QuotaPeak
[2];
491 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
493 /* Get the exception code */
494 Status
= _SEH2_GetExceptionCode();
498 /* Dereference the process */
499 ObDereferenceObject(Process
);
502 /* Hard Error Processing Mode */
503 case ProcessDefaultHardErrorMode
:
505 /* Set the return length*/
506 Length
= sizeof(ULONG
);
508 if (ProcessInformationLength
!= Length
)
510 Status
= STATUS_INFO_LENGTH_MISMATCH
;
514 /* Reference the process */
515 Status
= ObReferenceObjectByHandle(ProcessHandle
,
516 PROCESS_QUERY_INFORMATION
,
521 if (!NT_SUCCESS(Status
)) break;
523 /* Enter SEH for writing back data */
526 /* Write the current processing mode */
527 *(PULONG
)ProcessInformation
= Process
->
528 DefaultHardErrorProcessing
;
530 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
532 /* Get the exception code */
533 Status
= _SEH2_GetExceptionCode();
537 /* Dereference the process */
538 ObDereferenceObject(Process
);
541 /* Priority Boosting status */
542 case ProcessPriorityBoost
:
544 /* Set the return length*/
545 Length
= sizeof(ULONG
);
547 if (ProcessInformationLength
!= Length
)
549 Status
= STATUS_INFO_LENGTH_MISMATCH
;
553 /* Reference the process */
554 Status
= ObReferenceObjectByHandle(ProcessHandle
,
555 PROCESS_QUERY_INFORMATION
,
560 if (!NT_SUCCESS(Status
)) break;
562 /* Enter SEH for writing back data */
565 /* Return boost status */
566 *(PULONG
)ProcessInformation
= Process
->Pcb
.DisableBoost
?
569 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
571 /* Get the exception code */
572 Status
= _SEH2_GetExceptionCode();
576 /* Dereference the process */
577 ObDereferenceObject(Process
);
581 case ProcessDeviceMap
:
583 /* Set the return length*/
584 Length
= sizeof(PROCESS_DEVICEMAP_INFORMATION
);
586 if (ProcessInformationLength
!= Length
)
588 Status
= STATUS_INFO_LENGTH_MISMATCH
;
592 /* Reference the process */
593 Status
= ObReferenceObjectByHandle(ProcessHandle
,
594 PROCESS_QUERY_INFORMATION
,
599 if (!NT_SUCCESS(Status
)) break;
601 /* Query the device map information */
602 ObQueryDeviceMapInformation(Process
, &DeviceMap
);
604 /* Enter SEH for writing back data */
607 *(PPROCESS_DEVICEMAP_INFORMATION
)ProcessInformation
= DeviceMap
;
609 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
611 /* Get the exception code */
612 Status
= _SEH2_GetExceptionCode();
616 /* Dereference the process */
617 ObDereferenceObject(Process
);
621 case ProcessPriorityClass
:
623 /* Set the return length*/
624 Length
= sizeof(PROCESS_PRIORITY_CLASS
);
626 if (ProcessInformationLength
!= Length
)
628 Status
= STATUS_INFO_LENGTH_MISMATCH
;
632 /* Reference the process */
633 Status
= ObReferenceObjectByHandle(ProcessHandle
,
634 PROCESS_QUERY_INFORMATION
,
639 if (!NT_SUCCESS(Status
)) break;
641 /* Enter SEH for writing back data */
644 /* Return current priority class */
645 PsPriorityClass
->PriorityClass
= Process
->PriorityClass
;
646 PsPriorityClass
->Foreground
= FALSE
;
648 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
650 /* Get the exception code */
651 Status
= _SEH2_GetExceptionCode();
655 /* Dereference the process */
656 ObDereferenceObject(Process
);
659 case ProcessImageFileName
:
661 /* Reference the process */
662 Status
= ObReferenceObjectByHandle(ProcessHandle
,
663 PROCESS_QUERY_INFORMATION
,
668 if (!NT_SUCCESS(Status
)) break;
670 /* Get the image path */
671 Status
= SeLocateProcessImageName(Process
, &ImageName
);
672 if (NT_SUCCESS(Status
))
674 /* Set return length */
675 Length
= ImageName
->MaximumLength
+
676 sizeof(OBJECT_NAME_INFORMATION
);
678 /* Make sure it's large enough */
679 if (Length
<= ProcessInformationLength
)
681 /* Enter SEH to protect write */
685 RtlCopyMemory(ProcessInformation
,
690 ((PUNICODE_STRING
)ProcessInformation
)->Buffer
=
691 (PWSTR
)((PUNICODE_STRING
)ProcessInformation
+ 1);
693 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
695 /* Get the exception code */
696 Status
= _SEH2_GetExceptionCode();
702 /* Buffer too small */
703 Status
= STATUS_INFO_LENGTH_MISMATCH
;
706 /* Free the image path */
707 ExFreePool(ImageName
);
709 /* Dereference the process */
710 ObDereferenceObject(Process
);
713 /* Per-process security cookie */
716 /* Get the current process and cookie */
717 Process
= PsGetCurrentProcess();
718 Cookie
= Process
->Cookie
;
721 LARGE_INTEGER SystemTime
;
725 /* Generate a new cookie */
726 KeQuerySystemTime(&SystemTime
);
727 Prcb
= KeGetCurrentPrcb();
728 NewCookie
= Prcb
->KeSystemCalls
^ Prcb
->InterruptTime
^
729 SystemTime
.u
.LowPart
^ SystemTime
.u
.HighPart
;
731 /* Set the new cookie or return the current one */
732 Cookie
= InterlockedCompareExchange((LONG
*)&Process
->Cookie
,
735 if (!Cookie
) Cookie
= NewCookie
;
737 /* Set return length */
738 Length
= sizeof(ULONG
);
741 /* Enter SEH to protect write */
744 /* Write back the cookie */
745 *(PULONG
)ProcessInformation
= Cookie
;
747 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
749 /* Get the exception code */
750 Status
= _SEH2_GetExceptionCode();
755 /* Not yet implemented, or unknown */
756 case ProcessBasePriority
:
757 case ProcessRaisePriority
:
758 case ProcessExceptionPort
:
759 case ProcessAccessToken
:
761 case ProcessIoPortHandlers
:
762 case ProcessUserModeIOPL
:
763 case ProcessEnableAlignmentFaultFixup
:
764 case ProcessAffinityMask
:
765 case ProcessForegroundInformation
:
767 DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass
);
768 Status
= STATUS_INVALID_INFO_CLASS
;
771 /* Protect write with SEH */
774 /* Check if caller wanted return length */
775 if (ReturnLength
) *ReturnLength
= Length
;
777 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
779 /* Get exception code */
780 Status
= _SEH2_GetExceptionCode();
792 NtSetInformationProcess(IN HANDLE ProcessHandle
,
793 IN PROCESSINFOCLASS ProcessInformationClass
,
794 IN PVOID ProcessInformation
,
795 IN ULONG ProcessInformationLength
)
798 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
801 HANDLE PortHandle
= NULL
;
802 HANDLE TokenHandle
= NULL
;
803 PROCESS_SESSION_INFORMATION SessionInfo
= {0};
804 PROCESS_PRIORITY_CLASS PriorityClass
= {0};
808 /* Verify Information Class validity */
810 Status
= DefaultSetInfoBufferCheck(ProcessInformationClass
,
812 RTL_NUMBER_OF(PsProcessInfoClass
),
814 ProcessInformationLength
,
816 if (!NT_SUCCESS(Status
)) return Status
;
819 /* Check what class this is */
820 Access
= PROCESS_SET_INFORMATION
;
821 if (ProcessInformationClass
== ProcessSessionInformation
)
823 /* Setting the Session ID needs a special mask */
824 Access
|= PROCESS_SET_SESSIONID
;
826 else if (ProcessInformationClass
== ProcessExceptionPort
)
828 /* Setting the exception port needs a special mask */
829 Access
|= PROCESS_SUSPEND_RESUME
;
832 /* Reference the process */
833 Status
= ObReferenceObjectByHandle(ProcessHandle
,
839 if (!NT_SUCCESS(Status
)) return Status
;
841 /* Check what kind of information class this is */
842 switch (ProcessInformationClass
)
844 /* Error/Exception Port */
845 case ProcessExceptionPort
:
847 /* Check buffer length */
848 if (ProcessInformationLength
!= sizeof(HANDLE
))
850 Status
= STATUS_INFO_LENGTH_MISMATCH
;
854 /* Use SEH for capture */
857 /* Capture the handle */
858 PortHandle
= *(PHANDLE
)ProcessInformation
;
860 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
862 /* Get the exception code */
863 Status
= _SEH2_GetExceptionCode();
866 if (!NT_SUCCESS(Status
)) break;
868 /* Get the LPC Port */
869 Status
= ObReferenceObjectByHandle(PortHandle
,
873 (PVOID
)&ExceptionPort
,
875 if (!NT_SUCCESS(Status
)) break;
877 /* Change the pointer */
878 if (InterlockedCompareExchangePointer(&Process
->ExceptionPort
,
882 /* We already had one, fail */
883 ObDereferenceObject(ExceptionPort
);
884 Status
= STATUS_PORT_ALREADY_SET
;
889 case ProcessAccessToken
:
891 /* Check buffer length */
892 if (ProcessInformationLength
!= sizeof(PROCESS_ACCESS_TOKEN
))
894 Status
= STATUS_INFO_LENGTH_MISMATCH
;
898 /* Use SEH for capture */
901 /* Save the token handle */
902 TokenHandle
= ((PPROCESS_ACCESS_TOKEN
)ProcessInformation
)->
905 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
907 /* Get the exception code */
908 Status
= _SEH2_GetExceptionCode();
911 if (!NT_SUCCESS(Status
)) break;
913 /* Assign the actual token */
914 Status
= PspSetPrimaryToken(Process
, TokenHandle
, NULL
);
917 /* Hard error processing */
918 case ProcessDefaultHardErrorMode
:
920 /* Check buffer length */
921 if (ProcessInformationLength
!= sizeof(ULONG
))
923 Status
= STATUS_INFO_LENGTH_MISMATCH
;
927 /* Enter SEH for direct buffer read */
930 /* Update the current mode abd return the previous one */
931 InterlockedExchange((LONG
*)&Process
->DefaultHardErrorProcessing
,
932 *(PLONG
)ProcessInformation
);
934 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
936 /* Get exception code */
937 Status
= _SEH2_GetExceptionCode();
943 case ProcessSessionInformation
:
945 /* Check buffer length */
946 if (ProcessInformationLength
!= sizeof(PROCESS_SESSION_INFORMATION
))
948 Status
= STATUS_INFO_LENGTH_MISMATCH
;
952 /* Enter SEH for capture */
955 /* Capture the caller's buffer */
956 SessionInfo
= *(PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
958 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
960 /* Get the exception code */
961 Status
= _SEH2_GetExceptionCode();
964 if (!NT_SUCCESS(Status
)) break;
966 /* Setting the session id requires the SeTcbPrivilege */
967 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
969 /* Can't set the session ID, bail out. */
970 Status
= STATUS_PRIVILEGE_NOT_HELD
;
974 /* FIXME - update the session id for the process token */
975 //Status = PsLockProcess(Process, FALSE);
976 if (!NT_SUCCESS(Status
)) break;
978 /* Write the session ID in the EPROCESS */
979 Process
->Session
= SessionInfo
.SessionId
;
981 /* Check if the process also has a PEB */
985 * Attach to the process to make sure we're in the right
986 * context to access the PEB structure
988 KeAttachProcess(&Process
->Pcb
);
990 /* Enter SEH for write to user-mode PEB */
993 /* Write the session ID */
994 Process
->Peb
->SessionId
= SessionInfo
.SessionId
;
996 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
998 /* Get exception code */
999 Status
= _SEH2_GetExceptionCode();
1003 /* Detach from the process */
1007 /* Unlock the process */
1008 //PsUnlockProcess(Process);
1011 case ProcessPriorityClass
:
1013 /* Check buffer length */
1014 if (ProcessInformationLength
!= sizeof(PROCESS_PRIORITY_CLASS
))
1016 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1020 /* Enter SEH for capture */
1023 /* Capture the caller's buffer */
1024 PriorityClass
= *(PPROCESS_PRIORITY_CLASS
)ProcessInformation
;
1026 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1028 /* Get the exception code */
1029 Status
= _SEH2_GetExceptionCode();
1032 if (!NT_SUCCESS(Status
)) break;
1034 /* Check for invalid PriorityClass value */
1035 if (PriorityClass
.PriorityClass
> PROCESS_PRIORITY_CLASS_ABOVE_NORMAL
)
1037 Status
= STATUS_INVALID_PARAMETER
;
1041 /* TODO: Check privileges */
1043 /* Check if we have a job */
1046 DPRINT1("Jobs not yet supported\n");
1049 /* Set process priority class */
1050 Process
->PriorityClass
= PriorityClass
.PriorityClass
;
1052 /* Set process priority mode (foreground or background) */
1053 PsSetProcessPriorityByClass(Process
,
1054 !PriorityClass
.Foreground
? PsProcessPriorityBackground
:
1055 PsProcessPriorityForeground
);
1057 Status
= STATUS_SUCCESS
;
1060 case ProcessQuotaLimits
:
1062 /* Check buffer length */
1063 if (ProcessInformationLength
!= sizeof(QUOTA_LIMITS
))
1065 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1069 DPRINT1("Not implemented: ProcessQuotaLimits\n");
1070 Status
= STATUS_NOT_IMPLEMENTED
;
1073 case ProcessBasePriority
:
1075 /* Check buffer length */
1076 if (ProcessInformationLength
!= sizeof(KPRIORITY
))
1078 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1082 DPRINT1("Not implemented: ProcessBasePriority\n");
1083 Status
= STATUS_NOT_IMPLEMENTED
;
1086 case ProcessRaisePriority
:
1088 /* Check buffer length */
1089 if (ProcessInformationLength
!= sizeof(ULONG
))
1091 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1095 DPRINT1("Not implemented: ProcessRaisePriority\n");
1096 Status
= STATUS_NOT_IMPLEMENTED
;
1099 case ProcessWx86Information
:
1101 /* Check buffer length */
1102 if (ProcessInformationLength
!= sizeof(HANDLE
))
1104 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1108 DPRINT1("Not implemented: ProcessWx86Information\n");
1109 Status
= STATUS_NOT_IMPLEMENTED
;
1112 case ProcessDebugPort
:
1114 /* Check buffer length */
1115 if (ProcessInformationLength
!= sizeof(HANDLE
))
1117 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1121 DPRINT1("Not implemented: ProcessDebugPort\n");
1122 Status
= STATUS_NOT_IMPLEMENTED
;
1125 /* We currently don't implement any of these */
1126 case ProcessLdtInformation
:
1127 case ProcessLdtSize
:
1128 case ProcessIoPortHandlers
:
1129 case ProcessWorkingSetWatch
:
1130 case ProcessUserModeIOPL
:
1131 case ProcessEnableAlignmentFaultFixup
:
1132 case ProcessAffinityMask
:
1133 DPRINT1("Not implemented: %lx\n", ProcessInformationClass
);
1134 Status
= STATUS_NOT_IMPLEMENTED
;
1137 /* Supposedly these are invalid...!? verify! */
1138 case ProcessBasicInformation
:
1139 case ProcessIoCounters
:
1141 case ProcessPooledUsageAndLimits
:
1142 case ProcessHandleCount
:
1143 case ProcessWow64Information
:
1145 DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass
);
1146 Status
= STATUS_INVALID_INFO_CLASS
;
1149 /* Dereference and return status */
1150 ObDereferenceObject(Process
);
1159 NtSetInformationThread(IN HANDLE ThreadHandle
,
1160 IN THREADINFOCLASS ThreadInformationClass
,
1161 IN PVOID ThreadInformation
,
1162 IN ULONG ThreadInformationLength
)
1166 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1168 HANDLE TokenHandle
= NULL
;
1169 KPRIORITY Priority
= 0;
1170 KAFFINITY Affinity
= 0, CombinedAffinity
;
1171 PVOID Address
= NULL
;
1173 ULONG DisableBoost
= 0;
1174 ULONG IdealProcessor
= 0;
1177 PVOID
*ExpansionSlots
;
1178 PETHREAD ProcThread
;
1181 /* Verify Information Class validity */
1183 Status
= DefaultSetInfoBufferCheck(ThreadInformationClass
,
1185 RTL_NUMBER_OF(PsThreadInfoClass
),
1187 ThreadInformationLength
,
1189 if (!NT_SUCCESS(Status
)) return Status
;
1192 /* Check what class this is */
1193 Access
= THREAD_SET_INFORMATION
;
1194 if (ThreadInformationClass
== ThreadImpersonationToken
)
1196 /* Setting the impersonation token needs a special mask */
1197 Access
= THREAD_SET_THREAD_TOKEN
;
1200 /* Reference the process */
1201 Status
= ObReferenceObjectByHandle(ThreadHandle
,
1207 if (!NT_SUCCESS(Status
)) return Status
;
1209 /* Check what kind of information class this is */
1210 switch (ThreadInformationClass
)
1212 /* Thread priority */
1213 case ThreadPriority
:
1215 /* Check buffer length */
1216 if (ThreadInformationLength
!= sizeof(KPRIORITY
))
1218 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1222 /* Use SEH for capture */
1225 /* Get the priority */
1226 Priority
= *(PLONG
)ThreadInformation
;
1228 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1230 /* Get the exception code */
1231 Status
= _SEH2_GetExceptionCode();
1234 if (!NT_SUCCESS(Status
)) break;
1237 if ((Priority
> HIGH_PRIORITY
) ||
1238 (Priority
<= LOW_PRIORITY
))
1241 Status
= STATUS_INVALID_PARAMETER
;
1245 /* Set the priority */
1246 KeSetPriorityThread(&Thread
->Tcb
, Priority
);
1249 case ThreadBasePriority
:
1251 /* Check buffer length */
1252 if (ThreadInformationLength
!= sizeof(LONG
))
1254 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1258 /* Use SEH for capture */
1261 /* Get the priority */
1262 Priority
= *(PLONG
)ThreadInformation
;
1264 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1266 /* Get the exception code */
1267 Status
= _SEH2_GetExceptionCode();
1270 if (!NT_SUCCESS(Status
)) break;
1273 if ((Priority
> THREAD_BASE_PRIORITY_MAX
) ||
1274 (Priority
< THREAD_BASE_PRIORITY_MIN
))
1276 /* These ones are OK */
1277 if ((Priority
!= THREAD_BASE_PRIORITY_LOWRT
+ 1) &&
1278 (Priority
!= THREAD_BASE_PRIORITY_IDLE
- 1))
1280 /* Check if the process is real time */
1281 if (PsGetCurrentProcess()->PriorityClass
!=
1282 PROCESS_PRIORITY_CLASS_REALTIME
)
1284 /* It isn't, fail */
1285 Status
= STATUS_INVALID_PARAMETER
;
1291 /* Set the base priority */
1292 KeSetBasePriorityThread(&Thread
->Tcb
, Priority
);
1295 case ThreadAffinityMask
:
1297 /* Check buffer length */
1298 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1300 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1304 /* Use SEH for capture */
1307 /* Get the priority */
1308 Affinity
= *(PULONG_PTR
)ThreadInformation
;
1310 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1312 /* Get the exception code */
1313 Status
= _SEH2_GetExceptionCode();
1316 if (!NT_SUCCESS(Status
)) break;
1322 Status
= STATUS_INVALID_PARAMETER
;
1326 /* Get the process */
1327 Process
= Thread
->ThreadsProcess
;
1329 /* Try to acquire rundown */
1330 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1333 KeEnterCriticalRegion();
1334 ExAcquirePushLockShared(&Process
->ProcessLock
);
1337 CombinedAffinity
= Affinity
& Process
->Pcb
.Affinity
;
1338 if (CombinedAffinity
!= Affinity
)
1341 Status
= STATUS_INVALID_PARAMETER
;
1345 /* Set the affinity */
1346 KeSetAffinityThread(&Thread
->Tcb
, CombinedAffinity
);
1349 /* Release the lock and rundown */
1350 ExReleasePushLockShared(&Process
->ProcessLock
);
1351 KeLeaveCriticalRegion();
1352 ExReleaseRundownProtection(&Process
->RundownProtect
);
1357 Status
= STATUS_PROCESS_IS_TERMINATING
;
1363 case ThreadImpersonationToken
:
1365 /* Check buffer length */
1366 if (ThreadInformationLength
!= sizeof(HANDLE
))
1368 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1372 /* Use SEH for capture */
1375 /* Save the token handle */
1376 TokenHandle
= *(PHANDLE
)ThreadInformation
;
1378 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1380 /* Get the exception code */
1381 Status
= _SEH2_GetExceptionCode();
1384 if (!NT_SUCCESS(Status
)) break;
1386 /* Assign the actual token */
1387 Status
= PsAssignImpersonationToken(Thread
, TokenHandle
);
1390 case ThreadQuerySetWin32StartAddress
:
1392 /* Check buffer length */
1393 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1395 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1399 /* Use SEH for capture */
1402 /* Get the priority */
1403 Address
= *(PVOID
*)ThreadInformation
;
1405 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1407 /* Get the exception code */
1408 Status
= _SEH2_GetExceptionCode();
1411 if (!NT_SUCCESS(Status
)) break;
1413 /* Set the address */
1414 Thread
->Win32StartAddress
= Address
;
1417 case ThreadIdealProcessor
:
1419 /* Check buffer length */
1420 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1422 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1426 /* Use SEH for capture */
1429 /* Get the priority */
1430 IdealProcessor
= *(PULONG_PTR
)ThreadInformation
;
1432 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1434 /* Get the exception code */
1435 Status
= _SEH2_GetExceptionCode();
1438 if (!NT_SUCCESS(Status
)) break;
1441 if (IdealProcessor
> MAXIMUM_PROCESSORS
)
1444 Status
= STATUS_INVALID_PARAMETER
;
1449 Status
= KeSetIdealProcessorThread(&Thread
->Tcb
,
1450 (CCHAR
)IdealProcessor
);
1452 /* Get the TEB and protect the thread */
1453 Teb
= Thread
->Tcb
.Teb
;
1454 if ((Teb
) && (ExAcquireRundownProtection(&Thread
->RundownProtect
)))
1456 /* Save the ideal processor */
1457 Teb
->IdealProcessor
= Thread
->Tcb
.IdealProcessor
;
1459 /* Release rundown protection */
1460 ExReleaseRundownProtection(&Thread
->RundownProtect
);
1465 case ThreadPriorityBoost
:
1467 /* Check buffer length */
1468 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1470 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1474 /* Use SEH for capture */
1477 /* Get the priority */
1478 DisableBoost
= *(PULONG_PTR
)ThreadInformation
;
1480 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1482 /* Get the exception code */
1483 Status
= _SEH2_GetExceptionCode();
1486 if (!NT_SUCCESS(Status
)) break;
1488 /* Call the kernel */
1489 KeSetDisableBoostThread(&Thread
->Tcb
, (BOOLEAN
)DisableBoost
);
1492 case ThreadZeroTlsCell
:
1494 /* Check buffer length */
1495 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1497 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1501 /* Use SEH for capture */
1504 /* Get the priority */
1505 TlsIndex
= *(PULONG_PTR
)ThreadInformation
;
1507 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1509 /* Get the exception code */
1510 Status
= _SEH2_GetExceptionCode();
1513 if (!NT_SUCCESS(Status
)) break;
1515 /* This is only valid for the current thread */
1516 if (Thread
!= PsGetCurrentThread())
1519 Status
= STATUS_INVALID_PARAMETER
;
1523 /* Get the process */
1524 Process
= Thread
->ThreadsProcess
;
1526 /* Loop the threads */
1527 ProcThread
= PsGetNextProcessThread(Process
, NULL
);
1530 /* Acquire rundown */
1531 if (ExAcquireRundownProtection(&ProcThread
->RundownProtect
))
1534 Teb
= ProcThread
->Tcb
.Teb
;
1537 /* Check if we're in the expansion range */
1538 if (TlsIndex
> TLS_MINIMUM_AVAILABLE
- 1)
1540 if (TlsIndex
< (TLS_MINIMUM_AVAILABLE
+
1541 TLS_EXPANSION_SLOTS
) - 1)
1543 /* Check if we have expansion slots */
1544 ExpansionSlots
= Teb
->TlsExpansionSlots
;
1547 /* Clear the index */
1548 ExpansionSlots
[TlsIndex
- TLS_MINIMUM_AVAILABLE
] = 0;
1554 /* Clear the index */
1555 Teb
->TlsSlots
[TlsIndex
] = NULL
;
1559 /* Release rundown */
1560 ExReleaseRundownProtection(&ProcThread
->RundownProtect
);
1563 /* Go to the next thread */
1564 ProcThread
= PsGetNextProcessThread(Process
, ProcThread
);
1571 /* We don't implement it yet */
1572 DPRINT1("Not implemented: %lx\n", ThreadInformationClass
);
1573 Status
= STATUS_NOT_IMPLEMENTED
;
1576 /* Dereference and return status */
1577 ObDereferenceObject(Thread
);
1586 NtQueryInformationThread(IN HANDLE ThreadHandle
,
1587 IN THREADINFOCLASS ThreadInformationClass
,
1588 OUT PVOID ThreadInformation
,
1589 IN ULONG ThreadInformationLength
,
1590 OUT PULONG ReturnLength OPTIONAL
)
1593 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1594 NTSTATUS Status
= STATUS_SUCCESS
;
1597 PTHREAD_BASIC_INFORMATION ThreadBasicInfo
=
1598 (PTHREAD_BASIC_INFORMATION
)ThreadInformation
;
1599 PKERNEL_USER_TIMES ThreadTime
= (PKERNEL_USER_TIMES
)ThreadInformation
;
1603 if (PreviousMode
!= KernelMode
)
1607 ProbeForWrite(ThreadInformation
,
1608 ThreadInformationLength
,
1613 ProbeForWriteUlong(ReturnLength
);
1616 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1618 Status
= _SEH2_GetExceptionCode();
1622 if (!NT_SUCCESS(Status
)) return Status
;
1625 /* Check what class this is */
1626 Access
= THREAD_QUERY_INFORMATION
;
1628 /* Reference the process */
1629 Status
= ObReferenceObjectByHandle(ThreadHandle
,
1635 if (!NT_SUCCESS(Status
)) return Status
;
1637 /* Check what kind of information class this is */
1638 switch (ThreadInformationClass
)
1640 /* Basic thread information */
1641 case ThreadBasicInformation
:
1643 /* Set return length */
1644 Length
= sizeof(THREAD_BASIC_INFORMATION
);
1646 if (ThreadInformationLength
!= Length
)
1648 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1651 /* Protect writes with SEH */
1654 /* Write all the information from the ETHREAD/KTHREAD */
1655 ThreadBasicInfo
->ExitStatus
= Thread
->ExitStatus
;
1656 ThreadBasicInfo
->TebBaseAddress
= (PVOID
)Thread
->Tcb
.Teb
;
1657 ThreadBasicInfo
->ClientId
= Thread
->Cid
;
1658 ThreadBasicInfo
->AffinityMask
= Thread
->Tcb
.Affinity
;
1659 ThreadBasicInfo
->Priority
= Thread
->Tcb
.Priority
;
1660 ThreadBasicInfo
->BasePriority
= KeQueryBasePriorityThread(&Thread
->Tcb
);
1662 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1664 /* Get exception code */
1665 Status
= _SEH2_GetExceptionCode();
1670 /* Thread time information */
1673 /* Set the return length */
1674 Length
= sizeof(KERNEL_USER_TIMES
);
1676 if (ThreadInformationLength
!= Length
)
1678 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1681 /* Protect writes with SEH */
1684 /* Copy time information from ETHREAD/KTHREAD */
1685 ThreadTime
->KernelTime
.QuadPart
= Thread
->Tcb
.KernelTime
*
1687 ThreadTime
->UserTime
.QuadPart
= Thread
->Tcb
.UserTime
*
1689 ThreadTime
->CreateTime
= Thread
->CreateTime
;
1690 ThreadTime
->ExitTime
= Thread
->ExitTime
;
1692 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1694 /* Get exception code */
1695 Status
= _SEH2_GetExceptionCode();
1700 case ThreadQuerySetWin32StartAddress
:
1702 /* Set the return length*/
1703 Length
= sizeof(PVOID
);
1705 if (ThreadInformationLength
!= Length
)
1707 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1710 /* Protect write with SEH */
1713 /* Return the Win32 Start Address */
1714 *(PVOID
*)ThreadInformation
= Thread
->Win32StartAddress
;
1716 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1718 /* Get exception code */
1719 Status
= _SEH2_GetExceptionCode();
1724 case ThreadPerformanceCount
:
1726 /* Set the return length*/
1727 Length
= sizeof(LARGE_INTEGER
);
1729 if (ThreadInformationLength
!= Length
)
1731 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1734 /* Protect write with SEH */
1738 (*(PLARGE_INTEGER
)ThreadInformation
).QuadPart
= 0;
1740 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1742 /* Get exception code */
1743 Status
= _SEH2_GetExceptionCode();
1748 case ThreadAmILastThread
:
1750 /* Set the return length*/
1751 Length
= sizeof(ULONG
);
1753 if (ThreadInformationLength
!= Length
)
1755 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1758 /* Protect write with SEH */
1761 /* Return whether or not we are the last thread */
1762 *(PULONG
)ThreadInformation
= ((Thread
->ThreadsProcess
->
1763 ThreadListHead
.Flink
->Flink
==
1764 &Thread
->ThreadsProcess
->
1768 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1770 /* Get exception code */
1771 Status
= _SEH2_GetExceptionCode();
1776 case ThreadIsIoPending
:
1778 /* Set the return length*/
1779 Length
= sizeof(ULONG
);
1781 if (ThreadInformationLength
!= Length
)
1783 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1786 /* Raise the IRQL to protect the IRP list */
1787 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1789 /* Protect write with SEH */
1792 /* Check if the IRP list is empty or not */
1793 *(PULONG
)ThreadInformation
= !IsListEmpty(&Thread
->IrpList
);
1795 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1797 /* Get exception code */
1798 Status
= _SEH2_GetExceptionCode();
1802 /* Lower IRQL back */
1803 KeLowerIrql(OldIrql
);
1806 case ThreadDescriptorTableEntry
:
1807 DPRINT1("NtQueryInformationThread(): case ThreadDescriptorTableEntry not implemented!\n");
1808 Status
= STATUS_NOT_IMPLEMENTED
;
1811 case ThreadPriorityBoost
:
1813 /* Set the return length*/
1814 Length
= sizeof(ULONG
);
1816 if (ThreadInformationLength
!= Length
)
1818 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1824 *(PULONG
)ThreadInformation
= Thread
->Tcb
.DisableBoost
? 1 : 0;
1826 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1828 Status
= _SEH2_GetExceptionCode();
1836 /* Not yet implemented */
1837 DPRINT1("Not implemented: %lx\n", ThreadInformationClass
);
1838 Status
= STATUS_NOT_IMPLEMENTED
;
1841 /* Protect write with SEH */
1844 /* Check if caller wanted return length */
1845 if (ReturnLength
) *ReturnLength
= Length
;
1847 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1849 /* Get exception code */
1850 Status
= _SEH2_GetExceptionCode();
1854 /* Dereference the thread, and return */
1855 ObDereferenceObject(Thread
);