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 PROCESS_DEVICEMAP_INFORMATION DeviceMap
;
78 PUNICODE_STRING ImageName
;
82 /* Check validity of Information Class */
84 Status
= DefaultQueryInfoBufferCheck(ProcessInformationClass
,
86 RTL_NUMBER_OF(PsProcessInfoClass
),
88 ProcessInformationLength
,
91 if (!NT_SUCCESS(Status
)) return Status
;
94 if((ProcessInformationClass
== ProcessCookie
) &&
95 (ProcessHandle
!= NtCurrentProcess()))
98 * Retreiving the process cookie is only allowed for the calling process
99 * itself! XP only allowes NtCurrentProcess() as process handles even if
100 * a real handle actually represents the current process.
102 return STATUS_INVALID_PARAMETER
;
105 /* Check the information class */
106 switch (ProcessInformationClass
)
108 /* Basic process information */
109 case ProcessBasicInformation
:
111 /* Set return length */
112 Length
= sizeof(PROCESS_BASIC_INFORMATION
);
114 if (ProcessInformationLength
!= Length
)
116 Status
= STATUS_INFO_LENGTH_MISMATCH
;
120 /* Reference the process */
121 Status
= ObReferenceObjectByHandle(ProcessHandle
,
122 PROCESS_QUERY_INFORMATION
,
127 if (!NT_SUCCESS(Status
)) break;
129 /* Protect writes with SEH */
132 /* Write all the information from the EPROCESS/KPROCESS */
133 ProcessBasicInfo
->ExitStatus
= Process
->ExitStatus
;
134 ProcessBasicInfo
->PebBaseAddress
= Process
->Peb
;
135 ProcessBasicInfo
->AffinityMask
= Process
->Pcb
.Affinity
;
136 ProcessBasicInfo
->UniqueProcessId
= (ULONG_PTR
)Process
->
138 ProcessBasicInfo
->InheritedFromUniqueProcessId
=
139 (ULONG
)Process
->InheritedFromUniqueProcessId
;
140 ProcessBasicInfo
->BasePriority
= Process
->Pcb
.BasePriority
;
143 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
145 /* Get exception code */
146 Status
= _SEH2_GetExceptionCode();
150 /* Dereference the process */
151 ObDereferenceObject(Process
);
154 /* Quote limits: not implemented */
155 case ProcessQuotaLimits
:
157 Length
= sizeof(QUOTA_LIMITS
);
158 if (ProcessInformationLength
!= Length
)
160 Status
= STATUS_INFO_LENGTH_MISMATCH
;
164 /* Reference the process */
165 Status
= ObReferenceObjectByHandle(ProcessHandle
,
166 PROCESS_QUERY_INFORMATION
,
171 if (!NT_SUCCESS(Status
)) break;
173 /* TODO: Implement this case */
174 DPRINT1("Query ProcessQuotaLimits unimplemented\n");
175 Status
= STATUS_NOT_IMPLEMENTED
;
177 /* Dereference the process */
178 ObDereferenceObject(Process
);
181 case ProcessIoCounters
:
183 Length
= sizeof(IO_COUNTERS
);
184 if (ProcessInformationLength
!= Length
)
186 Status
= STATUS_INFO_LENGTH_MISMATCH
;
190 /* Reference the process */
191 Status
= ObReferenceObjectByHandle(ProcessHandle
,
192 PROCESS_QUERY_INFORMATION
,
197 if (!NT_SUCCESS(Status
)) break;
201 IoCounters
->ReadOperationCount
= Process
->ReadOperationCount
.QuadPart
;
202 IoCounters
->ReadTransferCount
= Process
->ReadTransferCount
.QuadPart
;
203 IoCounters
->WriteOperationCount
= Process
->WriteOperationCount
.QuadPart
;
204 IoCounters
->WriteTransferCount
= Process
->WriteTransferCount
.QuadPart
;
205 IoCounters
->OtherOperationCount
= Process
->OtherOperationCount
.QuadPart
;
206 IoCounters
->OtherTransferCount
= Process
->OtherTransferCount
.QuadPart
;
208 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
210 /* Ignore exception */
214 /* Set status to success in any case */
215 Status
= STATUS_SUCCESS
;
217 /* Dereference the process */
218 ObDereferenceObject(Process
);
224 /* Set the return length */
225 Length
= sizeof(KERNEL_USER_TIMES
);
227 if (ProcessInformationLength
!= Length
)
229 Status
= STATUS_INFO_LENGTH_MISMATCH
;
233 /* Reference the process */
234 Status
= ObReferenceObjectByHandle(ProcessHandle
,
235 PROCESS_QUERY_INFORMATION
,
240 if (!NT_SUCCESS(Status
)) break;
242 /* Protect writes with SEH */
245 /* Copy time information from EPROCESS/KPROCESS */
246 ProcessTime
->CreateTime
= Process
->CreateTime
;
247 ProcessTime
->UserTime
.QuadPart
= Process
->Pcb
.UserTime
*
249 ProcessTime
->KernelTime
.QuadPart
= Process
->Pcb
.KernelTime
*
251 ProcessTime
->ExitTime
= Process
->ExitTime
;
253 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
255 /* Get exception code */
256 Status
= _SEH2_GetExceptionCode();
260 /* Dereference the process */
261 ObDereferenceObject(Process
);
264 /* Process Debug Port */
265 case ProcessDebugPort
:
267 /* Set return length */
268 Length
= sizeof(HANDLE
);
270 if (ProcessInformationLength
!= Length
)
272 Status
= STATUS_INFO_LENGTH_MISMATCH
;
276 /* Reference the process */
277 Status
= ObReferenceObjectByHandle(ProcessHandle
,
278 PROCESS_QUERY_INFORMATION
,
283 if (!NT_SUCCESS(Status
)) break;
285 /* Protect write with SEH */
288 /* Return whether or not we have a debug port */
289 *(PHANDLE
)ProcessInformation
= (Process
->DebugPort
?
292 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
294 /* Get exception code */
295 Status
= _SEH2_GetExceptionCode();
299 /* Dereference the process */
300 ObDereferenceObject(Process
);
303 /* LDT, WS and VDM Information: not implemented */
304 case ProcessLdtInformation
:
305 case ProcessWorkingSetWatch
:
306 case ProcessWx86Information
:
308 /* Reference the process */
309 Status
= ObReferenceObjectByHandle(ProcessHandle
,
310 PROCESS_QUERY_INFORMATION
,
315 if (!NT_SUCCESS(Status
)) break;
317 DPRINT1("Not implemented: %lx\n", ProcessInformationClass
);
319 /* Dereference the process */
320 ObDereferenceObject(Process
);
321 Status
= STATUS_NOT_IMPLEMENTED
;
324 case ProcessHandleCount
:
326 /* Set the return length*/
327 Length
= sizeof(ULONG
);
329 if (ProcessInformationLength
!= Length
)
331 Status
= STATUS_INFO_LENGTH_MISMATCH
;
335 /* Reference the process */
336 Status
= ObReferenceObjectByHandle(ProcessHandle
,
337 PROCESS_QUERY_INFORMATION
,
342 if (!NT_SUCCESS(Status
)) break;
344 /* Count the number of handles this process has */
345 HandleCount
= ObGetProcessHandleCount(Process
);
347 /* Protect write in SEH */
350 /* Return the count of handles */
351 *(PULONG
)ProcessInformation
= HandleCount
;
353 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
355 /* Get the exception code */
356 Status
= _SEH2_GetExceptionCode();
360 /* Dereference the process */
361 ObDereferenceObject(Process
);
364 /* Session ID for the process */
365 case ProcessSessionInformation
:
367 /* Set the return length*/
368 Length
= sizeof(PROCESS_SESSION_INFORMATION
);
370 if (ProcessInformationLength
!= Length
)
372 Status
= STATUS_INFO_LENGTH_MISMATCH
;
376 /* Reference the process */
377 Status
= ObReferenceObjectByHandle(ProcessHandle
,
378 PROCESS_QUERY_INFORMATION
,
383 if (!NT_SUCCESS(Status
)) break;
385 /* Enter SEH for write safety */
388 /* Write back the Session ID */
389 SessionInfo
->SessionId
= Process
->Session
;
391 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
393 /* Get the exception code */
394 Status
= _SEH2_GetExceptionCode();
398 /* Dereference the process */
399 ObDereferenceObject(Process
);
402 /* WOW64: Not implemented */
403 case ProcessWow64Information
:
404 Status
= STATUS_NOT_IMPLEMENTED
;
407 /* Virtual Memory Statistics */
408 case ProcessVmCounters
:
410 /* Set the return length */
411 Length
= sizeof(VM_COUNTERS
);
413 if (ProcessInformationLength
!= Length
)
415 Status
= STATUS_INFO_LENGTH_MISMATCH
;
419 /* Reference the process */
420 Status
= ObReferenceObjectByHandle(ProcessHandle
,
421 PROCESS_QUERY_INFORMATION
,
426 if (!NT_SUCCESS(Status
)) break;
428 /* Enter SEH for write safety */
431 /* Return data from EPROCESS */
432 VmCounters
->PeakVirtualSize
= Process
->PeakVirtualSize
;
433 VmCounters
->VirtualSize
= Process
->VirtualSize
;
434 VmCounters
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
435 VmCounters
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
436 VmCounters
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
437 VmCounters
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeak
[0];
438 VmCounters
->QuotaPagedPoolUsage
= Process
->QuotaUsage
[0];
439 VmCounters
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeak
[1];
440 VmCounters
->QuotaNonPagedPoolUsage
= Process
->QuotaUsage
[1];
441 VmCounters
->PagefileUsage
= Process
->QuotaUsage
[2];
442 VmCounters
->PeakPagefileUsage
= Process
->QuotaPeak
[2];
445 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
447 /* Get the exception code */
448 Status
= _SEH2_GetExceptionCode();
452 /* Dereference the process */
453 ObDereferenceObject(Process
);
456 /* Hard Error Processing Mode */
457 case ProcessDefaultHardErrorMode
:
459 /* Set the return length*/
460 Length
= sizeof(ULONG
);
462 if (ProcessInformationLength
!= Length
)
464 Status
= STATUS_INFO_LENGTH_MISMATCH
;
468 /* Reference the process */
469 Status
= ObReferenceObjectByHandle(ProcessHandle
,
470 PROCESS_QUERY_INFORMATION
,
475 if (!NT_SUCCESS(Status
)) break;
477 /* Enter SEH for writing back data */
480 /* Write the current processing mode */
481 *(PULONG
)ProcessInformation
= Process
->
482 DefaultHardErrorProcessing
;
484 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
486 /* Get the exception code */
487 Status
= _SEH2_GetExceptionCode();
491 /* Dereference the process */
492 ObDereferenceObject(Process
);
495 /* Priority Boosting status */
496 case ProcessPriorityBoost
:
498 /* Set the return length*/
499 Length
= sizeof(ULONG
);
501 if (ProcessInformationLength
!= Length
)
503 Status
= STATUS_INFO_LENGTH_MISMATCH
;
507 /* Reference the process */
508 Status
= ObReferenceObjectByHandle(ProcessHandle
,
509 PROCESS_QUERY_INFORMATION
,
514 if (!NT_SUCCESS(Status
)) break;
516 /* Enter SEH for writing back data */
519 /* Return boost status */
520 *(PULONG
)ProcessInformation
= Process
->Pcb
.DisableBoost
?
523 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
525 /* Get the exception code */
526 Status
= _SEH2_GetExceptionCode();
530 /* Dereference the process */
531 ObDereferenceObject(Process
);
535 case ProcessDeviceMap
:
537 /* Set the return length*/
538 Length
= sizeof(PROCESS_DEVICEMAP_INFORMATION
);
540 if (ProcessInformationLength
!= Length
)
542 Status
= STATUS_INFO_LENGTH_MISMATCH
;
546 /* Reference the process */
547 Status
= ObReferenceObjectByHandle(ProcessHandle
,
548 PROCESS_QUERY_INFORMATION
,
553 if (!NT_SUCCESS(Status
)) break;
555 /* Query the device map information */
556 ObQueryDeviceMapInformation(Process
, &DeviceMap
);
558 /* Enter SEH for writing back data */
561 *(PPROCESS_DEVICEMAP_INFORMATION
)ProcessInformation
= DeviceMap
;
563 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
565 /* Get the exception code */
566 Status
= _SEH2_GetExceptionCode();
570 /* Dereference the process */
571 ObDereferenceObject(Process
);
575 case ProcessPriorityClass
:
577 /* Set the return length*/
578 Length
= sizeof(PROCESS_PRIORITY_CLASS
);
580 if (ProcessInformationLength
!= Length
)
582 Status
= STATUS_INFO_LENGTH_MISMATCH
;
586 /* Reference the process */
587 Status
= ObReferenceObjectByHandle(ProcessHandle
,
588 PROCESS_QUERY_INFORMATION
,
593 if (!NT_SUCCESS(Status
)) break;
595 /* Enter SEH for writing back data */
598 /* Return current priority class */
599 PsPriorityClass
->PriorityClass
= Process
->PriorityClass
;
600 PsPriorityClass
->Foreground
= FALSE
;
602 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
604 /* Get the exception code */
605 Status
= _SEH2_GetExceptionCode();
609 /* Dereference the process */
610 ObDereferenceObject(Process
);
613 case ProcessImageFileName
:
615 /* Reference the process */
616 Status
= ObReferenceObjectByHandle(ProcessHandle
,
617 PROCESS_QUERY_INFORMATION
,
622 if (!NT_SUCCESS(Status
)) break;
624 /* Get the image path */
625 Status
= SeLocateProcessImageName(Process
, &ImageName
);
626 if (NT_SUCCESS(Status
))
628 /* Set return length */
629 Length
= ImageName
->MaximumLength
+
630 sizeof(OBJECT_NAME_INFORMATION
);
632 /* Make sure it's large enough */
633 if (Length
<= ProcessInformationLength
)
635 /* Enter SEH to protect write */
639 RtlCopyMemory(ProcessInformation
,
644 ((PUNICODE_STRING
)ProcessInformation
)->Buffer
=
645 (PWSTR
)((PUNICODE_STRING
)ProcessInformation
+ 1);
647 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
649 /* Get the exception code */
650 Status
= _SEH2_GetExceptionCode();
656 /* Buffer too small */
657 Status
= STATUS_INFO_LENGTH_MISMATCH
;
660 /* Free the image path */
661 ExFreePool(ImageName
);
663 /* Dereference the process */
664 ObDereferenceObject(Process
);
667 /* Per-process security cookie */
670 /* Get the current process and cookie */
671 Process
= PsGetCurrentProcess();
672 Cookie
= Process
->Cookie
;
675 LARGE_INTEGER SystemTime
;
679 /* Generate a new cookie */
680 KeQuerySystemTime(&SystemTime
);
681 Prcb
= KeGetCurrentPrcb();
682 NewCookie
= Prcb
->KeSystemCalls
^ Prcb
->InterruptTime
^
683 SystemTime
.u
.LowPart
^ SystemTime
.u
.HighPart
;
685 /* Set the new cookie or return the current one */
686 Cookie
= InterlockedCompareExchange((LONG
*)&Process
->Cookie
,
689 if (!Cookie
) Cookie
= NewCookie
;
691 /* Set return length */
692 Length
= sizeof(ULONG
);
695 /* Enter SEH to protect write */
698 /* Write back the cookie */
699 *(PULONG
)ProcessInformation
= Cookie
;
701 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
703 /* Get the exception code */
704 Status
= _SEH2_GetExceptionCode();
709 /* Not yet implemented, or unknown */
710 case ProcessBasePriority
:
711 case ProcessRaisePriority
:
712 case ProcessExceptionPort
:
713 case ProcessAccessToken
:
715 case ProcessIoPortHandlers
:
716 case ProcessUserModeIOPL
:
717 case ProcessEnableAlignmentFaultFixup
:
718 case ProcessAffinityMask
:
719 case ProcessForegroundInformation
:
721 DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass
);
722 Status
= STATUS_INVALID_INFO_CLASS
;
725 /* Protect write with SEH */
728 /* Check if caller wanted return length */
729 if (ReturnLength
) *ReturnLength
= Length
;
731 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
733 /* Get exception code */
734 Status
= _SEH2_GetExceptionCode();
746 NtSetInformationProcess(IN HANDLE ProcessHandle
,
747 IN PROCESSINFOCLASS ProcessInformationClass
,
748 IN PVOID ProcessInformation
,
749 IN ULONG ProcessInformationLength
)
752 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
755 HANDLE PortHandle
= NULL
;
756 HANDLE TokenHandle
= NULL
;
757 PROCESS_SESSION_INFORMATION SessionInfo
= {0};
758 PROCESS_PRIORITY_CLASS PriorityClass
= {0};
762 /* Verify Information Class validity */
764 Status
= DefaultSetInfoBufferCheck(ProcessInformationClass
,
766 RTL_NUMBER_OF(PsProcessInfoClass
),
768 ProcessInformationLength
,
770 if (!NT_SUCCESS(Status
)) return Status
;
773 /* Check what class this is */
774 Access
= PROCESS_SET_INFORMATION
;
775 if (ProcessInformationClass
== ProcessSessionInformation
)
777 /* Setting the Session ID needs a special mask */
778 Access
|= PROCESS_SET_SESSIONID
;
780 else if (ProcessInformationClass
== ProcessExceptionPort
)
782 /* Setting the exception port needs a special mask */
783 Access
|= PROCESS_SUSPEND_RESUME
;
786 /* Reference the process */
787 Status
= ObReferenceObjectByHandle(ProcessHandle
,
793 if (!NT_SUCCESS(Status
)) return Status
;
795 /* Check what kind of information class this is */
796 switch (ProcessInformationClass
)
798 /* Error/Exception Port */
799 case ProcessExceptionPort
:
801 /* Check buffer length */
802 if (ProcessInformationLength
!= sizeof(HANDLE
))
804 Status
= STATUS_INFO_LENGTH_MISMATCH
;
808 /* Use SEH for capture */
811 /* Capture the handle */
812 PortHandle
= *(PHANDLE
)ProcessInformation
;
814 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
816 /* Get the exception code */
817 Status
= _SEH2_GetExceptionCode();
820 if (!NT_SUCCESS(Status
)) break;
822 /* Get the LPC Port */
823 Status
= ObReferenceObjectByHandle(PortHandle
,
827 (PVOID
)&ExceptionPort
,
829 if (!NT_SUCCESS(Status
)) break;
831 /* Change the pointer */
832 if (InterlockedCompareExchangePointer(&Process
->ExceptionPort
,
836 /* We already had one, fail */
837 ObDereferenceObject(ExceptionPort
);
838 Status
= STATUS_PORT_ALREADY_SET
;
843 case ProcessAccessToken
:
845 /* Check buffer length */
846 if (ProcessInformationLength
!= sizeof(PROCESS_ACCESS_TOKEN
))
848 Status
= STATUS_INFO_LENGTH_MISMATCH
;
852 /* Use SEH for capture */
855 /* Save the token handle */
856 TokenHandle
= ((PPROCESS_ACCESS_TOKEN
)ProcessInformation
)->
859 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
861 /* Get the exception code */
862 Status
= _SEH2_GetExceptionCode();
865 if (!NT_SUCCESS(Status
)) break;
867 /* Assign the actual token */
868 Status
= PspSetPrimaryToken(Process
, TokenHandle
, NULL
);
871 /* Hard error processing */
872 case ProcessDefaultHardErrorMode
:
874 /* Check buffer length */
875 if (ProcessInformationLength
!= sizeof(ULONG
))
877 Status
= STATUS_INFO_LENGTH_MISMATCH
;
881 /* Enter SEH for direct buffer read */
884 /* Update the current mode abd return the previous one */
885 InterlockedExchange((LONG
*)&Process
->DefaultHardErrorProcessing
,
886 *(PLONG
)ProcessInformation
);
888 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
890 /* Get exception code */
891 Status
= _SEH2_GetExceptionCode();
897 case ProcessSessionInformation
:
899 /* Check buffer length */
900 if (ProcessInformationLength
!= sizeof(PROCESS_SESSION_INFORMATION
))
902 Status
= STATUS_INFO_LENGTH_MISMATCH
;
906 /* Enter SEH for capture */
909 /* Capture the caller's buffer */
910 SessionInfo
= *(PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
912 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
914 /* Get the exception code */
915 Status
= _SEH2_GetExceptionCode();
918 if (!NT_SUCCESS(Status
)) break;
920 /* Setting the session id requires the SeTcbPrivilege */
921 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
923 /* Can't set the session ID, bail out. */
924 Status
= STATUS_PRIVILEGE_NOT_HELD
;
928 /* FIXME - update the session id for the process token */
929 //Status = PsLockProcess(Process, FALSE);
930 if (!NT_SUCCESS(Status
)) break;
932 /* Write the session ID in the EPROCESS */
933 Process
->Session
= SessionInfo
.SessionId
;
935 /* Check if the process also has a PEB */
939 * Attach to the process to make sure we're in the right
940 * context to access the PEB structure
942 KeAttachProcess(&Process
->Pcb
);
944 /* Enter SEH for write to user-mode PEB */
947 /* Write the session ID */
948 Process
->Peb
->SessionId
= SessionInfo
.SessionId
;
950 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
952 /* Get exception code */
953 Status
= _SEH2_GetExceptionCode();
957 /* Detach from the process */
961 /* Unlock the process */
962 //PsUnlockProcess(Process);
965 case ProcessPriorityClass
:
967 /* Check buffer length */
968 if (ProcessInformationLength
!= sizeof(PROCESS_PRIORITY_CLASS
))
970 Status
= STATUS_INFO_LENGTH_MISMATCH
;
974 /* Enter SEH for capture */
977 /* Capture the caller's buffer */
978 PriorityClass
= *(PPROCESS_PRIORITY_CLASS
)ProcessInformation
;
980 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
982 /* Get the exception code */
983 Status
= _SEH2_GetExceptionCode();
986 if (!NT_SUCCESS(Status
)) break;
988 /* Check for invalid PriorityClass value */
989 if (PriorityClass
.PriorityClass
> PROCESS_PRIORITY_CLASS_ABOVE_NORMAL
)
991 Status
= STATUS_INVALID_PARAMETER
;
995 /* TODO: Check privileges */
997 /* Check if we have a job */
1000 DPRINT1("Jobs not yet supported\n");
1003 /* Set process priority class */
1004 Process
->PriorityClass
= PriorityClass
.PriorityClass
;
1006 /* Set process priority mode (foreground or background) */
1007 PsSetProcessPriorityByClass(Process
,
1008 !PriorityClass
.Foreground
? PsProcessPriorityBackground
:
1009 PsProcessPriorityForeground
);
1011 Status
= STATUS_SUCCESS
;
1014 /* We currently don't implement any of these */
1015 case ProcessQuotaLimits
:
1016 case ProcessBasePriority
:
1017 case ProcessRaisePriority
:
1018 case ProcessLdtInformation
:
1019 case ProcessLdtSize
:
1020 case ProcessIoPortHandlers
:
1021 case ProcessWorkingSetWatch
:
1022 case ProcessUserModeIOPL
:
1023 case ProcessEnableAlignmentFaultFixup
:
1024 case ProcessAffinityMask
:
1025 DPRINT1("Not implemented: %lx\n", ProcessInformationClass
);
1026 Status
= STATUS_NOT_IMPLEMENTED
;
1029 /* Supposedly these are invalid...!? verify! */
1030 case ProcessBasicInformation
:
1031 case ProcessIoCounters
:
1033 case ProcessPooledUsageAndLimits
:
1034 case ProcessWx86Information
:
1035 case ProcessHandleCount
:
1036 case ProcessWow64Information
:
1037 case ProcessDebugPort
:
1039 DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass
);
1040 Status
= STATUS_INVALID_INFO_CLASS
;
1043 /* Dereference and return status */
1044 ObDereferenceObject(Process
);
1053 NtSetInformationThread(IN HANDLE ThreadHandle
,
1054 IN THREADINFOCLASS ThreadInformationClass
,
1055 IN PVOID ThreadInformation
,
1056 IN ULONG ThreadInformationLength
)
1060 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1062 HANDLE TokenHandle
= NULL
;
1063 KPRIORITY Priority
= 0;
1064 KAFFINITY Affinity
= 0, CombinedAffinity
;
1065 PVOID Address
= NULL
;
1067 ULONG DisableBoost
= 0;
1068 ULONG IdealProcessor
= 0;
1071 PVOID
*ExpansionSlots
;
1072 PETHREAD ProcThread
;
1075 /* Verify Information Class validity */
1077 Status
= DefaultSetInfoBufferCheck(ThreadInformationClass
,
1079 RTL_NUMBER_OF(PsThreadInfoClass
),
1081 ThreadInformationLength
,
1083 if (!NT_SUCCESS(Status
)) return Status
;
1086 /* Check what class this is */
1087 Access
= THREAD_SET_INFORMATION
;
1088 if (ThreadInformationClass
== ThreadImpersonationToken
)
1090 /* Setting the impersonation token needs a special mask */
1091 Access
= THREAD_SET_THREAD_TOKEN
;
1094 /* Reference the process */
1095 Status
= ObReferenceObjectByHandle(ThreadHandle
,
1101 if (!NT_SUCCESS(Status
)) return Status
;
1103 /* Check what kind of information class this is */
1104 switch (ThreadInformationClass
)
1106 /* Thread priority */
1107 case ThreadPriority
:
1109 /* Check buffer length */
1110 if (ThreadInformationLength
!= sizeof(KPRIORITY
))
1112 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1116 /* Use SEH for capture */
1119 /* Get the priority */
1120 Priority
= *(PLONG
)ThreadInformation
;
1122 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1124 /* Get the exception code */
1125 Status
= _SEH2_GetExceptionCode();
1128 if (!NT_SUCCESS(Status
)) break;
1131 if ((Priority
> HIGH_PRIORITY
) ||
1132 (Priority
<= LOW_PRIORITY
))
1135 Status
= STATUS_INVALID_PARAMETER
;
1139 /* Set the priority */
1140 KeSetPriorityThread(&Thread
->Tcb
, Priority
);
1143 case ThreadBasePriority
:
1145 /* Check buffer length */
1146 if (ThreadInformationLength
!= sizeof(LONG
))
1148 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1152 /* Use SEH for capture */
1155 /* Get the priority */
1156 Priority
= *(PLONG
)ThreadInformation
;
1158 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1160 /* Get the exception code */
1161 Status
= _SEH2_GetExceptionCode();
1164 if (!NT_SUCCESS(Status
)) break;
1167 if ((Priority
> THREAD_BASE_PRIORITY_MAX
) ||
1168 (Priority
< THREAD_BASE_PRIORITY_MIN
))
1170 /* These ones are OK */
1171 if ((Priority
!= THREAD_BASE_PRIORITY_LOWRT
+ 1) &&
1172 (Priority
!= THREAD_BASE_PRIORITY_IDLE
- 1))
1174 /* Check if the process is real time */
1175 if (PsGetCurrentProcess()->PriorityClass
!=
1176 PROCESS_PRIORITY_CLASS_REALTIME
)
1178 /* It isn't, fail */
1179 Status
= STATUS_INVALID_PARAMETER
;
1185 /* Set the base priority */
1186 KeSetBasePriorityThread(&Thread
->Tcb
, Priority
);
1189 case ThreadAffinityMask
:
1191 /* Check buffer length */
1192 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1194 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1198 /* Use SEH for capture */
1201 /* Get the priority */
1202 Affinity
= *(PULONG_PTR
)ThreadInformation
;
1204 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1206 /* Get the exception code */
1207 Status
= _SEH2_GetExceptionCode();
1210 if (!NT_SUCCESS(Status
)) break;
1216 Status
= STATUS_INVALID_PARAMETER
;
1220 /* Get the process */
1221 Process
= Thread
->ThreadsProcess
;
1223 /* Try to acquire rundown */
1224 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1227 KeEnterCriticalRegion();
1228 ExAcquirePushLockShared(&Process
->ProcessLock
);
1231 CombinedAffinity
= Affinity
& Process
->Pcb
.Affinity
;
1232 if (CombinedAffinity
!= Affinity
)
1235 Status
= STATUS_INVALID_PARAMETER
;
1239 /* Set the affinity */
1240 KeSetAffinityThread(&Thread
->Tcb
, CombinedAffinity
);
1243 /* Release the lock and rundown */
1244 ExReleasePushLockShared(&Process
->ProcessLock
);
1245 KeLeaveCriticalRegion();
1246 ExReleaseRundownProtection(&Process
->RundownProtect
);
1251 Status
= STATUS_PROCESS_IS_TERMINATING
;
1257 case ThreadImpersonationToken
:
1259 /* Check buffer length */
1260 if (ThreadInformationLength
!= sizeof(HANDLE
))
1262 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1266 /* Use SEH for capture */
1269 /* Save the token handle */
1270 TokenHandle
= *(PHANDLE
)ThreadInformation
;
1272 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1274 /* Get the exception code */
1275 Status
= _SEH2_GetExceptionCode();
1278 if (!NT_SUCCESS(Status
)) break;
1280 /* Assign the actual token */
1281 Status
= PsAssignImpersonationToken(Thread
, TokenHandle
);
1284 case ThreadQuerySetWin32StartAddress
:
1286 /* Check buffer length */
1287 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1289 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1293 /* Use SEH for capture */
1296 /* Get the priority */
1297 Address
= *(PVOID
*)ThreadInformation
;
1299 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1301 /* Get the exception code */
1302 Status
= _SEH2_GetExceptionCode();
1305 if (!NT_SUCCESS(Status
)) break;
1307 /* Set the address */
1308 Thread
->Win32StartAddress
= Address
;
1311 case ThreadIdealProcessor
:
1313 /* Check buffer length */
1314 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1316 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1320 /* Use SEH for capture */
1323 /* Get the priority */
1324 IdealProcessor
= *(PULONG_PTR
)ThreadInformation
;
1326 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1328 /* Get the exception code */
1329 Status
= _SEH2_GetExceptionCode();
1332 if (!NT_SUCCESS(Status
)) break;
1335 if (IdealProcessor
> MAXIMUM_PROCESSORS
)
1338 Status
= STATUS_INVALID_PARAMETER
;
1343 Status
= KeSetIdealProcessorThread(&Thread
->Tcb
,
1344 (CCHAR
)IdealProcessor
);
1346 /* Get the TEB and protect the thread */
1347 Teb
= Thread
->Tcb
.Teb
;
1348 if ((Teb
) && (ExAcquireRundownProtection(&Thread
->RundownProtect
)))
1350 /* Save the ideal processor */
1351 Teb
->IdealProcessor
= Thread
->Tcb
.IdealProcessor
;
1353 /* Release rundown protection */
1354 ExReleaseRundownProtection(&Thread
->RundownProtect
);
1359 case ThreadPriorityBoost
:
1361 /* Check buffer length */
1362 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1364 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1368 /* Use SEH for capture */
1371 /* Get the priority */
1372 DisableBoost
= *(PULONG_PTR
)ThreadInformation
;
1374 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1376 /* Get the exception code */
1377 Status
= _SEH2_GetExceptionCode();
1380 if (!NT_SUCCESS(Status
)) break;
1382 /* Call the kernel */
1383 KeSetDisableBoostThread(&Thread
->Tcb
, (BOOLEAN
)DisableBoost
);
1386 case ThreadZeroTlsCell
:
1388 /* Check buffer length */
1389 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1391 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1395 /* Use SEH for capture */
1398 /* Get the priority */
1399 TlsIndex
= *(PULONG_PTR
)ThreadInformation
;
1401 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1403 /* Get the exception code */
1404 Status
= _SEH2_GetExceptionCode();
1407 if (!NT_SUCCESS(Status
)) break;
1409 /* This is only valid for the current thread */
1410 if (Thread
!= PsGetCurrentThread())
1413 Status
= STATUS_INVALID_PARAMETER
;
1417 /* Get the process */
1418 Process
= Thread
->ThreadsProcess
;
1420 /* Loop the threads */
1421 ProcThread
= PsGetNextProcessThread(Process
, NULL
);
1424 /* Acquire rundown */
1425 if (ExAcquireRundownProtection(&ProcThread
->RundownProtect
))
1428 Teb
= ProcThread
->Tcb
.Teb
;
1431 /* Check if we're in the expansion range */
1432 if (TlsIndex
> TLS_MINIMUM_AVAILABLE
- 1)
1434 if (TlsIndex
< (TLS_MINIMUM_AVAILABLE
+
1435 TLS_EXPANSION_SLOTS
) - 1)
1437 /* Check if we have expansion slots */
1438 ExpansionSlots
= Teb
->TlsExpansionSlots
;
1441 /* Clear the index */
1442 ExpansionSlots
[TlsIndex
- TLS_MINIMUM_AVAILABLE
] = 0;
1448 /* Clear the index */
1449 Teb
->TlsSlots
[TlsIndex
] = NULL
;
1453 /* Release rundown */
1454 ExReleaseRundownProtection(&ProcThread
->RundownProtect
);
1457 /* Go to the next thread */
1458 ProcThread
= PsGetNextProcessThread(Process
, ProcThread
);
1465 /* We don't implement it yet */
1466 DPRINT1("Not implemented: %lx\n", ThreadInformationClass
);
1467 Status
= STATUS_NOT_IMPLEMENTED
;
1470 /* Dereference and return status */
1471 ObDereferenceObject(Thread
);
1480 NtQueryInformationThread(IN HANDLE ThreadHandle
,
1481 IN THREADINFOCLASS ThreadInformationClass
,
1482 OUT PVOID ThreadInformation
,
1483 IN ULONG ThreadInformationLength
,
1484 OUT PULONG ReturnLength OPTIONAL
)
1487 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1488 NTSTATUS Status
= STATUS_SUCCESS
;
1491 PTHREAD_BASIC_INFORMATION ThreadBasicInfo
=
1492 (PTHREAD_BASIC_INFORMATION
)ThreadInformation
;
1493 PKERNEL_USER_TIMES ThreadTime
= (PKERNEL_USER_TIMES
)ThreadInformation
;
1497 if (PreviousMode
!= KernelMode
)
1501 ProbeForWrite(ThreadInformation
,
1502 ThreadInformationLength
,
1507 ProbeForWriteUlong(ReturnLength
);
1510 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1512 Status
= _SEH2_GetExceptionCode();
1516 if (!NT_SUCCESS(Status
)) return Status
;
1519 /* Check what class this is */
1520 Access
= THREAD_QUERY_INFORMATION
;
1522 /* Reference the process */
1523 Status
= ObReferenceObjectByHandle(ThreadHandle
,
1529 if (!NT_SUCCESS(Status
)) return Status
;
1531 /* Check what kind of information class this is */
1532 switch (ThreadInformationClass
)
1534 /* Basic thread information */
1535 case ThreadBasicInformation
:
1537 /* Set return length */
1538 Length
= sizeof(THREAD_BASIC_INFORMATION
);
1540 if (ThreadInformationLength
!= Length
)
1542 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1545 /* Protect writes with SEH */
1548 /* Write all the information from the ETHREAD/KTHREAD */
1549 ThreadBasicInfo
->ExitStatus
= Thread
->ExitStatus
;
1550 ThreadBasicInfo
->TebBaseAddress
= (PVOID
)Thread
->Tcb
.Teb
;
1551 ThreadBasicInfo
->ClientId
= Thread
->Cid
;
1552 ThreadBasicInfo
->AffinityMask
= Thread
->Tcb
.Affinity
;
1553 ThreadBasicInfo
->Priority
= Thread
->Tcb
.Priority
;
1554 ThreadBasicInfo
->BasePriority
= KeQueryBasePriorityThread(&Thread
->Tcb
);
1556 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1558 /* Get exception code */
1559 Status
= _SEH2_GetExceptionCode();
1564 /* Thread time information */
1567 /* Set the return length */
1568 Length
= sizeof(KERNEL_USER_TIMES
);
1570 if (ThreadInformationLength
!= Length
)
1572 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1575 /* Protect writes with SEH */
1578 /* Copy time information from ETHREAD/KTHREAD */
1579 ThreadTime
->KernelTime
.QuadPart
= Thread
->Tcb
.KernelTime
*
1581 ThreadTime
->UserTime
.QuadPart
= Thread
->Tcb
.UserTime
*
1583 ThreadTime
->CreateTime
= Thread
->CreateTime
;
1584 ThreadTime
->ExitTime
= Thread
->ExitTime
;
1586 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1588 /* Get exception code */
1589 Status
= _SEH2_GetExceptionCode();
1594 case ThreadQuerySetWin32StartAddress
:
1596 /* Set the return length*/
1597 Length
= sizeof(PVOID
);
1599 if (ThreadInformationLength
!= Length
)
1601 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1604 /* Protect write with SEH */
1607 /* Return the Win32 Start Address */
1608 *(PVOID
*)ThreadInformation
= Thread
->Win32StartAddress
;
1610 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1612 /* Get exception code */
1613 Status
= _SEH2_GetExceptionCode();
1618 case ThreadPerformanceCount
:
1620 /* Set the return length*/
1621 Length
= sizeof(LARGE_INTEGER
);
1623 if (ThreadInformationLength
!= Length
)
1625 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1628 /* Protect write with SEH */
1632 (*(PLARGE_INTEGER
)ThreadInformation
).QuadPart
= 0;
1634 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1636 /* Get exception code */
1637 Status
= _SEH2_GetExceptionCode();
1642 case ThreadAmILastThread
:
1644 /* Set the return length*/
1645 Length
= sizeof(ULONG
);
1647 if (ThreadInformationLength
!= Length
)
1649 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1652 /* Protect write with SEH */
1655 /* Return whether or not we are the last thread */
1656 *(PULONG
)ThreadInformation
= ((Thread
->ThreadsProcess
->
1657 ThreadListHead
.Flink
->Flink
==
1658 &Thread
->ThreadsProcess
->
1662 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1664 /* Get exception code */
1665 Status
= _SEH2_GetExceptionCode();
1670 case ThreadIsIoPending
:
1672 /* Set the return length*/
1673 Length
= sizeof(ULONG
);
1675 if (ThreadInformationLength
!= Length
)
1677 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1680 /* Raise the IRQL to protect the IRP list */
1681 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1683 /* Protect write with SEH */
1686 /* Check if the IRP list is empty or not */
1687 *(PULONG
)ThreadInformation
= !IsListEmpty(&Thread
->IrpList
);
1689 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1691 /* Get exception code */
1692 Status
= _SEH2_GetExceptionCode();
1696 /* Lower IRQL back */
1697 KeLowerIrql(OldIrql
);
1700 case ThreadDescriptorTableEntry
:
1701 DPRINT1("NtQueryInformationThread(): case ThreadDescriptorTableEntry not implemented!\n");
1702 Status
= STATUS_NOT_IMPLEMENTED
;
1705 case ThreadPriorityBoost
:
1707 /* Set the return length*/
1708 Length
= sizeof(ULONG
);
1710 if (ThreadInformationLength
!= Length
)
1712 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1718 *(PULONG
)ThreadInformation
= Thread
->Tcb
.DisableBoost
? 1 : 0;
1720 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1722 Status
= _SEH2_GetExceptionCode();
1730 /* Not yet implemented */
1731 DPRINT1("Not implemented: %lx\n", ThreadInformationClass
);
1732 Status
= STATUS_NOT_IMPLEMENTED
;
1735 /* Protect write with SEH */
1738 /* Check if caller wanted return length */
1739 if (ReturnLength
) *ReturnLength
= Length
;
1741 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1743 /* Get exception code */
1744 Status
= _SEH2_GetExceptionCode();
1748 /* Dereference the thread, and return */
1749 ObDereferenceObject(Thread
);