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)
11 /* INCLUDES ******************************************************************/
17 /* Include Information Class Tables */
18 #include "internal/ps_i.h"
21 ULONG PspTraceLevel
= 0;
23 /* PRIVATE FUNCTIONS *********************************************************/
27 PsReferenceProcessFilePointer(IN PEPROCESS Process
,
28 OUT PFILE_OBJECT
*FileObject
)
33 /* Lock the process */
34 ExAcquireRundownProtection(&Process
->RundownProtect
);
37 Section
= Process
->SectionObject
;
40 /* Get the file object and reference it */
41 *FileObject
= MmGetFileObjectForSection((PVOID
)Section
);
42 ObReferenceObject(*FileObject
);
45 /* Release the protection */
46 ExReleaseRundownProtection(&Process
->RundownProtect
);
49 return Section
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
;
52 /* PUBLIC FUNCTIONS **********************************************************/
59 NtQueryInformationProcess(IN HANDLE ProcessHandle
,
60 IN PROCESSINFOCLASS ProcessInformationClass
,
61 OUT PVOID ProcessInformation
,
62 IN ULONG ProcessInformationLength
,
63 OUT PULONG ReturnLength OPTIONAL
)
66 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
69 PPROCESS_BASIC_INFORMATION ProcessBasicInfo
=
70 (PPROCESS_BASIC_INFORMATION
)ProcessInformation
;
71 PKERNEL_USER_TIMES ProcessTime
= (PKERNEL_USER_TIMES
)ProcessInformation
;
72 PPROCESS_PRIORITY_CLASS PsPriorityClass
= (PPROCESS_PRIORITY_CLASS
)ProcessInformation
;
74 PPROCESS_SESSION_INFORMATION SessionInfo
=
75 (PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
76 PVM_COUNTERS VmCounters
= (PVM_COUNTERS
)ProcessInformation
;
77 PIO_COUNTERS IoCounters
= (PIO_COUNTERS
)ProcessInformation
;
78 PQUOTA_LIMITS QuotaLimits
= (PQUOTA_LIMITS
)ProcessInformation
;
79 PROCESS_DEVICEMAP_INFORMATION DeviceMap
;
80 PUNICODE_STRING ImageName
;
84 /* Check for user-mode caller */
85 if (PreviousMode
!= KernelMode
)
87 /* Prepare to probe parameters */
90 /* Probe the buffer */
91 ProbeForWrite(ProcessInformation
,
92 ProcessInformationLength
,
95 /* Probe the return length if required */
96 if (ReturnLength
) ProbeForWriteUlong(ReturnLength
);
98 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
100 /* Return the exception code */
101 _SEH2_YIELD(return _SEH2_GetExceptionCode());
106 if((ProcessInformationClass
== ProcessCookie
) &&
107 (ProcessHandle
!= NtCurrentProcess()))
110 * Retreiving the process cookie is only allowed for the calling process
111 * itself! XP only allowes NtCurrentProcess() as process handles even if
112 * a real handle actually represents the current process.
114 return STATUS_INVALID_PARAMETER
;
117 /* Check the information class */
118 switch (ProcessInformationClass
)
120 /* Basic process information */
121 case ProcessBasicInformation
:
123 /* Set return length */
124 Length
= sizeof(PROCESS_BASIC_INFORMATION
);
126 if (ProcessInformationLength
!= Length
)
128 Status
= STATUS_INFO_LENGTH_MISMATCH
;
132 /* Reference the process */
133 Status
= ObReferenceObjectByHandle(ProcessHandle
,
134 PROCESS_QUERY_INFORMATION
,
139 if (!NT_SUCCESS(Status
)) break;
141 /* Protect writes with SEH */
144 /* Write all the information from the EPROCESS/KPROCESS */
145 ProcessBasicInfo
->ExitStatus
= Process
->ExitStatus
;
146 ProcessBasicInfo
->PebBaseAddress
= Process
->Peb
;
147 ProcessBasicInfo
->AffinityMask
= Process
->Pcb
.Affinity
;
148 ProcessBasicInfo
->UniqueProcessId
= (ULONG_PTR
)Process
->
150 ProcessBasicInfo
->InheritedFromUniqueProcessId
=
151 (ULONG
)Process
->InheritedFromUniqueProcessId
;
152 ProcessBasicInfo
->BasePriority
= Process
->Pcb
.BasePriority
;
155 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
157 /* Get exception code */
158 Status
= _SEH2_GetExceptionCode();
162 /* Dereference the process */
163 ObDereferenceObject(Process
);
166 /* Process quota limits */
167 case ProcessQuotaLimits
:
169 Length
= sizeof(QUOTA_LIMITS
);
170 if (ProcessInformationLength
!= Length
)
172 Status
= STATUS_INFO_LENGTH_MISMATCH
;
176 /* Reference the process */
177 Status
= ObReferenceObjectByHandle(ProcessHandle
,
178 PROCESS_QUERY_INFORMATION
,
183 if (!NT_SUCCESS(Status
)) break;
185 /* Indicate success */
186 Status
= STATUS_SUCCESS
;
190 /* Set max/min working set sizes */
191 QuotaLimits
->MaximumWorkingSetSize
=
192 Process
->Vm
.MaximumWorkingSetSize
<< PAGE_SHIFT
;
193 QuotaLimits
->MinimumWorkingSetSize
=
194 Process
->Vm
.MinimumWorkingSetSize
<< PAGE_SHIFT
;
196 /* Set default time limits */
197 QuotaLimits
->TimeLimit
.LowPart
= MAXULONG
;
198 QuotaLimits
->TimeLimit
.HighPart
= MAXULONG
;
200 /* Is quota block a default one? */
201 if (Process
->QuotaBlock
== &PspDefaultQuotaBlock
)
203 /* Set default pools and pagefile limits */
204 QuotaLimits
->PagedPoolLimit
= (SIZE_T
)-1;
205 QuotaLimits
->NonPagedPoolLimit
= (SIZE_T
)-1;
206 QuotaLimits
->PagefileLimit
= (SIZE_T
)-1;
210 /* Get limits from non-default quota block */
211 QuotaLimits
->PagedPoolLimit
=
212 Process
->QuotaBlock
->QuotaEntry
[PagedPool
].Limit
;
213 QuotaLimits
->NonPagedPoolLimit
=
214 Process
->QuotaBlock
->QuotaEntry
[NonPagedPool
].Limit
;
215 QuotaLimits
->PagefileLimit
=
216 Process
->QuotaBlock
->QuotaEntry
[2].Limit
;
219 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
221 /* Get exception code */
222 Status
= _SEH2_GetExceptionCode();
226 /* Dereference the process */
227 ObDereferenceObject(Process
);
230 case ProcessIoCounters
:
232 Length
= sizeof(IO_COUNTERS
);
233 if (ProcessInformationLength
!= Length
)
235 Status
= STATUS_INFO_LENGTH_MISMATCH
;
239 /* Reference the process */
240 Status
= ObReferenceObjectByHandle(ProcessHandle
,
241 PROCESS_QUERY_INFORMATION
,
246 if (!NT_SUCCESS(Status
)) break;
250 IoCounters
->ReadOperationCount
= Process
->ReadOperationCount
.QuadPart
;
251 IoCounters
->ReadTransferCount
= Process
->ReadTransferCount
.QuadPart
;
252 IoCounters
->WriteOperationCount
= Process
->WriteOperationCount
.QuadPart
;
253 IoCounters
->WriteTransferCount
= Process
->WriteTransferCount
.QuadPart
;
254 IoCounters
->OtherOperationCount
= Process
->OtherOperationCount
.QuadPart
;
255 IoCounters
->OtherTransferCount
= Process
->OtherTransferCount
.QuadPart
;
257 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
259 /* Ignore exception */
263 /* Set status to success in any case */
264 Status
= STATUS_SUCCESS
;
266 /* Dereference the process */
267 ObDereferenceObject(Process
);
273 /* Set the return length */
274 Length
= sizeof(KERNEL_USER_TIMES
);
276 if (ProcessInformationLength
!= Length
)
278 Status
= STATUS_INFO_LENGTH_MISMATCH
;
282 /* Reference the process */
283 Status
= ObReferenceObjectByHandle(ProcessHandle
,
284 PROCESS_QUERY_INFORMATION
,
289 if (!NT_SUCCESS(Status
)) break;
291 /* Protect writes with SEH */
294 /* Copy time information from EPROCESS/KPROCESS */
295 ProcessTime
->CreateTime
= Process
->CreateTime
;
296 ProcessTime
->UserTime
.QuadPart
= Process
->Pcb
.UserTime
*
298 ProcessTime
->KernelTime
.QuadPart
= Process
->Pcb
.KernelTime
*
300 ProcessTime
->ExitTime
= Process
->ExitTime
;
302 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
304 /* Get exception code */
305 Status
= _SEH2_GetExceptionCode();
309 /* Dereference the process */
310 ObDereferenceObject(Process
);
313 /* Process Debug Port */
314 case ProcessDebugPort
:
316 /* Set return length */
317 Length
= sizeof(HANDLE
);
319 if (ProcessInformationLength
!= Length
)
321 Status
= STATUS_INFO_LENGTH_MISMATCH
;
325 /* Reference the process */
326 Status
= ObReferenceObjectByHandle(ProcessHandle
,
327 PROCESS_QUERY_INFORMATION
,
332 if (!NT_SUCCESS(Status
)) break;
334 /* Protect write with SEH */
337 /* Return whether or not we have a debug port */
338 *(PHANDLE
)ProcessInformation
= (Process
->DebugPort
?
341 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
343 /* Get exception code */
344 Status
= _SEH2_GetExceptionCode();
348 /* Dereference the process */
349 ObDereferenceObject(Process
);
352 /* LDT, WS and VDM Information: not implemented */
353 case ProcessLdtInformation
:
354 case ProcessWorkingSetWatch
:
355 case ProcessWx86Information
:
357 /* Reference the process */
358 Status
= ObReferenceObjectByHandle(ProcessHandle
,
359 PROCESS_QUERY_INFORMATION
,
364 if (!NT_SUCCESS(Status
)) break;
366 DPRINT1("Not implemented: %lx\n", ProcessInformationClass
);
368 /* Dereference the process */
369 ObDereferenceObject(Process
);
370 Status
= STATUS_NOT_IMPLEMENTED
;
373 case ProcessHandleCount
:
375 /* Set the return length*/
376 Length
= sizeof(ULONG
);
378 if (ProcessInformationLength
!= Length
)
380 Status
= STATUS_INFO_LENGTH_MISMATCH
;
384 /* Reference the process */
385 Status
= ObReferenceObjectByHandle(ProcessHandle
,
386 PROCESS_QUERY_INFORMATION
,
391 if (!NT_SUCCESS(Status
)) break;
393 /* Count the number of handles this process has */
394 HandleCount
= ObGetProcessHandleCount(Process
);
396 /* Protect write in SEH */
399 /* Return the count of handles */
400 *(PULONG
)ProcessInformation
= HandleCount
;
402 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
404 /* Get the exception code */
405 Status
= _SEH2_GetExceptionCode();
409 /* Dereference the process */
410 ObDereferenceObject(Process
);
413 /* Session ID for the process */
414 case ProcessSessionInformation
:
416 /* Set the return length*/
417 Length
= sizeof(PROCESS_SESSION_INFORMATION
);
419 if (ProcessInformationLength
!= Length
)
421 Status
= STATUS_INFO_LENGTH_MISMATCH
;
425 /* Reference the process */
426 Status
= ObReferenceObjectByHandle(ProcessHandle
,
427 PROCESS_QUERY_INFORMATION
,
432 if (!NT_SUCCESS(Status
)) break;
434 /* Enter SEH for write safety */
437 /* Write back the Session ID */
438 SessionInfo
->SessionId
= Process
->Session
;
440 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
442 /* Get the exception code */
443 Status
= _SEH2_GetExceptionCode();
447 /* Dereference the process */
448 ObDereferenceObject(Process
);
451 /* WOW64: Not implemented */
452 case ProcessWow64Information
:
454 /* Set the return length */
455 Length
= sizeof(ULONG_PTR
);
457 if (ProcessInformationLength
!= Length
)
459 Status
= STATUS_INFO_LENGTH_MISMATCH
;
463 /* Reference the process */
464 Status
= ObReferenceObjectByHandle(ProcessHandle
,
465 PROCESS_QUERY_INFORMATION
,
470 if (!NT_SUCCESS(Status
)) break;
472 DPRINT1("Not implemented: ProcessWow64Information\n");
474 /* Dereference the process */
475 ObDereferenceObject(Process
);
476 Status
= STATUS_NOT_IMPLEMENTED
;
479 /* Virtual Memory Statistics */
480 case ProcessVmCounters
:
482 /* Set the return length */
483 Length
= sizeof(VM_COUNTERS
);
485 if (ProcessInformationLength
!= Length
)
487 Status
= STATUS_INFO_LENGTH_MISMATCH
;
491 /* Reference the process */
492 Status
= ObReferenceObjectByHandle(ProcessHandle
,
493 PROCESS_QUERY_INFORMATION
,
498 if (!NT_SUCCESS(Status
)) break;
500 /* Enter SEH for write safety */
503 /* Return data from EPROCESS */
504 VmCounters
->PeakVirtualSize
= Process
->PeakVirtualSize
;
505 VmCounters
->VirtualSize
= Process
->VirtualSize
;
506 VmCounters
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
507 VmCounters
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
508 VmCounters
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
509 VmCounters
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeak
[0];
510 VmCounters
->QuotaPagedPoolUsage
= Process
->QuotaUsage
[0];
511 VmCounters
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeak
[1];
512 VmCounters
->QuotaNonPagedPoolUsage
= Process
->QuotaUsage
[1];
513 VmCounters
->PagefileUsage
= Process
->QuotaUsage
[2];
514 VmCounters
->PeakPagefileUsage
= Process
->QuotaPeak
[2];
517 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
519 /* Get the exception code */
520 Status
= _SEH2_GetExceptionCode();
524 /* Dereference the process */
525 ObDereferenceObject(Process
);
528 /* Hard Error Processing Mode */
529 case ProcessDefaultHardErrorMode
:
531 /* Set the return length*/
532 Length
= sizeof(ULONG
);
534 if (ProcessInformationLength
!= Length
)
536 Status
= STATUS_INFO_LENGTH_MISMATCH
;
540 /* Reference the process */
541 Status
= ObReferenceObjectByHandle(ProcessHandle
,
542 PROCESS_QUERY_INFORMATION
,
547 if (!NT_SUCCESS(Status
)) break;
549 /* Enter SEH for writing back data */
552 /* Write the current processing mode */
553 *(PULONG
)ProcessInformation
= Process
->
554 DefaultHardErrorProcessing
;
556 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
558 /* Get the exception code */
559 Status
= _SEH2_GetExceptionCode();
563 /* Dereference the process */
564 ObDereferenceObject(Process
);
567 /* Priority Boosting status */
568 case ProcessPriorityBoost
:
570 /* Set the return length*/
571 Length
= sizeof(ULONG
);
573 if (ProcessInformationLength
!= Length
)
575 Status
= STATUS_INFO_LENGTH_MISMATCH
;
579 /* Reference the process */
580 Status
= ObReferenceObjectByHandle(ProcessHandle
,
581 PROCESS_QUERY_INFORMATION
,
586 if (!NT_SUCCESS(Status
)) break;
588 /* Enter SEH for writing back data */
591 /* Return boost status */
592 *(PULONG
)ProcessInformation
= Process
->Pcb
.DisableBoost
?
595 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
597 /* Get the exception code */
598 Status
= _SEH2_GetExceptionCode();
602 /* Dereference the process */
603 ObDereferenceObject(Process
);
607 case ProcessDeviceMap
:
609 /* Set the return length*/
610 Length
= sizeof(PROCESS_DEVICEMAP_INFORMATION
);
612 if (ProcessInformationLength
!= Length
)
614 Status
= STATUS_INFO_LENGTH_MISMATCH
;
618 /* Reference the process */
619 Status
= ObReferenceObjectByHandle(ProcessHandle
,
620 PROCESS_QUERY_INFORMATION
,
625 if (!NT_SUCCESS(Status
)) break;
627 /* Query the device map information */
628 ObQueryDeviceMapInformation(Process
, &DeviceMap
);
630 /* Enter SEH for writing back data */
633 *(PPROCESS_DEVICEMAP_INFORMATION
)ProcessInformation
= DeviceMap
;
635 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
637 /* Get the exception code */
638 Status
= _SEH2_GetExceptionCode();
642 /* Dereference the process */
643 ObDereferenceObject(Process
);
647 case ProcessPriorityClass
:
649 /* Set the return length*/
650 Length
= sizeof(PROCESS_PRIORITY_CLASS
);
652 if (ProcessInformationLength
!= Length
)
654 Status
= STATUS_INFO_LENGTH_MISMATCH
;
658 /* Reference the process */
659 Status
= ObReferenceObjectByHandle(ProcessHandle
,
660 PROCESS_QUERY_INFORMATION
,
665 if (!NT_SUCCESS(Status
)) break;
667 /* Enter SEH for writing back data */
670 /* Return current priority class */
671 PsPriorityClass
->PriorityClass
= Process
->PriorityClass
;
672 PsPriorityClass
->Foreground
= FALSE
;
674 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
676 /* Get the exception code */
677 Status
= _SEH2_GetExceptionCode();
681 /* Dereference the process */
682 ObDereferenceObject(Process
);
685 case ProcessImageFileName
:
687 /* Reference the process */
688 Status
= ObReferenceObjectByHandle(ProcessHandle
,
689 PROCESS_QUERY_INFORMATION
,
694 if (!NT_SUCCESS(Status
)) break;
696 /* Get the image path */
697 Status
= SeLocateProcessImageName(Process
, &ImageName
);
698 if (NT_SUCCESS(Status
))
700 /* Set return length */
701 Length
= ImageName
->MaximumLength
+
702 sizeof(OBJECT_NAME_INFORMATION
);
704 /* Make sure it's large enough */
705 if (Length
<= ProcessInformationLength
)
707 /* Enter SEH to protect write */
711 RtlCopyMemory(ProcessInformation
,
716 ((PUNICODE_STRING
)ProcessInformation
)->Buffer
=
717 (PWSTR
)((PUNICODE_STRING
)ProcessInformation
+ 1);
719 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
721 /* Get the exception code */
722 Status
= _SEH2_GetExceptionCode();
728 /* Buffer too small */
729 Status
= STATUS_INFO_LENGTH_MISMATCH
;
732 /* Free the image path */
733 ExFreePool(ImageName
);
735 /* Dereference the process */
736 ObDereferenceObject(Process
);
739 case ProcessBreakOnTermination
:
741 /* Set the return length*/
742 Length
= sizeof(ULONG
);
743 if (ProcessInformationLength
!= Length
)
745 Status
= STATUS_INFO_LENGTH_MISMATCH
;
749 /* Reference the process */
750 Status
= ObReferenceObjectByHandle(ProcessHandle
,
751 PROCESS_QUERY_INFORMATION
,
756 if (!NT_SUCCESS(Status
)) break;
758 /* Enter SEH for writing back data */
761 /* Return the BreakOnTermination state */
762 *(PULONG
)ProcessInformation
= Process
->BreakOnTermination
;
764 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
766 /* Get the exception code */
767 Status
= _SEH2_GetExceptionCode();
771 /* Dereference the process */
772 ObDereferenceObject(Process
);
775 /* Per-process security cookie */
778 /* Get the current process and cookie */
779 Process
= PsGetCurrentProcess();
780 Cookie
= Process
->Cookie
;
783 LARGE_INTEGER SystemTime
;
787 /* Generate a new cookie */
788 KeQuerySystemTime(&SystemTime
);
789 Prcb
= KeGetCurrentPrcb();
790 NewCookie
= Prcb
->KeSystemCalls
^ Prcb
->InterruptTime
^
791 SystemTime
.u
.LowPart
^ SystemTime
.u
.HighPart
;
793 /* Set the new cookie or return the current one */
794 Cookie
= InterlockedCompareExchange((LONG
*)&Process
->Cookie
,
797 if (!Cookie
) Cookie
= NewCookie
;
799 /* Set return length */
800 Length
= sizeof(ULONG
);
803 /* Indicate success */
804 Status
= STATUS_SUCCESS
;
806 /* Enter SEH to protect write */
809 /* Write back the cookie */
810 *(PULONG
)ProcessInformation
= Cookie
;
812 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
814 /* Get the exception code */
815 Status
= _SEH2_GetExceptionCode();
820 /* Not yet implemented, or unknown */
821 case ProcessBasePriority
:
822 case ProcessRaisePriority
:
823 case ProcessExceptionPort
:
824 case ProcessAccessToken
:
826 case ProcessIoPortHandlers
:
827 case ProcessUserModeIOPL
:
828 case ProcessEnableAlignmentFaultFixup
:
829 case ProcessAffinityMask
:
830 case ProcessForegroundInformation
:
832 DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass
);
833 Status
= STATUS_INVALID_INFO_CLASS
;
836 /* Protect write with SEH */
839 /* Check if caller wanted return length */
840 if (ReturnLength
) *ReturnLength
= Length
;
842 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
844 /* Get exception code */
845 Status
= _SEH2_GetExceptionCode();
857 NtSetInformationProcess(IN HANDLE ProcessHandle
,
858 IN PROCESSINFOCLASS ProcessInformationClass
,
859 IN PVOID ProcessInformation
,
860 IN ULONG ProcessInformationLength
)
863 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
866 HANDLE PortHandle
= NULL
;
867 HANDLE TokenHandle
= NULL
;
868 PROCESS_SESSION_INFORMATION SessionInfo
= {0};
869 PROCESS_PRIORITY_CLASS PriorityClass
= {0};
874 /* Verify Information Class validity */
876 Status
= DefaultSetInfoBufferCheck(ProcessInformationClass
,
878 RTL_NUMBER_OF(PsProcessInfoClass
),
880 ProcessInformationLength
,
882 if (!NT_SUCCESS(Status
)) return Status
;
885 /* Check what class this is */
886 Access
= PROCESS_SET_INFORMATION
;
887 if (ProcessInformationClass
== ProcessSessionInformation
)
889 /* Setting the Session ID needs a special mask */
890 Access
|= PROCESS_SET_SESSIONID
;
892 else if (ProcessInformationClass
== ProcessExceptionPort
)
894 /* Setting the exception port needs a special mask */
895 Access
|= PROCESS_SUSPEND_RESUME
;
898 /* Reference the process */
899 Status
= ObReferenceObjectByHandle(ProcessHandle
,
905 if (!NT_SUCCESS(Status
)) return Status
;
907 /* Check what kind of information class this is */
908 switch (ProcessInformationClass
)
910 /* Error/Exception Port */
911 case ProcessExceptionPort
:
913 /* Check buffer length */
914 if (ProcessInformationLength
!= sizeof(HANDLE
))
916 Status
= STATUS_INFO_LENGTH_MISMATCH
;
920 /* Use SEH for capture */
923 /* Capture the handle */
924 PortHandle
= *(PHANDLE
)ProcessInformation
;
926 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
928 /* Get the exception code */
929 Status
= _SEH2_GetExceptionCode();
934 /* Get the LPC Port */
935 Status
= ObReferenceObjectByHandle(PortHandle
,
939 (PVOID
)&ExceptionPort
,
941 if (!NT_SUCCESS(Status
)) break;
943 /* Change the pointer */
944 if (InterlockedCompareExchangePointer(&Process
->ExceptionPort
,
948 /* We already had one, fail */
949 ObDereferenceObject(ExceptionPort
);
950 Status
= STATUS_PORT_ALREADY_SET
;
955 case ProcessAccessToken
:
957 /* Check buffer length */
958 if (ProcessInformationLength
!= sizeof(PROCESS_ACCESS_TOKEN
))
960 Status
= STATUS_INFO_LENGTH_MISMATCH
;
964 /* Use SEH for capture */
967 /* Save the token handle */
968 TokenHandle
= ((PPROCESS_ACCESS_TOKEN
)ProcessInformation
)->
971 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
973 /* Get the exception code */
974 Status
= _SEH2_GetExceptionCode();
979 /* Assign the actual token */
980 Status
= PspSetPrimaryToken(Process
, TokenHandle
, NULL
);
983 /* Hard error processing */
984 case ProcessDefaultHardErrorMode
:
986 /* Check buffer length */
987 if (ProcessInformationLength
!= sizeof(ULONG
))
989 Status
= STATUS_INFO_LENGTH_MISMATCH
;
993 /* Enter SEH for direct buffer read */
996 /* Update the current mode abd return the previous one */
997 InterlockedExchange((LONG
*)&Process
->DefaultHardErrorProcessing
,
998 *(PLONG
)ProcessInformation
);
1000 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1002 /* Get exception code */
1003 Status
= _SEH2_GetExceptionCode();
1009 case ProcessSessionInformation
:
1011 /* Check buffer length */
1012 if (ProcessInformationLength
!= sizeof(PROCESS_SESSION_INFORMATION
))
1014 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1018 /* Enter SEH for capture */
1021 /* Capture the caller's buffer */
1022 SessionInfo
= *(PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
1024 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1026 /* Get the exception code */
1027 Status
= _SEH2_GetExceptionCode();
1032 /* Setting the session id requires the SeTcbPrivilege */
1033 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
1035 /* Can't set the session ID, bail out. */
1036 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1040 /* FIXME - update the session id for the process token */
1041 //Status = PsLockProcess(Process, FALSE);
1042 if (!NT_SUCCESS(Status
)) break;
1044 /* Write the session ID in the EPROCESS */
1045 Process
->Session
= SessionInfo
.SessionId
;
1047 /* Check if the process also has a PEB */
1051 * Attach to the process to make sure we're in the right
1052 * context to access the PEB structure
1054 KeAttachProcess(&Process
->Pcb
);
1056 /* Enter SEH for write to user-mode PEB */
1059 /* Write the session ID */
1060 Process
->Peb
->SessionId
= SessionInfo
.SessionId
;
1062 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1064 /* Get exception code */
1065 Status
= _SEH2_GetExceptionCode();
1069 /* Detach from the process */
1073 /* Unlock the process */
1074 //PsUnlockProcess(Process);
1077 case ProcessPriorityClass
:
1079 /* Check buffer length */
1080 if (ProcessInformationLength
!= sizeof(PROCESS_PRIORITY_CLASS
))
1082 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1086 /* Enter SEH for capture */
1089 /* Capture the caller's buffer */
1090 PriorityClass
= *(PPROCESS_PRIORITY_CLASS
)ProcessInformation
;
1092 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1094 /* Return the exception code */
1095 Status
= _SEH2_GetExceptionCode();
1100 /* Check for invalid PriorityClass value */
1101 if (PriorityClass
.PriorityClass
> PROCESS_PRIORITY_CLASS_ABOVE_NORMAL
)
1103 Status
= STATUS_INVALID_PARAMETER
;
1107 /* TODO: Check privileges */
1109 /* Check if we have a job */
1112 DPRINT1("Jobs not yet supported\n");
1115 /* Set process priority class */
1116 Process
->PriorityClass
= PriorityClass
.PriorityClass
;
1118 /* Set process priority mode (foreground or background) */
1119 PsSetProcessPriorityByClass(Process
,
1120 !PriorityClass
.Foreground
? PsProcessPriorityBackground
:
1121 PsProcessPriorityForeground
);
1123 Status
= STATUS_SUCCESS
;
1126 case ProcessQuotaLimits
:
1128 /* Check buffer length */
1129 if (ProcessInformationLength
!= sizeof(QUOTA_LIMITS
))
1131 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1135 DPRINT1("Not implemented: ProcessQuotaLimits\n");
1136 Status
= STATUS_NOT_IMPLEMENTED
;
1139 case ProcessBasePriority
:
1141 /* Check buffer length */
1142 if (ProcessInformationLength
!= sizeof(KPRIORITY
))
1144 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1148 DPRINT1("Not implemented: ProcessBasePriority\n");
1149 Status
= STATUS_NOT_IMPLEMENTED
;
1152 case ProcessRaisePriority
:
1154 /* Check buffer length */
1155 if (ProcessInformationLength
!= sizeof(ULONG
))
1157 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1161 DPRINT1("Not implemented: ProcessRaisePriority\n");
1162 Status
= STATUS_NOT_IMPLEMENTED
;
1165 case ProcessWx86Information
:
1167 /* Check buffer length */
1168 if (ProcessInformationLength
!= sizeof(HANDLE
))
1170 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1174 DPRINT1("Not implemented: ProcessWx86Information\n");
1175 Status
= STATUS_NOT_IMPLEMENTED
;
1178 case ProcessDebugPort
:
1180 /* Check buffer length */
1181 if (ProcessInformationLength
!= sizeof(HANDLE
))
1183 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1187 DPRINT1("Not implemented: ProcessDebugPort\n");
1188 Status
= STATUS_NOT_IMPLEMENTED
;
1191 case ProcessBreakOnTermination
:
1193 /* Check buffer length */
1194 if (ProcessInformationLength
!= sizeof(ULONG
))
1196 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1200 /* Enter SEH for direct buffer read */
1203 Break
= *(PULONG
)ProcessInformation
;
1205 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1207 /* Get exception code */
1209 Status
= _SEH2_GetExceptionCode();
1214 /* Setting 'break on termination' requires the SeDebugPrivilege */
1215 if (!SeSinglePrivilegeCheck(SeDebugPrivilege
, PreviousMode
))
1217 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1221 /* Set or clear the flag */
1224 PspSetProcessFlag(Process
, PSF_BREAK_ON_TERMINATION_BIT
);
1228 PspClearProcessFlag(Process
, PSF_BREAK_ON_TERMINATION_BIT
);
1233 /* We currently don't implement any of these */
1234 case ProcessLdtInformation
:
1235 case ProcessLdtSize
:
1236 case ProcessIoPortHandlers
:
1237 case ProcessWorkingSetWatch
:
1238 case ProcessUserModeIOPL
:
1239 case ProcessEnableAlignmentFaultFixup
:
1240 case ProcessAffinityMask
:
1241 DPRINT1("Not implemented: %lx\n", ProcessInformationClass
);
1242 Status
= STATUS_NOT_IMPLEMENTED
;
1245 /* Supposedly these are invalid...!? verify! */
1246 case ProcessBasicInformation
:
1247 case ProcessIoCounters
:
1249 case ProcessPooledUsageAndLimits
:
1250 case ProcessHandleCount
:
1251 case ProcessWow64Information
:
1253 DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass
);
1254 Status
= STATUS_INVALID_INFO_CLASS
;
1257 /* Dereference and return status */
1258 ObDereferenceObject(Process
);
1267 NtSetInformationThread(IN HANDLE ThreadHandle
,
1268 IN THREADINFOCLASS ThreadInformationClass
,
1269 IN PVOID ThreadInformation
,
1270 IN ULONG ThreadInformationLength
)
1274 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1276 HANDLE TokenHandle
= NULL
;
1277 KPRIORITY Priority
= 0;
1278 KAFFINITY Affinity
= 0, CombinedAffinity
;
1279 PVOID Address
= NULL
;
1281 ULONG DisableBoost
= 0;
1282 ULONG IdealProcessor
= 0;
1285 PVOID
*ExpansionSlots
;
1286 PETHREAD ProcThread
;
1289 /* Verify Information Class validity */
1291 Status
= DefaultSetInfoBufferCheck(ThreadInformationClass
,
1293 RTL_NUMBER_OF(PsThreadInfoClass
),
1295 ThreadInformationLength
,
1297 if (!NT_SUCCESS(Status
)) return Status
;
1300 /* Check what class this is */
1301 Access
= THREAD_SET_INFORMATION
;
1302 if (ThreadInformationClass
== ThreadImpersonationToken
)
1304 /* Setting the impersonation token needs a special mask */
1305 Access
= THREAD_SET_THREAD_TOKEN
;
1308 /* Reference the thread */
1309 Status
= ObReferenceObjectByHandle(ThreadHandle
,
1315 if (!NT_SUCCESS(Status
)) return Status
;
1317 /* Check what kind of information class this is */
1318 switch (ThreadInformationClass
)
1320 /* Thread priority */
1321 case ThreadPriority
:
1323 /* Check buffer length */
1324 if (ThreadInformationLength
!= sizeof(KPRIORITY
))
1326 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1330 /* Use SEH for capture */
1333 /* Get the priority */
1334 Priority
= *(PLONG
)ThreadInformation
;
1336 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1338 /* Get the exception code */
1339 Status
= _SEH2_GetExceptionCode();
1345 if ((Priority
> HIGH_PRIORITY
) ||
1346 (Priority
<= LOW_PRIORITY
))
1349 Status
= STATUS_INVALID_PARAMETER
;
1353 /* Set the priority */
1354 KeSetPriorityThread(&Thread
->Tcb
, Priority
);
1357 case ThreadBasePriority
:
1359 /* Check buffer length */
1360 if (ThreadInformationLength
!= sizeof(LONG
))
1362 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1366 /* Use SEH for capture */
1369 /* Get the priority */
1370 Priority
= *(PLONG
)ThreadInformation
;
1372 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1374 /* Get the exception code */
1375 Status
= _SEH2_GetExceptionCode();
1381 if ((Priority
> THREAD_BASE_PRIORITY_MAX
) ||
1382 (Priority
< THREAD_BASE_PRIORITY_MIN
))
1384 /* These ones are OK */
1385 if ((Priority
!= THREAD_BASE_PRIORITY_LOWRT
+ 1) &&
1386 (Priority
!= THREAD_BASE_PRIORITY_IDLE
- 1))
1388 /* Check if the process is real time */
1389 if (PsGetCurrentProcess()->PriorityClass
!=
1390 PROCESS_PRIORITY_CLASS_REALTIME
)
1392 /* It isn't, fail */
1393 Status
= STATUS_INVALID_PARAMETER
;
1399 /* Set the base priority */
1400 KeSetBasePriorityThread(&Thread
->Tcb
, Priority
);
1403 case ThreadAffinityMask
:
1405 /* Check buffer length */
1406 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1408 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1412 /* Use SEH for capture */
1415 /* Get the priority */
1416 Affinity
= *(PULONG_PTR
)ThreadInformation
;
1418 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1420 /* Get the exception code */
1421 Status
= _SEH2_GetExceptionCode();
1429 Status
= STATUS_INVALID_PARAMETER
;
1433 /* Get the process */
1434 Process
= Thread
->ThreadsProcess
;
1436 /* Try to acquire rundown */
1437 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1440 KeEnterCriticalRegion();
1441 ExAcquirePushLockShared(&Process
->ProcessLock
);
1444 CombinedAffinity
= Affinity
& Process
->Pcb
.Affinity
;
1445 if (CombinedAffinity
!= Affinity
)
1448 Status
= STATUS_INVALID_PARAMETER
;
1452 /* Set the affinity */
1453 KeSetAffinityThread(&Thread
->Tcb
, CombinedAffinity
);
1456 /* Release the lock and rundown */
1457 ExReleasePushLockShared(&Process
->ProcessLock
);
1458 KeLeaveCriticalRegion();
1459 ExReleaseRundownProtection(&Process
->RundownProtect
);
1464 Status
= STATUS_PROCESS_IS_TERMINATING
;
1470 case ThreadImpersonationToken
:
1472 /* Check buffer length */
1473 if (ThreadInformationLength
!= sizeof(HANDLE
))
1475 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1479 /* Use SEH for capture */
1482 /* Save the token handle */
1483 TokenHandle
= *(PHANDLE
)ThreadInformation
;
1485 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1487 /* Get the exception code */
1488 Status
= _SEH2_GetExceptionCode();
1493 /* Assign the actual token */
1494 Status
= PsAssignImpersonationToken(Thread
, TokenHandle
);
1497 case ThreadQuerySetWin32StartAddress
:
1499 /* Check buffer length */
1500 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1502 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1506 /* Use SEH for capture */
1509 /* Get the priority */
1510 Address
= *(PVOID
*)ThreadInformation
;
1512 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1514 /* Get the exception code */
1515 Status
= _SEH2_GetExceptionCode();
1520 /* Set the address */
1521 Thread
->Win32StartAddress
= Address
;
1524 case ThreadIdealProcessor
:
1526 /* Check buffer length */
1527 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1529 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1533 /* Use SEH for capture */
1536 /* Get the priority */
1537 IdealProcessor
= *(PULONG_PTR
)ThreadInformation
;
1539 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1541 /* Get the exception code */
1542 Status
= _SEH2_GetExceptionCode();
1548 if (IdealProcessor
> MAXIMUM_PROCESSORS
)
1551 Status
= STATUS_INVALID_PARAMETER
;
1556 Status
= KeSetIdealProcessorThread(&Thread
->Tcb
,
1557 (CCHAR
)IdealProcessor
);
1559 /* Get the TEB and protect the thread */
1560 Teb
= Thread
->Tcb
.Teb
;
1561 if ((Teb
) && (ExAcquireRundownProtection(&Thread
->RundownProtect
)))
1563 /* Save the ideal processor */
1564 Teb
->IdealProcessor
= Thread
->Tcb
.IdealProcessor
;
1566 /* Release rundown protection */
1567 ExReleaseRundownProtection(&Thread
->RundownProtect
);
1572 case ThreadPriorityBoost
:
1574 /* Check buffer length */
1575 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1577 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1581 /* Use SEH for capture */
1584 /* Get the priority */
1585 DisableBoost
= *(PULONG_PTR
)ThreadInformation
;
1587 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1589 /* Get the exception code */
1590 Status
= _SEH2_GetExceptionCode();
1595 /* Call the kernel */
1596 KeSetDisableBoostThread(&Thread
->Tcb
, (BOOLEAN
)DisableBoost
);
1599 case ThreadZeroTlsCell
:
1601 /* Check buffer length */
1602 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1604 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1608 /* Use SEH for capture */
1611 /* Get the priority */
1612 TlsIndex
= *(PULONG_PTR
)ThreadInformation
;
1614 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1616 /* Get the exception code */
1617 Status
= _SEH2_GetExceptionCode();
1622 /* This is only valid for the current thread */
1623 if (Thread
!= PsGetCurrentThread())
1626 Status
= STATUS_INVALID_PARAMETER
;
1630 /* Get the process */
1631 Process
= Thread
->ThreadsProcess
;
1633 /* Loop the threads */
1634 ProcThread
= PsGetNextProcessThread(Process
, NULL
);
1637 /* Acquire rundown */
1638 if (ExAcquireRundownProtection(&ProcThread
->RundownProtect
))
1641 Teb
= ProcThread
->Tcb
.Teb
;
1644 /* Check if we're in the expansion range */
1645 if (TlsIndex
> TLS_MINIMUM_AVAILABLE
- 1)
1647 if (TlsIndex
< (TLS_MINIMUM_AVAILABLE
+
1648 TLS_EXPANSION_SLOTS
) - 1)
1650 /* Check if we have expansion slots */
1651 ExpansionSlots
= Teb
->TlsExpansionSlots
;
1654 /* Clear the index */
1655 ExpansionSlots
[TlsIndex
- TLS_MINIMUM_AVAILABLE
] = 0;
1661 /* Clear the index */
1662 Teb
->TlsSlots
[TlsIndex
] = NULL
;
1666 /* Release rundown */
1667 ExReleaseRundownProtection(&ProcThread
->RundownProtect
);
1670 /* Go to the next thread */
1671 ProcThread
= PsGetNextProcessThread(Process
, ProcThread
);
1678 /* We don't implement it yet */
1679 DPRINT1("Not implemented: %lx\n", ThreadInformationClass
);
1680 Status
= STATUS_NOT_IMPLEMENTED
;
1683 /* Dereference and return status */
1684 ObDereferenceObject(Thread
);
1693 NtQueryInformationThread(IN HANDLE ThreadHandle
,
1694 IN THREADINFOCLASS ThreadInformationClass
,
1695 OUT PVOID ThreadInformation
,
1696 IN ULONG ThreadInformationLength
,
1697 OUT PULONG ReturnLength OPTIONAL
)
1700 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1704 PTHREAD_BASIC_INFORMATION ThreadBasicInfo
=
1705 (PTHREAD_BASIC_INFORMATION
)ThreadInformation
;
1706 PKERNEL_USER_TIMES ThreadTime
= (PKERNEL_USER_TIMES
)ThreadInformation
;
1710 /* Check if we were called from user mode */
1711 if (PreviousMode
!= KernelMode
)
1716 /* Probe the buffer */
1717 ProbeForWrite(ThreadInformation
,
1718 ThreadInformationLength
,
1721 /* Probe the return length if required */
1722 if (ReturnLength
) ProbeForWriteUlong(ReturnLength
);
1724 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1726 /* Return the exception code */
1727 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1732 /* Check what class this is */
1733 Access
= THREAD_QUERY_INFORMATION
;
1735 /* Reference the process */
1736 Status
= ObReferenceObjectByHandle(ThreadHandle
,
1742 if (!NT_SUCCESS(Status
)) return Status
;
1744 /* Check what kind of information class this is */
1745 switch (ThreadInformationClass
)
1747 /* Basic thread information */
1748 case ThreadBasicInformation
:
1750 /* Set return length */
1751 Length
= sizeof(THREAD_BASIC_INFORMATION
);
1753 if (ThreadInformationLength
!= Length
)
1755 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1758 /* Protect writes with SEH */
1761 /* Write all the information from the ETHREAD/KTHREAD */
1762 ThreadBasicInfo
->ExitStatus
= Thread
->ExitStatus
;
1763 ThreadBasicInfo
->TebBaseAddress
= (PVOID
)Thread
->Tcb
.Teb
;
1764 ThreadBasicInfo
->ClientId
= Thread
->Cid
;
1765 ThreadBasicInfo
->AffinityMask
= Thread
->Tcb
.Affinity
;
1766 ThreadBasicInfo
->Priority
= Thread
->Tcb
.Priority
;
1767 ThreadBasicInfo
->BasePriority
= KeQueryBasePriorityThread(&Thread
->Tcb
);
1769 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1771 /* Get exception code */
1772 Status
= _SEH2_GetExceptionCode();
1777 /* Thread time information */
1780 /* Set the return length */
1781 Length
= sizeof(KERNEL_USER_TIMES
);
1783 if (ThreadInformationLength
!= Length
)
1785 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1788 /* Protect writes with SEH */
1791 /* Copy time information from ETHREAD/KTHREAD */
1792 ThreadTime
->KernelTime
.QuadPart
= Thread
->Tcb
.KernelTime
*
1794 ThreadTime
->UserTime
.QuadPart
= Thread
->Tcb
.UserTime
*
1796 ThreadTime
->CreateTime
= Thread
->CreateTime
;
1797 ThreadTime
->ExitTime
= Thread
->ExitTime
;
1799 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1801 /* Get exception code */
1802 Status
= _SEH2_GetExceptionCode();
1807 case ThreadQuerySetWin32StartAddress
:
1809 /* Set the return length*/
1810 Length
= sizeof(PVOID
);
1812 if (ThreadInformationLength
!= Length
)
1814 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1817 /* Protect write with SEH */
1820 /* Return the Win32 Start Address */
1821 *(PVOID
*)ThreadInformation
= Thread
->Win32StartAddress
;
1823 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1825 /* Get exception code */
1826 Status
= _SEH2_GetExceptionCode();
1831 case ThreadPerformanceCount
:
1833 /* Set the return length*/
1834 Length
= sizeof(LARGE_INTEGER
);
1836 if (ThreadInformationLength
!= Length
)
1838 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1841 /* Protect write with SEH */
1845 (*(PLARGE_INTEGER
)ThreadInformation
).QuadPart
= 0;
1847 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1849 /* Get exception code */
1850 Status
= _SEH2_GetExceptionCode();
1855 case ThreadAmILastThread
:
1857 /* Set the return length*/
1858 Length
= sizeof(ULONG
);
1860 if (ThreadInformationLength
!= Length
)
1862 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1865 /* Protect write with SEH */
1868 /* Return whether or not we are the last thread */
1869 *(PULONG
)ThreadInformation
= ((Thread
->ThreadsProcess
->
1870 ThreadListHead
.Flink
->Flink
==
1871 &Thread
->ThreadsProcess
->
1875 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1877 /* Get exception code */
1878 Status
= _SEH2_GetExceptionCode();
1883 case ThreadIsIoPending
:
1885 /* Set the return length*/
1886 Length
= sizeof(ULONG
);
1888 if (ThreadInformationLength
!= Length
)
1890 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1893 /* Raise the IRQL to protect the IRP list */
1894 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1896 /* Protect write with SEH */
1899 /* Check if the IRP list is empty or not */
1900 *(PULONG
)ThreadInformation
= !IsListEmpty(&Thread
->IrpList
);
1902 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1904 /* Get exception code */
1905 Status
= _SEH2_GetExceptionCode();
1909 /* Lower IRQL back */
1910 KeLowerIrql(OldIrql
);
1913 /* LDT and GDT information */
1914 case ThreadDescriptorTableEntry
:
1917 /* Call the worker routine */
1918 Status
= PspQueryDescriptorThread(Thread
,
1920 ThreadInformationLength
,
1923 /* Only implemented on x86 */
1924 Status
= STATUS_NOT_IMPLEMENTED
;
1928 case ThreadPriorityBoost
:
1930 /* Set the return length*/
1931 Length
= sizeof(ULONG
);
1933 if (ThreadInformationLength
!= Length
)
1935 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1941 *(PULONG
)ThreadInformation
= Thread
->Tcb
.DisableBoost
? 1 : 0;
1943 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1945 Status
= _SEH2_GetExceptionCode();
1953 /* Not yet implemented */
1954 DPRINT1("Not implemented: %lx\n", ThreadInformationClass
);
1955 Status
= STATUS_NOT_IMPLEMENTED
;
1958 /* Protect write with SEH */
1961 /* Check if caller wanted return length */
1962 if (ReturnLength
) *ReturnLength
= Length
;
1964 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1966 /* Get exception code */
1967 Status
= _SEH2_GetExceptionCode();
1971 /* Dereference the thread, and return */
1972 ObDereferenceObject(Thread
);