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();
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 /* Probe the buffer */
90 ProbeForWrite(ProcessInformation
,
91 ProcessInformationLength
,
94 /* Probe the return length if required */
95 if (ReturnLength
) ProbeForWriteUlong(ReturnLength
);
97 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
99 /* Return the exception code */
100 _SEH2_YIELD(return _SEH2_GetExceptionCode());
105 if((ProcessInformationClass
== ProcessCookie
) &&
106 (ProcessHandle
!= NtCurrentProcess()))
109 * Retreiving the process cookie is only allowed for the calling process
110 * itself! XP only allowes NtCurrentProcess() as process handles even if
111 * a real handle actually represents the current process.
113 return STATUS_INVALID_PARAMETER
;
116 /* Check the information class */
117 switch (ProcessInformationClass
)
119 /* Basic process information */
120 case ProcessBasicInformation
:
122 /* Set return length */
123 Length
= sizeof(PROCESS_BASIC_INFORMATION
);
125 if (ProcessInformationLength
!= Length
)
127 Status
= STATUS_INFO_LENGTH_MISMATCH
;
131 /* Reference the process */
132 Status
= ObReferenceObjectByHandle(ProcessHandle
,
133 PROCESS_QUERY_INFORMATION
,
138 if (!NT_SUCCESS(Status
)) break;
140 /* Protect writes with SEH */
143 /* Write all the information from the EPROCESS/KPROCESS */
144 ProcessBasicInfo
->ExitStatus
= Process
->ExitStatus
;
145 ProcessBasicInfo
->PebBaseAddress
= Process
->Peb
;
146 ProcessBasicInfo
->AffinityMask
= Process
->Pcb
.Affinity
;
147 ProcessBasicInfo
->UniqueProcessId
= (ULONG_PTR
)Process
->
149 ProcessBasicInfo
->InheritedFromUniqueProcessId
=
150 (ULONG_PTR
)Process
->InheritedFromUniqueProcessId
;
151 ProcessBasicInfo
->BasePriority
= Process
->Pcb
.BasePriority
;
154 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
156 /* Get exception code */
157 Status
= _SEH2_GetExceptionCode();
161 /* Dereference the process */
162 ObDereferenceObject(Process
);
165 /* Process quota limits */
166 case ProcessQuotaLimits
:
168 Length
= sizeof(QUOTA_LIMITS
);
169 if (ProcessInformationLength
!= Length
)
171 Status
= STATUS_INFO_LENGTH_MISMATCH
;
175 /* Reference the process */
176 Status
= ObReferenceObjectByHandle(ProcessHandle
,
177 PROCESS_QUERY_INFORMATION
,
182 if (!NT_SUCCESS(Status
)) break;
184 /* Indicate success */
185 Status
= STATUS_SUCCESS
;
189 /* Set max/min working set sizes */
190 QuotaLimits
->MaximumWorkingSetSize
=
191 Process
->Vm
.MaximumWorkingSetSize
<< PAGE_SHIFT
;
192 QuotaLimits
->MinimumWorkingSetSize
=
193 Process
->Vm
.MinimumWorkingSetSize
<< PAGE_SHIFT
;
195 /* Set default time limits */
196 QuotaLimits
->TimeLimit
.LowPart
= MAXULONG
;
197 QuotaLimits
->TimeLimit
.HighPart
= MAXULONG
;
199 /* Is quota block a default one? */
200 if (Process
->QuotaBlock
== &PspDefaultQuotaBlock
)
202 /* Set default pools and pagefile limits */
203 QuotaLimits
->PagedPoolLimit
= (SIZE_T
)-1;
204 QuotaLimits
->NonPagedPoolLimit
= (SIZE_T
)-1;
205 QuotaLimits
->PagefileLimit
= (SIZE_T
)-1;
209 /* Get limits from non-default quota block */
210 QuotaLimits
->PagedPoolLimit
=
211 Process
->QuotaBlock
->QuotaEntry
[PagedPool
].Limit
;
212 QuotaLimits
->NonPagedPoolLimit
=
213 Process
->QuotaBlock
->QuotaEntry
[NonPagedPool
].Limit
;
214 QuotaLimits
->PagefileLimit
=
215 Process
->QuotaBlock
->QuotaEntry
[2].Limit
;
218 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
220 /* Get exception code */
221 Status
= _SEH2_GetExceptionCode();
225 /* Dereference the process */
226 ObDereferenceObject(Process
);
229 case ProcessIoCounters
:
231 Length
= sizeof(IO_COUNTERS
);
232 if (ProcessInformationLength
!= Length
)
234 Status
= STATUS_INFO_LENGTH_MISMATCH
;
238 /* Reference the process */
239 Status
= ObReferenceObjectByHandle(ProcessHandle
,
240 PROCESS_QUERY_INFORMATION
,
245 if (!NT_SUCCESS(Status
)) break;
249 IoCounters
->ReadOperationCount
= Process
->ReadOperationCount
.QuadPart
;
250 IoCounters
->ReadTransferCount
= Process
->ReadTransferCount
.QuadPart
;
251 IoCounters
->WriteOperationCount
= Process
->WriteOperationCount
.QuadPart
;
252 IoCounters
->WriteTransferCount
= Process
->WriteTransferCount
.QuadPart
;
253 IoCounters
->OtherOperationCount
= Process
->OtherOperationCount
.QuadPart
;
254 IoCounters
->OtherTransferCount
= Process
->OtherTransferCount
.QuadPart
;
256 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
258 /* Ignore exception */
262 /* Set status to success in any case */
263 Status
= STATUS_SUCCESS
;
265 /* Dereference the process */
266 ObDereferenceObject(Process
);
272 /* Set the return length */
273 Length
= sizeof(KERNEL_USER_TIMES
);
275 if (ProcessInformationLength
!= Length
)
277 Status
= STATUS_INFO_LENGTH_MISMATCH
;
281 /* Reference the process */
282 Status
= ObReferenceObjectByHandle(ProcessHandle
,
283 PROCESS_QUERY_INFORMATION
,
288 if (!NT_SUCCESS(Status
)) break;
290 /* Protect writes with SEH */
293 /* Copy time information from EPROCESS/KPROCESS */
294 ProcessTime
->CreateTime
= Process
->CreateTime
;
295 ProcessTime
->UserTime
.QuadPart
= Process
->Pcb
.UserTime
*
297 ProcessTime
->KernelTime
.QuadPart
= Process
->Pcb
.KernelTime
*
299 ProcessTime
->ExitTime
= Process
->ExitTime
;
301 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
303 /* Get exception code */
304 Status
= _SEH2_GetExceptionCode();
308 /* Dereference the process */
309 ObDereferenceObject(Process
);
312 /* Process Debug Port */
313 case ProcessDebugPort
:
315 /* Set return length */
316 Length
= sizeof(HANDLE
);
318 if (ProcessInformationLength
!= Length
)
320 Status
= STATUS_INFO_LENGTH_MISMATCH
;
324 /* Reference the process */
325 Status
= ObReferenceObjectByHandle(ProcessHandle
,
326 PROCESS_QUERY_INFORMATION
,
331 if (!NT_SUCCESS(Status
)) break;
333 /* Protect write with SEH */
336 /* Return whether or not we have a debug port */
337 *(PHANDLE
)ProcessInformation
= (Process
->DebugPort
?
340 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
342 /* Get exception code */
343 Status
= _SEH2_GetExceptionCode();
347 /* Dereference the process */
348 ObDereferenceObject(Process
);
351 /* LDT, WS and VDM Information: not implemented */
352 case ProcessLdtInformation
:
353 case ProcessWorkingSetWatch
:
354 case ProcessWx86Information
:
356 /* Reference the process */
357 Status
= ObReferenceObjectByHandle(ProcessHandle
,
358 PROCESS_QUERY_INFORMATION
,
363 if (!NT_SUCCESS(Status
)) break;
365 DPRINT1("Not implemented: %lx\n", ProcessInformationClass
);
367 /* Dereference the process */
368 ObDereferenceObject(Process
);
369 Status
= STATUS_NOT_IMPLEMENTED
;
372 case ProcessHandleCount
:
374 /* Set the return length*/
375 Length
= sizeof(ULONG
);
377 if (ProcessInformationLength
!= Length
)
379 Status
= STATUS_INFO_LENGTH_MISMATCH
;
383 /* Reference the process */
384 Status
= ObReferenceObjectByHandle(ProcessHandle
,
385 PROCESS_QUERY_INFORMATION
,
390 if (!NT_SUCCESS(Status
)) break;
392 /* Count the number of handles this process has */
393 HandleCount
= ObGetProcessHandleCount(Process
);
395 /* Protect write in SEH */
398 /* Return the count of handles */
399 *(PULONG
)ProcessInformation
= HandleCount
;
401 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
403 /* Get the exception code */
404 Status
= _SEH2_GetExceptionCode();
408 /* Dereference the process */
409 ObDereferenceObject(Process
);
412 /* Session ID for the process */
413 case ProcessSessionInformation
:
415 /* Set the return length*/
416 Length
= sizeof(PROCESS_SESSION_INFORMATION
);
418 if (ProcessInformationLength
!= Length
)
420 Status
= STATUS_INFO_LENGTH_MISMATCH
;
424 /* Reference the process */
425 Status
= ObReferenceObjectByHandle(ProcessHandle
,
426 PROCESS_QUERY_INFORMATION
,
431 if (!NT_SUCCESS(Status
)) break;
433 /* Enter SEH for write safety */
436 /* Write back the Session ID */
437 SessionInfo
->SessionId
= PtrToUlong(Process
->Session
);
439 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
441 /* Get the exception code */
442 Status
= _SEH2_GetExceptionCode();
446 /* Dereference the process */
447 ObDereferenceObject(Process
);
450 /* WOW64: Not implemented */
451 case ProcessWow64Information
:
453 /* Set the return length */
454 Length
= sizeof(ULONG_PTR
);
456 if (ProcessInformationLength
!= Length
)
458 Status
= STATUS_INFO_LENGTH_MISMATCH
;
462 /* Reference the process */
463 Status
= ObReferenceObjectByHandle(ProcessHandle
,
464 PROCESS_QUERY_INFORMATION
,
469 if (!NT_SUCCESS(Status
)) break;
471 DPRINT1("Not implemented: ProcessWow64Information\n");
473 /* Dereference the process */
474 ObDereferenceObject(Process
);
475 Status
= STATUS_NOT_IMPLEMENTED
;
478 /* Virtual Memory Statistics */
479 case ProcessVmCounters
:
481 /* Set the return length */
482 Length
= sizeof(VM_COUNTERS
);
484 if (ProcessInformationLength
!= Length
)
486 Status
= STATUS_INFO_LENGTH_MISMATCH
;
490 /* Reference the process */
491 Status
= ObReferenceObjectByHandle(ProcessHandle
,
492 PROCESS_QUERY_INFORMATION
,
497 if (!NT_SUCCESS(Status
)) break;
499 /* Enter SEH for write safety */
502 /* Return data from EPROCESS */
503 VmCounters
->PeakVirtualSize
= Process
->PeakVirtualSize
;
504 VmCounters
->VirtualSize
= Process
->VirtualSize
;
505 VmCounters
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
506 VmCounters
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
507 VmCounters
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
508 VmCounters
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeak
[0];
509 VmCounters
->QuotaPagedPoolUsage
= Process
->QuotaUsage
[0];
510 VmCounters
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeak
[1];
511 VmCounters
->QuotaNonPagedPoolUsage
= Process
->QuotaUsage
[1];
512 VmCounters
->PagefileUsage
= Process
->QuotaUsage
[2];
513 VmCounters
->PeakPagefileUsage
= Process
->QuotaPeak
[2];
516 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
518 /* Get the exception code */
519 Status
= _SEH2_GetExceptionCode();
523 /* Dereference the process */
524 ObDereferenceObject(Process
);
527 /* Hard Error Processing Mode */
528 case ProcessDefaultHardErrorMode
:
530 /* Set the return length*/
531 Length
= sizeof(ULONG
);
533 if (ProcessInformationLength
!= Length
)
535 Status
= STATUS_INFO_LENGTH_MISMATCH
;
539 /* Reference the process */
540 Status
= ObReferenceObjectByHandle(ProcessHandle
,
541 PROCESS_QUERY_INFORMATION
,
546 if (!NT_SUCCESS(Status
)) break;
548 /* Enter SEH for writing back data */
551 /* Write the current processing mode */
552 *(PULONG
)ProcessInformation
= Process
->
553 DefaultHardErrorProcessing
;
555 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
557 /* Get the exception code */
558 Status
= _SEH2_GetExceptionCode();
562 /* Dereference the process */
563 ObDereferenceObject(Process
);
566 /* Priority Boosting status */
567 case ProcessPriorityBoost
:
569 /* Set the return length*/
570 Length
= sizeof(ULONG
);
572 if (ProcessInformationLength
!= Length
)
574 Status
= STATUS_INFO_LENGTH_MISMATCH
;
578 /* Reference the process */
579 Status
= ObReferenceObjectByHandle(ProcessHandle
,
580 PROCESS_QUERY_INFORMATION
,
585 if (!NT_SUCCESS(Status
)) break;
587 /* Enter SEH for writing back data */
590 /* Return boost status */
591 *(PULONG
)ProcessInformation
= Process
->Pcb
.DisableBoost
?
594 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
596 /* Get the exception code */
597 Status
= _SEH2_GetExceptionCode();
601 /* Dereference the process */
602 ObDereferenceObject(Process
);
606 case ProcessDeviceMap
:
608 /* Set the return length*/
609 Length
= sizeof(PROCESS_DEVICEMAP_INFORMATION
);
611 if (ProcessInformationLength
!= Length
)
613 Status
= STATUS_INFO_LENGTH_MISMATCH
;
617 /* Reference the process */
618 Status
= ObReferenceObjectByHandle(ProcessHandle
,
619 PROCESS_QUERY_INFORMATION
,
624 if (!NT_SUCCESS(Status
)) break;
626 /* Query the device map information */
627 ObQueryDeviceMapInformation(Process
, &DeviceMap
);
629 /* Enter SEH for writing back data */
632 *(PPROCESS_DEVICEMAP_INFORMATION
)ProcessInformation
= DeviceMap
;
634 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
636 /* Get the exception code */
637 Status
= _SEH2_GetExceptionCode();
641 /* Dereference the process */
642 ObDereferenceObject(Process
);
646 case ProcessPriorityClass
:
648 /* Set the return length*/
649 Length
= sizeof(PROCESS_PRIORITY_CLASS
);
651 if (ProcessInformationLength
!= Length
)
653 Status
= STATUS_INFO_LENGTH_MISMATCH
;
657 /* Reference the process */
658 Status
= ObReferenceObjectByHandle(ProcessHandle
,
659 PROCESS_QUERY_INFORMATION
,
664 if (!NT_SUCCESS(Status
)) break;
666 /* Enter SEH for writing back data */
669 /* Return current priority class */
670 PsPriorityClass
->PriorityClass
= Process
->PriorityClass
;
671 PsPriorityClass
->Foreground
= FALSE
;
673 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
675 /* Get the exception code */
676 Status
= _SEH2_GetExceptionCode();
680 /* Dereference the process */
681 ObDereferenceObject(Process
);
684 case ProcessImageFileName
:
686 /* Reference the process */
687 Status
= ObReferenceObjectByHandle(ProcessHandle
,
688 PROCESS_QUERY_INFORMATION
,
693 if (!NT_SUCCESS(Status
)) break;
695 /* Get the image path */
696 Status
= SeLocateProcessImageName(Process
, &ImageName
);
697 if (NT_SUCCESS(Status
))
699 /* Set return length */
700 Length
= ImageName
->MaximumLength
+
701 sizeof(OBJECT_NAME_INFORMATION
);
703 /* Make sure it's large enough */
704 if (Length
<= ProcessInformationLength
)
706 /* Enter SEH to protect write */
710 RtlCopyMemory(ProcessInformation
,
715 ((PUNICODE_STRING
)ProcessInformation
)->Buffer
=
716 (PWSTR
)((PUNICODE_STRING
)ProcessInformation
+ 1);
718 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
720 /* Get the exception code */
721 Status
= _SEH2_GetExceptionCode();
727 /* Buffer too small */
728 Status
= STATUS_INFO_LENGTH_MISMATCH
;
731 /* Free the image path */
732 ExFreePool(ImageName
);
734 /* Dereference the process */
735 ObDereferenceObject(Process
);
738 /* Per-process security cookie */
741 /* Get the current process and cookie */
742 Process
= PsGetCurrentProcess();
743 Cookie
= Process
->Cookie
;
746 LARGE_INTEGER SystemTime
;
750 /* Generate a new cookie */
751 KeQuerySystemTime(&SystemTime
);
752 Prcb
= KeGetCurrentPrcb();
753 NewCookie
= Prcb
->KeSystemCalls
^ Prcb
->InterruptTime
^
754 SystemTime
.u
.LowPart
^ SystemTime
.u
.HighPart
;
756 /* Set the new cookie or return the current one */
757 Cookie
= InterlockedCompareExchange((LONG
*)&Process
->Cookie
,
760 if (!Cookie
) Cookie
= NewCookie
;
762 /* Set return length */
763 Length
= sizeof(ULONG
);
766 /* Indicate success */
767 Status
= STATUS_SUCCESS
;
769 /* Enter SEH to protect write */
772 /* Write back the cookie */
773 *(PULONG
)ProcessInformation
= Cookie
;
775 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
777 /* Get the exception code */
778 Status
= _SEH2_GetExceptionCode();
783 /* Not yet implemented, or unknown */
784 case ProcessBasePriority
:
785 case ProcessRaisePriority
:
786 case ProcessExceptionPort
:
787 case ProcessAccessToken
:
789 case ProcessIoPortHandlers
:
790 case ProcessUserModeIOPL
:
791 case ProcessEnableAlignmentFaultFixup
:
792 case ProcessAffinityMask
:
793 case ProcessForegroundInformation
:
795 DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass
);
796 Status
= STATUS_INVALID_INFO_CLASS
;
799 /* Protect write with SEH */
802 /* Check if caller wanted return length */
803 if (ReturnLength
) *ReturnLength
= Length
;
805 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
807 /* Get exception code */
808 Status
= _SEH2_GetExceptionCode();
820 NtSetInformationProcess(IN HANDLE ProcessHandle
,
821 IN PROCESSINFOCLASS ProcessInformationClass
,
822 IN PVOID ProcessInformation
,
823 IN ULONG ProcessInformationLength
)
826 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
829 HANDLE PortHandle
= NULL
;
830 HANDLE TokenHandle
= NULL
;
831 PROCESS_SESSION_INFORMATION SessionInfo
= {0};
832 PROCESS_PRIORITY_CLASS PriorityClass
= {0};
836 /* Verify Information Class validity */
838 Status
= DefaultSetInfoBufferCheck(ProcessInformationClass
,
840 RTL_NUMBER_OF(PsProcessInfoClass
),
842 ProcessInformationLength
,
844 if (!NT_SUCCESS(Status
)) return Status
;
847 /* Check what class this is */
848 Access
= PROCESS_SET_INFORMATION
;
849 if (ProcessInformationClass
== ProcessSessionInformation
)
851 /* Setting the Session ID needs a special mask */
852 Access
|= PROCESS_SET_SESSIONID
;
854 else if (ProcessInformationClass
== ProcessExceptionPort
)
856 /* Setting the exception port needs a special mask */
857 Access
|= PROCESS_SUSPEND_RESUME
;
860 /* Reference the process */
861 Status
= ObReferenceObjectByHandle(ProcessHandle
,
867 if (!NT_SUCCESS(Status
)) return Status
;
869 /* Check what kind of information class this is */
870 switch (ProcessInformationClass
)
872 /* Error/Exception Port */
873 case ProcessExceptionPort
:
875 /* Check buffer length */
876 if (ProcessInformationLength
!= sizeof(HANDLE
))
878 Status
= STATUS_INFO_LENGTH_MISMATCH
;
882 /* Use SEH for capture */
885 /* Capture the handle */
886 PortHandle
= *(PHANDLE
)ProcessInformation
;
888 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
890 /* Return the exception code */
891 _SEH2_YIELD(return _SEH2_GetExceptionCode());
895 /* Get the LPC Port */
896 Status
= ObReferenceObjectByHandle(PortHandle
,
900 (PVOID
)&ExceptionPort
,
902 if (!NT_SUCCESS(Status
)) break;
904 /* Change the pointer */
905 if (InterlockedCompareExchangePointer(&Process
->ExceptionPort
,
909 /* We already had one, fail */
910 ObDereferenceObject(ExceptionPort
);
911 Status
= STATUS_PORT_ALREADY_SET
;
916 case ProcessAccessToken
:
918 /* Check buffer length */
919 if (ProcessInformationLength
!= sizeof(PROCESS_ACCESS_TOKEN
))
921 Status
= STATUS_INFO_LENGTH_MISMATCH
;
925 /* Use SEH for capture */
928 /* Save the token handle */
929 TokenHandle
= ((PPROCESS_ACCESS_TOKEN
)ProcessInformation
)->
932 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
934 /* Return the exception code */
935 _SEH2_YIELD(return _SEH2_GetExceptionCode());
939 /* Assign the actual token */
940 Status
= PspSetPrimaryToken(Process
, TokenHandle
, NULL
);
943 /* Hard error processing */
944 case ProcessDefaultHardErrorMode
:
946 /* Check buffer length */
947 if (ProcessInformationLength
!= sizeof(ULONG
))
949 Status
= STATUS_INFO_LENGTH_MISMATCH
;
953 /* Enter SEH for direct buffer read */
956 /* Update the current mode abd return the previous one */
957 InterlockedExchange((LONG
*)&Process
->DefaultHardErrorProcessing
,
958 *(PLONG
)ProcessInformation
);
960 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
962 /* Get exception code */
963 Status
= _SEH2_GetExceptionCode();
969 case ProcessSessionInformation
:
971 /* Check buffer length */
972 if (ProcessInformationLength
!= sizeof(PROCESS_SESSION_INFORMATION
))
974 Status
= STATUS_INFO_LENGTH_MISMATCH
;
978 /* Enter SEH for capture */
981 /* Capture the caller's buffer */
982 SessionInfo
= *(PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
984 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
986 /* Return the exception code */
987 _SEH2_YIELD(return _SEH2_GetExceptionCode());
991 /* Setting the session id requires the SeTcbPrivilege */
992 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
994 /* Can't set the session ID, bail out. */
995 Status
= STATUS_PRIVILEGE_NOT_HELD
;
999 /* FIXME - update the session id for the process token */
1000 //Status = PsLockProcess(Process, FALSE);
1001 if (!NT_SUCCESS(Status
)) break;
1003 /* Write the session ID in the EPROCESS */
1004 Process
->Session
= (PVOID
)(ULONG_PTR
)SessionInfo
.SessionId
;
1006 /* Check if the process also has a PEB */
1010 * Attach to the process to make sure we're in the right
1011 * context to access the PEB structure
1013 KeAttachProcess(&Process
->Pcb
);
1015 /* Enter SEH for write to user-mode PEB */
1018 /* Write the session ID */
1019 Process
->Peb
->SessionId
= SessionInfo
.SessionId
;
1021 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1023 /* Get exception code */
1024 Status
= _SEH2_GetExceptionCode();
1028 /* Detach from the process */
1032 /* Unlock the process */
1033 //PsUnlockProcess(Process);
1036 case ProcessPriorityClass
:
1038 /* Check buffer length */
1039 if (ProcessInformationLength
!= sizeof(PROCESS_PRIORITY_CLASS
))
1041 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1045 /* Enter SEH for capture */
1048 /* Capture the caller's buffer */
1049 PriorityClass
= *(PPROCESS_PRIORITY_CLASS
)ProcessInformation
;
1051 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1053 /* Return the exception code */
1054 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1058 /* Check for invalid PriorityClass value */
1059 if (PriorityClass
.PriorityClass
> PROCESS_PRIORITY_CLASS_ABOVE_NORMAL
)
1061 Status
= STATUS_INVALID_PARAMETER
;
1065 /* TODO: Check privileges */
1067 /* Check if we have a job */
1070 DPRINT1("Jobs not yet supported\n");
1073 /* Set process priority class */
1074 Process
->PriorityClass
= PriorityClass
.PriorityClass
;
1076 /* Set process priority mode (foreground or background) */
1077 PsSetProcessPriorityByClass(Process
,
1078 !PriorityClass
.Foreground
? PsProcessPriorityBackground
:
1079 PsProcessPriorityForeground
);
1081 Status
= STATUS_SUCCESS
;
1084 case ProcessQuotaLimits
:
1086 /* Check buffer length */
1087 if (ProcessInformationLength
!= sizeof(QUOTA_LIMITS
))
1089 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1093 DPRINT1("Not implemented: ProcessQuotaLimits\n");
1094 Status
= STATUS_NOT_IMPLEMENTED
;
1097 case ProcessBasePriority
:
1099 /* Check buffer length */
1100 if (ProcessInformationLength
!= sizeof(KPRIORITY
))
1102 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1106 DPRINT1("Not implemented: ProcessBasePriority\n");
1107 Status
= STATUS_NOT_IMPLEMENTED
;
1110 case ProcessRaisePriority
:
1112 /* Check buffer length */
1113 if (ProcessInformationLength
!= sizeof(ULONG
))
1115 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1119 DPRINT1("Not implemented: ProcessRaisePriority\n");
1120 Status
= STATUS_NOT_IMPLEMENTED
;
1123 case ProcessWx86Information
:
1125 /* Check buffer length */
1126 if (ProcessInformationLength
!= sizeof(HANDLE
))
1128 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1132 DPRINT1("Not implemented: ProcessWx86Information\n");
1133 Status
= STATUS_NOT_IMPLEMENTED
;
1136 case ProcessDebugPort
:
1138 /* Check buffer length */
1139 if (ProcessInformationLength
!= sizeof(HANDLE
))
1141 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1145 DPRINT1("Not implemented: ProcessDebugPort\n");
1146 Status
= STATUS_NOT_IMPLEMENTED
;
1149 /* We currently don't implement any of these */
1150 case ProcessLdtInformation
:
1151 case ProcessLdtSize
:
1152 case ProcessIoPortHandlers
:
1153 case ProcessWorkingSetWatch
:
1154 case ProcessUserModeIOPL
:
1155 case ProcessEnableAlignmentFaultFixup
:
1156 case ProcessAffinityMask
:
1157 DPRINT1("Not implemented: %lx\n", ProcessInformationClass
);
1158 Status
= STATUS_NOT_IMPLEMENTED
;
1161 /* Supposedly these are invalid...!? verify! */
1162 case ProcessBasicInformation
:
1163 case ProcessIoCounters
:
1165 case ProcessPooledUsageAndLimits
:
1166 case ProcessHandleCount
:
1167 case ProcessWow64Information
:
1169 DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass
);
1170 Status
= STATUS_INVALID_INFO_CLASS
;
1173 /* Dereference and return status */
1174 ObDereferenceObject(Process
);
1183 NtSetInformationThread(IN HANDLE ThreadHandle
,
1184 IN THREADINFOCLASS ThreadInformationClass
,
1185 IN PVOID ThreadInformation
,
1186 IN ULONG ThreadInformationLength
)
1190 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1192 HANDLE TokenHandle
= NULL
;
1193 KPRIORITY Priority
= 0;
1194 KAFFINITY Affinity
= 0, CombinedAffinity
;
1195 PVOID Address
= NULL
;
1197 ULONG DisableBoost
= 0;
1198 ULONG IdealProcessor
= 0;
1201 PVOID
*ExpansionSlots
;
1202 PETHREAD ProcThread
;
1205 /* Verify Information Class validity */
1207 Status
= DefaultSetInfoBufferCheck(ThreadInformationClass
,
1209 RTL_NUMBER_OF(PsThreadInfoClass
),
1211 ThreadInformationLength
,
1213 if (!NT_SUCCESS(Status
)) return Status
;
1216 /* Check what class this is */
1217 Access
= THREAD_SET_INFORMATION
;
1218 if (ThreadInformationClass
== ThreadImpersonationToken
)
1220 /* Setting the impersonation token needs a special mask */
1221 Access
= THREAD_SET_THREAD_TOKEN
;
1224 /* Reference the process */
1225 Status
= ObReferenceObjectByHandle(ThreadHandle
,
1231 if (!NT_SUCCESS(Status
)) return Status
;
1233 /* Check what kind of information class this is */
1234 switch (ThreadInformationClass
)
1236 /* Thread priority */
1237 case ThreadPriority
:
1239 /* Check buffer length */
1240 if (ThreadInformationLength
!= sizeof(KPRIORITY
))
1242 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1246 /* Use SEH for capture */
1249 /* Get the priority */
1250 Priority
= *(PLONG
)ThreadInformation
;
1252 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1254 /* Return the exception code */
1255 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1260 if ((Priority
> HIGH_PRIORITY
) ||
1261 (Priority
<= LOW_PRIORITY
))
1264 Status
= STATUS_INVALID_PARAMETER
;
1268 /* Set the priority */
1269 KeSetPriorityThread(&Thread
->Tcb
, Priority
);
1272 case ThreadBasePriority
:
1274 /* Check buffer length */
1275 if (ThreadInformationLength
!= sizeof(LONG
))
1277 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1281 /* Use SEH for capture */
1284 /* Get the priority */
1285 Priority
= *(PLONG
)ThreadInformation
;
1287 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1289 /* Return the exception code */
1290 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1295 if ((Priority
> THREAD_BASE_PRIORITY_MAX
) ||
1296 (Priority
< THREAD_BASE_PRIORITY_MIN
))
1298 /* These ones are OK */
1299 if ((Priority
!= THREAD_BASE_PRIORITY_LOWRT
+ 1) &&
1300 (Priority
!= THREAD_BASE_PRIORITY_IDLE
- 1))
1302 /* Check if the process is real time */
1303 if (PsGetCurrentProcess()->PriorityClass
!=
1304 PROCESS_PRIORITY_CLASS_REALTIME
)
1306 /* It isn't, fail */
1307 Status
= STATUS_INVALID_PARAMETER
;
1313 /* Set the base priority */
1314 KeSetBasePriorityThread(&Thread
->Tcb
, Priority
);
1317 case ThreadAffinityMask
:
1319 /* Check buffer length */
1320 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1322 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1326 /* Use SEH for capture */
1329 /* Get the priority */
1330 Affinity
= *(PULONG_PTR
)ThreadInformation
;
1332 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1334 /* Return the exception code */
1335 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1343 Status
= STATUS_INVALID_PARAMETER
;
1347 /* Get the process */
1348 Process
= Thread
->ThreadsProcess
;
1350 /* Try to acquire rundown */
1351 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1354 KeEnterCriticalRegion();
1355 ExAcquirePushLockShared(&Process
->ProcessLock
);
1358 CombinedAffinity
= Affinity
& Process
->Pcb
.Affinity
;
1359 if (CombinedAffinity
!= Affinity
)
1362 Status
= STATUS_INVALID_PARAMETER
;
1366 /* Set the affinity */
1367 KeSetAffinityThread(&Thread
->Tcb
, CombinedAffinity
);
1370 /* Release the lock and rundown */
1371 ExReleasePushLockShared(&Process
->ProcessLock
);
1372 KeLeaveCriticalRegion();
1373 ExReleaseRundownProtection(&Process
->RundownProtect
);
1378 Status
= STATUS_PROCESS_IS_TERMINATING
;
1384 case ThreadImpersonationToken
:
1386 /* Check buffer length */
1387 if (ThreadInformationLength
!= sizeof(HANDLE
))
1389 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1393 /* Use SEH for capture */
1396 /* Save the token handle */
1397 TokenHandle
= *(PHANDLE
)ThreadInformation
;
1399 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1401 /* Return the exception code */
1402 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1406 /* Assign the actual token */
1407 Status
= PsAssignImpersonationToken(Thread
, TokenHandle
);
1410 case ThreadQuerySetWin32StartAddress
:
1412 /* Check buffer length */
1413 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1415 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1419 /* Use SEH for capture */
1422 /* Get the priority */
1423 Address
= *(PVOID
*)ThreadInformation
;
1425 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1427 /* Return the exception code */
1428 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1432 /* Set the address */
1433 Thread
->Win32StartAddress
= Address
;
1436 case ThreadIdealProcessor
:
1438 /* Check buffer length */
1439 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1441 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1445 /* Use SEH for capture */
1448 /* Get the priority */
1449 IdealProcessor
= *(PULONG_PTR
)ThreadInformation
;
1451 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1453 /* Return the exception code */
1454 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1459 if (IdealProcessor
> MAXIMUM_PROCESSORS
)
1462 Status
= STATUS_INVALID_PARAMETER
;
1467 Status
= KeSetIdealProcessorThread(&Thread
->Tcb
,
1468 (CCHAR
)IdealProcessor
);
1470 /* Get the TEB and protect the thread */
1471 Teb
= Thread
->Tcb
.Teb
;
1472 if ((Teb
) && (ExAcquireRundownProtection(&Thread
->RundownProtect
)))
1474 /* Save the ideal processor */
1475 Teb
->IdealProcessor
= Thread
->Tcb
.IdealProcessor
;
1477 /* Release rundown protection */
1478 ExReleaseRundownProtection(&Thread
->RundownProtect
);
1483 case ThreadPriorityBoost
:
1485 /* Check buffer length */
1486 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1488 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1492 /* Use SEH for capture */
1495 /* Get the priority */
1496 DisableBoost
= *(PULONG_PTR
)ThreadInformation
;
1498 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1500 /* Return the exception code */
1501 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1505 /* Call the kernel */
1506 KeSetDisableBoostThread(&Thread
->Tcb
, (BOOLEAN
)DisableBoost
);
1509 case ThreadZeroTlsCell
:
1511 /* Check buffer length */
1512 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1514 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1518 /* Use SEH for capture */
1521 /* Get the priority */
1522 TlsIndex
= *(PULONG_PTR
)ThreadInformation
;
1524 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1526 /* Return the exception code */
1527 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1531 /* This is only valid for the current thread */
1532 if (Thread
!= PsGetCurrentThread())
1535 Status
= STATUS_INVALID_PARAMETER
;
1539 /* Get the process */
1540 Process
= Thread
->ThreadsProcess
;
1542 /* Loop the threads */
1543 ProcThread
= PsGetNextProcessThread(Process
, NULL
);
1546 /* Acquire rundown */
1547 if (ExAcquireRundownProtection(&ProcThread
->RundownProtect
))
1550 Teb
= ProcThread
->Tcb
.Teb
;
1553 /* Check if we're in the expansion range */
1554 if (TlsIndex
> TLS_MINIMUM_AVAILABLE
- 1)
1556 if (TlsIndex
< (TLS_MINIMUM_AVAILABLE
+
1557 TLS_EXPANSION_SLOTS
) - 1)
1559 /* Check if we have expansion slots */
1560 ExpansionSlots
= Teb
->TlsExpansionSlots
;
1563 /* Clear the index */
1564 ExpansionSlots
[TlsIndex
- TLS_MINIMUM_AVAILABLE
] = 0;
1570 /* Clear the index */
1571 Teb
->TlsSlots
[TlsIndex
] = NULL
;
1575 /* Release rundown */
1576 ExReleaseRundownProtection(&ProcThread
->RundownProtect
);
1579 /* Go to the next thread */
1580 ProcThread
= PsGetNextProcessThread(Process
, ProcThread
);
1587 /* We don't implement it yet */
1588 DPRINT1("Not implemented: %lx\n", ThreadInformationClass
);
1589 Status
= STATUS_NOT_IMPLEMENTED
;
1592 /* Dereference and return status */
1593 ObDereferenceObject(Thread
);
1602 NtQueryInformationThread(IN HANDLE ThreadHandle
,
1603 IN THREADINFOCLASS ThreadInformationClass
,
1604 OUT PVOID ThreadInformation
,
1605 IN ULONG ThreadInformationLength
,
1606 OUT PULONG ReturnLength OPTIONAL
)
1609 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1613 PTHREAD_BASIC_INFORMATION ThreadBasicInfo
=
1614 (PTHREAD_BASIC_INFORMATION
)ThreadInformation
;
1615 PKERNEL_USER_TIMES ThreadTime
= (PKERNEL_USER_TIMES
)ThreadInformation
;
1619 /* Check if we were called from user mode */
1620 if (PreviousMode
!= KernelMode
)
1625 /* Probe the buffer */
1626 ProbeForWrite(ThreadInformation
,
1627 ThreadInformationLength
,
1630 /* Probe the return length if required */
1631 if (ReturnLength
) ProbeForWriteUlong(ReturnLength
);
1633 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1635 /* Return the exception code */
1636 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1641 /* Check what class this is */
1642 Access
= THREAD_QUERY_INFORMATION
;
1644 /* Reference the process */
1645 Status
= ObReferenceObjectByHandle(ThreadHandle
,
1651 if (!NT_SUCCESS(Status
)) return Status
;
1653 /* Check what kind of information class this is */
1654 switch (ThreadInformationClass
)
1656 /* Basic thread information */
1657 case ThreadBasicInformation
:
1659 /* Set return length */
1660 Length
= sizeof(THREAD_BASIC_INFORMATION
);
1662 if (ThreadInformationLength
!= Length
)
1664 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1667 /* Protect writes with SEH */
1670 /* Write all the information from the ETHREAD/KTHREAD */
1671 ThreadBasicInfo
->ExitStatus
= Thread
->ExitStatus
;
1672 ThreadBasicInfo
->TebBaseAddress
= (PVOID
)Thread
->Tcb
.Teb
;
1673 ThreadBasicInfo
->ClientId
= Thread
->Cid
;
1674 ThreadBasicInfo
->AffinityMask
= Thread
->Tcb
.Affinity
;
1675 ThreadBasicInfo
->Priority
= Thread
->Tcb
.Priority
;
1676 ThreadBasicInfo
->BasePriority
= KeQueryBasePriorityThread(&Thread
->Tcb
);
1678 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1680 /* Get exception code */
1681 Status
= _SEH2_GetExceptionCode();
1686 /* Thread time information */
1689 /* Set the return length */
1690 Length
= sizeof(KERNEL_USER_TIMES
);
1692 if (ThreadInformationLength
!= Length
)
1694 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1697 /* Protect writes with SEH */
1700 /* Copy time information from ETHREAD/KTHREAD */
1701 ThreadTime
->KernelTime
.QuadPart
= Thread
->Tcb
.KernelTime
*
1703 ThreadTime
->UserTime
.QuadPart
= Thread
->Tcb
.UserTime
*
1705 ThreadTime
->CreateTime
= Thread
->CreateTime
;
1706 ThreadTime
->ExitTime
= Thread
->ExitTime
;
1708 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1710 /* Get exception code */
1711 Status
= _SEH2_GetExceptionCode();
1716 case ThreadQuerySetWin32StartAddress
:
1718 /* Set the return length*/
1719 Length
= sizeof(PVOID
);
1721 if (ThreadInformationLength
!= Length
)
1723 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1726 /* Protect write with SEH */
1729 /* Return the Win32 Start Address */
1730 *(PVOID
*)ThreadInformation
= Thread
->Win32StartAddress
;
1732 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1734 /* Get exception code */
1735 Status
= _SEH2_GetExceptionCode();
1740 case ThreadPerformanceCount
:
1742 /* Set the return length*/
1743 Length
= sizeof(LARGE_INTEGER
);
1745 if (ThreadInformationLength
!= Length
)
1747 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1750 /* Protect write with SEH */
1754 (*(PLARGE_INTEGER
)ThreadInformation
).QuadPart
= 0;
1756 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1758 /* Get exception code */
1759 Status
= _SEH2_GetExceptionCode();
1764 case ThreadAmILastThread
:
1766 /* Set the return length*/
1767 Length
= sizeof(ULONG
);
1769 if (ThreadInformationLength
!= Length
)
1771 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1774 /* Protect write with SEH */
1777 /* Return whether or not we are the last thread */
1778 *(PULONG
)ThreadInformation
= ((Thread
->ThreadsProcess
->
1779 ThreadListHead
.Flink
->Flink
==
1780 &Thread
->ThreadsProcess
->
1784 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1786 /* Get exception code */
1787 Status
= _SEH2_GetExceptionCode();
1792 case ThreadIsIoPending
:
1794 /* Set the return length*/
1795 Length
= sizeof(ULONG
);
1797 if (ThreadInformationLength
!= Length
)
1799 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1802 /* Raise the IRQL to protect the IRP list */
1803 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1805 /* Protect write with SEH */
1808 /* Check if the IRP list is empty or not */
1809 *(PULONG
)ThreadInformation
= !IsListEmpty(&Thread
->IrpList
);
1811 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1813 /* Get exception code */
1814 Status
= _SEH2_GetExceptionCode();
1818 /* Lower IRQL back */
1819 KeLowerIrql(OldIrql
);
1822 /* LDT and GDT information */
1823 case ThreadDescriptorTableEntry
:
1826 /* Call the worker routine */
1827 Status
= PspQueryDescriptorThread(Thread
,
1829 ThreadInformationLength
,
1832 /* Only implemented on x86 */
1833 Status
= STATUS_NOT_IMPLEMENTED
;
1837 case ThreadPriorityBoost
:
1839 /* Set the return length*/
1840 Length
= sizeof(ULONG
);
1842 if (ThreadInformationLength
!= Length
)
1844 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1850 *(PULONG
)ThreadInformation
= Thread
->Tcb
.DisableBoost
? 1 : 0;
1852 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1854 Status
= _SEH2_GetExceptionCode();
1862 /* Not yet implemented */
1863 DPRINT1("Not implemented: %lx\n", ThreadInformationClass
);
1864 Status
= STATUS_NOT_IMPLEMENTED
;
1867 /* Protect write with SEH */
1870 /* Check if caller wanted return length */
1871 if (ReturnLength
) *ReturnLength
= Length
;
1873 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1875 /* Get exception code */
1876 Status
= _SEH2_GetExceptionCode();
1880 /* Dereference the thread, and return */
1881 ObDereferenceObject(Thread
);