2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ps/query.c
5 * PURPOSE: Process Manager: Thread/Process Query/Set Information
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 * Thomas Weidenmueller (w3seek@reactos.org)
11 /* INCLUDES ******************************************************************/
17 /* FIXME: From winbase.h... what to do? */
18 #define SEM_NOALIGNMENTFAULTEXCEPT 0x04
21 ULONG PspTraceLevel
= 0;
23 /* PRIVATE FUNCTIONS *********************************************************/
27 PsReferenceProcessFilePointer(IN PEPROCESS Process
,
28 OUT PFILE_OBJECT
*FileObject
)
33 /* Lock the process */
34 ExAcquireRundownProtection(&Process
->RundownProtect
);
37 Section
= Process
->SectionObject
;
40 /* Get the file object and reference it */
41 *FileObject
= MmGetFileObjectForSection((PVOID
)Section
);
42 ObReferenceObject(*FileObject
);
45 /* Release the protection */
46 ExReleaseRundownProtection(&Process
->RundownProtect
);
49 return Section
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
;
52 /* PUBLIC FUNCTIONS **********************************************************/
59 NtQueryInformationProcess(IN HANDLE ProcessHandle
,
60 IN PROCESSINFOCLASS ProcessInformationClass
,
61 OUT PVOID ProcessInformation
,
62 IN ULONG ProcessInformationLength
,
63 OUT PULONG ReturnLength OPTIONAL
)
66 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
70 PPROCESS_BASIC_INFORMATION ProcessBasicInfo
=
71 (PPROCESS_BASIC_INFORMATION
)ProcessInformation
;
72 PKERNEL_USER_TIMES ProcessTime
= (PKERNEL_USER_TIMES
)ProcessInformation
;
73 PPROCESS_PRIORITY_CLASS PsPriorityClass
= (PPROCESS_PRIORITY_CLASS
)ProcessInformation
;
75 PPROCESS_SESSION_INFORMATION SessionInfo
=
76 (PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
77 PVM_COUNTERS VmCounters
= (PVM_COUNTERS
)ProcessInformation
;
78 PIO_COUNTERS IoCounters
= (PIO_COUNTERS
)ProcessInformation
;
79 PQUOTA_LIMITS QuotaLimits
= (PQUOTA_LIMITS
)ProcessInformation
;
80 PROCESS_DEVICEMAP_INFORMATION DeviceMap
;
81 PUNICODE_STRING ImageName
;
82 ULONG Cookie
, ExecuteOptions
= 0;
86 /* Check for user-mode caller */
87 if (PreviousMode
!= KernelMode
)
89 /* Prepare to probe parameters */
92 /* Probe the buffer */
93 ProbeForWrite(ProcessInformation
,
94 ProcessInformationLength
,
97 /* Probe the return length if required */
98 if (ReturnLength
) ProbeForWriteUlong(ReturnLength
);
100 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
102 /* Return the exception code */
103 _SEH2_YIELD(return _SEH2_GetExceptionCode());
108 if (((ProcessInformationClass
== ProcessCookie
) ||
109 (ProcessInformationClass
== ProcessImageInformation
)) &&
110 (ProcessHandle
!= NtCurrentProcess()))
113 * Retreiving the process cookie is only allowed for the calling process
114 * itself! XP only allowes NtCurrentProcess() as process handles even if
115 * a real handle actually represents the current process.
117 return STATUS_INVALID_PARAMETER
;
120 /* Check the information class */
121 switch (ProcessInformationClass
)
123 /* Basic process information */
124 case ProcessBasicInformation
:
126 /* Set return length */
127 Length
= sizeof(PROCESS_BASIC_INFORMATION
);
129 if (ProcessInformationLength
!= Length
)
131 Status
= STATUS_INFO_LENGTH_MISMATCH
;
135 /* Reference the process */
136 Status
= ObReferenceObjectByHandle(ProcessHandle
,
137 PROCESS_QUERY_INFORMATION
,
142 if (!NT_SUCCESS(Status
)) break;
144 /* Protect writes with SEH */
147 /* Write all the information from the EPROCESS/KPROCESS */
148 ProcessBasicInfo
->ExitStatus
= Process
->ExitStatus
;
149 ProcessBasicInfo
->PebBaseAddress
= Process
->Peb
;
150 ProcessBasicInfo
->AffinityMask
= Process
->Pcb
.Affinity
;
151 ProcessBasicInfo
->UniqueProcessId
= (ULONG_PTR
)Process
->
153 ProcessBasicInfo
->InheritedFromUniqueProcessId
=
154 (ULONG
)Process
->InheritedFromUniqueProcessId
;
155 ProcessBasicInfo
->BasePriority
= Process
->Pcb
.BasePriority
;
158 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
160 /* Get exception code */
161 Status
= _SEH2_GetExceptionCode();
165 /* Dereference the process */
166 ObDereferenceObject(Process
);
169 /* Process quota limits */
170 case ProcessQuotaLimits
:
172 Length
= sizeof(QUOTA_LIMITS
);
173 if (ProcessInformationLength
!= Length
)
175 Status
= STATUS_INFO_LENGTH_MISMATCH
;
179 /* Reference the process */
180 Status
= ObReferenceObjectByHandle(ProcessHandle
,
181 PROCESS_QUERY_INFORMATION
,
186 if (!NT_SUCCESS(Status
)) break;
188 /* Indicate success */
189 Status
= STATUS_SUCCESS
;
193 /* Set max/min working set sizes */
194 QuotaLimits
->MaximumWorkingSetSize
=
195 Process
->Vm
.MaximumWorkingSetSize
<< PAGE_SHIFT
;
196 QuotaLimits
->MinimumWorkingSetSize
=
197 Process
->Vm
.MinimumWorkingSetSize
<< PAGE_SHIFT
;
199 /* Set default time limits */
200 QuotaLimits
->TimeLimit
.LowPart
= MAXULONG
;
201 QuotaLimits
->TimeLimit
.HighPart
= MAXULONG
;
203 /* Is quota block a default one? */
204 if (Process
->QuotaBlock
== &PspDefaultQuotaBlock
)
206 /* Set default pools and pagefile limits */
207 QuotaLimits
->PagedPoolLimit
= (SIZE_T
)-1;
208 QuotaLimits
->NonPagedPoolLimit
= (SIZE_T
)-1;
209 QuotaLimits
->PagefileLimit
= (SIZE_T
)-1;
213 /* Get limits from non-default quota block */
214 QuotaLimits
->PagedPoolLimit
=
215 Process
->QuotaBlock
->QuotaEntry
[PagedPool
].Limit
;
216 QuotaLimits
->NonPagedPoolLimit
=
217 Process
->QuotaBlock
->QuotaEntry
[NonPagedPool
].Limit
;
218 QuotaLimits
->PagefileLimit
=
219 Process
->QuotaBlock
->QuotaEntry
[2].Limit
;
222 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
224 /* Get exception code */
225 Status
= _SEH2_GetExceptionCode();
229 /* Dereference the process */
230 ObDereferenceObject(Process
);
233 case ProcessIoCounters
:
235 Length
= sizeof(IO_COUNTERS
);
236 if (ProcessInformationLength
!= Length
)
238 Status
= STATUS_INFO_LENGTH_MISMATCH
;
242 /* Reference the process */
243 Status
= ObReferenceObjectByHandle(ProcessHandle
,
244 PROCESS_QUERY_INFORMATION
,
249 if (!NT_SUCCESS(Status
)) break;
253 /* FIXME: Call KeQueryValuesProcess */
254 IoCounters
->ReadOperationCount
= Process
->ReadOperationCount
.QuadPart
;
255 IoCounters
->ReadTransferCount
= Process
->ReadTransferCount
.QuadPart
;
256 IoCounters
->WriteOperationCount
= Process
->WriteOperationCount
.QuadPart
;
257 IoCounters
->WriteTransferCount
= Process
->WriteTransferCount
.QuadPart
;
258 IoCounters
->OtherOperationCount
= Process
->OtherOperationCount
.QuadPart
;
259 IoCounters
->OtherTransferCount
= Process
->OtherTransferCount
.QuadPart
;
261 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
263 /* Ignore exception */
267 /* Set status to success in any case */
268 Status
= STATUS_SUCCESS
;
270 /* Dereference the process */
271 ObDereferenceObject(Process
);
277 /* Set the return length */
278 Length
= sizeof(KERNEL_USER_TIMES
);
280 if (ProcessInformationLength
!= Length
)
282 Status
= STATUS_INFO_LENGTH_MISMATCH
;
286 /* Reference the process */
287 Status
= ObReferenceObjectByHandle(ProcessHandle
,
288 PROCESS_QUERY_INFORMATION
,
293 if (!NT_SUCCESS(Status
)) break;
295 /* Protect writes with SEH */
298 /* Copy time information from EPROCESS/KPROCESS */
299 /* FIXME: Call KeQueryRuntimeProcess */
300 ProcessTime
->CreateTime
= Process
->CreateTime
;
301 ProcessTime
->UserTime
.QuadPart
= Process
->Pcb
.UserTime
*
303 ProcessTime
->KernelTime
.QuadPart
= Process
->Pcb
.KernelTime
*
305 ProcessTime
->ExitTime
= Process
->ExitTime
;
307 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
309 /* Get exception code */
310 Status
= _SEH2_GetExceptionCode();
314 /* Dereference the process */
315 ObDereferenceObject(Process
);
318 /* Process Debug Port */
319 case ProcessDebugPort
:
321 /* Set return length */
322 Length
= sizeof(HANDLE
);
324 if (ProcessInformationLength
!= Length
)
326 Status
= STATUS_INFO_LENGTH_MISMATCH
;
330 /* Reference the process */
331 Status
= ObReferenceObjectByHandle(ProcessHandle
,
332 PROCESS_QUERY_INFORMATION
,
337 if (!NT_SUCCESS(Status
)) break;
339 /* Protect write with SEH */
342 /* Return whether or not we have a debug port */
343 *(PHANDLE
)ProcessInformation
= (Process
->DebugPort
?
346 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
348 /* Get exception code */
349 Status
= _SEH2_GetExceptionCode();
353 /* Dereference the process */
354 ObDereferenceObject(Process
);
357 case ProcessHandleCount
:
359 /* Set the return length*/
360 Length
= sizeof(ULONG
);
362 if (ProcessInformationLength
!= Length
)
364 Status
= STATUS_INFO_LENGTH_MISMATCH
;
368 /* Reference the process */
369 Status
= ObReferenceObjectByHandle(ProcessHandle
,
370 PROCESS_QUERY_INFORMATION
,
375 if (!NT_SUCCESS(Status
)) break;
377 /* Count the number of handles this process has */
378 HandleCount
= ObGetProcessHandleCount(Process
);
380 /* Protect write in SEH */
383 /* Return the count of handles */
384 *(PULONG
)ProcessInformation
= HandleCount
;
386 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
388 /* Get the exception code */
389 Status
= _SEH2_GetExceptionCode();
393 /* Dereference the process */
394 ObDereferenceObject(Process
);
397 /* Session ID for the process */
398 case ProcessSessionInformation
:
400 /* Set the return length*/
401 Length
= sizeof(PROCESS_SESSION_INFORMATION
);
403 if (ProcessInformationLength
!= Length
)
405 Status
= STATUS_INFO_LENGTH_MISMATCH
;
409 /* Reference the process */
410 Status
= ObReferenceObjectByHandle(ProcessHandle
,
411 PROCESS_QUERY_INFORMATION
,
416 if (!NT_SUCCESS(Status
)) break;
418 /* Enter SEH for write safety */
421 /* Write back the Session ID */
422 SessionInfo
->SessionId
= PsGetProcessSessionId(Process
);
424 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
426 /* Get the exception code */
427 Status
= _SEH2_GetExceptionCode();
431 /* Dereference the process */
432 ObDereferenceObject(Process
);
435 /* Virtual Memory Statistics */
436 case ProcessVmCounters
:
438 /* Validate the input length */
439 if ((ProcessInformationLength
!= sizeof(VM_COUNTERS
)) &&
440 (ProcessInformationLength
!= sizeof(VM_COUNTERS_EX
)))
442 Status
= STATUS_INFO_LENGTH_MISMATCH
;
446 /* Reference the process */
447 Status
= ObReferenceObjectByHandle(ProcessHandle
,
448 PROCESS_QUERY_INFORMATION
,
453 if (!NT_SUCCESS(Status
)) break;
455 /* Enter SEH for write safety */
458 /* Return data from EPROCESS */
459 VmCounters
->PeakVirtualSize
= Process
->PeakVirtualSize
;
460 VmCounters
->VirtualSize
= Process
->VirtualSize
;
461 VmCounters
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
462 VmCounters
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
463 VmCounters
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
464 VmCounters
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeak
[0];
465 VmCounters
->QuotaPagedPoolUsage
= Process
->QuotaUsage
[0];
466 VmCounters
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeak
[1];
467 VmCounters
->QuotaNonPagedPoolUsage
= Process
->QuotaUsage
[1];
468 VmCounters
->PagefileUsage
= Process
->QuotaUsage
[2] << PAGE_SHIFT
;
469 VmCounters
->PeakPagefileUsage
= Process
->QuotaPeak
[2] << PAGE_SHIFT
;
470 //VmCounters->PrivateUsage = Process->CommitCharge << PAGE_SHIFT;
473 /* Set the return length */
474 Length
= ProcessInformationLength
;
476 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
478 /* Get the exception code */
479 Status
= _SEH2_GetExceptionCode();
483 /* Dereference the process */
484 ObDereferenceObject(Process
);
487 /* Hard Error Processing Mode */
488 case ProcessDefaultHardErrorMode
:
490 /* Set the return length*/
491 Length
= sizeof(ULONG
);
493 if (ProcessInformationLength
!= Length
)
495 Status
= STATUS_INFO_LENGTH_MISMATCH
;
499 /* Reference the process */
500 Status
= ObReferenceObjectByHandle(ProcessHandle
,
501 PROCESS_QUERY_INFORMATION
,
506 if (!NT_SUCCESS(Status
)) break;
508 /* Enter SEH for writing back data */
511 /* Write the current processing mode */
512 *(PULONG
)ProcessInformation
= Process
->
513 DefaultHardErrorProcessing
;
515 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
517 /* Get the exception code */
518 Status
= _SEH2_GetExceptionCode();
522 /* Dereference the process */
523 ObDereferenceObject(Process
);
526 /* Priority Boosting status */
527 case ProcessPriorityBoost
:
529 /* Set the return length */
530 Length
= sizeof(ULONG
);
532 if (ProcessInformationLength
!= Length
)
534 Status
= STATUS_INFO_LENGTH_MISMATCH
;
538 /* Reference the process */
539 Status
= ObReferenceObjectByHandle(ProcessHandle
,
540 PROCESS_QUERY_INFORMATION
,
545 if (!NT_SUCCESS(Status
)) break;
547 /* Enter SEH for writing back data */
550 /* Return boost status */
551 *(PULONG
)ProcessInformation
= Process
->Pcb
.DisableBoost
?
554 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
556 /* Get the exception code */
557 Status
= _SEH2_GetExceptionCode();
561 /* Dereference the process */
562 ObDereferenceObject(Process
);
566 case ProcessDeviceMap
:
568 /* Set the return length */
569 Length
= sizeof(PROCESS_DEVICEMAP_INFORMATION
);
571 if (ProcessInformationLength
!= Length
)
573 if (ProcessInformationLength
== sizeof(PROCESS_DEVICEMAP_INFORMATION_EX
))
575 DPRINT1("PROCESS_DEVICEMAP_INFORMATION_EX not supported!\n");
576 Status
= STATUS_NOT_IMPLEMENTED
;
580 Status
= STATUS_INFO_LENGTH_MISMATCH
;
585 /* Reference the process */
586 Status
= ObReferenceObjectByHandle(ProcessHandle
,
587 PROCESS_QUERY_INFORMATION
,
592 if (!NT_SUCCESS(Status
)) break;
594 /* Query the device map information */
595 ObQueryDeviceMapInformation(Process
, &DeviceMap
);
597 /* Enter SEH for writing back data */
600 *(PPROCESS_DEVICEMAP_INFORMATION
)ProcessInformation
= DeviceMap
;
602 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
604 /* Get the exception code */
605 Status
= _SEH2_GetExceptionCode();
609 /* Dereference the process */
610 ObDereferenceObject(Process
);
614 case ProcessPriorityClass
:
616 /* Set the return length*/
617 Length
= sizeof(PROCESS_PRIORITY_CLASS
);
619 if (ProcessInformationLength
!= Length
)
621 Status
= STATUS_INFO_LENGTH_MISMATCH
;
625 /* Reference the process */
626 Status
= ObReferenceObjectByHandle(ProcessHandle
,
627 PROCESS_QUERY_INFORMATION
,
632 if (!NT_SUCCESS(Status
)) break;
634 /* Enter SEH for writing back data */
637 /* Return current priority class */
638 PsPriorityClass
->PriorityClass
= Process
->PriorityClass
;
639 PsPriorityClass
->Foreground
= FALSE
;
641 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
643 /* Get the exception code */
644 Status
= _SEH2_GetExceptionCode();
648 /* Dereference the process */
649 ObDereferenceObject(Process
);
652 case ProcessImageFileName
:
654 /* Reference the process */
655 Status
= ObReferenceObjectByHandle(ProcessHandle
,
656 PROCESS_QUERY_INFORMATION
,
661 if (!NT_SUCCESS(Status
)) break;
663 /* Get the image path */
664 Status
= SeLocateProcessImageName(Process
, &ImageName
);
665 if (NT_SUCCESS(Status
))
667 /* Set return length */
668 Length
= ImageName
->MaximumLength
+
669 sizeof(OBJECT_NAME_INFORMATION
);
671 /* Make sure it's large enough */
672 if (Length
<= ProcessInformationLength
)
674 /* Enter SEH to protect write */
678 RtlCopyMemory(ProcessInformation
,
683 ((PUNICODE_STRING
)ProcessInformation
)->Buffer
=
684 (PWSTR
)((PUNICODE_STRING
)ProcessInformation
+ 1);
686 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
688 /* Get the exception code */
689 Status
= _SEH2_GetExceptionCode();
695 /* Buffer too small */
696 Status
= STATUS_INFO_LENGTH_MISMATCH
;
699 /* Free the image path */
700 ExFreePoolWithTag(ImageName
, TAG_SEPA
);
702 /* Dereference the process */
703 ObDereferenceObject(Process
);
706 case ProcessDebugFlags
:
708 /* Set the return length*/
709 Length
= sizeof(ULONG
);
710 if (ProcessInformationLength
!= Length
)
712 Status
= STATUS_INFO_LENGTH_MISMATCH
;
716 /* Reference the process */
717 Status
= ObReferenceObjectByHandle(ProcessHandle
,
718 PROCESS_QUERY_INFORMATION
,
723 if (!NT_SUCCESS(Status
)) break;
725 /* Enter SEH for writing back data */
728 /* Return the debug flag state */
729 *(PULONG
)ProcessInformation
= Process
->NoDebugInherit
? 0 : 1;
731 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
733 /* Get the exception code */
734 Status
= _SEH2_GetExceptionCode();
738 /* Dereference the process */
739 ObDereferenceObject(Process
);
742 case ProcessBreakOnTermination
:
744 /* Set the return length*/
745 Length
= sizeof(ULONG
);
746 if (ProcessInformationLength
!= Length
)
748 Status
= STATUS_INFO_LENGTH_MISMATCH
;
752 /* Reference the process */
753 Status
= ObReferenceObjectByHandle(ProcessHandle
,
754 PROCESS_QUERY_INFORMATION
,
759 if (!NT_SUCCESS(Status
)) break;
761 /* Enter SEH for writing back data */
764 /* Return the BreakOnTermination state */
765 *(PULONG
)ProcessInformation
= Process
->BreakOnTermination
;
767 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
769 /* Get the exception code */
770 Status
= _SEH2_GetExceptionCode();
774 /* Dereference the process */
775 ObDereferenceObject(Process
);
778 /* Per-process security cookie */
781 /* Get the current process and cookie */
782 Process
= PsGetCurrentProcess();
783 Cookie
= Process
->Cookie
;
786 LARGE_INTEGER SystemTime
;
790 /* Generate a new cookie */
791 KeQuerySystemTime(&SystemTime
);
792 Prcb
= KeGetCurrentPrcb();
793 NewCookie
= Prcb
->KeSystemCalls
^ Prcb
->InterruptTime
^
794 SystemTime
.u
.LowPart
^ SystemTime
.u
.HighPart
;
796 /* Set the new cookie or return the current one */
797 Cookie
= InterlockedCompareExchange((LONG
*)&Process
->Cookie
,
800 if (!Cookie
) Cookie
= NewCookie
;
802 /* Set return length */
803 Length
= sizeof(ULONG
);
806 /* Indicate success */
807 Status
= STATUS_SUCCESS
;
809 /* Enter SEH to protect write */
812 /* Write back the cookie */
813 *(PULONG
)ProcessInformation
= Cookie
;
815 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
817 /* Get the exception code */
818 Status
= _SEH2_GetExceptionCode();
823 case ProcessImageInformation
:
825 /* Set the length required and validate it */
826 Length
= sizeof(SECTION_IMAGE_INFORMATION
);
827 if (ProcessInformationLength
!= Length
)
830 Status
= STATUS_INFO_LENGTH_MISMATCH
;
834 /* Enter SEH to protect write */
837 MmGetImageInformation((PSECTION_IMAGE_INFORMATION
)ProcessInformation
);
839 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
841 /* Get the exception code */
842 Status
= _SEH2_GetExceptionCode();
846 /* Indicate success */
847 Status
= STATUS_SUCCESS
;
850 case ProcessDebugObjectHandle
:
852 /* Set the return length */
853 Length
= sizeof(HANDLE
);
854 if (ProcessInformationLength
!= Length
)
856 Status
= STATUS_INFO_LENGTH_MISMATCH
;
860 /* Reference the process */
861 Status
= ObReferenceObjectByHandle(ProcessHandle
,
862 PROCESS_QUERY_INFORMATION
,
867 if (!NT_SUCCESS(Status
)) break;
869 /* Get the debug port */
870 Status
= DbgkOpenProcessDebugPort(Process
, PreviousMode
, &DebugPort
);
872 /* Let go of the process */
873 ObDereferenceObject(Process
);
875 /* Protect write in SEH */
878 /* Return debug port's handle */
879 *(PHANDLE
)ProcessInformation
= DebugPort
;
881 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
883 /* Get the exception code */
884 Status
= _SEH2_GetExceptionCode();
889 case ProcessHandleTracing
:
890 DPRINT1("Handle tracing Not implemented: %lx\n", ProcessInformationClass
);
891 Status
= STATUS_NOT_IMPLEMENTED
;
894 case ProcessLUIDDeviceMapsEnabled
:
896 /* Set the return length */
897 Length
= sizeof(ULONG
);
898 if (ProcessInformationLength
!= Length
)
900 Status
= STATUS_INFO_LENGTH_MISMATCH
;
904 /* Indicate success */
905 Status
= STATUS_SUCCESS
;
907 /* Protect write in SEH */
910 /* Return FALSE -- we don't support this */
911 *(PULONG
)ProcessInformation
= FALSE
;
913 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
915 /* Get the exception code */
916 Status
= _SEH2_GetExceptionCode();
921 case ProcessWx86Information
:
923 /* Set the return length */
924 Length
= sizeof(ULONG
);
925 if (ProcessInformationLength
!= Length
)
927 Status
= STATUS_INFO_LENGTH_MISMATCH
;
931 /* Reference the process */
932 Status
= ObReferenceObjectByHandle(ProcessHandle
,
933 PROCESS_QUERY_INFORMATION
,
938 if (!NT_SUCCESS(Status
)) break;
940 /* Protect write in SEH */
943 /* Return if the flag is set */
944 *(PULONG
)ProcessInformation
= (ULONG
)Process
->VdmAllowed
;
946 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
948 /* Get the exception code */
949 Status
= _SEH2_GetExceptionCode();
953 /* Dereference the process */
954 ObDereferenceObject(Process
);
957 case ProcessWow64Information
:
959 /* Set return length */
960 Length
= sizeof(ULONG_PTR
);
961 if (ProcessInformationLength
!= Length
)
963 Status
= STATUS_INFO_LENGTH_MISMATCH
;
967 /* Reference the process */
968 Status
= ObReferenceObjectByHandle(ProcessHandle
,
969 PROCESS_QUERY_INFORMATION
,
974 if (!NT_SUCCESS(Status
)) break;
976 /* Make sure the process isn't dying */
977 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
979 /* Get the WOW64 process structure */
981 Wow64
= (ULONG_PTR
)Process
->Wow64Process
;
985 /* Release the lock */
986 ExReleaseRundownProtection(&Process
->RundownProtect
);
989 /* Protect write with SEH */
992 /* Return whether or not we have a debug port */
993 *(PULONG_PTR
)ProcessInformation
= Wow64
;
995 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
997 /* Get exception code */
998 Status
= _SEH2_GetExceptionCode();
1002 /* Dereference the process */
1003 ObDereferenceObject(Process
);
1006 case ProcessExecuteFlags
:
1008 /* Set return length */
1009 Length
= sizeof(ULONG
);
1010 if (ProcessInformationLength
!= Length
)
1012 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1016 if (ProcessHandle
!= NtCurrentProcess())
1018 return STATUS_INVALID_PARAMETER
;
1021 /* Get the options */
1022 Status
= MmGetExecuteOptions(&ExecuteOptions
);
1023 if (NT_SUCCESS(Status
))
1025 /* Protect write with SEH */
1029 *(PULONG
)ProcessInformation
= ExecuteOptions
;
1031 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1033 /* Get exception code */
1034 Status
= _SEH2_GetExceptionCode();
1040 case ProcessLdtInformation
:
1041 DPRINT1("VDM/16-bit not implemented: %lx\n", ProcessInformationClass
);
1042 Status
= STATUS_NOT_IMPLEMENTED
;
1045 case ProcessWorkingSetWatch
:
1046 DPRINT1("WS Watch Not implemented: %lx\n", ProcessInformationClass
);
1047 Status
= STATUS_NOT_IMPLEMENTED
;
1050 case ProcessPooledUsageAndLimits
:
1051 DPRINT1("Pool limits Not implemented: %lx\n", ProcessInformationClass
);
1052 Status
= STATUS_NOT_IMPLEMENTED
;
1055 /* Not supported by Server 2003 */
1057 DPRINT1("Unsupported info class: %lx\n", ProcessInformationClass
);
1058 Status
= STATUS_INVALID_INFO_CLASS
;
1061 /* Protect write with SEH */
1064 /* Check if caller wanted return length */
1065 if ((ReturnLength
) && (Length
)) *ReturnLength
= Length
;
1067 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1069 /* Get exception code */
1070 Status
= _SEH2_GetExceptionCode();
1082 NtSetInformationProcess(IN HANDLE ProcessHandle
,
1083 IN PROCESSINFOCLASS ProcessInformationClass
,
1084 IN PVOID ProcessInformation
,
1085 IN ULONG ProcessInformationLength
)
1088 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1091 HANDLE PortHandle
= NULL
;
1092 HANDLE TokenHandle
= NULL
;
1093 PROCESS_SESSION_INFORMATION SessionInfo
= {0};
1094 PROCESS_PRIORITY_CLASS PriorityClass
= {0};
1095 PROCESS_FOREGROUND_BACKGROUND Foreground
= {0};
1096 PVOID ExceptionPort
;
1098 KAFFINITY ValidAffinity
, Affinity
= 0;
1099 KPRIORITY BasePriority
= 0;
1100 UCHAR MemoryPriority
= 0;
1101 BOOLEAN DisableBoost
= 0;
1102 ULONG DefaultHardErrorMode
= 0;
1103 ULONG DebugFlags
= 0, EnableFixup
= 0, Boost
= 0;
1104 ULONG NoExecute
= 0, VdmPower
= 0;
1105 BOOLEAN HasPrivilege
;
1110 /* Verify Information Class validity */
1112 Status
= DefaultSetInfoBufferCheck(ProcessInformationClass
,
1114 RTL_NUMBER_OF(PsProcessInfoClass
),
1116 ProcessInformationLength
,
1118 if (!NT_SUCCESS(Status
)) return Status
;
1121 /* Check what class this is */
1122 Access
= PROCESS_SET_INFORMATION
;
1123 if (ProcessInformationClass
== ProcessSessionInformation
)
1125 /* Setting the Session ID needs a special mask */
1126 Access
|= PROCESS_SET_SESSIONID
;
1128 else if (ProcessInformationClass
== ProcessExceptionPort
)
1130 /* Setting the exception port needs a special mask */
1131 Access
|= PROCESS_SUSPEND_RESUME
;
1134 /* Reference the process */
1135 Status
= ObReferenceObjectByHandle(ProcessHandle
,
1141 if (!NT_SUCCESS(Status
)) return Status
;
1143 /* Check what kind of information class this is */
1144 switch (ProcessInformationClass
)
1146 case ProcessWx86Information
:
1148 /* Check buffer length */
1149 if (ProcessInformationLength
!= sizeof(HANDLE
))
1151 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1155 /* Use SEH for capture */
1158 /* Capture the boolean */
1159 VdmPower
= *(PULONG
)ProcessInformation
;
1161 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1163 /* Get the exception code */
1164 Status
= _SEH2_GetExceptionCode();
1169 /* Getting VDM powers requires the SeTcbPrivilege */
1170 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
1172 /* We don't hold the privilege, bail out */
1173 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1174 DPRINT1("Need TCB privilege\n");
1178 /* Set or clear the flag */
1181 PspSetProcessFlag(Process
, PSF_VDM_ALLOWED_BIT
);
1185 PspClearProcessFlag(Process
, PSF_VDM_ALLOWED_BIT
);
1189 /* Error/Exception Port */
1190 case ProcessExceptionPort
:
1192 /* Check buffer length */
1193 if (ProcessInformationLength
!= sizeof(HANDLE
))
1195 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1199 /* Use SEH for capture */
1202 /* Capture the handle */
1203 PortHandle
= *(PHANDLE
)ProcessInformation
;
1205 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1207 /* Get the exception code */
1208 Status
= _SEH2_GetExceptionCode();
1213 /* Setting the error port requires the SeTcbPrivilege */
1214 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
1216 /* We don't hold the privilege, bail out */
1217 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1221 /* Get the LPC Port */
1222 Status
= ObReferenceObjectByHandle(PortHandle
,
1226 (PVOID
)&ExceptionPort
,
1228 if (!NT_SUCCESS(Status
)) break;
1230 /* Change the pointer */
1231 if (InterlockedCompareExchangePointer(&Process
->ExceptionPort
,
1235 /* We already had one, fail */
1236 ObDereferenceObject(ExceptionPort
);
1237 Status
= STATUS_PORT_ALREADY_SET
;
1241 /* Security Token */
1242 case ProcessAccessToken
:
1244 /* Check buffer length */
1245 if (ProcessInformationLength
!= sizeof(PROCESS_ACCESS_TOKEN
))
1247 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1251 /* Use SEH for capture */
1254 /* Save the token handle */
1255 TokenHandle
= ((PPROCESS_ACCESS_TOKEN
)ProcessInformation
)->
1258 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1260 /* Get the exception code */
1261 Status
= _SEH2_GetExceptionCode();
1266 /* Assign the actual token */
1267 Status
= PspSetPrimaryToken(Process
, TokenHandle
, NULL
);
1270 /* Hard error processing */
1271 case ProcessDefaultHardErrorMode
:
1273 /* Check buffer length */
1274 if (ProcessInformationLength
!= sizeof(ULONG
))
1276 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1280 /* Enter SEH for direct buffer read */
1283 DefaultHardErrorMode
= *(PULONG
)ProcessInformation
;
1285 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1287 /* Get exception code */
1288 Status
= _SEH2_GetExceptionCode();
1294 Process
->DefaultHardErrorProcessing
= DefaultHardErrorMode
;
1296 /* Call Ke for the update */
1297 if (DefaultHardErrorMode
& SEM_NOALIGNMENTFAULTEXCEPT
)
1299 KeSetAutoAlignmentProcess(&Process
->Pcb
, TRUE
);
1303 KeSetAutoAlignmentProcess(&Process
->Pcb
, FALSE
);
1305 Status
= STATUS_SUCCESS
;
1309 case ProcessSessionInformation
:
1311 /* Check buffer length */
1312 if (ProcessInformationLength
!= sizeof(PROCESS_SESSION_INFORMATION
))
1314 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1318 /* Enter SEH for capture */
1321 /* Capture the caller's buffer */
1322 SessionInfo
= *(PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
1324 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1326 /* Get the exception code */
1327 Status
= _SEH2_GetExceptionCode();
1332 /* Setting the session id requires the SeTcbPrivilege */
1333 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
1335 /* We don't hold the privilege, bail out */
1336 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1340 #if 0 // OLD AND DEPRECATED CODE!!!!
1342 /* FIXME - update the session id for the process token */
1343 //Status = PsLockProcess(Process, FALSE);
1344 if (!NT_SUCCESS(Status
)) break;
1346 /* Write the session ID in the EPROCESS */
1347 Process
->Session
= UlongToPtr(SessionInfo
.SessionId
); // HACK!!!
1349 /* Check if the process also has a PEB */
1353 * Attach to the process to make sure we're in the right
1354 * context to access the PEB structure
1356 KeAttachProcess(&Process
->Pcb
);
1358 /* Enter SEH for write to user-mode PEB */
1361 /* Write the session ID */
1362 Process
->Peb
->SessionId
= SessionInfo
.SessionId
;
1364 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1366 /* Get exception code */
1367 Status
= _SEH2_GetExceptionCode();
1371 /* Detach from the process */
1375 /* Unlock the process */
1376 //PsUnlockProcess(Process);
1381 * Since we cannot change the session ID of the given
1382 * process anymore because it is set once and for all
1383 * at process creation time and because it is stored
1384 * inside the Process->Session structure managed by MM,
1385 * we fake changing it: we just return success if the
1386 * user-defined value is the same as the session ID of
1387 * the process, and otherwise we fail.
1389 if (SessionInfo
.SessionId
== PsGetProcessSessionId(Process
))
1391 Status
= STATUS_SUCCESS
;
1395 Status
= STATUS_ACCESS_DENIED
;
1400 case ProcessPriorityClass
:
1402 /* Check buffer length */
1403 if (ProcessInformationLength
!= sizeof(PROCESS_PRIORITY_CLASS
))
1405 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1409 /* Enter SEH for capture */
1412 /* Capture the caller's buffer */
1413 PriorityClass
= *(PPROCESS_PRIORITY_CLASS
)ProcessInformation
;
1415 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1417 /* Return the exception code */
1418 Status
= _SEH2_GetExceptionCode();
1423 /* Check for invalid PriorityClass value */
1424 if (PriorityClass
.PriorityClass
> PROCESS_PRIORITY_CLASS_ABOVE_NORMAL
)
1426 Status
= STATUS_INVALID_PARAMETER
;
1430 if ((PriorityClass
.PriorityClass
!= Process
->PriorityClass
) &&
1431 (PriorityClass
.PriorityClass
== PROCESS_PRIORITY_CLASS_REALTIME
))
1433 /* Check the privilege */
1434 HasPrivilege
= SeCheckPrivilegedObject(SeIncreaseBasePriorityPrivilege
,
1436 PROCESS_SET_INFORMATION
,
1440 ObDereferenceObject(Process
);
1441 DPRINT1("Privilege to change priority to realtime lacking\n");
1442 return STATUS_PRIVILEGE_NOT_HELD
;
1446 /* Check if we have a job */
1449 DPRINT1("Jobs not yet supported\n");
1452 /* Set process priority class */
1453 Process
->PriorityClass
= PriorityClass
.PriorityClass
;
1455 /* Set process priority mode (foreground or background) */
1456 PsSetProcessPriorityByClass(Process
,
1457 PriorityClass
.Foreground
?
1458 PsProcessPriorityForeground
:
1459 PsProcessPriorityBackground
);
1460 Status
= STATUS_SUCCESS
;
1463 case ProcessForegroundInformation
:
1465 /* Check buffer length */
1466 if (ProcessInformationLength
!= sizeof(PROCESS_FOREGROUND_BACKGROUND
))
1468 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1472 /* Enter SEH for capture */
1475 /* Capture the caller's buffer */
1476 Foreground
= *(PPROCESS_FOREGROUND_BACKGROUND
)ProcessInformation
;
1478 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1480 /* Return the exception code */
1481 Status
= _SEH2_GetExceptionCode();
1486 /* Set process priority mode (foreground or background) */
1487 PsSetProcessPriorityByClass(Process
,
1488 Foreground
.Foreground
?
1489 PsProcessPriorityForeground
:
1490 PsProcessPriorityBackground
);
1491 Status
= STATUS_SUCCESS
;
1494 case ProcessBasePriority
:
1496 /* Validate input length */
1497 if (ProcessInformationLength
!= sizeof(KPRIORITY
))
1499 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1503 /* Enter SEH for direct buffer read */
1506 BasePriority
= *(KPRIORITY
*)ProcessInformation
;
1508 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1510 /* Get exception code */
1512 Status
= _SEH2_GetExceptionCode();
1517 /* Extract the memory priority out of there */
1518 if (BasePriority
& 0x80000000)
1520 MemoryPriority
= MEMORY_PRIORITY_FOREGROUND
;
1521 BasePriority
&= ~0x80000000;
1525 MemoryPriority
= MEMORY_PRIORITY_BACKGROUND
;
1528 /* Validate the number */
1529 if ((BasePriority
> HIGH_PRIORITY
) || (BasePriority
<= LOW_PRIORITY
))
1531 return STATUS_INVALID_PARAMETER
;
1534 /* Check if the new base is higher */
1535 if (BasePriority
> Process
->Pcb
.BasePriority
)
1537 HasPrivilege
= SeCheckPrivilegedObject(SeIncreaseBasePriorityPrivilege
,
1539 PROCESS_SET_INFORMATION
,
1543 ObDereferenceObject(Process
);
1544 DPRINT1("Privilege to change priority from %lx to %lx lacking\n", BasePriority
, Process
->Pcb
.BasePriority
);
1545 return STATUS_PRIVILEGE_NOT_HELD
;
1550 KeSetPriorityAndQuantumProcess(&Process
->Pcb
, BasePriority
, 0);
1552 /* Now set the memory priority */
1553 MmSetMemoryPriorityProcess(Process
, MemoryPriority
);
1554 Status
= STATUS_SUCCESS
;
1557 case ProcessRaisePriority
:
1559 /* Validate input length */
1560 if (ProcessInformationLength
!= sizeof(ULONG
))
1562 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1566 /* Enter SEH for direct buffer read */
1569 Boost
= *(PULONG
)ProcessInformation
;
1571 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1573 /* Get exception code */
1575 Status
= _SEH2_GetExceptionCode();
1580 /* Make sure the process isn't dying */
1581 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1584 KeEnterCriticalRegion();
1585 ExAcquirePushLockShared(&Process
->ProcessLock
);
1587 /* Loop the threads */
1588 for (Next
= Process
->ThreadListHead
.Flink
;
1589 Next
!= &Process
->ThreadListHead
;
1592 /* Call Ke for the thread */
1593 Thread
= CONTAINING_RECORD(Next
, ETHREAD
, ThreadListEntry
);
1594 KeBoostPriorityThread(&Thread
->Tcb
, Boost
);
1597 /* Release the lock and rundown */
1598 ExReleasePushLockShared(&Process
->ProcessLock
);
1599 KeLeaveCriticalRegion();
1600 ExReleaseRundownProtection(&Process
->RundownProtect
);
1602 /* Set success code */
1603 Status
= STATUS_SUCCESS
;
1607 /* Avoid race conditions */
1608 Status
= STATUS_PROCESS_IS_TERMINATING
;
1612 case ProcessBreakOnTermination
:
1614 /* Check buffer length */
1615 if (ProcessInformationLength
!= sizeof(ULONG
))
1617 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1621 /* Enter SEH for direct buffer read */
1624 Break
= *(PULONG
)ProcessInformation
;
1626 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1628 /* Get exception code */
1630 Status
= _SEH2_GetExceptionCode();
1635 /* Setting 'break on termination' requires the SeDebugPrivilege */
1636 if (!SeSinglePrivilegeCheck(SeDebugPrivilege
, PreviousMode
))
1638 /* We don't hold the privilege, bail out */
1639 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1643 /* Set or clear the flag */
1646 PspSetProcessFlag(Process
, PSF_BREAK_ON_TERMINATION_BIT
);
1650 PspClearProcessFlag(Process
, PSF_BREAK_ON_TERMINATION_BIT
);
1655 case ProcessAffinityMask
:
1657 /* Check buffer length */
1658 if (ProcessInformationLength
!= sizeof(KAFFINITY
))
1660 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1664 /* Enter SEH for direct buffer read */
1667 Affinity
= *(PKAFFINITY
)ProcessInformation
;
1669 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1671 /* Get exception code */
1673 Status
= _SEH2_GetExceptionCode();
1678 /* Make sure it's valid for the CPUs present */
1679 ValidAffinity
= Affinity
& KeActiveProcessors
;
1680 if (!Affinity
|| (ValidAffinity
!= Affinity
))
1682 Status
= STATUS_INVALID_PARAMETER
;
1686 /* Check if it's within job affinity limits */
1689 /* Not yet implemented */
1691 Status
= STATUS_NOT_IMPLEMENTED
;
1695 /* Make sure the process isn't dying */
1696 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1699 KeEnterCriticalRegion();
1700 ExAcquirePushLockShared(&Process
->ProcessLock
);
1702 /* Call Ke to do the work */
1703 KeSetAffinityProcess(&Process
->Pcb
, ValidAffinity
);
1705 /* Release the lock and rundown */
1706 ExReleasePushLockShared(&Process
->ProcessLock
);
1707 KeLeaveCriticalRegion();
1708 ExReleaseRundownProtection(&Process
->RundownProtect
);
1710 /* Set success code */
1711 Status
= STATUS_SUCCESS
;
1715 /* Avoid race conditions */
1716 Status
= STATUS_PROCESS_IS_TERMINATING
;
1720 /* Priority Boosting status */
1721 case ProcessPriorityBoost
:
1723 /* Validate input length */
1724 if (ProcessInformationLength
!= sizeof(ULONG
))
1726 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1730 /* Enter SEH for direct buffer read */
1733 DisableBoost
= *(PBOOLEAN
)ProcessInformation
;
1735 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1737 /* Get exception code */
1739 Status
= _SEH2_GetExceptionCode();
1744 /* Make sure the process isn't dying */
1745 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1748 KeEnterCriticalRegion();
1749 ExAcquirePushLockShared(&Process
->ProcessLock
);
1751 /* Call Ke to do the work */
1752 KeSetDisableBoostProcess(&Process
->Pcb
, DisableBoost
);
1754 /* Loop the threads too */
1755 for (Next
= Process
->ThreadListHead
.Flink
;
1756 Next
!= &Process
->ThreadListHead
;
1759 /* Call Ke for the thread */
1760 Thread
= CONTAINING_RECORD(Next
, ETHREAD
, ThreadListEntry
);
1761 KeSetDisableBoostThread(&Thread
->Tcb
, DisableBoost
);
1764 /* Release the lock and rundown */
1765 ExReleasePushLockShared(&Process
->ProcessLock
);
1766 KeLeaveCriticalRegion();
1767 ExReleaseRundownProtection(&Process
->RundownProtect
);
1769 /* Set success code */
1770 Status
= STATUS_SUCCESS
;
1774 /* Avoid race conditions */
1775 Status
= STATUS_PROCESS_IS_TERMINATING
;
1779 case ProcessDebugFlags
:
1781 /* Check buffer length */
1782 if (ProcessInformationLength
!= sizeof(ULONG
))
1784 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1788 /* Enter SEH for direct buffer read */
1791 DebugFlags
= *(PULONG
)ProcessInformation
;
1793 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1795 /* Get exception code */
1796 Status
= _SEH2_GetExceptionCode();
1802 if (DebugFlags
& ~1)
1804 Status
= STATUS_INVALID_PARAMETER
;
1810 PspClearProcessFlag(Process
, PSF_NO_DEBUG_INHERIT_BIT
);
1814 PspSetProcessFlag(Process
, PSF_NO_DEBUG_INHERIT_BIT
);
1819 Status
= STATUS_SUCCESS
;
1822 case ProcessEnableAlignmentFaultFixup
:
1824 /* Check buffer length */
1825 if (ProcessInformationLength
!= sizeof(ULONG
))
1827 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1831 /* Enter SEH for direct buffer read */
1834 EnableFixup
= *(PULONG
)ProcessInformation
;
1836 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1838 /* Get exception code */
1839 Status
= _SEH2_GetExceptionCode();
1847 Process
->DefaultHardErrorProcessing
|= SEM_NOALIGNMENTFAULTEXCEPT
;
1851 Process
->DefaultHardErrorProcessing
&= ~SEM_NOALIGNMENTFAULTEXCEPT
;
1854 /* Call Ke for the update */
1855 KeSetAutoAlignmentProcess(&Process
->Pcb
, FALSE
);
1856 Status
= STATUS_SUCCESS
;
1859 case ProcessUserModeIOPL
:
1861 /* Only TCB can do this */
1862 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
1864 /* We don't hold the privilege, bail out */
1865 DPRINT1("Need TCB to set IOPL\n");
1866 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1870 /* Only supported on x86 */
1874 Status
= STATUS_NOT_IMPLEMENTED
;
1879 case ProcessExecuteFlags
:
1881 /* Check buffer length */
1882 if (ProcessInformationLength
!= sizeof(ULONG
))
1884 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1888 if (ProcessHandle
!= NtCurrentProcess())
1890 Status
= STATUS_INVALID_PARAMETER
;
1894 /* Enter SEH for direct buffer read */
1897 NoExecute
= *(PULONG
)ProcessInformation
;
1899 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1901 /* Get exception code */
1902 Status
= _SEH2_GetExceptionCode();
1907 /* Call Mm for the update */
1908 Status
= MmSetExecuteOptions(NoExecute
);
1911 /* We currently don't implement any of these */
1912 case ProcessLdtInformation
:
1913 case ProcessLdtSize
:
1914 case ProcessIoPortHandlers
:
1915 DPRINT1("VDM/16-bit Request not implemented: %lx\n", ProcessInformationClass
);
1916 Status
= STATUS_NOT_IMPLEMENTED
;
1919 case ProcessQuotaLimits
:
1920 DPRINT1("Quota Limits not implemented\n");
1921 Status
= STATUS_NOT_IMPLEMENTED
;
1924 case ProcessWorkingSetWatch
:
1925 DPRINT1("WS watch not implemented\n");
1926 Status
= STATUS_NOT_IMPLEMENTED
;
1929 case ProcessDeviceMap
:
1930 DPRINT1("Device map not implemented\n");
1931 Status
= STATUS_NOT_IMPLEMENTED
;
1934 case ProcessHandleTracing
:
1935 DPRINT1("Handle tracing not implemented\n");
1936 Status
= STATUS_NOT_IMPLEMENTED
;
1939 /* Anything else is invalid */
1941 DPRINT1("Invalid Server 2003 Info Class: %lx\n", ProcessInformationClass
);
1942 Status
= STATUS_INVALID_INFO_CLASS
;
1945 /* Dereference and return status */
1946 ObDereferenceObject(Process
);
1955 NtSetInformationThread(IN HANDLE ThreadHandle
,
1956 IN THREADINFOCLASS ThreadInformationClass
,
1957 IN PVOID ThreadInformation
,
1958 IN ULONG ThreadInformationLength
)
1962 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1964 HANDLE TokenHandle
= NULL
;
1965 KPRIORITY Priority
= 0;
1966 KAFFINITY Affinity
= 0, CombinedAffinity
;
1967 PVOID Address
= NULL
;
1969 ULONG_PTR DisableBoost
= 0;
1970 ULONG_PTR IdealProcessor
= 0;
1971 ULONG_PTR Break
= 0;
1973 ULONG_PTR TlsIndex
= 0;
1974 PVOID
*ExpansionSlots
;
1975 PETHREAD ProcThread
;
1978 /* Verify Information Class validity */
1980 Status
= DefaultSetInfoBufferCheck(ThreadInformationClass
,
1982 RTL_NUMBER_OF(PsThreadInfoClass
),
1984 ThreadInformationLength
,
1986 if (!NT_SUCCESS(Status
)) return Status
;
1989 /* Check what class this is */
1990 Access
= THREAD_SET_INFORMATION
;
1991 if (ThreadInformationClass
== ThreadImpersonationToken
)
1993 /* Setting the impersonation token needs a special mask */
1994 Access
= THREAD_SET_THREAD_TOKEN
;
1997 /* Reference the thread */
1998 Status
= ObReferenceObjectByHandle(ThreadHandle
,
2004 if (!NT_SUCCESS(Status
)) return Status
;
2006 /* Check what kind of information class this is */
2007 switch (ThreadInformationClass
)
2009 /* Thread priority */
2010 case ThreadPriority
:
2012 /* Check buffer length */
2013 if (ThreadInformationLength
!= sizeof(KPRIORITY
))
2015 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2019 /* Use SEH for capture */
2022 /* Get the priority */
2023 Priority
= *(PLONG
)ThreadInformation
;
2025 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2027 /* Get the exception code */
2028 Status
= _SEH2_GetExceptionCode();
2034 if ((Priority
> HIGH_PRIORITY
) ||
2035 (Priority
<= LOW_PRIORITY
))
2038 Status
= STATUS_INVALID_PARAMETER
;
2042 /* Set the priority */
2043 KeSetPriorityThread(&Thread
->Tcb
, Priority
);
2046 case ThreadBasePriority
:
2048 /* Check buffer length */
2049 if (ThreadInformationLength
!= sizeof(LONG
))
2051 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2055 /* Use SEH for capture */
2058 /* Get the priority */
2059 Priority
= *(PLONG
)ThreadInformation
;
2061 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2063 /* Get the exception code */
2064 Status
= _SEH2_GetExceptionCode();
2070 if ((Priority
> THREAD_BASE_PRIORITY_MAX
) ||
2071 (Priority
< THREAD_BASE_PRIORITY_MIN
))
2073 /* These ones are OK */
2074 if ((Priority
!= THREAD_BASE_PRIORITY_LOWRT
+ 1) &&
2075 (Priority
!= THREAD_BASE_PRIORITY_IDLE
- 1))
2077 /* Check if the process is real time */
2078 if (PsGetCurrentProcess()->PriorityClass
!=
2079 PROCESS_PRIORITY_CLASS_REALTIME
)
2081 /* It isn't, fail */
2082 Status
= STATUS_INVALID_PARAMETER
;
2088 /* Set the base priority */
2089 KeSetBasePriorityThread(&Thread
->Tcb
, Priority
);
2092 case ThreadAffinityMask
:
2094 /* Check buffer length */
2095 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
2097 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2101 /* Use SEH for capture */
2104 /* Get the priority */
2105 Affinity
= *(PULONG_PTR
)ThreadInformation
;
2107 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2109 /* Get the exception code */
2110 Status
= _SEH2_GetExceptionCode();
2119 Status
= STATUS_INVALID_PARAMETER
;
2123 /* Get the process */
2124 Process
= Thread
->ThreadsProcess
;
2126 /* Try to acquire rundown */
2127 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
2130 KeEnterCriticalRegion();
2131 ExAcquirePushLockShared(&Process
->ProcessLock
);
2134 CombinedAffinity
= Affinity
& Process
->Pcb
.Affinity
;
2135 if (CombinedAffinity
!= Affinity
)
2138 Status
= STATUS_INVALID_PARAMETER
;
2142 /* Set the affinity */
2143 KeSetAffinityThread(&Thread
->Tcb
, CombinedAffinity
);
2146 /* Release the lock and rundown */
2147 ExReleasePushLockShared(&Process
->ProcessLock
);
2148 KeLeaveCriticalRegion();
2149 ExReleaseRundownProtection(&Process
->RundownProtect
);
2154 Status
= STATUS_PROCESS_IS_TERMINATING
;
2160 case ThreadImpersonationToken
:
2162 /* Check buffer length */
2163 if (ThreadInformationLength
!= sizeof(HANDLE
))
2165 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2169 /* Use SEH for capture */
2172 /* Save the token handle */
2173 TokenHandle
= *(PHANDLE
)ThreadInformation
;
2175 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2177 /* Get the exception code */
2178 Status
= _SEH2_GetExceptionCode();
2183 /* Assign the actual token */
2184 Status
= PsAssignImpersonationToken(Thread
, TokenHandle
);
2187 case ThreadQuerySetWin32StartAddress
:
2189 /* Check buffer length */
2190 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
2192 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2196 /* Use SEH for capture */
2199 /* Get the priority */
2200 Address
= *(PVOID
*)ThreadInformation
;
2202 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2204 /* Get the exception code */
2205 Status
= _SEH2_GetExceptionCode();
2210 /* Set the address */
2211 Thread
->Win32StartAddress
= Address
;
2214 case ThreadIdealProcessor
:
2216 /* Check buffer length */
2217 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
2219 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2223 /* Use SEH for capture */
2226 /* Get the priority */
2227 IdealProcessor
= *(PULONG_PTR
)ThreadInformation
;
2229 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2231 /* Get the exception code */
2232 Status
= _SEH2_GetExceptionCode();
2238 if (IdealProcessor
> MAXIMUM_PROCESSORS
)
2241 Status
= STATUS_INVALID_PARAMETER
;
2246 Status
= KeSetIdealProcessorThread(&Thread
->Tcb
,
2247 (CCHAR
)IdealProcessor
);
2249 /* Get the TEB and protect the thread */
2250 Teb
= Thread
->Tcb
.Teb
;
2251 if ((Teb
) && (ExAcquireRundownProtection(&Thread
->RundownProtect
)))
2253 /* Save the ideal processor */
2254 Teb
->IdealProcessor
= Thread
->Tcb
.IdealProcessor
;
2256 /* Release rundown protection */
2257 ExReleaseRundownProtection(&Thread
->RundownProtect
);
2262 case ThreadPriorityBoost
:
2264 /* Check buffer length */
2265 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
2267 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2271 /* Use SEH for capture */
2274 /* Get the priority */
2275 DisableBoost
= *(PULONG_PTR
)ThreadInformation
;
2277 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2279 /* Get the exception code */
2280 Status
= _SEH2_GetExceptionCode();
2285 /* Call the kernel */
2286 KeSetDisableBoostThread(&Thread
->Tcb
, (BOOLEAN
)DisableBoost
);
2289 case ThreadZeroTlsCell
:
2291 /* Check buffer length */
2292 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
2294 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2298 /* Use SEH for capture */
2301 /* Get the priority */
2302 TlsIndex
= *(PULONG_PTR
)ThreadInformation
;
2304 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2306 /* Get the exception code */
2307 Status
= _SEH2_GetExceptionCode();
2312 /* This is only valid for the current thread */
2313 if (Thread
!= PsGetCurrentThread())
2316 Status
= STATUS_INVALID_PARAMETER
;
2320 /* Get the process */
2321 Process
= Thread
->ThreadsProcess
;
2323 /* Loop the threads */
2324 ProcThread
= PsGetNextProcessThread(Process
, NULL
);
2327 /* Acquire rundown */
2328 if (ExAcquireRundownProtection(&ProcThread
->RundownProtect
))
2331 Teb
= ProcThread
->Tcb
.Teb
;
2334 /* Check if we're in the expansion range */
2335 if (TlsIndex
> TLS_MINIMUM_AVAILABLE
- 1)
2337 if (TlsIndex
< (TLS_MINIMUM_AVAILABLE
+
2338 TLS_EXPANSION_SLOTS
) - 1)
2340 /* Check if we have expansion slots */
2341 ExpansionSlots
= Teb
->TlsExpansionSlots
;
2344 /* Clear the index */
2345 ExpansionSlots
[TlsIndex
- TLS_MINIMUM_AVAILABLE
] = 0;
2351 /* Clear the index */
2352 Teb
->TlsSlots
[TlsIndex
] = NULL
;
2356 /* Release rundown */
2357 ExReleaseRundownProtection(&ProcThread
->RundownProtect
);
2360 /* Go to the next thread */
2361 ProcThread
= PsGetNextProcessThread(Process
, ProcThread
);
2367 case ThreadBreakOnTermination
:
2369 /* Check buffer length */
2370 if (ThreadInformationLength
!= sizeof(ULONG
))
2372 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2376 /* Enter SEH for direct buffer read */
2379 Break
= *(PULONG
)ThreadInformation
;
2381 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2383 /* Get exception code */
2385 Status
= _SEH2_GetExceptionCode();
2390 /* Setting 'break on termination' requires the SeDebugPrivilege */
2391 if (!SeSinglePrivilegeCheck(SeDebugPrivilege
, PreviousMode
))
2393 /* We don't hold the privilege, bail out */
2394 Status
= STATUS_PRIVILEGE_NOT_HELD
;
2398 /* Set or clear the flag */
2401 PspSetCrossThreadFlag(Thread
, CT_BREAK_ON_TERMINATION_BIT
);
2405 PspClearCrossThreadFlag(Thread
, CT_BREAK_ON_TERMINATION_BIT
);
2410 /* We don't implement it yet */
2411 DPRINT1("Not implemented: %d\n", ThreadInformationClass
);
2412 Status
= STATUS_NOT_IMPLEMENTED
;
2415 /* Dereference and return status */
2416 ObDereferenceObject(Thread
);
2425 NtQueryInformationThread(IN HANDLE ThreadHandle
,
2426 IN THREADINFOCLASS ThreadInformationClass
,
2427 OUT PVOID ThreadInformation
,
2428 IN ULONG ThreadInformationLength
,
2429 OUT PULONG ReturnLength OPTIONAL
)
2432 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2436 PTHREAD_BASIC_INFORMATION ThreadBasicInfo
=
2437 (PTHREAD_BASIC_INFORMATION
)ThreadInformation
;
2438 PKERNEL_USER_TIMES ThreadTime
= (PKERNEL_USER_TIMES
)ThreadInformation
;
2440 ULONG ThreadTerminated
;
2443 /* Check if we were called from user mode */
2444 if (PreviousMode
!= KernelMode
)
2449 /* Probe the buffer */
2450 ProbeForWrite(ThreadInformation
,
2451 ThreadInformationLength
,
2454 /* Probe the return length if required */
2455 if (ReturnLength
) ProbeForWriteUlong(ReturnLength
);
2457 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2459 /* Return the exception code */
2460 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2465 /* Check what class this is */
2466 Access
= THREAD_QUERY_INFORMATION
;
2468 /* Reference the process */
2469 Status
= ObReferenceObjectByHandle(ThreadHandle
,
2475 if (!NT_SUCCESS(Status
)) return Status
;
2477 /* Check what kind of information class this is */
2478 switch (ThreadInformationClass
)
2480 /* Basic thread information */
2481 case ThreadBasicInformation
:
2483 /* Set return length */
2484 Length
= sizeof(THREAD_BASIC_INFORMATION
);
2486 if (ThreadInformationLength
!= Length
)
2488 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2491 /* Protect writes with SEH */
2494 /* Write all the information from the ETHREAD/KTHREAD */
2495 ThreadBasicInfo
->ExitStatus
= Thread
->ExitStatus
;
2496 ThreadBasicInfo
->TebBaseAddress
= (PVOID
)Thread
->Tcb
.Teb
;
2497 ThreadBasicInfo
->ClientId
= Thread
->Cid
;
2498 ThreadBasicInfo
->AffinityMask
= Thread
->Tcb
.Affinity
;
2499 ThreadBasicInfo
->Priority
= Thread
->Tcb
.Priority
;
2500 ThreadBasicInfo
->BasePriority
= KeQueryBasePriorityThread(&Thread
->Tcb
);
2502 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2504 /* Get exception code */
2505 Status
= _SEH2_GetExceptionCode();
2510 /* Thread time information */
2513 /* Set the return length */
2514 Length
= sizeof(KERNEL_USER_TIMES
);
2516 if (ThreadInformationLength
!= Length
)
2518 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2521 /* Protect writes with SEH */
2524 /* Copy time information from ETHREAD/KTHREAD */
2525 ThreadTime
->KernelTime
.QuadPart
= Thread
->Tcb
.KernelTime
* KeMaximumIncrement
;
2526 ThreadTime
->UserTime
.QuadPart
= Thread
->Tcb
.UserTime
* KeMaximumIncrement
;
2527 ThreadTime
->CreateTime
= Thread
->CreateTime
;
2529 /* Exit time is in a union and only valid on actual exit! */
2530 if (KeReadStateThread(&Thread
->Tcb
))
2532 ThreadTime
->ExitTime
= Thread
->ExitTime
;
2536 ThreadTime
->ExitTime
.QuadPart
= 0;
2539 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2541 /* Get exception code */
2542 Status
= _SEH2_GetExceptionCode();
2547 case ThreadQuerySetWin32StartAddress
:
2549 /* Set the return length*/
2550 Length
= sizeof(PVOID
);
2552 if (ThreadInformationLength
!= Length
)
2554 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2557 /* Protect write with SEH */
2560 /* Return the Win32 Start Address */
2561 *(PVOID
*)ThreadInformation
= Thread
->Win32StartAddress
;
2563 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2565 /* Get exception code */
2566 Status
= _SEH2_GetExceptionCode();
2571 case ThreadPerformanceCount
:
2573 /* Set the return length*/
2574 Length
= sizeof(LARGE_INTEGER
);
2576 if (ThreadInformationLength
!= Length
)
2578 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2581 /* Protect write with SEH */
2585 (*(PLARGE_INTEGER
)ThreadInformation
).QuadPart
= 0;
2587 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2589 /* Get exception code */
2590 Status
= _SEH2_GetExceptionCode();
2595 case ThreadAmILastThread
:
2597 /* Set the return length*/
2598 Length
= sizeof(ULONG
);
2600 if (ThreadInformationLength
!= Length
)
2602 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2605 /* Protect write with SEH */
2608 /* Return whether or not we are the last thread */
2609 *(PULONG
)ThreadInformation
= ((Thread
->ThreadsProcess
->
2610 ThreadListHead
.Flink
->Flink
==
2611 &Thread
->ThreadsProcess
->
2615 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2617 /* Get exception code */
2618 Status
= _SEH2_GetExceptionCode();
2623 case ThreadIsIoPending
:
2625 /* Set the return length*/
2626 Length
= sizeof(ULONG
);
2628 if (ThreadInformationLength
!= Length
)
2630 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2633 /* Raise the IRQL to protect the IRP list */
2634 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2636 /* Protect write with SEH */
2639 /* Check if the IRP list is empty or not */
2640 *(PULONG
)ThreadInformation
= !IsListEmpty(&Thread
->IrpList
);
2642 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2644 /* Get exception code */
2645 Status
= _SEH2_GetExceptionCode();
2649 /* Lower IRQL back */
2650 KeLowerIrql(OldIrql
);
2653 /* LDT and GDT information */
2654 case ThreadDescriptorTableEntry
:
2657 /* Call the worker routine */
2658 Status
= PspQueryDescriptorThread(Thread
,
2660 ThreadInformationLength
,
2663 /* Only implemented on x86 */
2664 Status
= STATUS_NOT_IMPLEMENTED
;
2668 case ThreadPriorityBoost
:
2670 /* Set the return length*/
2671 Length
= sizeof(ULONG
);
2673 if (ThreadInformationLength
!= Length
)
2675 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2681 *(PULONG
)ThreadInformation
= Thread
->Tcb
.DisableBoost
? 1 : 0;
2683 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2685 Status
= _SEH2_GetExceptionCode();
2690 case ThreadIsTerminated
:
2692 /* Set the return length*/
2693 Length
= sizeof(ThreadTerminated
);
2695 if (ThreadInformationLength
!= Length
)
2697 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2701 ThreadTerminated
= PsIsThreadTerminating(Thread
);
2705 *(PULONG
)ThreadInformation
= ThreadTerminated
? 1 : 0;
2707 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2709 Status
= _SEH2_GetExceptionCode();
2718 /* Not yet implemented */
2719 DPRINT1("Not implemented: %lx\n", ThreadInformationClass
);
2720 Status
= STATUS_NOT_IMPLEMENTED
;
2723 /* Protect write with SEH */
2726 /* Check if caller wanted return length */
2727 if (ReturnLength
) *ReturnLength
= Length
;
2729 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2731 /* Get exception code */
2732 Status
= _SEH2_GetExceptionCode();
2736 /* Dereference the thread, and return */
2737 ObDereferenceObject(Thread
);