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_PTR
)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
= PtrToUlong(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
:
451 /* Set the return length */
452 Length
= sizeof(ULONG_PTR
);
454 if (ProcessInformationLength
!= Length
)
456 Status
= STATUS_INFO_LENGTH_MISMATCH
;
460 /* Reference the process */
461 Status
= ObReferenceObjectByHandle(ProcessHandle
,
462 PROCESS_QUERY_INFORMATION
,
467 if (!NT_SUCCESS(Status
)) break;
469 DPRINT1("Not implemented: ProcessWow64Information\n");
471 /* Dereference the process */
472 ObDereferenceObject(Process
);
473 Status
= STATUS_NOT_IMPLEMENTED
;
476 /* Virtual Memory Statistics */
477 case ProcessVmCounters
:
479 /* Set the return length */
480 Length
= sizeof(VM_COUNTERS
);
482 if (ProcessInformationLength
!= Length
)
484 Status
= STATUS_INFO_LENGTH_MISMATCH
;
488 /* Reference the process */
489 Status
= ObReferenceObjectByHandle(ProcessHandle
,
490 PROCESS_QUERY_INFORMATION
,
495 if (!NT_SUCCESS(Status
)) break;
497 /* Enter SEH for write safety */
500 /* Return data from EPROCESS */
501 VmCounters
->PeakVirtualSize
= Process
->PeakVirtualSize
;
502 VmCounters
->VirtualSize
= Process
->VirtualSize
;
503 VmCounters
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
504 VmCounters
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
505 VmCounters
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
506 VmCounters
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeak
[0];
507 VmCounters
->QuotaPagedPoolUsage
= Process
->QuotaUsage
[0];
508 VmCounters
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeak
[1];
509 VmCounters
->QuotaNonPagedPoolUsage
= Process
->QuotaUsage
[1];
510 VmCounters
->PagefileUsage
= Process
->QuotaUsage
[2];
511 VmCounters
->PeakPagefileUsage
= Process
->QuotaPeak
[2];
514 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
516 /* Get the exception code */
517 Status
= _SEH2_GetExceptionCode();
521 /* Dereference the process */
522 ObDereferenceObject(Process
);
525 /* Hard Error Processing Mode */
526 case ProcessDefaultHardErrorMode
:
528 /* Set the return length*/
529 Length
= sizeof(ULONG
);
531 if (ProcessInformationLength
!= Length
)
533 Status
= STATUS_INFO_LENGTH_MISMATCH
;
537 /* Reference the process */
538 Status
= ObReferenceObjectByHandle(ProcessHandle
,
539 PROCESS_QUERY_INFORMATION
,
544 if (!NT_SUCCESS(Status
)) break;
546 /* Enter SEH for writing back data */
549 /* Write the current processing mode */
550 *(PULONG
)ProcessInformation
= Process
->
551 DefaultHardErrorProcessing
;
553 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
555 /* Get the exception code */
556 Status
= _SEH2_GetExceptionCode();
560 /* Dereference the process */
561 ObDereferenceObject(Process
);
564 /* Priority Boosting status */
565 case ProcessPriorityBoost
:
567 /* Set the return length*/
568 Length
= sizeof(ULONG
);
570 if (ProcessInformationLength
!= Length
)
572 Status
= STATUS_INFO_LENGTH_MISMATCH
;
576 /* Reference the process */
577 Status
= ObReferenceObjectByHandle(ProcessHandle
,
578 PROCESS_QUERY_INFORMATION
,
583 if (!NT_SUCCESS(Status
)) break;
585 /* Enter SEH for writing back data */
588 /* Return boost status */
589 *(PULONG
)ProcessInformation
= Process
->Pcb
.DisableBoost
?
592 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
594 /* Get the exception code */
595 Status
= _SEH2_GetExceptionCode();
599 /* Dereference the process */
600 ObDereferenceObject(Process
);
604 case ProcessDeviceMap
:
606 /* Set the return length*/
607 Length
= sizeof(PROCESS_DEVICEMAP_INFORMATION
);
609 if (ProcessInformationLength
!= Length
)
611 Status
= STATUS_INFO_LENGTH_MISMATCH
;
615 /* Reference the process */
616 Status
= ObReferenceObjectByHandle(ProcessHandle
,
617 PROCESS_QUERY_INFORMATION
,
622 if (!NT_SUCCESS(Status
)) break;
624 /* Query the device map information */
625 ObQueryDeviceMapInformation(Process
, &DeviceMap
);
627 /* Enter SEH for writing back data */
630 *(PPROCESS_DEVICEMAP_INFORMATION
)ProcessInformation
= DeviceMap
;
632 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
634 /* Get the exception code */
635 Status
= _SEH2_GetExceptionCode();
639 /* Dereference the process */
640 ObDereferenceObject(Process
);
644 case ProcessPriorityClass
:
646 /* Set the return length*/
647 Length
= sizeof(PROCESS_PRIORITY_CLASS
);
649 if (ProcessInformationLength
!= Length
)
651 Status
= STATUS_INFO_LENGTH_MISMATCH
;
655 /* Reference the process */
656 Status
= ObReferenceObjectByHandle(ProcessHandle
,
657 PROCESS_QUERY_INFORMATION
,
662 if (!NT_SUCCESS(Status
)) break;
664 /* Enter SEH for writing back data */
667 /* Return current priority class */
668 PsPriorityClass
->PriorityClass
= Process
->PriorityClass
;
669 PsPriorityClass
->Foreground
= FALSE
;
671 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
673 /* Get the exception code */
674 Status
= _SEH2_GetExceptionCode();
678 /* Dereference the process */
679 ObDereferenceObject(Process
);
682 case ProcessImageFileName
:
684 /* Reference the process */
685 Status
= ObReferenceObjectByHandle(ProcessHandle
,
686 PROCESS_QUERY_INFORMATION
,
691 if (!NT_SUCCESS(Status
)) break;
693 /* Get the image path */
694 Status
= SeLocateProcessImageName(Process
, &ImageName
);
695 if (NT_SUCCESS(Status
))
697 /* Set return length */
698 Length
= ImageName
->MaximumLength
+
699 sizeof(OBJECT_NAME_INFORMATION
);
701 /* Make sure it's large enough */
702 if (Length
<= ProcessInformationLength
)
704 /* Enter SEH to protect write */
708 RtlCopyMemory(ProcessInformation
,
713 ((PUNICODE_STRING
)ProcessInformation
)->Buffer
=
714 (PWSTR
)((PUNICODE_STRING
)ProcessInformation
+ 1);
716 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
718 /* Get the exception code */
719 Status
= _SEH2_GetExceptionCode();
725 /* Buffer too small */
726 Status
= STATUS_INFO_LENGTH_MISMATCH
;
729 /* Free the image path */
730 ExFreePool(ImageName
);
732 /* Dereference the process */
733 ObDereferenceObject(Process
);
736 /* Per-process security cookie */
739 /* Get the current process and cookie */
740 Process
= PsGetCurrentProcess();
741 Cookie
= Process
->Cookie
;
744 LARGE_INTEGER SystemTime
;
748 /* Generate a new cookie */
749 KeQuerySystemTime(&SystemTime
);
750 Prcb
= KeGetCurrentPrcb();
751 NewCookie
= Prcb
->KeSystemCalls
^ Prcb
->InterruptTime
^
752 SystemTime
.u
.LowPart
^ SystemTime
.u
.HighPart
;
754 /* Set the new cookie or return the current one */
755 Cookie
= InterlockedCompareExchange((LONG
*)&Process
->Cookie
,
758 if (!Cookie
) Cookie
= NewCookie
;
760 /* Set return length */
761 Length
= sizeof(ULONG
);
764 /* Enter SEH to protect write */
767 /* Write back the cookie */
768 *(PULONG
)ProcessInformation
= Cookie
;
770 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
772 /* Get the exception code */
773 Status
= _SEH2_GetExceptionCode();
778 /* Not yet implemented, or unknown */
779 case ProcessBasePriority
:
780 case ProcessRaisePriority
:
781 case ProcessExceptionPort
:
782 case ProcessAccessToken
:
784 case ProcessIoPortHandlers
:
785 case ProcessUserModeIOPL
:
786 case ProcessEnableAlignmentFaultFixup
:
787 case ProcessAffinityMask
:
788 case ProcessForegroundInformation
:
790 DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass
);
791 Status
= STATUS_INVALID_INFO_CLASS
;
794 /* Protect write with SEH */
797 /* Check if caller wanted return length */
798 if (ReturnLength
) *ReturnLength
= Length
;
800 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
802 /* Get exception code */
803 Status
= _SEH2_GetExceptionCode();
815 NtSetInformationProcess(IN HANDLE ProcessHandle
,
816 IN PROCESSINFOCLASS ProcessInformationClass
,
817 IN PVOID ProcessInformation
,
818 IN ULONG ProcessInformationLength
)
821 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
824 HANDLE PortHandle
= NULL
;
825 HANDLE TokenHandle
= NULL
;
826 PROCESS_SESSION_INFORMATION SessionInfo
= {0};
827 PROCESS_PRIORITY_CLASS PriorityClass
= {0};
831 /* Verify Information Class validity */
833 Status
= DefaultSetInfoBufferCheck(ProcessInformationClass
,
835 RTL_NUMBER_OF(PsProcessInfoClass
),
837 ProcessInformationLength
,
839 if (!NT_SUCCESS(Status
)) return Status
;
842 /* Check what class this is */
843 Access
= PROCESS_SET_INFORMATION
;
844 if (ProcessInformationClass
== ProcessSessionInformation
)
846 /* Setting the Session ID needs a special mask */
847 Access
|= PROCESS_SET_SESSIONID
;
849 else if (ProcessInformationClass
== ProcessExceptionPort
)
851 /* Setting the exception port needs a special mask */
852 Access
|= PROCESS_SUSPEND_RESUME
;
855 /* Reference the process */
856 Status
= ObReferenceObjectByHandle(ProcessHandle
,
862 if (!NT_SUCCESS(Status
)) return Status
;
864 /* Check what kind of information class this is */
865 switch (ProcessInformationClass
)
867 /* Error/Exception Port */
868 case ProcessExceptionPort
:
870 /* Check buffer length */
871 if (ProcessInformationLength
!= sizeof(HANDLE
))
873 Status
= STATUS_INFO_LENGTH_MISMATCH
;
877 /* Use SEH for capture */
880 /* Capture the handle */
881 PortHandle
= *(PHANDLE
)ProcessInformation
;
883 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
885 /* Get the exception code */
886 Status
= _SEH2_GetExceptionCode();
889 if (!NT_SUCCESS(Status
)) break;
891 /* Get the LPC Port */
892 Status
= ObReferenceObjectByHandle(PortHandle
,
896 (PVOID
)&ExceptionPort
,
898 if (!NT_SUCCESS(Status
)) break;
900 /* Change the pointer */
901 if (InterlockedCompareExchangePointer(&Process
->ExceptionPort
,
905 /* We already had one, fail */
906 ObDereferenceObject(ExceptionPort
);
907 Status
= STATUS_PORT_ALREADY_SET
;
912 case ProcessAccessToken
:
914 /* Check buffer length */
915 if (ProcessInformationLength
!= sizeof(PROCESS_ACCESS_TOKEN
))
917 Status
= STATUS_INFO_LENGTH_MISMATCH
;
921 /* Use SEH for capture */
924 /* Save the token handle */
925 TokenHandle
= ((PPROCESS_ACCESS_TOKEN
)ProcessInformation
)->
928 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
930 /* Get the exception code */
931 Status
= _SEH2_GetExceptionCode();
934 if (!NT_SUCCESS(Status
)) break;
936 /* Assign the actual token */
937 Status
= PspSetPrimaryToken(Process
, TokenHandle
, NULL
);
940 /* Hard error processing */
941 case ProcessDefaultHardErrorMode
:
943 /* Check buffer length */
944 if (ProcessInformationLength
!= sizeof(ULONG
))
946 Status
= STATUS_INFO_LENGTH_MISMATCH
;
950 /* Enter SEH for direct buffer read */
953 /* Update the current mode abd return the previous one */
954 InterlockedExchange((LONG
*)&Process
->DefaultHardErrorProcessing
,
955 *(PLONG
)ProcessInformation
);
957 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
959 /* Get exception code */
960 Status
= _SEH2_GetExceptionCode();
966 case ProcessSessionInformation
:
968 /* Check buffer length */
969 if (ProcessInformationLength
!= sizeof(PROCESS_SESSION_INFORMATION
))
971 Status
= STATUS_INFO_LENGTH_MISMATCH
;
975 /* Enter SEH for capture */
978 /* Capture the caller's buffer */
979 SessionInfo
= *(PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
981 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
983 /* Get the exception code */
984 Status
= _SEH2_GetExceptionCode();
987 if (!NT_SUCCESS(Status
)) break;
989 /* Setting the session id requires the SeTcbPrivilege */
990 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
992 /* Can't set the session ID, bail out. */
993 Status
= STATUS_PRIVILEGE_NOT_HELD
;
997 /* FIXME - update the session id for the process token */
998 //Status = PsLockProcess(Process, FALSE);
999 if (!NT_SUCCESS(Status
)) break;
1001 /* Write the session ID in the EPROCESS */
1002 Process
->Session
= SessionInfo
.SessionId
;
1004 /* Check if the process also has a PEB */
1008 * Attach to the process to make sure we're in the right
1009 * context to access the PEB structure
1011 KeAttachProcess(&Process
->Pcb
);
1013 /* Enter SEH for write to user-mode PEB */
1016 /* Write the session ID */
1017 Process
->Peb
->SessionId
= SessionInfo
.SessionId
;
1019 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1021 /* Get exception code */
1022 Status
= _SEH2_GetExceptionCode();
1026 /* Detach from the process */
1030 /* Unlock the process */
1031 //PsUnlockProcess(Process);
1034 case ProcessPriorityClass
:
1036 /* Check buffer length */
1037 if (ProcessInformationLength
!= sizeof(PROCESS_PRIORITY_CLASS
))
1039 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1043 /* Enter SEH for capture */
1046 /* Capture the caller's buffer */
1047 PriorityClass
= *(PPROCESS_PRIORITY_CLASS
)ProcessInformation
;
1049 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1051 /* Get the exception code */
1052 Status
= _SEH2_GetExceptionCode();
1055 if (!NT_SUCCESS(Status
)) break;
1057 /* Check for invalid PriorityClass value */
1058 if (PriorityClass
.PriorityClass
> PROCESS_PRIORITY_CLASS_ABOVE_NORMAL
)
1060 Status
= STATUS_INVALID_PARAMETER
;
1064 /* TODO: Check privileges */
1066 /* Check if we have a job */
1069 DPRINT1("Jobs not yet supported\n");
1072 /* Set process priority class */
1073 Process
->PriorityClass
= PriorityClass
.PriorityClass
;
1075 /* Set process priority mode (foreground or background) */
1076 PsSetProcessPriorityByClass(Process
,
1077 !PriorityClass
.Foreground
? PsProcessPriorityBackground
:
1078 PsProcessPriorityForeground
);
1080 Status
= STATUS_SUCCESS
;
1083 case ProcessQuotaLimits
:
1085 /* Check buffer length */
1086 if (ProcessInformationLength
!= sizeof(QUOTA_LIMITS
))
1088 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1092 DPRINT1("Not implemented: ProcessQuotaLimits\n");
1093 Status
= STATUS_NOT_IMPLEMENTED
;
1096 case ProcessBasePriority
:
1098 /* Check buffer length */
1099 if (ProcessInformationLength
!= sizeof(KPRIORITY
))
1101 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1105 DPRINT1("Not implemented: ProcessBasePriority\n");
1106 Status
= STATUS_NOT_IMPLEMENTED
;
1109 case ProcessRaisePriority
:
1111 /* Check buffer length */
1112 if (ProcessInformationLength
!= sizeof(ULONG
))
1114 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1118 DPRINT1("Not implemented: ProcessRaisePriority\n");
1119 Status
= STATUS_NOT_IMPLEMENTED
;
1122 case ProcessWx86Information
:
1124 /* Check buffer length */
1125 if (ProcessInformationLength
!= sizeof(HANDLE
))
1127 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1131 DPRINT1("Not implemented: ProcessWx86Information\n");
1132 Status
= STATUS_NOT_IMPLEMENTED
;
1135 case ProcessDebugPort
:
1137 /* Check buffer length */
1138 if (ProcessInformationLength
!= sizeof(HANDLE
))
1140 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1144 DPRINT1("Not implemented: ProcessDebugPort\n");
1145 Status
= STATUS_NOT_IMPLEMENTED
;
1148 /* We currently don't implement any of these */
1149 case ProcessLdtInformation
:
1150 case ProcessLdtSize
:
1151 case ProcessIoPortHandlers
:
1152 case ProcessWorkingSetWatch
:
1153 case ProcessUserModeIOPL
:
1154 case ProcessEnableAlignmentFaultFixup
:
1155 case ProcessAffinityMask
:
1156 DPRINT1("Not implemented: %lx\n", ProcessInformationClass
);
1157 Status
= STATUS_NOT_IMPLEMENTED
;
1160 /* Supposedly these are invalid...!? verify! */
1161 case ProcessBasicInformation
:
1162 case ProcessIoCounters
:
1164 case ProcessPooledUsageAndLimits
:
1165 case ProcessHandleCount
:
1166 case ProcessWow64Information
:
1168 DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass
);
1169 Status
= STATUS_INVALID_INFO_CLASS
;
1172 /* Dereference and return status */
1173 ObDereferenceObject(Process
);
1182 NtSetInformationThread(IN HANDLE ThreadHandle
,
1183 IN THREADINFOCLASS ThreadInformationClass
,
1184 IN PVOID ThreadInformation
,
1185 IN ULONG ThreadInformationLength
)
1189 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1191 HANDLE TokenHandle
= NULL
;
1192 KPRIORITY Priority
= 0;
1193 KAFFINITY Affinity
= 0, CombinedAffinity
;
1194 PVOID Address
= NULL
;
1196 ULONG DisableBoost
= 0;
1197 ULONG IdealProcessor
= 0;
1200 PVOID
*ExpansionSlots
;
1201 PETHREAD ProcThread
;
1204 /* Verify Information Class validity */
1206 Status
= DefaultSetInfoBufferCheck(ThreadInformationClass
,
1208 RTL_NUMBER_OF(PsThreadInfoClass
),
1210 ThreadInformationLength
,
1212 if (!NT_SUCCESS(Status
)) return Status
;
1215 /* Check what class this is */
1216 Access
= THREAD_SET_INFORMATION
;
1217 if (ThreadInformationClass
== ThreadImpersonationToken
)
1219 /* Setting the impersonation token needs a special mask */
1220 Access
= THREAD_SET_THREAD_TOKEN
;
1223 /* Reference the process */
1224 Status
= ObReferenceObjectByHandle(ThreadHandle
,
1230 if (!NT_SUCCESS(Status
)) return Status
;
1232 /* Check what kind of information class this is */
1233 switch (ThreadInformationClass
)
1235 /* Thread priority */
1236 case ThreadPriority
:
1238 /* Check buffer length */
1239 if (ThreadInformationLength
!= sizeof(KPRIORITY
))
1241 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1245 /* Use SEH for capture */
1248 /* Get the priority */
1249 Priority
= *(PLONG
)ThreadInformation
;
1251 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1253 /* Get the exception code */
1254 Status
= _SEH2_GetExceptionCode();
1257 if (!NT_SUCCESS(Status
)) break;
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 /* Get the exception code */
1290 Status
= _SEH2_GetExceptionCode();
1293 if (!NT_SUCCESS(Status
)) break;
1296 if ((Priority
> THREAD_BASE_PRIORITY_MAX
) ||
1297 (Priority
< THREAD_BASE_PRIORITY_MIN
))
1299 /* These ones are OK */
1300 if ((Priority
!= THREAD_BASE_PRIORITY_LOWRT
+ 1) &&
1301 (Priority
!= THREAD_BASE_PRIORITY_IDLE
- 1))
1303 /* Check if the process is real time */
1304 if (PsGetCurrentProcess()->PriorityClass
!=
1305 PROCESS_PRIORITY_CLASS_REALTIME
)
1307 /* It isn't, fail */
1308 Status
= STATUS_INVALID_PARAMETER
;
1314 /* Set the base priority */
1315 KeSetBasePriorityThread(&Thread
->Tcb
, Priority
);
1318 case ThreadAffinityMask
:
1320 /* Check buffer length */
1321 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1323 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1327 /* Use SEH for capture */
1330 /* Get the priority */
1331 Affinity
= *(PULONG_PTR
)ThreadInformation
;
1333 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1335 /* Get the exception code */
1336 Status
= _SEH2_GetExceptionCode();
1339 if (!NT_SUCCESS(Status
)) break;
1345 Status
= STATUS_INVALID_PARAMETER
;
1349 /* Get the process */
1350 Process
= Thread
->ThreadsProcess
;
1352 /* Try to acquire rundown */
1353 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1356 KeEnterCriticalRegion();
1357 ExAcquirePushLockShared(&Process
->ProcessLock
);
1360 CombinedAffinity
= Affinity
& Process
->Pcb
.Affinity
;
1361 if (CombinedAffinity
!= Affinity
)
1364 Status
= STATUS_INVALID_PARAMETER
;
1368 /* Set the affinity */
1369 KeSetAffinityThread(&Thread
->Tcb
, CombinedAffinity
);
1372 /* Release the lock and rundown */
1373 ExReleasePushLockShared(&Process
->ProcessLock
);
1374 KeLeaveCriticalRegion();
1375 ExReleaseRundownProtection(&Process
->RundownProtect
);
1380 Status
= STATUS_PROCESS_IS_TERMINATING
;
1386 case ThreadImpersonationToken
:
1388 /* Check buffer length */
1389 if (ThreadInformationLength
!= sizeof(HANDLE
))
1391 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1395 /* Use SEH for capture */
1398 /* Save the token handle */
1399 TokenHandle
= *(PHANDLE
)ThreadInformation
;
1401 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1403 /* Get the exception code */
1404 Status
= _SEH2_GetExceptionCode();
1407 if (!NT_SUCCESS(Status
)) break;
1409 /* Assign the actual token */
1410 Status
= PsAssignImpersonationToken(Thread
, TokenHandle
);
1413 case ThreadQuerySetWin32StartAddress
:
1415 /* Check buffer length */
1416 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1418 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1422 /* Use SEH for capture */
1425 /* Get the priority */
1426 Address
= *(PVOID
*)ThreadInformation
;
1428 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1430 /* Get the exception code */
1431 Status
= _SEH2_GetExceptionCode();
1434 if (!NT_SUCCESS(Status
)) break;
1436 /* Set the address */
1437 Thread
->Win32StartAddress
= Address
;
1440 case ThreadIdealProcessor
:
1442 /* Check buffer length */
1443 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1445 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1449 /* Use SEH for capture */
1452 /* Get the priority */
1453 IdealProcessor
= *(PULONG_PTR
)ThreadInformation
;
1455 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1457 /* Get the exception code */
1458 Status
= _SEH2_GetExceptionCode();
1461 if (!NT_SUCCESS(Status
)) break;
1464 if (IdealProcessor
> MAXIMUM_PROCESSORS
)
1467 Status
= STATUS_INVALID_PARAMETER
;
1472 Status
= KeSetIdealProcessorThread(&Thread
->Tcb
,
1473 (CCHAR
)IdealProcessor
);
1475 /* Get the TEB and protect the thread */
1476 Teb
= Thread
->Tcb
.Teb
;
1477 if ((Teb
) && (ExAcquireRundownProtection(&Thread
->RundownProtect
)))
1479 /* Save the ideal processor */
1480 Teb
->IdealProcessor
= Thread
->Tcb
.IdealProcessor
;
1482 /* Release rundown protection */
1483 ExReleaseRundownProtection(&Thread
->RundownProtect
);
1488 case ThreadPriorityBoost
:
1490 /* Check buffer length */
1491 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1493 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1497 /* Use SEH for capture */
1500 /* Get the priority */
1501 DisableBoost
= *(PULONG_PTR
)ThreadInformation
;
1503 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1505 /* Get the exception code */
1506 Status
= _SEH2_GetExceptionCode();
1509 if (!NT_SUCCESS(Status
)) break;
1511 /* Call the kernel */
1512 KeSetDisableBoostThread(&Thread
->Tcb
, (BOOLEAN
)DisableBoost
);
1515 case ThreadZeroTlsCell
:
1517 /* Check buffer length */
1518 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1520 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1524 /* Use SEH for capture */
1527 /* Get the priority */
1528 TlsIndex
= *(PULONG_PTR
)ThreadInformation
;
1530 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1532 /* Get the exception code */
1533 Status
= _SEH2_GetExceptionCode();
1536 if (!NT_SUCCESS(Status
)) break;
1538 /* This is only valid for the current thread */
1539 if (Thread
!= PsGetCurrentThread())
1542 Status
= STATUS_INVALID_PARAMETER
;
1546 /* Get the process */
1547 Process
= Thread
->ThreadsProcess
;
1549 /* Loop the threads */
1550 ProcThread
= PsGetNextProcessThread(Process
, NULL
);
1553 /* Acquire rundown */
1554 if (ExAcquireRundownProtection(&ProcThread
->RundownProtect
))
1557 Teb
= ProcThread
->Tcb
.Teb
;
1560 /* Check if we're in the expansion range */
1561 if (TlsIndex
> TLS_MINIMUM_AVAILABLE
- 1)
1563 if (TlsIndex
< (TLS_MINIMUM_AVAILABLE
+
1564 TLS_EXPANSION_SLOTS
) - 1)
1566 /* Check if we have expansion slots */
1567 ExpansionSlots
= Teb
->TlsExpansionSlots
;
1570 /* Clear the index */
1571 ExpansionSlots
[TlsIndex
- TLS_MINIMUM_AVAILABLE
] = 0;
1577 /* Clear the index */
1578 Teb
->TlsSlots
[TlsIndex
] = NULL
;
1582 /* Release rundown */
1583 ExReleaseRundownProtection(&ProcThread
->RundownProtect
);
1586 /* Go to the next thread */
1587 ProcThread
= PsGetNextProcessThread(Process
, ProcThread
);
1594 /* We don't implement it yet */
1595 DPRINT1("Not implemented: %lx\n", ThreadInformationClass
);
1596 Status
= STATUS_NOT_IMPLEMENTED
;
1599 /* Dereference and return status */
1600 ObDereferenceObject(Thread
);
1609 NtQueryInformationThread(IN HANDLE ThreadHandle
,
1610 IN THREADINFOCLASS ThreadInformationClass
,
1611 OUT PVOID ThreadInformation
,
1612 IN ULONG ThreadInformationLength
,
1613 OUT PULONG ReturnLength OPTIONAL
)
1616 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1617 NTSTATUS Status
= STATUS_SUCCESS
;
1620 PTHREAD_BASIC_INFORMATION ThreadBasicInfo
=
1621 (PTHREAD_BASIC_INFORMATION
)ThreadInformation
;
1622 PKERNEL_USER_TIMES ThreadTime
= (PKERNEL_USER_TIMES
)ThreadInformation
;
1626 if (PreviousMode
!= KernelMode
)
1630 ProbeForWrite(ThreadInformation
,
1631 ThreadInformationLength
,
1636 ProbeForWriteUlong(ReturnLength
);
1639 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1641 Status
= _SEH2_GetExceptionCode();
1645 if (!NT_SUCCESS(Status
)) return Status
;
1648 /* Check what class this is */
1649 Access
= THREAD_QUERY_INFORMATION
;
1651 /* Reference the process */
1652 Status
= ObReferenceObjectByHandle(ThreadHandle
,
1658 if (!NT_SUCCESS(Status
)) return Status
;
1660 /* Check what kind of information class this is */
1661 switch (ThreadInformationClass
)
1663 /* Basic thread information */
1664 case ThreadBasicInformation
:
1666 /* Set return length */
1667 Length
= sizeof(THREAD_BASIC_INFORMATION
);
1669 if (ThreadInformationLength
!= Length
)
1671 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1674 /* Protect writes with SEH */
1677 /* Write all the information from the ETHREAD/KTHREAD */
1678 ThreadBasicInfo
->ExitStatus
= Thread
->ExitStatus
;
1679 ThreadBasicInfo
->TebBaseAddress
= (PVOID
)Thread
->Tcb
.Teb
;
1680 ThreadBasicInfo
->ClientId
= Thread
->Cid
;
1681 ThreadBasicInfo
->AffinityMask
= Thread
->Tcb
.Affinity
;
1682 ThreadBasicInfo
->Priority
= Thread
->Tcb
.Priority
;
1683 ThreadBasicInfo
->BasePriority
= KeQueryBasePriorityThread(&Thread
->Tcb
);
1685 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1687 /* Get exception code */
1688 Status
= _SEH2_GetExceptionCode();
1693 /* Thread time information */
1696 /* Set the return length */
1697 Length
= sizeof(KERNEL_USER_TIMES
);
1699 if (ThreadInformationLength
!= Length
)
1701 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1704 /* Protect writes with SEH */
1707 /* Copy time information from ETHREAD/KTHREAD */
1708 ThreadTime
->KernelTime
.QuadPart
= Thread
->Tcb
.KernelTime
*
1710 ThreadTime
->UserTime
.QuadPart
= Thread
->Tcb
.UserTime
*
1712 ThreadTime
->CreateTime
= Thread
->CreateTime
;
1713 ThreadTime
->ExitTime
= Thread
->ExitTime
;
1715 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1717 /* Get exception code */
1718 Status
= _SEH2_GetExceptionCode();
1723 case ThreadQuerySetWin32StartAddress
:
1725 /* Set the return length*/
1726 Length
= sizeof(PVOID
);
1728 if (ThreadInformationLength
!= Length
)
1730 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1733 /* Protect write with SEH */
1736 /* Return the Win32 Start Address */
1737 *(PVOID
*)ThreadInformation
= Thread
->Win32StartAddress
;
1739 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1741 /* Get exception code */
1742 Status
= _SEH2_GetExceptionCode();
1747 case ThreadPerformanceCount
:
1749 /* Set the return length*/
1750 Length
= sizeof(LARGE_INTEGER
);
1752 if (ThreadInformationLength
!= Length
)
1754 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1757 /* Protect write with SEH */
1761 (*(PLARGE_INTEGER
)ThreadInformation
).QuadPart
= 0;
1763 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1765 /* Get exception code */
1766 Status
= _SEH2_GetExceptionCode();
1771 case ThreadAmILastThread
:
1773 /* Set the return length*/
1774 Length
= sizeof(ULONG
);
1776 if (ThreadInformationLength
!= Length
)
1778 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1781 /* Protect write with SEH */
1784 /* Return whether or not we are the last thread */
1785 *(PULONG
)ThreadInformation
= ((Thread
->ThreadsProcess
->
1786 ThreadListHead
.Flink
->Flink
==
1787 &Thread
->ThreadsProcess
->
1791 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1793 /* Get exception code */
1794 Status
= _SEH2_GetExceptionCode();
1799 case ThreadIsIoPending
:
1801 /* Set the return length*/
1802 Length
= sizeof(ULONG
);
1804 if (ThreadInformationLength
!= Length
)
1806 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1809 /* Raise the IRQL to protect the IRP list */
1810 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1812 /* Protect write with SEH */
1815 /* Check if the IRP list is empty or not */
1816 *(PULONG
)ThreadInformation
= !IsListEmpty(&Thread
->IrpList
);
1818 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1820 /* Get exception code */
1821 Status
= _SEH2_GetExceptionCode();
1825 /* Lower IRQL back */
1826 KeLowerIrql(OldIrql
);
1829 case ThreadDescriptorTableEntry
:
1830 DPRINT1("NtQueryInformationThread(): case ThreadDescriptorTableEntry not implemented!\n");
1831 Status
= STATUS_NOT_IMPLEMENTED
;
1834 case ThreadPriorityBoost
:
1836 /* Set the return length*/
1837 Length
= sizeof(ULONG
);
1839 if (ThreadInformationLength
!= Length
)
1841 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1847 *(PULONG
)ThreadInformation
= Thread
->Tcb
.DisableBoost
? 1 : 0;
1849 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1851 Status
= _SEH2_GetExceptionCode();
1859 /* Not yet implemented */
1860 DPRINT1("Not implemented: %lx\n", ThreadInformationClass
);
1861 Status
= STATUS_NOT_IMPLEMENTED
;
1864 /* Protect write with SEH */
1867 /* Check if caller wanted return length */
1868 if (ReturnLength
) *ReturnLength
= Length
;
1870 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1872 /* Get exception code */
1873 Status
= _SEH2_GetExceptionCode();
1877 /* Dereference the thread, and return */
1878 ObDereferenceObject(Thread
);