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 validity of Information Class */
85 Status
= DefaultQueryInfoBufferCheck(ProcessInformationClass
,
87 RTL_NUMBER_OF(PsProcessInfoClass
),
89 ProcessInformationLength
,
92 if (!NT_SUCCESS(Status
)) return Status
;
95 if((ProcessInformationClass
== ProcessCookie
) &&
96 (ProcessHandle
!= NtCurrentProcess()))
99 * Retreiving the process cookie is only allowed for the calling process
100 * itself! XP only allowes NtCurrentProcess() as process handles even if
101 * a real handle actually represents the current process.
103 return STATUS_INVALID_PARAMETER
;
106 /* Check the information class */
107 switch (ProcessInformationClass
)
109 /* Basic process information */
110 case ProcessBasicInformation
:
112 /* Set return length */
113 Length
= sizeof(PROCESS_BASIC_INFORMATION
);
115 if (ProcessInformationLength
!= Length
)
117 Status
= STATUS_INFO_LENGTH_MISMATCH
;
121 /* Reference the process */
122 Status
= ObReferenceObjectByHandle(ProcessHandle
,
123 PROCESS_QUERY_INFORMATION
,
128 if (!NT_SUCCESS(Status
)) break;
130 /* Protect writes with SEH */
133 /* Write all the information from the EPROCESS/KPROCESS */
134 ProcessBasicInfo
->ExitStatus
= Process
->ExitStatus
;
135 ProcessBasicInfo
->PebBaseAddress
= Process
->Peb
;
136 ProcessBasicInfo
->AffinityMask
= Process
->Pcb
.Affinity
;
137 ProcessBasicInfo
->UniqueProcessId
= (ULONG_PTR
)Process
->
139 ProcessBasicInfo
->InheritedFromUniqueProcessId
=
140 (ULONG
)Process
->InheritedFromUniqueProcessId
;
141 ProcessBasicInfo
->BasePriority
= Process
->Pcb
.BasePriority
;
144 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
146 /* Get exception code */
147 Status
= _SEH2_GetExceptionCode();
151 /* Dereference the process */
152 ObDereferenceObject(Process
);
155 /* Process quota limits */
156 case ProcessQuotaLimits
:
158 Length
= sizeof(QUOTA_LIMITS
);
159 if (ProcessInformationLength
!= Length
)
161 Status
= STATUS_INFO_LENGTH_MISMATCH
;
165 /* Reference the process */
166 Status
= ObReferenceObjectByHandle(ProcessHandle
,
167 PROCESS_QUERY_INFORMATION
,
172 if (!NT_SUCCESS(Status
)) break;
174 /* Indicate success */
175 Status
= STATUS_SUCCESS
;
179 /* Set max/min working set sizes */
180 QuotaLimits
->MaximumWorkingSetSize
=
181 Process
->Vm
.MaximumWorkingSetSize
<< PAGE_SHIFT
;
182 QuotaLimits
->MinimumWorkingSetSize
=
183 Process
->Vm
.MinimumWorkingSetSize
<< PAGE_SHIFT
;
185 /* Set default time limits */
186 QuotaLimits
->TimeLimit
.LowPart
= (ULONG
)-1;
187 QuotaLimits
->TimeLimit
.HighPart
= (ULONG
)-1;
189 /* Is quota block a default one? */
190 if (Process
->QuotaBlock
== &PspDefaultQuotaBlock
)
192 /* Set default pools and pagefile limits */
193 QuotaLimits
->PagedPoolLimit
= (SIZE_T
)-1;
194 QuotaLimits
->NonPagedPoolLimit
= (SIZE_T
)-1;
195 QuotaLimits
->PagefileLimit
= (SIZE_T
)-1;
199 /* Get limits from non-default quota block */
200 QuotaLimits
->PagedPoolLimit
=
201 Process
->QuotaBlock
->QuotaEntry
[PagedPool
].Limit
;
202 QuotaLimits
->NonPagedPoolLimit
=
203 Process
->QuotaBlock
->QuotaEntry
[NonPagedPool
].Limit
;
204 QuotaLimits
->PagefileLimit
=
205 Process
->QuotaBlock
->QuotaEntry
[2].Limit
;
208 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
210 /* Get exception code */
211 Status
= _SEH2_GetExceptionCode();
215 /* Dereference the process */
216 ObDereferenceObject(Process
);
219 case ProcessIoCounters
:
221 Length
= sizeof(IO_COUNTERS
);
222 if (ProcessInformationLength
!= Length
)
224 Status
= STATUS_INFO_LENGTH_MISMATCH
;
228 /* Reference the process */
229 Status
= ObReferenceObjectByHandle(ProcessHandle
,
230 PROCESS_QUERY_INFORMATION
,
235 if (!NT_SUCCESS(Status
)) break;
239 IoCounters
->ReadOperationCount
= Process
->ReadOperationCount
.QuadPart
;
240 IoCounters
->ReadTransferCount
= Process
->ReadTransferCount
.QuadPart
;
241 IoCounters
->WriteOperationCount
= Process
->WriteOperationCount
.QuadPart
;
242 IoCounters
->WriteTransferCount
= Process
->WriteTransferCount
.QuadPart
;
243 IoCounters
->OtherOperationCount
= Process
->OtherOperationCount
.QuadPart
;
244 IoCounters
->OtherTransferCount
= Process
->OtherTransferCount
.QuadPart
;
246 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
248 /* Ignore exception */
252 /* Set status to success in any case */
253 Status
= STATUS_SUCCESS
;
255 /* Dereference the process */
256 ObDereferenceObject(Process
);
262 /* Set the return length */
263 Length
= sizeof(KERNEL_USER_TIMES
);
265 if (ProcessInformationLength
!= Length
)
267 Status
= STATUS_INFO_LENGTH_MISMATCH
;
271 /* Reference the process */
272 Status
= ObReferenceObjectByHandle(ProcessHandle
,
273 PROCESS_QUERY_INFORMATION
,
278 if (!NT_SUCCESS(Status
)) break;
280 /* Protect writes with SEH */
283 /* Copy time information from EPROCESS/KPROCESS */
284 ProcessTime
->CreateTime
= Process
->CreateTime
;
285 ProcessTime
->UserTime
.QuadPart
= Process
->Pcb
.UserTime
*
287 ProcessTime
->KernelTime
.QuadPart
= Process
->Pcb
.KernelTime
*
289 ProcessTime
->ExitTime
= Process
->ExitTime
;
291 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
293 /* Get exception code */
294 Status
= _SEH2_GetExceptionCode();
298 /* Dereference the process */
299 ObDereferenceObject(Process
);
302 /* Process Debug Port */
303 case ProcessDebugPort
:
305 /* Set return length */
306 Length
= sizeof(HANDLE
);
308 if (ProcessInformationLength
!= Length
)
310 Status
= STATUS_INFO_LENGTH_MISMATCH
;
314 /* Reference the process */
315 Status
= ObReferenceObjectByHandle(ProcessHandle
,
316 PROCESS_QUERY_INFORMATION
,
321 if (!NT_SUCCESS(Status
)) break;
323 /* Protect write with SEH */
326 /* Return whether or not we have a debug port */
327 *(PHANDLE
)ProcessInformation
= (Process
->DebugPort
?
330 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
332 /* Get exception code */
333 Status
= _SEH2_GetExceptionCode();
337 /* Dereference the process */
338 ObDereferenceObject(Process
);
341 /* LDT, WS and VDM Information: not implemented */
342 case ProcessLdtInformation
:
343 case ProcessWorkingSetWatch
:
344 case ProcessWx86Information
:
346 /* Reference the process */
347 Status
= ObReferenceObjectByHandle(ProcessHandle
,
348 PROCESS_QUERY_INFORMATION
,
353 if (!NT_SUCCESS(Status
)) break;
355 DPRINT1("Not implemented: %lx\n", ProcessInformationClass
);
357 /* Dereference the process */
358 ObDereferenceObject(Process
);
359 Status
= STATUS_NOT_IMPLEMENTED
;
362 case ProcessHandleCount
:
364 /* Set the return length*/
365 Length
= sizeof(ULONG
);
367 if (ProcessInformationLength
!= Length
)
369 Status
= STATUS_INFO_LENGTH_MISMATCH
;
373 /* Reference the process */
374 Status
= ObReferenceObjectByHandle(ProcessHandle
,
375 PROCESS_QUERY_INFORMATION
,
380 if (!NT_SUCCESS(Status
)) break;
382 /* Count the number of handles this process has */
383 HandleCount
= ObGetProcessHandleCount(Process
);
385 /* Protect write in SEH */
388 /* Return the count of handles */
389 *(PULONG
)ProcessInformation
= HandleCount
;
391 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
393 /* Get the exception code */
394 Status
= _SEH2_GetExceptionCode();
398 /* Dereference the process */
399 ObDereferenceObject(Process
);
402 /* Session ID for the process */
403 case ProcessSessionInformation
:
405 /* Set the return length*/
406 Length
= sizeof(PROCESS_SESSION_INFORMATION
);
408 if (ProcessInformationLength
!= Length
)
410 Status
= STATUS_INFO_LENGTH_MISMATCH
;
414 /* Reference the process */
415 Status
= ObReferenceObjectByHandle(ProcessHandle
,
416 PROCESS_QUERY_INFORMATION
,
421 if (!NT_SUCCESS(Status
)) break;
423 /* Enter SEH for write safety */
426 /* Write back the Session ID */
427 SessionInfo
->SessionId
= Process
->Session
;
429 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
431 /* Get the exception code */
432 Status
= _SEH2_GetExceptionCode();
436 /* Dereference the process */
437 ObDereferenceObject(Process
);
440 /* WOW64: Not implemented */
441 case ProcessWow64Information
:
442 Status
= STATUS_NOT_IMPLEMENTED
;
445 /* Virtual Memory Statistics */
446 case ProcessVmCounters
:
448 /* Set the return length */
449 Length
= sizeof(VM_COUNTERS
);
451 if (ProcessInformationLength
!= Length
)
453 Status
= STATUS_INFO_LENGTH_MISMATCH
;
457 /* Reference the process */
458 Status
= ObReferenceObjectByHandle(ProcessHandle
,
459 PROCESS_QUERY_INFORMATION
,
464 if (!NT_SUCCESS(Status
)) break;
466 /* Enter SEH for write safety */
469 /* Return data from EPROCESS */
470 VmCounters
->PeakVirtualSize
= Process
->PeakVirtualSize
;
471 VmCounters
->VirtualSize
= Process
->VirtualSize
;
472 VmCounters
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
473 VmCounters
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
474 VmCounters
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
475 VmCounters
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeak
[0];
476 VmCounters
->QuotaPagedPoolUsage
= Process
->QuotaUsage
[0];
477 VmCounters
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeak
[1];
478 VmCounters
->QuotaNonPagedPoolUsage
= Process
->QuotaUsage
[1];
479 VmCounters
->PagefileUsage
= Process
->QuotaUsage
[2];
480 VmCounters
->PeakPagefileUsage
= Process
->QuotaPeak
[2];
483 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
485 /* Get the exception code */
486 Status
= _SEH2_GetExceptionCode();
490 /* Dereference the process */
491 ObDereferenceObject(Process
);
494 /* Hard Error Processing Mode */
495 case ProcessDefaultHardErrorMode
:
497 /* Set the return length*/
498 Length
= sizeof(ULONG
);
500 if (ProcessInformationLength
!= Length
)
502 Status
= STATUS_INFO_LENGTH_MISMATCH
;
506 /* Reference the process */
507 Status
= ObReferenceObjectByHandle(ProcessHandle
,
508 PROCESS_QUERY_INFORMATION
,
513 if (!NT_SUCCESS(Status
)) break;
515 /* Enter SEH for writing back data */
518 /* Write the current processing mode */
519 *(PULONG
)ProcessInformation
= Process
->
520 DefaultHardErrorProcessing
;
522 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
524 /* Get the exception code */
525 Status
= _SEH2_GetExceptionCode();
529 /* Dereference the process */
530 ObDereferenceObject(Process
);
533 /* Priority Boosting status */
534 case ProcessPriorityBoost
:
536 /* Set the return length*/
537 Length
= sizeof(ULONG
);
539 if (ProcessInformationLength
!= Length
)
541 Status
= STATUS_INFO_LENGTH_MISMATCH
;
545 /* Reference the process */
546 Status
= ObReferenceObjectByHandle(ProcessHandle
,
547 PROCESS_QUERY_INFORMATION
,
552 if (!NT_SUCCESS(Status
)) break;
554 /* Enter SEH for writing back data */
557 /* Return boost status */
558 *(PULONG
)ProcessInformation
= Process
->Pcb
.DisableBoost
?
561 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
563 /* Get the exception code */
564 Status
= _SEH2_GetExceptionCode();
568 /* Dereference the process */
569 ObDereferenceObject(Process
);
573 case ProcessDeviceMap
:
575 /* Set the return length*/
576 Length
= sizeof(PROCESS_DEVICEMAP_INFORMATION
);
578 if (ProcessInformationLength
!= Length
)
580 Status
= STATUS_INFO_LENGTH_MISMATCH
;
584 /* Reference the process */
585 Status
= ObReferenceObjectByHandle(ProcessHandle
,
586 PROCESS_QUERY_INFORMATION
,
591 if (!NT_SUCCESS(Status
)) break;
593 /* Query the device map information */
594 ObQueryDeviceMapInformation(Process
, &DeviceMap
);
596 /* Enter SEH for writing back data */
599 *(PPROCESS_DEVICEMAP_INFORMATION
)ProcessInformation
= DeviceMap
;
601 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
603 /* Get the exception code */
604 Status
= _SEH2_GetExceptionCode();
608 /* Dereference the process */
609 ObDereferenceObject(Process
);
613 case ProcessPriorityClass
:
615 /* Set the return length*/
616 Length
= sizeof(PROCESS_PRIORITY_CLASS
);
618 if (ProcessInformationLength
!= Length
)
620 Status
= STATUS_INFO_LENGTH_MISMATCH
;
624 /* Reference the process */
625 Status
= ObReferenceObjectByHandle(ProcessHandle
,
626 PROCESS_QUERY_INFORMATION
,
631 if (!NT_SUCCESS(Status
)) break;
633 /* Enter SEH for writing back data */
636 /* Return current priority class */
637 PsPriorityClass
->PriorityClass
= Process
->PriorityClass
;
638 PsPriorityClass
->Foreground
= FALSE
;
640 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
642 /* Get the exception code */
643 Status
= _SEH2_GetExceptionCode();
647 /* Dereference the process */
648 ObDereferenceObject(Process
);
651 case ProcessImageFileName
:
653 /* Reference the process */
654 Status
= ObReferenceObjectByHandle(ProcessHandle
,
655 PROCESS_QUERY_INFORMATION
,
660 if (!NT_SUCCESS(Status
)) break;
662 /* Get the image path */
663 Status
= SeLocateProcessImageName(Process
, &ImageName
);
664 if (NT_SUCCESS(Status
))
666 /* Set return length */
667 Length
= ImageName
->MaximumLength
+
668 sizeof(OBJECT_NAME_INFORMATION
);
670 /* Make sure it's large enough */
671 if (Length
<= ProcessInformationLength
)
673 /* Enter SEH to protect write */
677 RtlCopyMemory(ProcessInformation
,
682 ((PUNICODE_STRING
)ProcessInformation
)->Buffer
=
683 (PWSTR
)((PUNICODE_STRING
)ProcessInformation
+ 1);
685 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
687 /* Get the exception code */
688 Status
= _SEH2_GetExceptionCode();
694 /* Buffer too small */
695 Status
= STATUS_INFO_LENGTH_MISMATCH
;
698 /* Free the image path */
699 ExFreePool(ImageName
);
701 /* Dereference the process */
702 ObDereferenceObject(Process
);
705 /* Per-process security cookie */
708 /* Get the current process and cookie */
709 Process
= PsGetCurrentProcess();
710 Cookie
= Process
->Cookie
;
713 LARGE_INTEGER SystemTime
;
717 /* Generate a new cookie */
718 KeQuerySystemTime(&SystemTime
);
719 Prcb
= KeGetCurrentPrcb();
720 NewCookie
= Prcb
->KeSystemCalls
^ Prcb
->InterruptTime
^
721 SystemTime
.u
.LowPart
^ SystemTime
.u
.HighPart
;
723 /* Set the new cookie or return the current one */
724 Cookie
= InterlockedCompareExchange((LONG
*)&Process
->Cookie
,
727 if (!Cookie
) Cookie
= NewCookie
;
729 /* Set return length */
730 Length
= sizeof(ULONG
);
733 /* Enter SEH to protect write */
736 /* Write back the cookie */
737 *(PULONG
)ProcessInformation
= Cookie
;
739 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
741 /* Get the exception code */
742 Status
= _SEH2_GetExceptionCode();
747 /* Not yet implemented, or unknown */
748 case ProcessBasePriority
:
749 case ProcessRaisePriority
:
750 case ProcessExceptionPort
:
751 case ProcessAccessToken
:
753 case ProcessIoPortHandlers
:
754 case ProcessUserModeIOPL
:
755 case ProcessEnableAlignmentFaultFixup
:
756 case ProcessAffinityMask
:
757 case ProcessForegroundInformation
:
759 DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass
);
760 Status
= STATUS_INVALID_INFO_CLASS
;
763 /* Protect write with SEH */
766 /* Check if caller wanted return length */
767 if (ReturnLength
) *ReturnLength
= Length
;
769 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
771 /* Get exception code */
772 Status
= _SEH2_GetExceptionCode();
784 NtSetInformationProcess(IN HANDLE ProcessHandle
,
785 IN PROCESSINFOCLASS ProcessInformationClass
,
786 IN PVOID ProcessInformation
,
787 IN ULONG ProcessInformationLength
)
790 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
793 HANDLE PortHandle
= NULL
;
794 HANDLE TokenHandle
= NULL
;
795 PROCESS_SESSION_INFORMATION SessionInfo
= {0};
796 PROCESS_PRIORITY_CLASS PriorityClass
= {0};
800 /* Verify Information Class validity */
802 Status
= DefaultSetInfoBufferCheck(ProcessInformationClass
,
804 RTL_NUMBER_OF(PsProcessInfoClass
),
806 ProcessInformationLength
,
808 if (!NT_SUCCESS(Status
)) return Status
;
811 /* Check what class this is */
812 Access
= PROCESS_SET_INFORMATION
;
813 if (ProcessInformationClass
== ProcessSessionInformation
)
815 /* Setting the Session ID needs a special mask */
816 Access
|= PROCESS_SET_SESSIONID
;
818 else if (ProcessInformationClass
== ProcessExceptionPort
)
820 /* Setting the exception port needs a special mask */
821 Access
|= PROCESS_SUSPEND_RESUME
;
824 /* Reference the process */
825 Status
= ObReferenceObjectByHandle(ProcessHandle
,
831 if (!NT_SUCCESS(Status
)) return Status
;
833 /* Check what kind of information class this is */
834 switch (ProcessInformationClass
)
836 /* Error/Exception Port */
837 case ProcessExceptionPort
:
839 /* Check buffer length */
840 if (ProcessInformationLength
!= sizeof(HANDLE
))
842 Status
= STATUS_INFO_LENGTH_MISMATCH
;
846 /* Use SEH for capture */
849 /* Capture the handle */
850 PortHandle
= *(PHANDLE
)ProcessInformation
;
852 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
854 /* Get the exception code */
855 Status
= _SEH2_GetExceptionCode();
858 if (!NT_SUCCESS(Status
)) break;
860 /* Get the LPC Port */
861 Status
= ObReferenceObjectByHandle(PortHandle
,
865 (PVOID
)&ExceptionPort
,
867 if (!NT_SUCCESS(Status
)) break;
869 /* Change the pointer */
870 if (InterlockedCompareExchangePointer(&Process
->ExceptionPort
,
874 /* We already had one, fail */
875 ObDereferenceObject(ExceptionPort
);
876 Status
= STATUS_PORT_ALREADY_SET
;
881 case ProcessAccessToken
:
883 /* Check buffer length */
884 if (ProcessInformationLength
!= sizeof(PROCESS_ACCESS_TOKEN
))
886 Status
= STATUS_INFO_LENGTH_MISMATCH
;
890 /* Use SEH for capture */
893 /* Save the token handle */
894 TokenHandle
= ((PPROCESS_ACCESS_TOKEN
)ProcessInformation
)->
897 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
899 /* Get the exception code */
900 Status
= _SEH2_GetExceptionCode();
903 if (!NT_SUCCESS(Status
)) break;
905 /* Assign the actual token */
906 Status
= PspSetPrimaryToken(Process
, TokenHandle
, NULL
);
909 /* Hard error processing */
910 case ProcessDefaultHardErrorMode
:
912 /* Check buffer length */
913 if (ProcessInformationLength
!= sizeof(ULONG
))
915 Status
= STATUS_INFO_LENGTH_MISMATCH
;
919 /* Enter SEH for direct buffer read */
922 /* Update the current mode abd return the previous one */
923 InterlockedExchange((LONG
*)&Process
->DefaultHardErrorProcessing
,
924 *(PLONG
)ProcessInformation
);
926 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
928 /* Get exception code */
929 Status
= _SEH2_GetExceptionCode();
935 case ProcessSessionInformation
:
937 /* Check buffer length */
938 if (ProcessInformationLength
!= sizeof(PROCESS_SESSION_INFORMATION
))
940 Status
= STATUS_INFO_LENGTH_MISMATCH
;
944 /* Enter SEH for capture */
947 /* Capture the caller's buffer */
948 SessionInfo
= *(PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
950 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
952 /* Get the exception code */
953 Status
= _SEH2_GetExceptionCode();
956 if (!NT_SUCCESS(Status
)) break;
958 /* Setting the session id requires the SeTcbPrivilege */
959 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
961 /* Can't set the session ID, bail out. */
962 Status
= STATUS_PRIVILEGE_NOT_HELD
;
966 /* FIXME - update the session id for the process token */
967 //Status = PsLockProcess(Process, FALSE);
968 if (!NT_SUCCESS(Status
)) break;
970 /* Write the session ID in the EPROCESS */
971 Process
->Session
= SessionInfo
.SessionId
;
973 /* Check if the process also has a PEB */
977 * Attach to the process to make sure we're in the right
978 * context to access the PEB structure
980 KeAttachProcess(&Process
->Pcb
);
982 /* Enter SEH for write to user-mode PEB */
985 /* Write the session ID */
986 Process
->Peb
->SessionId
= SessionInfo
.SessionId
;
988 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
990 /* Get exception code */
991 Status
= _SEH2_GetExceptionCode();
995 /* Detach from the process */
999 /* Unlock the process */
1000 //PsUnlockProcess(Process);
1003 case ProcessPriorityClass
:
1005 /* Check buffer length */
1006 if (ProcessInformationLength
!= sizeof(PROCESS_PRIORITY_CLASS
))
1008 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1012 /* Enter SEH for capture */
1015 /* Capture the caller's buffer */
1016 PriorityClass
= *(PPROCESS_PRIORITY_CLASS
)ProcessInformation
;
1018 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1020 /* Get the exception code */
1021 Status
= _SEH2_GetExceptionCode();
1024 if (!NT_SUCCESS(Status
)) break;
1026 /* Check for invalid PriorityClass value */
1027 if (PriorityClass
.PriorityClass
> PROCESS_PRIORITY_CLASS_ABOVE_NORMAL
)
1029 Status
= STATUS_INVALID_PARAMETER
;
1033 /* TODO: Check privileges */
1035 /* Check if we have a job */
1038 DPRINT1("Jobs not yet supported\n");
1041 /* Set process priority class */
1042 Process
->PriorityClass
= PriorityClass
.PriorityClass
;
1044 /* Set process priority mode (foreground or background) */
1045 PsSetProcessPriorityByClass(Process
,
1046 !PriorityClass
.Foreground
? PsProcessPriorityBackground
:
1047 PsProcessPriorityForeground
);
1049 Status
= STATUS_SUCCESS
;
1052 /* We currently don't implement any of these */
1053 case ProcessQuotaLimits
:
1054 case ProcessBasePriority
:
1055 case ProcessRaisePriority
:
1056 case ProcessLdtInformation
:
1057 case ProcessLdtSize
:
1058 case ProcessIoPortHandlers
:
1059 case ProcessWorkingSetWatch
:
1060 case ProcessUserModeIOPL
:
1061 case ProcessEnableAlignmentFaultFixup
:
1062 case ProcessAffinityMask
:
1063 DPRINT1("Not implemented: %lx\n", ProcessInformationClass
);
1064 Status
= STATUS_NOT_IMPLEMENTED
;
1067 /* Supposedly these are invalid...!? verify! */
1068 case ProcessBasicInformation
:
1069 case ProcessIoCounters
:
1071 case ProcessPooledUsageAndLimits
:
1072 case ProcessWx86Information
:
1073 case ProcessHandleCount
:
1074 case ProcessWow64Information
:
1075 case ProcessDebugPort
:
1077 DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass
);
1078 Status
= STATUS_INVALID_INFO_CLASS
;
1081 /* Dereference and return status */
1082 ObDereferenceObject(Process
);
1091 NtSetInformationThread(IN HANDLE ThreadHandle
,
1092 IN THREADINFOCLASS ThreadInformationClass
,
1093 IN PVOID ThreadInformation
,
1094 IN ULONG ThreadInformationLength
)
1098 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1100 HANDLE TokenHandle
= NULL
;
1101 KPRIORITY Priority
= 0;
1102 KAFFINITY Affinity
= 0, CombinedAffinity
;
1103 PVOID Address
= NULL
;
1105 ULONG DisableBoost
= 0;
1106 ULONG IdealProcessor
= 0;
1109 PVOID
*ExpansionSlots
;
1110 PETHREAD ProcThread
;
1113 /* Verify Information Class validity */
1115 Status
= DefaultSetInfoBufferCheck(ThreadInformationClass
,
1117 RTL_NUMBER_OF(PsThreadInfoClass
),
1119 ThreadInformationLength
,
1121 if (!NT_SUCCESS(Status
)) return Status
;
1124 /* Check what class this is */
1125 Access
= THREAD_SET_INFORMATION
;
1126 if (ThreadInformationClass
== ThreadImpersonationToken
)
1128 /* Setting the impersonation token needs a special mask */
1129 Access
= THREAD_SET_THREAD_TOKEN
;
1132 /* Reference the process */
1133 Status
= ObReferenceObjectByHandle(ThreadHandle
,
1139 if (!NT_SUCCESS(Status
)) return Status
;
1141 /* Check what kind of information class this is */
1142 switch (ThreadInformationClass
)
1144 /* Thread priority */
1145 case ThreadPriority
:
1147 /* Check buffer length */
1148 if (ThreadInformationLength
!= sizeof(KPRIORITY
))
1150 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1154 /* Use SEH for capture */
1157 /* Get the priority */
1158 Priority
= *(PLONG
)ThreadInformation
;
1160 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1162 /* Get the exception code */
1163 Status
= _SEH2_GetExceptionCode();
1166 if (!NT_SUCCESS(Status
)) break;
1169 if ((Priority
> HIGH_PRIORITY
) ||
1170 (Priority
<= LOW_PRIORITY
))
1173 Status
= STATUS_INVALID_PARAMETER
;
1177 /* Set the priority */
1178 KeSetPriorityThread(&Thread
->Tcb
, Priority
);
1181 case ThreadBasePriority
:
1183 /* Check buffer length */
1184 if (ThreadInformationLength
!= sizeof(LONG
))
1186 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1190 /* Use SEH for capture */
1193 /* Get the priority */
1194 Priority
= *(PLONG
)ThreadInformation
;
1196 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1198 /* Get the exception code */
1199 Status
= _SEH2_GetExceptionCode();
1202 if (!NT_SUCCESS(Status
)) break;
1205 if ((Priority
> THREAD_BASE_PRIORITY_MAX
) ||
1206 (Priority
< THREAD_BASE_PRIORITY_MIN
))
1208 /* These ones are OK */
1209 if ((Priority
!= THREAD_BASE_PRIORITY_LOWRT
+ 1) &&
1210 (Priority
!= THREAD_BASE_PRIORITY_IDLE
- 1))
1212 /* Check if the process is real time */
1213 if (PsGetCurrentProcess()->PriorityClass
!=
1214 PROCESS_PRIORITY_CLASS_REALTIME
)
1216 /* It isn't, fail */
1217 Status
= STATUS_INVALID_PARAMETER
;
1223 /* Set the base priority */
1224 KeSetBasePriorityThread(&Thread
->Tcb
, Priority
);
1227 case ThreadAffinityMask
:
1229 /* Check buffer length */
1230 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1232 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1236 /* Use SEH for capture */
1239 /* Get the priority */
1240 Affinity
= *(PULONG_PTR
)ThreadInformation
;
1242 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1244 /* Get the exception code */
1245 Status
= _SEH2_GetExceptionCode();
1248 if (!NT_SUCCESS(Status
)) break;
1254 Status
= STATUS_INVALID_PARAMETER
;
1258 /* Get the process */
1259 Process
= Thread
->ThreadsProcess
;
1261 /* Try to acquire rundown */
1262 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1265 KeEnterCriticalRegion();
1266 ExAcquirePushLockShared(&Process
->ProcessLock
);
1269 CombinedAffinity
= Affinity
& Process
->Pcb
.Affinity
;
1270 if (CombinedAffinity
!= Affinity
)
1273 Status
= STATUS_INVALID_PARAMETER
;
1277 /* Set the affinity */
1278 KeSetAffinityThread(&Thread
->Tcb
, CombinedAffinity
);
1281 /* Release the lock and rundown */
1282 ExReleasePushLockShared(&Process
->ProcessLock
);
1283 KeLeaveCriticalRegion();
1284 ExReleaseRundownProtection(&Process
->RundownProtect
);
1289 Status
= STATUS_PROCESS_IS_TERMINATING
;
1295 case ThreadImpersonationToken
:
1297 /* Check buffer length */
1298 if (ThreadInformationLength
!= sizeof(HANDLE
))
1300 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1304 /* Use SEH for capture */
1307 /* Save the token handle */
1308 TokenHandle
= *(PHANDLE
)ThreadInformation
;
1310 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1312 /* Get the exception code */
1313 Status
= _SEH2_GetExceptionCode();
1316 if (!NT_SUCCESS(Status
)) break;
1318 /* Assign the actual token */
1319 Status
= PsAssignImpersonationToken(Thread
, TokenHandle
);
1322 case ThreadQuerySetWin32StartAddress
:
1324 /* Check buffer length */
1325 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1327 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1331 /* Use SEH for capture */
1334 /* Get the priority */
1335 Address
= *(PVOID
*)ThreadInformation
;
1337 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1339 /* Get the exception code */
1340 Status
= _SEH2_GetExceptionCode();
1343 if (!NT_SUCCESS(Status
)) break;
1345 /* Set the address */
1346 Thread
->Win32StartAddress
= Address
;
1349 case ThreadIdealProcessor
:
1351 /* Check buffer length */
1352 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1354 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1358 /* Use SEH for capture */
1361 /* Get the priority */
1362 IdealProcessor
= *(PULONG_PTR
)ThreadInformation
;
1364 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1366 /* Get the exception code */
1367 Status
= _SEH2_GetExceptionCode();
1370 if (!NT_SUCCESS(Status
)) break;
1373 if (IdealProcessor
> MAXIMUM_PROCESSORS
)
1376 Status
= STATUS_INVALID_PARAMETER
;
1381 Status
= KeSetIdealProcessorThread(&Thread
->Tcb
,
1382 (CCHAR
)IdealProcessor
);
1384 /* Get the TEB and protect the thread */
1385 Teb
= Thread
->Tcb
.Teb
;
1386 if ((Teb
) && (ExAcquireRundownProtection(&Thread
->RundownProtect
)))
1388 /* Save the ideal processor */
1389 Teb
->IdealProcessor
= Thread
->Tcb
.IdealProcessor
;
1391 /* Release rundown protection */
1392 ExReleaseRundownProtection(&Thread
->RundownProtect
);
1397 case ThreadPriorityBoost
:
1399 /* Check buffer length */
1400 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1402 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1406 /* Use SEH for capture */
1409 /* Get the priority */
1410 DisableBoost
= *(PULONG_PTR
)ThreadInformation
;
1412 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1414 /* Get the exception code */
1415 Status
= _SEH2_GetExceptionCode();
1418 if (!NT_SUCCESS(Status
)) break;
1420 /* Call the kernel */
1421 KeSetDisableBoostThread(&Thread
->Tcb
, (BOOLEAN
)DisableBoost
);
1424 case ThreadZeroTlsCell
:
1426 /* Check buffer length */
1427 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1429 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1433 /* Use SEH for capture */
1436 /* Get the priority */
1437 TlsIndex
= *(PULONG_PTR
)ThreadInformation
;
1439 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1441 /* Get the exception code */
1442 Status
= _SEH2_GetExceptionCode();
1445 if (!NT_SUCCESS(Status
)) break;
1447 /* This is only valid for the current thread */
1448 if (Thread
!= PsGetCurrentThread())
1451 Status
= STATUS_INVALID_PARAMETER
;
1455 /* Get the process */
1456 Process
= Thread
->ThreadsProcess
;
1458 /* Loop the threads */
1459 ProcThread
= PsGetNextProcessThread(Process
, NULL
);
1462 /* Acquire rundown */
1463 if (ExAcquireRundownProtection(&ProcThread
->RundownProtect
))
1466 Teb
= ProcThread
->Tcb
.Teb
;
1469 /* Check if we're in the expansion range */
1470 if (TlsIndex
> TLS_MINIMUM_AVAILABLE
- 1)
1472 if (TlsIndex
< (TLS_MINIMUM_AVAILABLE
+
1473 TLS_EXPANSION_SLOTS
) - 1)
1475 /* Check if we have expansion slots */
1476 ExpansionSlots
= Teb
->TlsExpansionSlots
;
1479 /* Clear the index */
1480 ExpansionSlots
[TlsIndex
- TLS_MINIMUM_AVAILABLE
] = 0;
1486 /* Clear the index */
1487 Teb
->TlsSlots
[TlsIndex
] = NULL
;
1491 /* Release rundown */
1492 ExReleaseRundownProtection(&ProcThread
->RundownProtect
);
1495 /* Go to the next thread */
1496 ProcThread
= PsGetNextProcessThread(Process
, ProcThread
);
1503 /* We don't implement it yet */
1504 DPRINT1("Not implemented: %lx\n", ThreadInformationClass
);
1505 Status
= STATUS_NOT_IMPLEMENTED
;
1508 /* Dereference and return status */
1509 ObDereferenceObject(Thread
);
1518 NtQueryInformationThread(IN HANDLE ThreadHandle
,
1519 IN THREADINFOCLASS ThreadInformationClass
,
1520 OUT PVOID ThreadInformation
,
1521 IN ULONG ThreadInformationLength
,
1522 OUT PULONG ReturnLength OPTIONAL
)
1525 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1526 NTSTATUS Status
= STATUS_SUCCESS
;
1529 PTHREAD_BASIC_INFORMATION ThreadBasicInfo
=
1530 (PTHREAD_BASIC_INFORMATION
)ThreadInformation
;
1531 PKERNEL_USER_TIMES ThreadTime
= (PKERNEL_USER_TIMES
)ThreadInformation
;
1535 if (PreviousMode
!= KernelMode
)
1539 ProbeForWrite(ThreadInformation
,
1540 ThreadInformationLength
,
1545 ProbeForWriteUlong(ReturnLength
);
1548 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1550 Status
= _SEH2_GetExceptionCode();
1554 if (!NT_SUCCESS(Status
)) return Status
;
1557 /* Check what class this is */
1558 Access
= THREAD_QUERY_INFORMATION
;
1560 /* Reference the process */
1561 Status
= ObReferenceObjectByHandle(ThreadHandle
,
1567 if (!NT_SUCCESS(Status
)) return Status
;
1569 /* Check what kind of information class this is */
1570 switch (ThreadInformationClass
)
1572 /* Basic thread information */
1573 case ThreadBasicInformation
:
1575 /* Set return length */
1576 Length
= sizeof(THREAD_BASIC_INFORMATION
);
1578 if (ThreadInformationLength
!= Length
)
1580 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1583 /* Protect writes with SEH */
1586 /* Write all the information from the ETHREAD/KTHREAD */
1587 ThreadBasicInfo
->ExitStatus
= Thread
->ExitStatus
;
1588 ThreadBasicInfo
->TebBaseAddress
= (PVOID
)Thread
->Tcb
.Teb
;
1589 ThreadBasicInfo
->ClientId
= Thread
->Cid
;
1590 ThreadBasicInfo
->AffinityMask
= Thread
->Tcb
.Affinity
;
1591 ThreadBasicInfo
->Priority
= Thread
->Tcb
.Priority
;
1592 ThreadBasicInfo
->BasePriority
= KeQueryBasePriorityThread(&Thread
->Tcb
);
1594 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1596 /* Get exception code */
1597 Status
= _SEH2_GetExceptionCode();
1602 /* Thread time information */
1605 /* Set the return length */
1606 Length
= sizeof(KERNEL_USER_TIMES
);
1608 if (ThreadInformationLength
!= Length
)
1610 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1613 /* Protect writes with SEH */
1616 /* Copy time information from ETHREAD/KTHREAD */
1617 ThreadTime
->KernelTime
.QuadPart
= Thread
->Tcb
.KernelTime
*
1619 ThreadTime
->UserTime
.QuadPart
= Thread
->Tcb
.UserTime
*
1621 ThreadTime
->CreateTime
= Thread
->CreateTime
;
1622 ThreadTime
->ExitTime
= Thread
->ExitTime
;
1624 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1626 /* Get exception code */
1627 Status
= _SEH2_GetExceptionCode();
1632 case ThreadQuerySetWin32StartAddress
:
1634 /* Set the return length*/
1635 Length
= sizeof(PVOID
);
1637 if (ThreadInformationLength
!= Length
)
1639 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1642 /* Protect write with SEH */
1645 /* Return the Win32 Start Address */
1646 *(PVOID
*)ThreadInformation
= Thread
->Win32StartAddress
;
1648 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1650 /* Get exception code */
1651 Status
= _SEH2_GetExceptionCode();
1656 case ThreadPerformanceCount
:
1658 /* Set the return length*/
1659 Length
= sizeof(LARGE_INTEGER
);
1661 if (ThreadInformationLength
!= Length
)
1663 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1666 /* Protect write with SEH */
1670 (*(PLARGE_INTEGER
)ThreadInformation
).QuadPart
= 0;
1672 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1674 /* Get exception code */
1675 Status
= _SEH2_GetExceptionCode();
1680 case ThreadAmILastThread
:
1682 /* Set the return length*/
1683 Length
= sizeof(ULONG
);
1685 if (ThreadInformationLength
!= Length
)
1687 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1690 /* Protect write with SEH */
1693 /* Return whether or not we are the last thread */
1694 *(PULONG
)ThreadInformation
= ((Thread
->ThreadsProcess
->
1695 ThreadListHead
.Flink
->Flink
==
1696 &Thread
->ThreadsProcess
->
1700 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1702 /* Get exception code */
1703 Status
= _SEH2_GetExceptionCode();
1708 case ThreadIsIoPending
:
1710 /* Set the return length*/
1711 Length
= sizeof(ULONG
);
1713 if (ThreadInformationLength
!= Length
)
1715 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1718 /* Raise the IRQL to protect the IRP list */
1719 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1721 /* Protect write with SEH */
1724 /* Check if the IRP list is empty or not */
1725 *(PULONG
)ThreadInformation
= !IsListEmpty(&Thread
->IrpList
);
1727 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1729 /* Get exception code */
1730 Status
= _SEH2_GetExceptionCode();
1734 /* Lower IRQL back */
1735 KeLowerIrql(OldIrql
);
1738 case ThreadDescriptorTableEntry
:
1739 DPRINT1("NtQueryInformationThread(): case ThreadDescriptorTableEntry not implemented!\n");
1740 Status
= STATUS_NOT_IMPLEMENTED
;
1743 case ThreadPriorityBoost
:
1745 /* Set the return length*/
1746 Length
= sizeof(ULONG
);
1748 if (ThreadInformationLength
!= Length
)
1750 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1756 *(PULONG
)ThreadInformation
= Thread
->Tcb
.DisableBoost
? 1 : 0;
1758 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1760 Status
= _SEH2_GetExceptionCode();
1768 /* Not yet implemented */
1769 DPRINT1("Not implemented: %lx\n", ThreadInformationClass
);
1770 Status
= STATUS_NOT_IMPLEMENTED
;
1773 /* Protect write with SEH */
1776 /* Check if caller wanted return length */
1777 if (ReturnLength
) *ReturnLength
= Length
;
1779 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1781 /* Get exception code */
1782 Status
= _SEH2_GetExceptionCode();
1786 /* Dereference the thread, and return */
1787 ObDereferenceObject(Thread
);