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 ******************************************************************/
18 ULONG PspTraceLevel
= 0;
20 /* PRIVATE FUNCTIONS *********************************************************/
24 PsReferenceProcessFilePointer(IN PEPROCESS Process
,
25 OUT PFILE_OBJECT
*FileObject
)
30 /* Lock the process */
31 ExAcquireRundownProtection(&Process
->RundownProtect
);
34 Section
= Process
->SectionObject
;
37 /* Get the file object and reference it */
38 *FileObject
= MmGetFileObjectForSection((PVOID
)Section
);
39 ObReferenceObject(*FileObject
);
42 /* Release the protection */
43 ExReleaseRundownProtection(&Process
->RundownProtect
);
46 return Section
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
;
49 /* PUBLIC FUNCTIONS **********************************************************/
56 NtQueryInformationProcess(IN HANDLE ProcessHandle
,
57 IN PROCESSINFOCLASS ProcessInformationClass
,
58 OUT PVOID ProcessInformation
,
59 IN ULONG ProcessInformationLength
,
60 OUT PULONG ReturnLength OPTIONAL
)
63 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
67 PPROCESS_BASIC_INFORMATION ProcessBasicInfo
=
68 (PPROCESS_BASIC_INFORMATION
)ProcessInformation
;
69 PKERNEL_USER_TIMES ProcessTime
= (PKERNEL_USER_TIMES
)ProcessInformation
;
70 ULONG UserTime
, KernelTime
;
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
;
80 ULONG Cookie
, ExecuteOptions
= 0;
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 (ProcessInformationClass
== ProcessImageInformation
)) &&
108 (ProcessHandle
!= NtCurrentProcess()))
111 * Retrieving the process cookie is only allowed for the calling process
112 * itself! XP only allows NtCurrentProcess() as process handles even if
113 * a real handle actually represents the current process.
115 return STATUS_INVALID_PARAMETER
;
118 /* Check the information class */
119 switch (ProcessInformationClass
)
121 /* Basic process information */
122 case ProcessBasicInformation
:
124 /* Set return length */
125 Length
= sizeof(PROCESS_BASIC_INFORMATION
);
127 if (ProcessInformationLength
!= Length
)
129 Status
= STATUS_INFO_LENGTH_MISMATCH
;
133 /* Reference the process */
134 Status
= ObReferenceObjectByHandle(ProcessHandle
,
135 PROCESS_QUERY_INFORMATION
,
140 if (!NT_SUCCESS(Status
)) break;
142 /* Protect writes with SEH */
145 /* Write all the information from the EPROCESS/KPROCESS */
146 ProcessBasicInfo
->ExitStatus
= Process
->ExitStatus
;
147 ProcessBasicInfo
->PebBaseAddress
= Process
->Peb
;
148 ProcessBasicInfo
->AffinityMask
= Process
->Pcb
.Affinity
;
149 ProcessBasicInfo
->UniqueProcessId
= (ULONG_PTR
)Process
->
151 ProcessBasicInfo
->InheritedFromUniqueProcessId
=
152 (ULONG_PTR
)Process
->InheritedFromUniqueProcessId
;
153 ProcessBasicInfo
->BasePriority
= Process
->Pcb
.BasePriority
;
156 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
158 /* Get exception code */
159 Status
= _SEH2_GetExceptionCode();
163 /* Dereference the process */
164 ObDereferenceObject(Process
);
167 /* Process quota limits */
168 case ProcessQuotaLimits
:
170 Length
= sizeof(QUOTA_LIMITS
);
171 if (ProcessInformationLength
!= Length
)
173 Status
= STATUS_INFO_LENGTH_MISMATCH
;
177 /* Reference the process */
178 Status
= ObReferenceObjectByHandle(ProcessHandle
,
179 PROCESS_QUERY_INFORMATION
,
184 if (!NT_SUCCESS(Status
)) break;
186 /* Indicate success */
187 Status
= STATUS_SUCCESS
;
191 /* Set max/min working set sizes */
192 QuotaLimits
->MaximumWorkingSetSize
=
193 Process
->Vm
.MaximumWorkingSetSize
<< PAGE_SHIFT
;
194 QuotaLimits
->MinimumWorkingSetSize
=
195 Process
->Vm
.MinimumWorkingSetSize
<< PAGE_SHIFT
;
197 /* Set default time limits */
198 QuotaLimits
->TimeLimit
.LowPart
= MAXULONG
;
199 QuotaLimits
->TimeLimit
.HighPart
= MAXULONG
;
201 /* Is quota block a default one? */
202 if (Process
->QuotaBlock
== &PspDefaultQuotaBlock
)
204 /* Set default pools and pagefile limits */
205 QuotaLimits
->PagedPoolLimit
= (SIZE_T
)-1;
206 QuotaLimits
->NonPagedPoolLimit
= (SIZE_T
)-1;
207 QuotaLimits
->PagefileLimit
= (SIZE_T
)-1;
211 /* Get limits from non-default quota block */
212 QuotaLimits
->PagedPoolLimit
=
213 Process
->QuotaBlock
->QuotaEntry
[PagedPool
].Limit
;
214 QuotaLimits
->NonPagedPoolLimit
=
215 Process
->QuotaBlock
->QuotaEntry
[NonPagedPool
].Limit
;
216 QuotaLimits
->PagefileLimit
=
217 Process
->QuotaBlock
->QuotaEntry
[2].Limit
;
220 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
222 /* Get exception code */
223 Status
= _SEH2_GetExceptionCode();
227 /* Dereference the process */
228 ObDereferenceObject(Process
);
231 case ProcessIoCounters
:
233 Length
= sizeof(IO_COUNTERS
);
234 if (ProcessInformationLength
!= Length
)
236 Status
= STATUS_INFO_LENGTH_MISMATCH
;
240 /* Reference the process */
241 Status
= ObReferenceObjectByHandle(ProcessHandle
,
242 PROCESS_QUERY_INFORMATION
,
247 if (!NT_SUCCESS(Status
)) break;
251 /* FIXME: Call KeQueryValuesProcess */
252 IoCounters
->ReadOperationCount
= Process
->ReadOperationCount
.QuadPart
;
253 IoCounters
->ReadTransferCount
= Process
->ReadTransferCount
.QuadPart
;
254 IoCounters
->WriteOperationCount
= Process
->WriteOperationCount
.QuadPart
;
255 IoCounters
->WriteTransferCount
= Process
->WriteTransferCount
.QuadPart
;
256 IoCounters
->OtherOperationCount
= Process
->OtherOperationCount
.QuadPart
;
257 IoCounters
->OtherTransferCount
= Process
->OtherTransferCount
.QuadPart
;
259 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
261 /* Ignore exception */
265 /* Set status to success in any case */
266 Status
= STATUS_SUCCESS
;
268 /* Dereference the process */
269 ObDereferenceObject(Process
);
275 /* Set the return length */
276 Length
= sizeof(KERNEL_USER_TIMES
);
278 if (ProcessInformationLength
!= Length
)
280 Status
= STATUS_INFO_LENGTH_MISMATCH
;
284 /* Reference the process */
285 Status
= ObReferenceObjectByHandle(ProcessHandle
,
286 PROCESS_QUERY_INFORMATION
,
291 if (!NT_SUCCESS(Status
)) break;
293 /* Protect writes with SEH */
296 /* Copy time information from EPROCESS/KPROCESS */
297 KernelTime
= KeQueryRuntimeProcess(&Process
->Pcb
, &UserTime
);
298 ProcessTime
->CreateTime
= Process
->CreateTime
;
299 ProcessTime
->UserTime
.QuadPart
= (LONGLONG
)UserTime
* KeMaximumIncrement
;
300 ProcessTime
->KernelTime
.QuadPart
= (LONGLONG
)KernelTime
* KeMaximumIncrement
;
301 ProcessTime
->ExitTime
= Process
->ExitTime
;
303 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
305 /* Get exception code */
306 Status
= _SEH2_GetExceptionCode();
310 /* Dereference the process */
311 ObDereferenceObject(Process
);
314 /* Process Debug Port */
315 case ProcessDebugPort
:
317 /* Set return length */
318 Length
= sizeof(HANDLE
);
320 if (ProcessInformationLength
!= Length
)
322 Status
= STATUS_INFO_LENGTH_MISMATCH
;
326 /* Reference the process */
327 Status
= ObReferenceObjectByHandle(ProcessHandle
,
328 PROCESS_QUERY_INFORMATION
,
333 if (!NT_SUCCESS(Status
)) break;
335 /* Protect write with SEH */
338 /* Return whether or not we have a debug port */
339 *(PHANDLE
)ProcessInformation
= (Process
->DebugPort
?
342 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
344 /* Get exception code */
345 Status
= _SEH2_GetExceptionCode();
349 /* Dereference the process */
350 ObDereferenceObject(Process
);
353 case ProcessHandleCount
:
355 /* Set the return length*/
356 Length
= sizeof(ULONG
);
358 if (ProcessInformationLength
!= Length
)
360 Status
= STATUS_INFO_LENGTH_MISMATCH
;
364 /* Reference the process */
365 Status
= ObReferenceObjectByHandle(ProcessHandle
,
366 PROCESS_QUERY_INFORMATION
,
371 if (!NT_SUCCESS(Status
)) break;
373 /* Count the number of handles this process has */
374 HandleCount
= ObGetProcessHandleCount(Process
);
376 /* Protect write in SEH */
379 /* Return the count of handles */
380 *(PULONG
)ProcessInformation
= HandleCount
;
382 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
384 /* Get the exception code */
385 Status
= _SEH2_GetExceptionCode();
389 /* Dereference the process */
390 ObDereferenceObject(Process
);
393 /* Session ID for the process */
394 case ProcessSessionInformation
:
396 /* Set the return length*/
397 Length
= sizeof(PROCESS_SESSION_INFORMATION
);
399 if (ProcessInformationLength
!= Length
)
401 Status
= STATUS_INFO_LENGTH_MISMATCH
;
405 /* Reference the process */
406 Status
= ObReferenceObjectByHandle(ProcessHandle
,
407 PROCESS_QUERY_INFORMATION
,
412 if (!NT_SUCCESS(Status
)) break;
414 /* Enter SEH for write safety */
417 /* Write back the Session ID */
418 SessionInfo
->SessionId
= PsGetProcessSessionId(Process
);
420 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
422 /* Get the exception code */
423 Status
= _SEH2_GetExceptionCode();
427 /* Dereference the process */
428 ObDereferenceObject(Process
);
431 /* Virtual Memory Statistics */
432 case ProcessVmCounters
:
434 /* Validate the input length */
435 if ((ProcessInformationLength
!= sizeof(VM_COUNTERS
)) &&
436 (ProcessInformationLength
!= sizeof(VM_COUNTERS_EX
)))
438 Status
= STATUS_INFO_LENGTH_MISMATCH
;
442 /* Reference the process */
443 Status
= ObReferenceObjectByHandle(ProcessHandle
,
444 PROCESS_QUERY_INFORMATION
,
449 if (!NT_SUCCESS(Status
)) break;
451 /* Enter SEH for write safety */
454 /* Return data from EPROCESS */
455 VmCounters
->PeakVirtualSize
= Process
->PeakVirtualSize
;
456 VmCounters
->VirtualSize
= Process
->VirtualSize
;
457 VmCounters
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
458 VmCounters
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
459 VmCounters
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
460 VmCounters
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeak
[0];
461 VmCounters
->QuotaPagedPoolUsage
= Process
->QuotaUsage
[0];
462 VmCounters
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeak
[1];
463 VmCounters
->QuotaNonPagedPoolUsage
= Process
->QuotaUsage
[1];
464 VmCounters
->PagefileUsage
= Process
->QuotaUsage
[2] << PAGE_SHIFT
;
465 VmCounters
->PeakPagefileUsage
= Process
->QuotaPeak
[2] << PAGE_SHIFT
;
466 //VmCounters->PrivateUsage = Process->CommitCharge << PAGE_SHIFT;
469 /* Set the return length */
470 Length
= ProcessInformationLength
;
472 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
474 /* Get the exception code */
475 Status
= _SEH2_GetExceptionCode();
479 /* Dereference the process */
480 ObDereferenceObject(Process
);
483 /* Hard Error Processing Mode */
484 case ProcessDefaultHardErrorMode
:
486 /* Set the return length*/
487 Length
= sizeof(ULONG
);
489 if (ProcessInformationLength
!= Length
)
491 Status
= STATUS_INFO_LENGTH_MISMATCH
;
495 /* Reference the process */
496 Status
= ObReferenceObjectByHandle(ProcessHandle
,
497 PROCESS_QUERY_INFORMATION
,
502 if (!NT_SUCCESS(Status
)) break;
504 /* Enter SEH for writing back data */
507 /* Write the current processing mode */
508 *(PULONG
)ProcessInformation
= Process
->
509 DefaultHardErrorProcessing
;
511 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
513 /* Get the exception code */
514 Status
= _SEH2_GetExceptionCode();
518 /* Dereference the process */
519 ObDereferenceObject(Process
);
522 /* Priority Boosting status */
523 case ProcessPriorityBoost
:
525 /* Set the return length */
526 Length
= sizeof(ULONG
);
528 if (ProcessInformationLength
!= Length
)
530 Status
= STATUS_INFO_LENGTH_MISMATCH
;
534 /* Reference the process */
535 Status
= ObReferenceObjectByHandle(ProcessHandle
,
536 PROCESS_QUERY_INFORMATION
,
541 if (!NT_SUCCESS(Status
)) break;
543 /* Enter SEH for writing back data */
546 /* Return boost status */
547 *(PULONG
)ProcessInformation
= Process
->Pcb
.DisableBoost
?
550 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
552 /* Get the exception code */
553 Status
= _SEH2_GetExceptionCode();
557 /* Dereference the process */
558 ObDereferenceObject(Process
);
562 case ProcessDeviceMap
:
564 /* Set the return length */
565 Length
= sizeof(PROCESS_DEVICEMAP_INFORMATION
);
567 if (ProcessInformationLength
!= Length
)
569 if (ProcessInformationLength
== sizeof(PROCESS_DEVICEMAP_INFORMATION_EX
))
571 DPRINT1("PROCESS_DEVICEMAP_INFORMATION_EX not supported!\n");
572 Status
= STATUS_NOT_IMPLEMENTED
;
576 Status
= STATUS_INFO_LENGTH_MISMATCH
;
581 /* Reference the process */
582 Status
= ObReferenceObjectByHandle(ProcessHandle
,
583 PROCESS_QUERY_INFORMATION
,
588 if (!NT_SUCCESS(Status
)) break;
590 /* Query the device map information */
591 ObQueryDeviceMapInformation(Process
, &DeviceMap
);
593 /* Enter SEH for writing back data */
596 *(PPROCESS_DEVICEMAP_INFORMATION
)ProcessInformation
= DeviceMap
;
598 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
600 /* Get the exception code */
601 Status
= _SEH2_GetExceptionCode();
605 /* Dereference the process */
606 ObDereferenceObject(Process
);
610 case ProcessPriorityClass
:
612 /* Set the return length*/
613 Length
= sizeof(PROCESS_PRIORITY_CLASS
);
615 if (ProcessInformationLength
!= Length
)
617 Status
= STATUS_INFO_LENGTH_MISMATCH
;
621 /* Reference the process */
622 Status
= ObReferenceObjectByHandle(ProcessHandle
,
623 PROCESS_QUERY_INFORMATION
,
628 if (!NT_SUCCESS(Status
)) break;
630 /* Enter SEH for writing back data */
633 /* Return current priority class */
634 PsPriorityClass
->PriorityClass
= Process
->PriorityClass
;
635 PsPriorityClass
->Foreground
= FALSE
;
637 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
639 /* Get the exception code */
640 Status
= _SEH2_GetExceptionCode();
644 /* Dereference the process */
645 ObDereferenceObject(Process
);
648 case ProcessImageFileName
:
650 /* Reference the process */
651 Status
= ObReferenceObjectByHandle(ProcessHandle
,
652 PROCESS_QUERY_INFORMATION
,
657 if (!NT_SUCCESS(Status
)) break;
659 /* Get the image path */
660 Status
= SeLocateProcessImageName(Process
, &ImageName
);
661 if (NT_SUCCESS(Status
))
663 /* Set return length */
664 Length
= ImageName
->MaximumLength
+
665 sizeof(OBJECT_NAME_INFORMATION
);
667 /* Make sure it's large enough */
668 if (Length
<= ProcessInformationLength
)
670 /* Enter SEH to protect write */
674 RtlCopyMemory(ProcessInformation
,
679 ((PUNICODE_STRING
)ProcessInformation
)->Buffer
=
680 (PWSTR
)((PUNICODE_STRING
)ProcessInformation
+ 1);
682 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
684 /* Get the exception code */
685 Status
= _SEH2_GetExceptionCode();
691 /* Buffer too small */
692 Status
= STATUS_INFO_LENGTH_MISMATCH
;
695 /* Free the image path */
696 ExFreePoolWithTag(ImageName
, TAG_SEPA
);
698 /* Dereference the process */
699 ObDereferenceObject(Process
);
702 case ProcessDebugFlags
:
704 /* Set the return length*/
705 Length
= sizeof(ULONG
);
706 if (ProcessInformationLength
!= Length
)
708 Status
= STATUS_INFO_LENGTH_MISMATCH
;
712 /* Reference the process */
713 Status
= ObReferenceObjectByHandle(ProcessHandle
,
714 PROCESS_QUERY_INFORMATION
,
719 if (!NT_SUCCESS(Status
)) break;
721 /* Enter SEH for writing back data */
724 /* Return the debug flag state */
725 *(PULONG
)ProcessInformation
= Process
->NoDebugInherit
? 0 : 1;
727 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
729 /* Get the exception code */
730 Status
= _SEH2_GetExceptionCode();
734 /* Dereference the process */
735 ObDereferenceObject(Process
);
738 case ProcessBreakOnTermination
:
740 /* Set the return length*/
741 Length
= sizeof(ULONG
);
742 if (ProcessInformationLength
!= Length
)
744 Status
= STATUS_INFO_LENGTH_MISMATCH
;
748 /* Reference the process */
749 Status
= ObReferenceObjectByHandle(ProcessHandle
,
750 PROCESS_QUERY_INFORMATION
,
755 if (!NT_SUCCESS(Status
)) break;
757 /* Enter SEH for writing back data */
760 /* Return the BreakOnTermination state */
761 *(PULONG
)ProcessInformation
= Process
->BreakOnTermination
;
763 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
765 /* Get the exception code */
766 Status
= _SEH2_GetExceptionCode();
770 /* Dereference the process */
771 ObDereferenceObject(Process
);
774 /* Per-process security cookie */
777 /* Get the current process and cookie */
778 Process
= PsGetCurrentProcess();
779 Cookie
= Process
->Cookie
;
782 LARGE_INTEGER SystemTime
;
786 /* Generate a new cookie */
787 KeQuerySystemTime(&SystemTime
);
788 Prcb
= KeGetCurrentPrcb();
789 NewCookie
= Prcb
->KeSystemCalls
^ Prcb
->InterruptTime
^
790 SystemTime
.u
.LowPart
^ SystemTime
.u
.HighPart
;
792 /* Set the new cookie or return the current one */
793 Cookie
= InterlockedCompareExchange((LONG
*)&Process
->Cookie
,
796 if (!Cookie
) Cookie
= NewCookie
;
798 /* Set return length */
799 Length
= sizeof(ULONG
);
802 /* Indicate success */
803 Status
= STATUS_SUCCESS
;
805 /* Enter SEH to protect write */
808 /* Write back the cookie */
809 *(PULONG
)ProcessInformation
= Cookie
;
811 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
813 /* Get the exception code */
814 Status
= _SEH2_GetExceptionCode();
819 case ProcessImageInformation
:
821 /* Set the length required and validate it */
822 Length
= sizeof(SECTION_IMAGE_INFORMATION
);
823 if (ProcessInformationLength
!= Length
)
826 Status
= STATUS_INFO_LENGTH_MISMATCH
;
830 /* Enter SEH to protect write */
833 MmGetImageInformation((PSECTION_IMAGE_INFORMATION
)ProcessInformation
);
835 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
837 /* Get the exception code */
838 Status
= _SEH2_GetExceptionCode();
842 /* Indicate success */
843 Status
= STATUS_SUCCESS
;
846 case ProcessDebugObjectHandle
:
848 /* Set the return length */
849 Length
= sizeof(HANDLE
);
850 if (ProcessInformationLength
!= Length
)
852 Status
= STATUS_INFO_LENGTH_MISMATCH
;
856 /* Reference the process */
857 Status
= ObReferenceObjectByHandle(ProcessHandle
,
858 PROCESS_QUERY_INFORMATION
,
863 if (!NT_SUCCESS(Status
)) break;
865 /* Get the debug port */
866 Status
= DbgkOpenProcessDebugPort(Process
, PreviousMode
, &DebugPort
);
868 /* Let go of the process */
869 ObDereferenceObject(Process
);
871 /* Protect write in SEH */
874 /* Return debug port's handle */
875 *(PHANDLE
)ProcessInformation
= DebugPort
;
877 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
879 /* Get the exception code */
880 Status
= _SEH2_GetExceptionCode();
885 case ProcessHandleTracing
:
886 DPRINT1("Handle tracing Not implemented: %lx\n", ProcessInformationClass
);
887 Status
= STATUS_NOT_IMPLEMENTED
;
890 case ProcessLUIDDeviceMapsEnabled
:
892 /* Set the return length */
893 Length
= sizeof(ULONG
);
894 if (ProcessInformationLength
!= Length
)
896 Status
= STATUS_INFO_LENGTH_MISMATCH
;
900 /* Indicate success */
901 Status
= STATUS_SUCCESS
;
903 /* Protect write in SEH */
906 /* Return FALSE -- we don't support this */
907 *(PULONG
)ProcessInformation
= FALSE
;
909 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
911 /* Get the exception code */
912 Status
= _SEH2_GetExceptionCode();
917 case ProcessWx86Information
:
919 /* Set the return length */
920 Length
= sizeof(ULONG
);
921 if (ProcessInformationLength
!= Length
)
923 Status
= STATUS_INFO_LENGTH_MISMATCH
;
927 /* Reference the process */
928 Status
= ObReferenceObjectByHandle(ProcessHandle
,
929 PROCESS_QUERY_INFORMATION
,
934 if (!NT_SUCCESS(Status
)) break;
936 /* Protect write in SEH */
939 /* Return if the flag is set */
940 *(PULONG
)ProcessInformation
= (ULONG
)Process
->VdmAllowed
;
942 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
944 /* Get the exception code */
945 Status
= _SEH2_GetExceptionCode();
949 /* Dereference the process */
950 ObDereferenceObject(Process
);
953 case ProcessWow64Information
:
955 /* Set return length */
956 Length
= sizeof(ULONG_PTR
);
957 if (ProcessInformationLength
!= Length
)
960 Status
= STATUS_INFO_LENGTH_MISMATCH
;
964 /* Reference the process */
965 Status
= ObReferenceObjectByHandle(ProcessHandle
,
966 PROCESS_QUERY_INFORMATION
,
971 if (!NT_SUCCESS(Status
)) break;
973 /* Make sure the process isn't dying */
974 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
976 /* Get the WOW64 process structure */
978 Wow64
= (ULONG_PTR
)Process
->Wow64Process
;
982 /* Release the lock */
983 ExReleaseRundownProtection(&Process
->RundownProtect
);
986 /* Protect write with SEH */
989 /* Return whether or not we have a debug port */
990 *(PULONG_PTR
)ProcessInformation
= Wow64
;
992 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
994 /* Get exception code */
995 Status
= _SEH2_GetExceptionCode();
999 /* Dereference the process */
1000 ObDereferenceObject(Process
);
1003 case ProcessExecuteFlags
:
1005 /* Set return length */
1006 Length
= sizeof(ULONG
);
1007 if (ProcessInformationLength
!= Length
)
1009 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1013 if (ProcessHandle
!= NtCurrentProcess())
1015 return STATUS_INVALID_PARAMETER
;
1018 /* Get the options */
1019 Status
= MmGetExecuteOptions(&ExecuteOptions
);
1020 if (NT_SUCCESS(Status
))
1022 /* Protect write with SEH */
1026 *(PULONG
)ProcessInformation
= ExecuteOptions
;
1028 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1030 /* Get exception code */
1031 Status
= _SEH2_GetExceptionCode();
1037 case ProcessLdtInformation
:
1038 DPRINT1("VDM/16-bit not implemented: %lx\n", ProcessInformationClass
);
1039 Status
= STATUS_NOT_IMPLEMENTED
;
1042 case ProcessWorkingSetWatch
:
1043 DPRINT1("WS Watch Not implemented: %lx\n", ProcessInformationClass
);
1044 Status
= STATUS_NOT_IMPLEMENTED
;
1047 case ProcessPooledUsageAndLimits
:
1048 DPRINT1("Pool limits Not implemented: %lx\n", ProcessInformationClass
);
1049 Status
= STATUS_NOT_IMPLEMENTED
;
1052 /* Not supported by Server 2003 */
1054 DPRINT1("Unsupported info class: %lx\n", ProcessInformationClass
);
1055 Status
= STATUS_INVALID_INFO_CLASS
;
1058 /* Protect write with SEH */
1061 /* Check if caller wanted return length */
1062 if ((ReturnLength
) && (Length
)) *ReturnLength
= Length
;
1064 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1066 /* Get exception code */
1067 Status
= _SEH2_GetExceptionCode();
1079 NtSetInformationProcess(IN HANDLE ProcessHandle
,
1080 IN PROCESSINFOCLASS ProcessInformationClass
,
1081 IN PVOID ProcessInformation
,
1082 IN ULONG ProcessInformationLength
)
1085 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1088 HANDLE PortHandle
= NULL
;
1089 HANDLE TokenHandle
= NULL
;
1090 PROCESS_SESSION_INFORMATION SessionInfo
= {0};
1091 PROCESS_PRIORITY_CLASS PriorityClass
= {0};
1092 PROCESS_FOREGROUND_BACKGROUND Foreground
= {0};
1093 PVOID ExceptionPort
;
1095 KAFFINITY ValidAffinity
, Affinity
= 0;
1096 KPRIORITY BasePriority
= 0;
1097 UCHAR MemoryPriority
= 0;
1098 BOOLEAN DisableBoost
= 0;
1099 ULONG DefaultHardErrorMode
= 0;
1100 ULONG DebugFlags
= 0, EnableFixup
= 0, Boost
= 0;
1101 ULONG NoExecute
= 0, VdmPower
= 0;
1102 BOOLEAN HasPrivilege
;
1107 /* Verify Information Class validity */
1109 Status
= DefaultSetInfoBufferCheck(ProcessInformationClass
,
1111 RTL_NUMBER_OF(PsProcessInfoClass
),
1113 ProcessInformationLength
,
1115 if (!NT_SUCCESS(Status
)) return Status
;
1118 /* Check what class this is */
1119 Access
= PROCESS_SET_INFORMATION
;
1120 if (ProcessInformationClass
== ProcessSessionInformation
)
1122 /* Setting the Session ID needs a special mask */
1123 Access
|= PROCESS_SET_SESSIONID
;
1125 else if (ProcessInformationClass
== ProcessExceptionPort
)
1127 /* Setting the exception port needs a special mask */
1128 Access
|= PROCESS_SUSPEND_RESUME
;
1131 /* Reference the process */
1132 Status
= ObReferenceObjectByHandle(ProcessHandle
,
1138 if (!NT_SUCCESS(Status
)) return Status
;
1140 /* Check what kind of information class this is */
1141 switch (ProcessInformationClass
)
1143 case ProcessWx86Information
:
1145 /* Check buffer length */
1146 if (ProcessInformationLength
!= sizeof(HANDLE
))
1148 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1152 /* Use SEH for capture */
1155 /* Capture the boolean */
1156 VdmPower
= *(PULONG
)ProcessInformation
;
1158 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1160 /* Get the exception code */
1161 Status
= _SEH2_GetExceptionCode();
1166 /* Getting VDM powers requires the SeTcbPrivilege */
1167 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
1169 /* We don't hold the privilege, bail out */
1170 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1171 DPRINT1("Need TCB privilege\n");
1175 /* Set or clear the flag */
1178 PspSetProcessFlag(Process
, PSF_VDM_ALLOWED_BIT
);
1182 PspClearProcessFlag(Process
, PSF_VDM_ALLOWED_BIT
);
1186 /* Error/Exception Port */
1187 case ProcessExceptionPort
:
1189 /* Check buffer length */
1190 if (ProcessInformationLength
!= sizeof(HANDLE
))
1192 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1196 /* Use SEH for capture */
1199 /* Capture the handle */
1200 PortHandle
= *(PHANDLE
)ProcessInformation
;
1202 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1204 /* Get the exception code */
1205 Status
= _SEH2_GetExceptionCode();
1210 /* Setting the error port requires the SeTcbPrivilege */
1211 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
1213 /* We don't hold the privilege, bail out */
1214 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1218 /* Get the LPC Port */
1219 Status
= ObReferenceObjectByHandle(PortHandle
,
1223 (PVOID
)&ExceptionPort
,
1225 if (!NT_SUCCESS(Status
)) break;
1227 /* Change the pointer */
1228 if (InterlockedCompareExchangePointer(&Process
->ExceptionPort
,
1232 /* We already had one, fail */
1233 ObDereferenceObject(ExceptionPort
);
1234 Status
= STATUS_PORT_ALREADY_SET
;
1238 /* Security Token */
1239 case ProcessAccessToken
:
1241 /* Check buffer length */
1242 if (ProcessInformationLength
!= sizeof(PROCESS_ACCESS_TOKEN
))
1244 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1248 /* Use SEH for capture */
1251 /* Save the token handle */
1252 TokenHandle
= ((PPROCESS_ACCESS_TOKEN
)ProcessInformation
)->
1255 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1257 /* Get the exception code */
1258 Status
= _SEH2_GetExceptionCode();
1263 /* Assign the actual token */
1264 Status
= PspSetPrimaryToken(Process
, TokenHandle
, NULL
);
1267 /* Hard error processing */
1268 case ProcessDefaultHardErrorMode
:
1270 /* Check buffer length */
1271 if (ProcessInformationLength
!= sizeof(ULONG
))
1273 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1277 /* Enter SEH for direct buffer read */
1280 DefaultHardErrorMode
= *(PULONG
)ProcessInformation
;
1282 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1284 /* Get exception code */
1285 Status
= _SEH2_GetExceptionCode();
1291 Process
->DefaultHardErrorProcessing
= DefaultHardErrorMode
;
1293 /* Call Ke for the update */
1294 if (DefaultHardErrorMode
& SEM_NOALIGNMENTFAULTEXCEPT
)
1296 KeSetAutoAlignmentProcess(&Process
->Pcb
, TRUE
);
1300 KeSetAutoAlignmentProcess(&Process
->Pcb
, FALSE
);
1302 Status
= STATUS_SUCCESS
;
1306 case ProcessSessionInformation
:
1308 /* Check buffer length */
1309 if (ProcessInformationLength
!= sizeof(PROCESS_SESSION_INFORMATION
))
1311 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1315 /* Enter SEH for capture */
1318 /* Capture the caller's buffer */
1319 SessionInfo
= *(PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
1321 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1323 /* Get the exception code */
1324 Status
= _SEH2_GetExceptionCode();
1329 /* Setting the session id requires the SeTcbPrivilege */
1330 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
1332 /* We don't hold the privilege, bail out */
1333 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1337 #if 0 // OLD AND DEPRECATED CODE!!!!
1339 /* FIXME - update the session id for the process token */
1340 //Status = PsLockProcess(Process, FALSE);
1341 if (!NT_SUCCESS(Status
)) break;
1343 /* Write the session ID in the EPROCESS */
1344 Process
->Session
= UlongToPtr(SessionInfo
.SessionId
); // HACK!!!
1346 /* Check if the process also has a PEB */
1350 * Attach to the process to make sure we're in the right
1351 * context to access the PEB structure
1353 KeAttachProcess(&Process
->Pcb
);
1355 /* Enter SEH for write to user-mode PEB */
1358 /* Write the session ID */
1359 Process
->Peb
->SessionId
= SessionInfo
.SessionId
;
1361 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1363 /* Get exception code */
1364 Status
= _SEH2_GetExceptionCode();
1368 /* Detach from the process */
1372 /* Unlock the process */
1373 //PsUnlockProcess(Process);
1378 * Since we cannot change the session ID of the given
1379 * process anymore because it is set once and for all
1380 * at process creation time and because it is stored
1381 * inside the Process->Session structure managed by MM,
1382 * we fake changing it: we just return success if the
1383 * user-defined value is the same as the session ID of
1384 * the process, and otherwise we fail.
1386 if (SessionInfo
.SessionId
== PsGetProcessSessionId(Process
))
1388 Status
= STATUS_SUCCESS
;
1392 Status
= STATUS_ACCESS_DENIED
;
1397 case ProcessPriorityClass
:
1399 /* Check buffer length */
1400 if (ProcessInformationLength
!= sizeof(PROCESS_PRIORITY_CLASS
))
1402 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1406 /* Enter SEH for capture */
1409 /* Capture the caller's buffer */
1410 PriorityClass
= *(PPROCESS_PRIORITY_CLASS
)ProcessInformation
;
1412 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1414 /* Return the exception code */
1415 Status
= _SEH2_GetExceptionCode();
1420 /* Check for invalid PriorityClass value */
1421 if (PriorityClass
.PriorityClass
> PROCESS_PRIORITY_CLASS_ABOVE_NORMAL
)
1423 Status
= STATUS_INVALID_PARAMETER
;
1427 if ((PriorityClass
.PriorityClass
!= Process
->PriorityClass
) &&
1428 (PriorityClass
.PriorityClass
== PROCESS_PRIORITY_CLASS_REALTIME
))
1430 /* Check the privilege */
1431 HasPrivilege
= SeCheckPrivilegedObject(SeIncreaseBasePriorityPrivilege
,
1433 PROCESS_SET_INFORMATION
,
1437 ObDereferenceObject(Process
);
1438 DPRINT1("Privilege to change priority to realtime lacking\n");
1439 return STATUS_PRIVILEGE_NOT_HELD
;
1443 /* Check if we have a job */
1446 DPRINT1("Jobs not yet supported\n");
1449 /* Set process priority class */
1450 Process
->PriorityClass
= PriorityClass
.PriorityClass
;
1452 /* Set process priority mode (foreground or background) */
1453 PsSetProcessPriorityByClass(Process
,
1454 PriorityClass
.Foreground
?
1455 PsProcessPriorityForeground
:
1456 PsProcessPriorityBackground
);
1457 Status
= STATUS_SUCCESS
;
1460 case ProcessForegroundInformation
:
1462 /* Check buffer length */
1463 if (ProcessInformationLength
!= sizeof(PROCESS_FOREGROUND_BACKGROUND
))
1465 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1469 /* Enter SEH for capture */
1472 /* Capture the caller's buffer */
1473 Foreground
= *(PPROCESS_FOREGROUND_BACKGROUND
)ProcessInformation
;
1475 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1477 /* Return the exception code */
1478 Status
= _SEH2_GetExceptionCode();
1483 /* Set process priority mode (foreground or background) */
1484 PsSetProcessPriorityByClass(Process
,
1485 Foreground
.Foreground
?
1486 PsProcessPriorityForeground
:
1487 PsProcessPriorityBackground
);
1488 Status
= STATUS_SUCCESS
;
1491 case ProcessBasePriority
:
1493 /* Validate input length */
1494 if (ProcessInformationLength
!= sizeof(KPRIORITY
))
1496 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1500 /* Enter SEH for direct buffer read */
1503 BasePriority
= *(KPRIORITY
*)ProcessInformation
;
1505 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1507 /* Get exception code */
1509 Status
= _SEH2_GetExceptionCode();
1514 /* Extract the memory priority out of there */
1515 if (BasePriority
& 0x80000000)
1517 MemoryPriority
= MEMORY_PRIORITY_FOREGROUND
;
1518 BasePriority
&= ~0x80000000;
1522 MemoryPriority
= MEMORY_PRIORITY_BACKGROUND
;
1525 /* Validate the number */
1526 if ((BasePriority
> HIGH_PRIORITY
) || (BasePriority
<= LOW_PRIORITY
))
1528 ObDereferenceObject(Process
);
1529 return STATUS_INVALID_PARAMETER
;
1532 /* Check if the new base is higher */
1533 if (BasePriority
> Process
->Pcb
.BasePriority
)
1535 HasPrivilege
= SeCheckPrivilegedObject(SeIncreaseBasePriorityPrivilege
,
1537 PROCESS_SET_INFORMATION
,
1541 ObDereferenceObject(Process
);
1542 DPRINT1("Privilege to change priority from %lx to %lx lacking\n", BasePriority
, Process
->Pcb
.BasePriority
);
1543 return STATUS_PRIVILEGE_NOT_HELD
;
1548 KeSetPriorityAndQuantumProcess(&Process
->Pcb
, BasePriority
, 0);
1550 /* Now set the memory priority */
1551 MmSetMemoryPriorityProcess(Process
, MemoryPriority
);
1552 Status
= STATUS_SUCCESS
;
1555 case ProcessRaisePriority
:
1557 /* Validate input length */
1558 if (ProcessInformationLength
!= sizeof(ULONG
))
1560 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1564 /* Enter SEH for direct buffer read */
1567 Boost
= *(PULONG
)ProcessInformation
;
1569 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1571 /* Get exception code */
1573 Status
= _SEH2_GetExceptionCode();
1578 /* Make sure the process isn't dying */
1579 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1582 KeEnterCriticalRegion();
1583 ExAcquirePushLockShared(&Process
->ProcessLock
);
1585 /* Loop the threads */
1586 for (Next
= Process
->ThreadListHead
.Flink
;
1587 Next
!= &Process
->ThreadListHead
;
1590 /* Call Ke for the thread */
1591 Thread
= CONTAINING_RECORD(Next
, ETHREAD
, ThreadListEntry
);
1592 KeBoostPriorityThread(&Thread
->Tcb
, Boost
);
1595 /* Release the lock and rundown */
1596 ExReleasePushLockShared(&Process
->ProcessLock
);
1597 KeLeaveCriticalRegion();
1598 ExReleaseRundownProtection(&Process
->RundownProtect
);
1600 /* Set success code */
1601 Status
= STATUS_SUCCESS
;
1605 /* Avoid race conditions */
1606 Status
= STATUS_PROCESS_IS_TERMINATING
;
1610 case ProcessBreakOnTermination
:
1612 /* Check buffer length */
1613 if (ProcessInformationLength
!= sizeof(ULONG
))
1615 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1619 /* Enter SEH for direct buffer read */
1622 Break
= *(PULONG
)ProcessInformation
;
1624 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1626 /* Get exception code */
1628 Status
= _SEH2_GetExceptionCode();
1633 /* Setting 'break on termination' requires the SeDebugPrivilege */
1634 if (!SeSinglePrivilegeCheck(SeDebugPrivilege
, PreviousMode
))
1636 /* We don't hold the privilege, bail out */
1637 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1641 /* Set or clear the flag */
1644 PspSetProcessFlag(Process
, PSF_BREAK_ON_TERMINATION_BIT
);
1648 PspClearProcessFlag(Process
, PSF_BREAK_ON_TERMINATION_BIT
);
1653 case ProcessAffinityMask
:
1655 /* Check buffer length */
1656 if (ProcessInformationLength
!= sizeof(KAFFINITY
))
1658 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1662 /* Enter SEH for direct buffer read */
1665 Affinity
= *(PKAFFINITY
)ProcessInformation
;
1667 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1669 /* Get exception code */
1671 Status
= _SEH2_GetExceptionCode();
1676 /* Make sure it's valid for the CPUs present */
1677 ValidAffinity
= Affinity
& KeActiveProcessors
;
1678 if (!Affinity
|| (ValidAffinity
!= Affinity
))
1680 Status
= STATUS_INVALID_PARAMETER
;
1684 /* Check if it's within job affinity limits */
1687 /* Not yet implemented */
1689 Status
= STATUS_NOT_IMPLEMENTED
;
1693 /* Make sure the process isn't dying */
1694 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1697 KeEnterCriticalRegion();
1698 ExAcquirePushLockShared(&Process
->ProcessLock
);
1700 /* Call Ke to do the work */
1701 KeSetAffinityProcess(&Process
->Pcb
, ValidAffinity
);
1703 /* Release the lock and rundown */
1704 ExReleasePushLockShared(&Process
->ProcessLock
);
1705 KeLeaveCriticalRegion();
1706 ExReleaseRundownProtection(&Process
->RundownProtect
);
1708 /* Set success code */
1709 Status
= STATUS_SUCCESS
;
1713 /* Avoid race conditions */
1714 Status
= STATUS_PROCESS_IS_TERMINATING
;
1718 /* Priority Boosting status */
1719 case ProcessPriorityBoost
:
1721 /* Validate input length */
1722 if (ProcessInformationLength
!= sizeof(ULONG
))
1724 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1728 /* Enter SEH for direct buffer read */
1731 DisableBoost
= *(PBOOLEAN
)ProcessInformation
;
1733 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1735 /* Get exception code */
1737 Status
= _SEH2_GetExceptionCode();
1742 /* Make sure the process isn't dying */
1743 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1746 KeEnterCriticalRegion();
1747 ExAcquirePushLockShared(&Process
->ProcessLock
);
1749 /* Call Ke to do the work */
1750 KeSetDisableBoostProcess(&Process
->Pcb
, DisableBoost
);
1752 /* Loop the threads too */
1753 for (Next
= Process
->ThreadListHead
.Flink
;
1754 Next
!= &Process
->ThreadListHead
;
1757 /* Call Ke for the thread */
1758 Thread
= CONTAINING_RECORD(Next
, ETHREAD
, ThreadListEntry
);
1759 KeSetDisableBoostThread(&Thread
->Tcb
, DisableBoost
);
1762 /* Release the lock and rundown */
1763 ExReleasePushLockShared(&Process
->ProcessLock
);
1764 KeLeaveCriticalRegion();
1765 ExReleaseRundownProtection(&Process
->RundownProtect
);
1767 /* Set success code */
1768 Status
= STATUS_SUCCESS
;
1772 /* Avoid race conditions */
1773 Status
= STATUS_PROCESS_IS_TERMINATING
;
1777 case ProcessDebugFlags
:
1779 /* Check buffer length */
1780 if (ProcessInformationLength
!= sizeof(ULONG
))
1782 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1786 /* Enter SEH for direct buffer read */
1789 DebugFlags
= *(PULONG
)ProcessInformation
;
1791 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1793 /* Get exception code */
1794 Status
= _SEH2_GetExceptionCode();
1800 if (DebugFlags
& ~1)
1802 Status
= STATUS_INVALID_PARAMETER
;
1808 PspClearProcessFlag(Process
, PSF_NO_DEBUG_INHERIT_BIT
);
1812 PspSetProcessFlag(Process
, PSF_NO_DEBUG_INHERIT_BIT
);
1817 Status
= STATUS_SUCCESS
;
1820 case ProcessEnableAlignmentFaultFixup
:
1822 /* Check buffer length */
1823 if (ProcessInformationLength
!= sizeof(ULONG
))
1825 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1829 /* Enter SEH for direct buffer read */
1832 EnableFixup
= *(PULONG
)ProcessInformation
;
1834 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1836 /* Get exception code */
1837 Status
= _SEH2_GetExceptionCode();
1845 Process
->DefaultHardErrorProcessing
|= SEM_NOALIGNMENTFAULTEXCEPT
;
1849 Process
->DefaultHardErrorProcessing
&= ~SEM_NOALIGNMENTFAULTEXCEPT
;
1852 /* Call Ke for the update */
1853 KeSetAutoAlignmentProcess(&Process
->Pcb
, FALSE
);
1854 Status
= STATUS_SUCCESS
;
1857 case ProcessUserModeIOPL
:
1859 /* Only TCB can do this */
1860 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
1862 /* We don't hold the privilege, bail out */
1863 DPRINT1("Need TCB to set IOPL\n");
1864 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1868 /* Only supported on x86 */
1872 Status
= STATUS_NOT_IMPLEMENTED
;
1877 case ProcessExecuteFlags
:
1879 /* Check buffer length */
1880 if (ProcessInformationLength
!= sizeof(ULONG
))
1882 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1886 if (ProcessHandle
!= NtCurrentProcess())
1888 Status
= STATUS_INVALID_PARAMETER
;
1892 /* Enter SEH for direct buffer read */
1895 NoExecute
= *(PULONG
)ProcessInformation
;
1897 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1899 /* Get exception code */
1900 Status
= _SEH2_GetExceptionCode();
1905 /* Call Mm for the update */
1906 Status
= MmSetExecuteOptions(NoExecute
);
1909 /* We currently don't implement any of these */
1910 case ProcessLdtInformation
:
1911 case ProcessLdtSize
:
1912 case ProcessIoPortHandlers
:
1913 DPRINT1("VDM/16-bit Request not implemented: %lx\n", ProcessInformationClass
);
1914 Status
= STATUS_NOT_IMPLEMENTED
;
1917 case ProcessQuotaLimits
:
1919 Status
= PspSetQuotaLimits(Process
,
1922 ProcessInformationLength
,
1926 case ProcessWorkingSetWatch
:
1927 DPRINT1("WS watch not implemented\n");
1928 Status
= STATUS_NOT_IMPLEMENTED
;
1931 case ProcessDeviceMap
:
1932 DPRINT1("Device map not implemented\n");
1933 Status
= STATUS_NOT_IMPLEMENTED
;
1936 case ProcessHandleTracing
:
1937 DPRINT1("Handle tracing not implemented\n");
1938 Status
= STATUS_NOT_IMPLEMENTED
;
1941 /* Anything else is invalid */
1943 DPRINT1("Invalid Server 2003 Info Class: %lx\n", ProcessInformationClass
);
1944 Status
= STATUS_INVALID_INFO_CLASS
;
1947 /* Dereference and return status */
1948 ObDereferenceObject(Process
);
1957 NtSetInformationThread(IN HANDLE ThreadHandle
,
1958 IN THREADINFOCLASS ThreadInformationClass
,
1959 IN PVOID ThreadInformation
,
1960 IN ULONG ThreadInformationLength
)
1964 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1966 HANDLE TokenHandle
= NULL
;
1967 KPRIORITY Priority
= 0;
1968 KAFFINITY Affinity
= 0, CombinedAffinity
;
1969 PVOID Address
= NULL
;
1971 ULONG_PTR DisableBoost
= 0;
1972 ULONG_PTR IdealProcessor
= 0;
1973 ULONG_PTR Break
= 0;
1975 ULONG_PTR TlsIndex
= 0;
1976 PVOID
*ExpansionSlots
;
1977 PETHREAD ProcThread
;
1980 /* Verify Information Class validity */
1982 Status
= DefaultSetInfoBufferCheck(ThreadInformationClass
,
1984 RTL_NUMBER_OF(PsThreadInfoClass
),
1986 ThreadInformationLength
,
1988 if (!NT_SUCCESS(Status
)) return Status
;
1991 /* Check what class this is */
1992 Access
= THREAD_SET_INFORMATION
;
1993 if (ThreadInformationClass
== ThreadImpersonationToken
)
1995 /* Setting the impersonation token needs a special mask */
1996 Access
= THREAD_SET_THREAD_TOKEN
;
1999 /* Reference the thread */
2000 Status
= ObReferenceObjectByHandle(ThreadHandle
,
2006 if (!NT_SUCCESS(Status
)) return Status
;
2008 /* Check what kind of information class this is */
2009 switch (ThreadInformationClass
)
2011 /* Thread priority */
2012 case ThreadPriority
:
2014 /* Check buffer length */
2015 if (ThreadInformationLength
!= sizeof(KPRIORITY
))
2017 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2021 /* Use SEH for capture */
2024 /* Get the priority */
2025 Priority
= *(PLONG
)ThreadInformation
;
2027 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2029 /* Get the exception code */
2030 Status
= _SEH2_GetExceptionCode();
2036 if ((Priority
> HIGH_PRIORITY
) ||
2037 (Priority
<= LOW_PRIORITY
))
2040 Status
= STATUS_INVALID_PARAMETER
;
2044 /* Set the priority */
2045 KeSetPriorityThread(&Thread
->Tcb
, Priority
);
2048 case ThreadBasePriority
:
2050 /* Check buffer length */
2051 if (ThreadInformationLength
!= sizeof(LONG
))
2053 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2057 /* Use SEH for capture */
2060 /* Get the priority */
2061 Priority
= *(PLONG
)ThreadInformation
;
2063 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2065 /* Get the exception code */
2066 Status
= _SEH2_GetExceptionCode();
2072 if ((Priority
> THREAD_BASE_PRIORITY_MAX
) ||
2073 (Priority
< THREAD_BASE_PRIORITY_MIN
))
2075 /* These ones are OK */
2076 if ((Priority
!= THREAD_BASE_PRIORITY_LOWRT
+ 1) &&
2077 (Priority
!= THREAD_BASE_PRIORITY_IDLE
- 1))
2079 /* Check if the process is real time */
2080 if (PsGetCurrentProcess()->PriorityClass
!=
2081 PROCESS_PRIORITY_CLASS_REALTIME
)
2083 /* It isn't, fail */
2084 Status
= STATUS_INVALID_PARAMETER
;
2090 /* Set the base priority */
2091 KeSetBasePriorityThread(&Thread
->Tcb
, Priority
);
2094 case ThreadAffinityMask
:
2096 /* Check buffer length */
2097 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
2099 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2103 /* Use SEH for capture */
2106 /* Get the priority */
2107 Affinity
= *(PULONG_PTR
)ThreadInformation
;
2109 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2111 /* Get the exception code */
2112 Status
= _SEH2_GetExceptionCode();
2121 Status
= STATUS_INVALID_PARAMETER
;
2125 /* Get the process */
2126 Process
= Thread
->ThreadsProcess
;
2128 /* Try to acquire rundown */
2129 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
2132 KeEnterCriticalRegion();
2133 ExAcquirePushLockShared(&Process
->ProcessLock
);
2136 CombinedAffinity
= Affinity
& Process
->Pcb
.Affinity
;
2137 if (CombinedAffinity
!= Affinity
)
2140 Status
= STATUS_INVALID_PARAMETER
;
2144 /* Set the affinity */
2145 KeSetAffinityThread(&Thread
->Tcb
, CombinedAffinity
);
2148 /* Release the lock and rundown */
2149 ExReleasePushLockShared(&Process
->ProcessLock
);
2150 KeLeaveCriticalRegion();
2151 ExReleaseRundownProtection(&Process
->RundownProtect
);
2156 Status
= STATUS_PROCESS_IS_TERMINATING
;
2162 case ThreadImpersonationToken
:
2164 /* Check buffer length */
2165 if (ThreadInformationLength
!= sizeof(HANDLE
))
2167 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2171 /* Use SEH for capture */
2174 /* Save the token handle */
2175 TokenHandle
= *(PHANDLE
)ThreadInformation
;
2177 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2179 /* Get the exception code */
2180 Status
= _SEH2_GetExceptionCode();
2185 /* Assign the actual token */
2186 Status
= PsAssignImpersonationToken(Thread
, TokenHandle
);
2189 case ThreadQuerySetWin32StartAddress
:
2191 /* Check buffer length */
2192 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
2194 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2198 /* Use SEH for capture */
2201 /* Get the priority */
2202 Address
= *(PVOID
*)ThreadInformation
;
2204 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2206 /* Get the exception code */
2207 Status
= _SEH2_GetExceptionCode();
2212 /* Set the address */
2213 Thread
->Win32StartAddress
= Address
;
2216 case ThreadIdealProcessor
:
2218 /* Check buffer length */
2219 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
2221 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2225 /* Use SEH for capture */
2228 /* Get the priority */
2229 IdealProcessor
= *(PULONG_PTR
)ThreadInformation
;
2231 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2233 /* Get the exception code */
2234 Status
= _SEH2_GetExceptionCode();
2240 if (IdealProcessor
> MAXIMUM_PROCESSORS
)
2243 Status
= STATUS_INVALID_PARAMETER
;
2248 Status
= KeSetIdealProcessorThread(&Thread
->Tcb
,
2249 (CCHAR
)IdealProcessor
);
2251 /* Get the TEB and protect the thread */
2252 Teb
= Thread
->Tcb
.Teb
;
2253 if ((Teb
) && (ExAcquireRundownProtection(&Thread
->RundownProtect
)))
2255 /* Save the ideal processor */
2256 Teb
->IdealProcessor
= Thread
->Tcb
.IdealProcessor
;
2258 /* Release rundown protection */
2259 ExReleaseRundownProtection(&Thread
->RundownProtect
);
2264 case ThreadPriorityBoost
:
2266 /* Check buffer length */
2267 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
2269 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2273 /* Use SEH for capture */
2276 /* Get the priority */
2277 DisableBoost
= *(PULONG_PTR
)ThreadInformation
;
2279 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2281 /* Get the exception code */
2282 Status
= _SEH2_GetExceptionCode();
2287 /* Call the kernel */
2288 KeSetDisableBoostThread(&Thread
->Tcb
, (BOOLEAN
)DisableBoost
);
2291 case ThreadZeroTlsCell
:
2293 /* Check buffer length */
2294 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
2296 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2300 /* Use SEH for capture */
2303 /* Get the priority */
2304 TlsIndex
= *(PULONG_PTR
)ThreadInformation
;
2306 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2308 /* Get the exception code */
2309 Status
= _SEH2_GetExceptionCode();
2314 /* This is only valid for the current thread */
2315 if (Thread
!= PsGetCurrentThread())
2318 Status
= STATUS_INVALID_PARAMETER
;
2322 /* Get the process */
2323 Process
= Thread
->ThreadsProcess
;
2325 /* Loop the threads */
2326 ProcThread
= PsGetNextProcessThread(Process
, NULL
);
2329 /* Acquire rundown */
2330 if (ExAcquireRundownProtection(&ProcThread
->RundownProtect
))
2333 Teb
= ProcThread
->Tcb
.Teb
;
2336 /* Check if we're in the expansion range */
2337 if (TlsIndex
> TLS_MINIMUM_AVAILABLE
- 1)
2339 if (TlsIndex
< (TLS_MINIMUM_AVAILABLE
+
2340 TLS_EXPANSION_SLOTS
) - 1)
2342 /* Check if we have expansion slots */
2343 ExpansionSlots
= Teb
->TlsExpansionSlots
;
2346 /* Clear the index */
2347 ExpansionSlots
[TlsIndex
- TLS_MINIMUM_AVAILABLE
] = 0;
2353 /* Clear the index */
2354 Teb
->TlsSlots
[TlsIndex
] = NULL
;
2358 /* Release rundown */
2359 ExReleaseRundownProtection(&ProcThread
->RundownProtect
);
2362 /* Go to the next thread */
2363 ProcThread
= PsGetNextProcessThread(Process
, ProcThread
);
2369 case ThreadBreakOnTermination
:
2371 /* Check buffer length */
2372 if (ThreadInformationLength
!= sizeof(ULONG
))
2374 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2378 /* Enter SEH for direct buffer read */
2381 Break
= *(PULONG
)ThreadInformation
;
2383 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2385 /* Get exception code */
2387 Status
= _SEH2_GetExceptionCode();
2392 /* Setting 'break on termination' requires the SeDebugPrivilege */
2393 if (!SeSinglePrivilegeCheck(SeDebugPrivilege
, PreviousMode
))
2395 /* We don't hold the privilege, bail out */
2396 Status
= STATUS_PRIVILEGE_NOT_HELD
;
2400 /* Set or clear the flag */
2403 PspSetCrossThreadFlag(Thread
, CT_BREAK_ON_TERMINATION_BIT
);
2407 PspClearCrossThreadFlag(Thread
, CT_BREAK_ON_TERMINATION_BIT
);
2412 /* We don't implement it yet */
2413 DPRINT1("Not implemented: %d\n", ThreadInformationClass
);
2414 Status
= STATUS_NOT_IMPLEMENTED
;
2417 /* Dereference and return status */
2418 ObDereferenceObject(Thread
);
2427 NtQueryInformationThread(IN HANDLE ThreadHandle
,
2428 IN THREADINFOCLASS ThreadInformationClass
,
2429 OUT PVOID ThreadInformation
,
2430 IN ULONG ThreadInformationLength
,
2431 OUT PULONG ReturnLength OPTIONAL
)
2434 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2438 PTHREAD_BASIC_INFORMATION ThreadBasicInfo
=
2439 (PTHREAD_BASIC_INFORMATION
)ThreadInformation
;
2440 PKERNEL_USER_TIMES ThreadTime
= (PKERNEL_USER_TIMES
)ThreadInformation
;
2442 ULONG ThreadTerminated
;
2445 /* Check if we were called from user mode */
2446 if (PreviousMode
!= KernelMode
)
2451 /* Probe the buffer */
2452 ProbeForWrite(ThreadInformation
,
2453 ThreadInformationLength
,
2456 /* Probe the return length if required */
2457 if (ReturnLength
) ProbeForWriteUlong(ReturnLength
);
2459 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2461 /* Return the exception code */
2462 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2467 /* Check what class this is */
2468 Access
= THREAD_QUERY_INFORMATION
;
2470 /* Reference the process */
2471 Status
= ObReferenceObjectByHandle(ThreadHandle
,
2477 if (!NT_SUCCESS(Status
)) return Status
;
2479 /* Check what kind of information class this is */
2480 switch (ThreadInformationClass
)
2482 /* Basic thread information */
2483 case ThreadBasicInformation
:
2485 /* Set return length */
2486 Length
= sizeof(THREAD_BASIC_INFORMATION
);
2488 if (ThreadInformationLength
!= Length
)
2490 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2493 /* Protect writes with SEH */
2496 /* Write all the information from the ETHREAD/KTHREAD */
2497 ThreadBasicInfo
->ExitStatus
= Thread
->ExitStatus
;
2498 ThreadBasicInfo
->TebBaseAddress
= (PVOID
)Thread
->Tcb
.Teb
;
2499 ThreadBasicInfo
->ClientId
= Thread
->Cid
;
2500 ThreadBasicInfo
->AffinityMask
= Thread
->Tcb
.Affinity
;
2501 ThreadBasicInfo
->Priority
= Thread
->Tcb
.Priority
;
2502 ThreadBasicInfo
->BasePriority
= KeQueryBasePriorityThread(&Thread
->Tcb
);
2504 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2506 /* Get exception code */
2507 Status
= _SEH2_GetExceptionCode();
2512 /* Thread time information */
2515 /* Set the return length */
2516 Length
= sizeof(KERNEL_USER_TIMES
);
2518 if (ThreadInformationLength
!= Length
)
2520 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2523 /* Protect writes with SEH */
2526 /* Copy time information from ETHREAD/KTHREAD */
2527 ThreadTime
->KernelTime
.QuadPart
= Thread
->Tcb
.KernelTime
* KeMaximumIncrement
;
2528 ThreadTime
->UserTime
.QuadPart
= Thread
->Tcb
.UserTime
* KeMaximumIncrement
;
2529 ThreadTime
->CreateTime
= Thread
->CreateTime
;
2531 /* Exit time is in a union and only valid on actual exit! */
2532 if (KeReadStateThread(&Thread
->Tcb
))
2534 ThreadTime
->ExitTime
= Thread
->ExitTime
;
2538 ThreadTime
->ExitTime
.QuadPart
= 0;
2541 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2543 /* Get exception code */
2544 Status
= _SEH2_GetExceptionCode();
2549 case ThreadQuerySetWin32StartAddress
:
2551 /* Set the return length*/
2552 Length
= sizeof(PVOID
);
2554 if (ThreadInformationLength
!= Length
)
2556 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2559 /* Protect write with SEH */
2562 /* Return the Win32 Start Address */
2563 *(PVOID
*)ThreadInformation
= Thread
->Win32StartAddress
;
2565 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2567 /* Get exception code */
2568 Status
= _SEH2_GetExceptionCode();
2573 case ThreadPerformanceCount
:
2575 /* Set the return length*/
2576 Length
= sizeof(LARGE_INTEGER
);
2578 if (ThreadInformationLength
!= Length
)
2580 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2583 /* Protect write with SEH */
2587 (*(PLARGE_INTEGER
)ThreadInformation
).QuadPart
= 0;
2589 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2591 /* Get exception code */
2592 Status
= _SEH2_GetExceptionCode();
2597 case ThreadAmILastThread
:
2599 /* Set the return length*/
2600 Length
= sizeof(ULONG
);
2602 if (ThreadInformationLength
!= Length
)
2604 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2607 /* Protect write with SEH */
2610 /* Return whether or not we are the last thread */
2611 *(PULONG
)ThreadInformation
= ((Thread
->ThreadsProcess
->
2612 ThreadListHead
.Flink
->Flink
==
2613 &Thread
->ThreadsProcess
->
2617 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2619 /* Get exception code */
2620 Status
= _SEH2_GetExceptionCode();
2625 case ThreadIsIoPending
:
2627 /* Set the return length*/
2628 Length
= sizeof(ULONG
);
2630 if (ThreadInformationLength
!= Length
)
2632 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2635 /* Raise the IRQL to protect the IRP list */
2636 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2638 /* Protect write with SEH */
2641 /* Check if the IRP list is empty or not */
2642 *(PULONG
)ThreadInformation
= !IsListEmpty(&Thread
->IrpList
);
2644 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2646 /* Get exception code */
2647 Status
= _SEH2_GetExceptionCode();
2651 /* Lower IRQL back */
2652 KeLowerIrql(OldIrql
);
2655 /* LDT and GDT information */
2656 case ThreadDescriptorTableEntry
:
2659 /* Call the worker routine */
2660 Status
= PspQueryDescriptorThread(Thread
,
2662 ThreadInformationLength
,
2665 /* Only implemented on x86 */
2666 Status
= STATUS_NOT_IMPLEMENTED
;
2670 case ThreadPriorityBoost
:
2672 /* Set the return length*/
2673 Length
= sizeof(ULONG
);
2675 if (ThreadInformationLength
!= Length
)
2677 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2683 *(PULONG
)ThreadInformation
= Thread
->Tcb
.DisableBoost
? 1 : 0;
2685 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2687 Status
= _SEH2_GetExceptionCode();
2692 case ThreadIsTerminated
:
2694 /* Set the return length*/
2695 Length
= sizeof(ThreadTerminated
);
2697 if (ThreadInformationLength
!= Length
)
2699 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2703 ThreadTerminated
= PsIsThreadTerminating(Thread
);
2707 *(PULONG
)ThreadInformation
= ThreadTerminated
? 1 : 0;
2709 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2711 Status
= _SEH2_GetExceptionCode();
2720 /* Not yet implemented */
2721 DPRINT1("Not implemented: %lx\n", ThreadInformationClass
);
2722 Status
= STATUS_NOT_IMPLEMENTED
;
2725 /* Protect write with SEH */
2728 /* Check if caller wanted return length */
2729 if (ReturnLength
) *ReturnLength
= Length
;
2731 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2733 /* Get exception code */
2734 Status
= _SEH2_GetExceptionCode();
2738 /* Dereference the thread, and return */
2739 ObDereferenceObject(Thread
);