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 ULONG UserTime
, KernelTime
;
74 PPROCESS_PRIORITY_CLASS PsPriorityClass
= (PPROCESS_PRIORITY_CLASS
)ProcessInformation
;
76 PPROCESS_SESSION_INFORMATION SessionInfo
=
77 (PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
78 PVM_COUNTERS VmCounters
= (PVM_COUNTERS
)ProcessInformation
;
79 PIO_COUNTERS IoCounters
= (PIO_COUNTERS
)ProcessInformation
;
80 PQUOTA_LIMITS QuotaLimits
= (PQUOTA_LIMITS
)ProcessInformation
;
81 PROCESS_DEVICEMAP_INFORMATION DeviceMap
;
82 PUNICODE_STRING ImageName
;
83 ULONG Cookie
, ExecuteOptions
= 0;
87 /* Check for user-mode caller */
88 if (PreviousMode
!= KernelMode
)
90 /* Prepare to probe parameters */
93 /* Probe the buffer */
94 ProbeForWrite(ProcessInformation
,
95 ProcessInformationLength
,
98 /* Probe the return length if required */
99 if (ReturnLength
) ProbeForWriteUlong(ReturnLength
);
101 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
103 /* Return the exception code */
104 _SEH2_YIELD(return _SEH2_GetExceptionCode());
109 if (((ProcessInformationClass
== ProcessCookie
) ||
110 (ProcessInformationClass
== ProcessImageInformation
)) &&
111 (ProcessHandle
!= NtCurrentProcess()))
114 * Retrieving the process cookie is only allowed for the calling process
115 * itself! XP only allows NtCurrentProcess() as process handles even if
116 * a real handle actually represents the current process.
118 return STATUS_INVALID_PARAMETER
;
121 /* Check the information class */
122 switch (ProcessInformationClass
)
124 /* Basic process information */
125 case ProcessBasicInformation
:
127 /* Set return length */
128 Length
= sizeof(PROCESS_BASIC_INFORMATION
);
130 if (ProcessInformationLength
!= Length
)
132 Status
= STATUS_INFO_LENGTH_MISMATCH
;
136 /* Reference the process */
137 Status
= ObReferenceObjectByHandle(ProcessHandle
,
138 PROCESS_QUERY_INFORMATION
,
143 if (!NT_SUCCESS(Status
)) break;
145 /* Protect writes with SEH */
148 /* Write all the information from the EPROCESS/KPROCESS */
149 ProcessBasicInfo
->ExitStatus
= Process
->ExitStatus
;
150 ProcessBasicInfo
->PebBaseAddress
= Process
->Peb
;
151 ProcessBasicInfo
->AffinityMask
= Process
->Pcb
.Affinity
;
152 ProcessBasicInfo
->UniqueProcessId
= (ULONG_PTR
)Process
->
154 ProcessBasicInfo
->InheritedFromUniqueProcessId
=
155 (ULONG_PTR
)Process
->InheritedFromUniqueProcessId
;
156 ProcessBasicInfo
->BasePriority
= Process
->Pcb
.BasePriority
;
159 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
161 /* Get exception code */
162 Status
= _SEH2_GetExceptionCode();
166 /* Dereference the process */
167 ObDereferenceObject(Process
);
170 /* Process quota limits */
171 case ProcessQuotaLimits
:
173 Length
= sizeof(QUOTA_LIMITS
);
174 if (ProcessInformationLength
!= Length
)
176 Status
= STATUS_INFO_LENGTH_MISMATCH
;
180 /* Reference the process */
181 Status
= ObReferenceObjectByHandle(ProcessHandle
,
182 PROCESS_QUERY_INFORMATION
,
187 if (!NT_SUCCESS(Status
)) break;
189 /* Indicate success */
190 Status
= STATUS_SUCCESS
;
194 /* Set max/min working set sizes */
195 QuotaLimits
->MaximumWorkingSetSize
=
196 Process
->Vm
.MaximumWorkingSetSize
<< PAGE_SHIFT
;
197 QuotaLimits
->MinimumWorkingSetSize
=
198 Process
->Vm
.MinimumWorkingSetSize
<< PAGE_SHIFT
;
200 /* Set default time limits */
201 QuotaLimits
->TimeLimit
.LowPart
= MAXULONG
;
202 QuotaLimits
->TimeLimit
.HighPart
= MAXULONG
;
204 /* Is quota block a default one? */
205 if (Process
->QuotaBlock
== &PspDefaultQuotaBlock
)
207 /* Set default pools and pagefile limits */
208 QuotaLimits
->PagedPoolLimit
= (SIZE_T
)-1;
209 QuotaLimits
->NonPagedPoolLimit
= (SIZE_T
)-1;
210 QuotaLimits
->PagefileLimit
= (SIZE_T
)-1;
214 /* Get limits from non-default quota block */
215 QuotaLimits
->PagedPoolLimit
=
216 Process
->QuotaBlock
->QuotaEntry
[PagedPool
].Limit
;
217 QuotaLimits
->NonPagedPoolLimit
=
218 Process
->QuotaBlock
->QuotaEntry
[NonPagedPool
].Limit
;
219 QuotaLimits
->PagefileLimit
=
220 Process
->QuotaBlock
->QuotaEntry
[2].Limit
;
223 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
225 /* Get exception code */
226 Status
= _SEH2_GetExceptionCode();
230 /* Dereference the process */
231 ObDereferenceObject(Process
);
234 case ProcessIoCounters
:
236 Length
= sizeof(IO_COUNTERS
);
237 if (ProcessInformationLength
!= Length
)
239 Status
= STATUS_INFO_LENGTH_MISMATCH
;
243 /* Reference the process */
244 Status
= ObReferenceObjectByHandle(ProcessHandle
,
245 PROCESS_QUERY_INFORMATION
,
250 if (!NT_SUCCESS(Status
)) break;
254 /* FIXME: Call KeQueryValuesProcess */
255 IoCounters
->ReadOperationCount
= Process
->ReadOperationCount
.QuadPart
;
256 IoCounters
->ReadTransferCount
= Process
->ReadTransferCount
.QuadPart
;
257 IoCounters
->WriteOperationCount
= Process
->WriteOperationCount
.QuadPart
;
258 IoCounters
->WriteTransferCount
= Process
->WriteTransferCount
.QuadPart
;
259 IoCounters
->OtherOperationCount
= Process
->OtherOperationCount
.QuadPart
;
260 IoCounters
->OtherTransferCount
= Process
->OtherTransferCount
.QuadPart
;
262 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
264 /* Ignore exception */
268 /* Set status to success in any case */
269 Status
= STATUS_SUCCESS
;
271 /* Dereference the process */
272 ObDereferenceObject(Process
);
278 /* Set the return length */
279 Length
= sizeof(KERNEL_USER_TIMES
);
281 if (ProcessInformationLength
!= Length
)
283 Status
= STATUS_INFO_LENGTH_MISMATCH
;
287 /* Reference the process */
288 Status
= ObReferenceObjectByHandle(ProcessHandle
,
289 PROCESS_QUERY_INFORMATION
,
294 if (!NT_SUCCESS(Status
)) break;
296 /* Protect writes with SEH */
299 /* Copy time information from EPROCESS/KPROCESS */
300 KernelTime
= KeQueryRuntimeProcess(&Process
->Pcb
, &UserTime
);
301 ProcessTime
->CreateTime
= Process
->CreateTime
;
302 ProcessTime
->UserTime
.QuadPart
= (LONGLONG
)UserTime
* KeMaximumIncrement
;
303 ProcessTime
->KernelTime
.QuadPart
= (LONGLONG
)KernelTime
* KeMaximumIncrement
;
304 ProcessTime
->ExitTime
= Process
->ExitTime
;
306 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
308 /* Get exception code */
309 Status
= _SEH2_GetExceptionCode();
313 /* Dereference the process */
314 ObDereferenceObject(Process
);
317 /* Process Debug Port */
318 case ProcessDebugPort
:
320 /* Set return length */
321 Length
= sizeof(HANDLE
);
323 if (ProcessInformationLength
!= Length
)
325 Status
= STATUS_INFO_LENGTH_MISMATCH
;
329 /* Reference the process */
330 Status
= ObReferenceObjectByHandle(ProcessHandle
,
331 PROCESS_QUERY_INFORMATION
,
336 if (!NT_SUCCESS(Status
)) break;
338 /* Protect write with SEH */
341 /* Return whether or not we have a debug port */
342 *(PHANDLE
)ProcessInformation
= (Process
->DebugPort
?
345 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
347 /* Get exception code */
348 Status
= _SEH2_GetExceptionCode();
352 /* Dereference the process */
353 ObDereferenceObject(Process
);
356 case ProcessHandleCount
:
358 /* Set the return length*/
359 Length
= sizeof(ULONG
);
361 if (ProcessInformationLength
!= Length
)
363 Status
= STATUS_INFO_LENGTH_MISMATCH
;
367 /* Reference the process */
368 Status
= ObReferenceObjectByHandle(ProcessHandle
,
369 PROCESS_QUERY_INFORMATION
,
374 if (!NT_SUCCESS(Status
)) break;
376 /* Count the number of handles this process has */
377 HandleCount
= ObGetProcessHandleCount(Process
);
379 /* Protect write in SEH */
382 /* Return the count of handles */
383 *(PULONG
)ProcessInformation
= HandleCount
;
385 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
387 /* Get the exception code */
388 Status
= _SEH2_GetExceptionCode();
392 /* Dereference the process */
393 ObDereferenceObject(Process
);
396 /* Session ID for the process */
397 case ProcessSessionInformation
:
399 /* Set the return length*/
400 Length
= sizeof(PROCESS_SESSION_INFORMATION
);
402 if (ProcessInformationLength
!= Length
)
404 Status
= STATUS_INFO_LENGTH_MISMATCH
;
408 /* Reference the process */
409 Status
= ObReferenceObjectByHandle(ProcessHandle
,
410 PROCESS_QUERY_INFORMATION
,
415 if (!NT_SUCCESS(Status
)) break;
417 /* Enter SEH for write safety */
420 /* Write back the Session ID */
421 SessionInfo
->SessionId
= PsGetProcessSessionId(Process
);
423 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
425 /* Get the exception code */
426 Status
= _SEH2_GetExceptionCode();
430 /* Dereference the process */
431 ObDereferenceObject(Process
);
434 /* Virtual Memory Statistics */
435 case ProcessVmCounters
:
437 /* Validate the input length */
438 if ((ProcessInformationLength
!= sizeof(VM_COUNTERS
)) &&
439 (ProcessInformationLength
!= sizeof(VM_COUNTERS_EX
)))
441 Status
= STATUS_INFO_LENGTH_MISMATCH
;
445 /* Reference the process */
446 Status
= ObReferenceObjectByHandle(ProcessHandle
,
447 PROCESS_QUERY_INFORMATION
,
452 if (!NT_SUCCESS(Status
)) break;
454 /* Enter SEH for write safety */
457 /* Return data from EPROCESS */
458 VmCounters
->PeakVirtualSize
= Process
->PeakVirtualSize
;
459 VmCounters
->VirtualSize
= Process
->VirtualSize
;
460 VmCounters
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
461 VmCounters
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
462 VmCounters
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
463 VmCounters
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeak
[0];
464 VmCounters
->QuotaPagedPoolUsage
= Process
->QuotaUsage
[0];
465 VmCounters
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeak
[1];
466 VmCounters
->QuotaNonPagedPoolUsage
= Process
->QuotaUsage
[1];
467 VmCounters
->PagefileUsage
= Process
->QuotaUsage
[2] << PAGE_SHIFT
;
468 VmCounters
->PeakPagefileUsage
= Process
->QuotaPeak
[2] << PAGE_SHIFT
;
469 //VmCounters->PrivateUsage = Process->CommitCharge << PAGE_SHIFT;
472 /* Set the return length */
473 Length
= ProcessInformationLength
;
475 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
477 /* Get the exception code */
478 Status
= _SEH2_GetExceptionCode();
482 /* Dereference the process */
483 ObDereferenceObject(Process
);
486 /* Hard Error Processing Mode */
487 case ProcessDefaultHardErrorMode
:
489 /* Set the return length*/
490 Length
= sizeof(ULONG
);
492 if (ProcessInformationLength
!= Length
)
494 Status
= STATUS_INFO_LENGTH_MISMATCH
;
498 /* Reference the process */
499 Status
= ObReferenceObjectByHandle(ProcessHandle
,
500 PROCESS_QUERY_INFORMATION
,
505 if (!NT_SUCCESS(Status
)) break;
507 /* Enter SEH for writing back data */
510 /* Write the current processing mode */
511 *(PULONG
)ProcessInformation
= Process
->
512 DefaultHardErrorProcessing
;
514 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
516 /* Get the exception code */
517 Status
= _SEH2_GetExceptionCode();
521 /* Dereference the process */
522 ObDereferenceObject(Process
);
525 /* Priority Boosting status */
526 case ProcessPriorityBoost
:
528 /* Set the return length */
529 Length
= sizeof(ULONG
);
531 if (ProcessInformationLength
!= Length
)
533 Status
= STATUS_INFO_LENGTH_MISMATCH
;
537 /* Reference the process */
538 Status
= ObReferenceObjectByHandle(ProcessHandle
,
539 PROCESS_QUERY_INFORMATION
,
544 if (!NT_SUCCESS(Status
)) break;
546 /* Enter SEH for writing back data */
549 /* Return boost status */
550 *(PULONG
)ProcessInformation
= Process
->Pcb
.DisableBoost
?
553 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
555 /* Get the exception code */
556 Status
= _SEH2_GetExceptionCode();
560 /* Dereference the process */
561 ObDereferenceObject(Process
);
565 case ProcessDeviceMap
:
567 /* Set the return length */
568 Length
= sizeof(PROCESS_DEVICEMAP_INFORMATION
);
570 if (ProcessInformationLength
!= Length
)
572 if (ProcessInformationLength
== sizeof(PROCESS_DEVICEMAP_INFORMATION_EX
))
574 DPRINT1("PROCESS_DEVICEMAP_INFORMATION_EX not supported!\n");
575 Status
= STATUS_NOT_IMPLEMENTED
;
579 Status
= STATUS_INFO_LENGTH_MISMATCH
;
584 /* Reference the process */
585 Status
= ObReferenceObjectByHandle(ProcessHandle
,
586 PROCESS_QUERY_INFORMATION
,
591 if (!NT_SUCCESS(Status
)) break;
593 /* Query the device map information */
594 ObQueryDeviceMapInformation(Process
, &DeviceMap
);
596 /* Enter SEH for writing back data */
599 *(PPROCESS_DEVICEMAP_INFORMATION
)ProcessInformation
= DeviceMap
;
601 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
603 /* Get the exception code */
604 Status
= _SEH2_GetExceptionCode();
608 /* Dereference the process */
609 ObDereferenceObject(Process
);
613 case ProcessPriorityClass
:
615 /* Set the return length*/
616 Length
= sizeof(PROCESS_PRIORITY_CLASS
);
618 if (ProcessInformationLength
!= Length
)
620 Status
= STATUS_INFO_LENGTH_MISMATCH
;
624 /* Reference the process */
625 Status
= ObReferenceObjectByHandle(ProcessHandle
,
626 PROCESS_QUERY_INFORMATION
,
631 if (!NT_SUCCESS(Status
)) break;
633 /* Enter SEH for writing back data */
636 /* Return current priority class */
637 PsPriorityClass
->PriorityClass
= Process
->PriorityClass
;
638 PsPriorityClass
->Foreground
= FALSE
;
640 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
642 /* Get the exception code */
643 Status
= _SEH2_GetExceptionCode();
647 /* Dereference the process */
648 ObDereferenceObject(Process
);
651 case ProcessImageFileName
:
653 /* Reference the process */
654 Status
= ObReferenceObjectByHandle(ProcessHandle
,
655 PROCESS_QUERY_INFORMATION
,
660 if (!NT_SUCCESS(Status
)) break;
662 /* Get the image path */
663 Status
= SeLocateProcessImageName(Process
, &ImageName
);
664 if (NT_SUCCESS(Status
))
666 /* Set return length */
667 Length
= ImageName
->MaximumLength
+
668 sizeof(OBJECT_NAME_INFORMATION
);
670 /* Make sure it's large enough */
671 if (Length
<= ProcessInformationLength
)
673 /* Enter SEH to protect write */
677 RtlCopyMemory(ProcessInformation
,
682 ((PUNICODE_STRING
)ProcessInformation
)->Buffer
=
683 (PWSTR
)((PUNICODE_STRING
)ProcessInformation
+ 1);
685 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
687 /* Get the exception code */
688 Status
= _SEH2_GetExceptionCode();
694 /* Buffer too small */
695 Status
= STATUS_INFO_LENGTH_MISMATCH
;
698 /* Free the image path */
699 ExFreePoolWithTag(ImageName
, TAG_SEPA
);
701 /* Dereference the process */
702 ObDereferenceObject(Process
);
705 case ProcessDebugFlags
:
707 /* Set the return length*/
708 Length
= sizeof(ULONG
);
709 if (ProcessInformationLength
!= Length
)
711 Status
= STATUS_INFO_LENGTH_MISMATCH
;
715 /* Reference the process */
716 Status
= ObReferenceObjectByHandle(ProcessHandle
,
717 PROCESS_QUERY_INFORMATION
,
722 if (!NT_SUCCESS(Status
)) break;
724 /* Enter SEH for writing back data */
727 /* Return the debug flag state */
728 *(PULONG
)ProcessInformation
= Process
->NoDebugInherit
? 0 : 1;
730 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
732 /* Get the exception code */
733 Status
= _SEH2_GetExceptionCode();
737 /* Dereference the process */
738 ObDereferenceObject(Process
);
741 case ProcessBreakOnTermination
:
743 /* Set the return length*/
744 Length
= sizeof(ULONG
);
745 if (ProcessInformationLength
!= Length
)
747 Status
= STATUS_INFO_LENGTH_MISMATCH
;
751 /* Reference the process */
752 Status
= ObReferenceObjectByHandle(ProcessHandle
,
753 PROCESS_QUERY_INFORMATION
,
758 if (!NT_SUCCESS(Status
)) break;
760 /* Enter SEH for writing back data */
763 /* Return the BreakOnTermination state */
764 *(PULONG
)ProcessInformation
= Process
->BreakOnTermination
;
766 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
768 /* Get the exception code */
769 Status
= _SEH2_GetExceptionCode();
773 /* Dereference the process */
774 ObDereferenceObject(Process
);
777 /* Per-process security cookie */
780 /* Get the current process and cookie */
781 Process
= PsGetCurrentProcess();
782 Cookie
= Process
->Cookie
;
785 LARGE_INTEGER SystemTime
;
789 /* Generate a new cookie */
790 KeQuerySystemTime(&SystemTime
);
791 Prcb
= KeGetCurrentPrcb();
792 NewCookie
= Prcb
->KeSystemCalls
^ Prcb
->InterruptTime
^
793 SystemTime
.u
.LowPart
^ SystemTime
.u
.HighPart
;
795 /* Set the new cookie or return the current one */
796 Cookie
= InterlockedCompareExchange((LONG
*)&Process
->Cookie
,
799 if (!Cookie
) Cookie
= NewCookie
;
801 /* Set return length */
802 Length
= sizeof(ULONG
);
805 /* Indicate success */
806 Status
= STATUS_SUCCESS
;
808 /* Enter SEH to protect write */
811 /* Write back the cookie */
812 *(PULONG
)ProcessInformation
= Cookie
;
814 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
816 /* Get the exception code */
817 Status
= _SEH2_GetExceptionCode();
822 case ProcessImageInformation
:
824 /* Set the length required and validate it */
825 Length
= sizeof(SECTION_IMAGE_INFORMATION
);
826 if (ProcessInformationLength
!= Length
)
829 Status
= STATUS_INFO_LENGTH_MISMATCH
;
833 /* Enter SEH to protect write */
836 MmGetImageInformation((PSECTION_IMAGE_INFORMATION
)ProcessInformation
);
838 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
840 /* Get the exception code */
841 Status
= _SEH2_GetExceptionCode();
845 /* Indicate success */
846 Status
= STATUS_SUCCESS
;
849 case ProcessDebugObjectHandle
:
851 /* Set the return length */
852 Length
= sizeof(HANDLE
);
853 if (ProcessInformationLength
!= Length
)
855 Status
= STATUS_INFO_LENGTH_MISMATCH
;
859 /* Reference the process */
860 Status
= ObReferenceObjectByHandle(ProcessHandle
,
861 PROCESS_QUERY_INFORMATION
,
866 if (!NT_SUCCESS(Status
)) break;
868 /* Get the debug port */
869 Status
= DbgkOpenProcessDebugPort(Process
, PreviousMode
, &DebugPort
);
871 /* Let go of the process */
872 ObDereferenceObject(Process
);
874 /* Protect write in SEH */
877 /* Return debug port's handle */
878 *(PHANDLE
)ProcessInformation
= DebugPort
;
880 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
882 /* Get the exception code */
883 Status
= _SEH2_GetExceptionCode();
888 case ProcessHandleTracing
:
889 DPRINT1("Handle tracing Not implemented: %lx\n", ProcessInformationClass
);
890 Status
= STATUS_NOT_IMPLEMENTED
;
893 case ProcessLUIDDeviceMapsEnabled
:
895 /* Set the return length */
896 Length
= sizeof(ULONG
);
897 if (ProcessInformationLength
!= Length
)
899 Status
= STATUS_INFO_LENGTH_MISMATCH
;
903 /* Indicate success */
904 Status
= STATUS_SUCCESS
;
906 /* Protect write in SEH */
909 /* Return FALSE -- we don't support this */
910 *(PULONG
)ProcessInformation
= FALSE
;
912 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
914 /* Get the exception code */
915 Status
= _SEH2_GetExceptionCode();
920 case ProcessWx86Information
:
922 /* Set the return length */
923 Length
= sizeof(ULONG
);
924 if (ProcessInformationLength
!= Length
)
926 Status
= STATUS_INFO_LENGTH_MISMATCH
;
930 /* Reference the process */
931 Status
= ObReferenceObjectByHandle(ProcessHandle
,
932 PROCESS_QUERY_INFORMATION
,
937 if (!NT_SUCCESS(Status
)) break;
939 /* Protect write in SEH */
942 /* Return if the flag is set */
943 *(PULONG
)ProcessInformation
= (ULONG
)Process
->VdmAllowed
;
945 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
947 /* Get the exception code */
948 Status
= _SEH2_GetExceptionCode();
952 /* Dereference the process */
953 ObDereferenceObject(Process
);
956 case ProcessWow64Information
:
958 /* Set return length */
959 Length
= sizeof(ULONG_PTR
);
960 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 ObDereferenceObject(Process
);
1532 return STATUS_INVALID_PARAMETER
;
1535 /* Check if the new base is higher */
1536 if (BasePriority
> Process
->Pcb
.BasePriority
)
1538 HasPrivilege
= SeCheckPrivilegedObject(SeIncreaseBasePriorityPrivilege
,
1540 PROCESS_SET_INFORMATION
,
1544 ObDereferenceObject(Process
);
1545 DPRINT1("Privilege to change priority from %lx to %lx lacking\n", BasePriority
, Process
->Pcb
.BasePriority
);
1546 return STATUS_PRIVILEGE_NOT_HELD
;
1551 KeSetPriorityAndQuantumProcess(&Process
->Pcb
, BasePriority
, 0);
1553 /* Now set the memory priority */
1554 MmSetMemoryPriorityProcess(Process
, MemoryPriority
);
1555 Status
= STATUS_SUCCESS
;
1558 case ProcessRaisePriority
:
1560 /* Validate input length */
1561 if (ProcessInformationLength
!= sizeof(ULONG
))
1563 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1567 /* Enter SEH for direct buffer read */
1570 Boost
= *(PULONG
)ProcessInformation
;
1572 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1574 /* Get exception code */
1576 Status
= _SEH2_GetExceptionCode();
1581 /* Make sure the process isn't dying */
1582 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1585 KeEnterCriticalRegion();
1586 ExAcquirePushLockShared(&Process
->ProcessLock
);
1588 /* Loop the threads */
1589 for (Next
= Process
->ThreadListHead
.Flink
;
1590 Next
!= &Process
->ThreadListHead
;
1593 /* Call Ke for the thread */
1594 Thread
= CONTAINING_RECORD(Next
, ETHREAD
, ThreadListEntry
);
1595 KeBoostPriorityThread(&Thread
->Tcb
, Boost
);
1598 /* Release the lock and rundown */
1599 ExReleasePushLockShared(&Process
->ProcessLock
);
1600 KeLeaveCriticalRegion();
1601 ExReleaseRundownProtection(&Process
->RundownProtect
);
1603 /* Set success code */
1604 Status
= STATUS_SUCCESS
;
1608 /* Avoid race conditions */
1609 Status
= STATUS_PROCESS_IS_TERMINATING
;
1613 case ProcessBreakOnTermination
:
1615 /* Check buffer length */
1616 if (ProcessInformationLength
!= sizeof(ULONG
))
1618 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1622 /* Enter SEH for direct buffer read */
1625 Break
= *(PULONG
)ProcessInformation
;
1627 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1629 /* Get exception code */
1631 Status
= _SEH2_GetExceptionCode();
1636 /* Setting 'break on termination' requires the SeDebugPrivilege */
1637 if (!SeSinglePrivilegeCheck(SeDebugPrivilege
, PreviousMode
))
1639 /* We don't hold the privilege, bail out */
1640 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1644 /* Set or clear the flag */
1647 PspSetProcessFlag(Process
, PSF_BREAK_ON_TERMINATION_BIT
);
1651 PspClearProcessFlag(Process
, PSF_BREAK_ON_TERMINATION_BIT
);
1656 case ProcessAffinityMask
:
1658 /* Check buffer length */
1659 if (ProcessInformationLength
!= sizeof(KAFFINITY
))
1661 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1665 /* Enter SEH for direct buffer read */
1668 Affinity
= *(PKAFFINITY
)ProcessInformation
;
1670 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1672 /* Get exception code */
1674 Status
= _SEH2_GetExceptionCode();
1679 /* Make sure it's valid for the CPUs present */
1680 ValidAffinity
= Affinity
& KeActiveProcessors
;
1681 if (!Affinity
|| (ValidAffinity
!= Affinity
))
1683 Status
= STATUS_INVALID_PARAMETER
;
1687 /* Check if it's within job affinity limits */
1690 /* Not yet implemented */
1692 Status
= STATUS_NOT_IMPLEMENTED
;
1696 /* Make sure the process isn't dying */
1697 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1700 KeEnterCriticalRegion();
1701 ExAcquirePushLockShared(&Process
->ProcessLock
);
1703 /* Call Ke to do the work */
1704 KeSetAffinityProcess(&Process
->Pcb
, ValidAffinity
);
1706 /* Release the lock and rundown */
1707 ExReleasePushLockShared(&Process
->ProcessLock
);
1708 KeLeaveCriticalRegion();
1709 ExReleaseRundownProtection(&Process
->RundownProtect
);
1711 /* Set success code */
1712 Status
= STATUS_SUCCESS
;
1716 /* Avoid race conditions */
1717 Status
= STATUS_PROCESS_IS_TERMINATING
;
1721 /* Priority Boosting status */
1722 case ProcessPriorityBoost
:
1724 /* Validate input length */
1725 if (ProcessInformationLength
!= sizeof(ULONG
))
1727 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1731 /* Enter SEH for direct buffer read */
1734 DisableBoost
= *(PBOOLEAN
)ProcessInformation
;
1736 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1738 /* Get exception code */
1740 Status
= _SEH2_GetExceptionCode();
1745 /* Make sure the process isn't dying */
1746 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1749 KeEnterCriticalRegion();
1750 ExAcquirePushLockShared(&Process
->ProcessLock
);
1752 /* Call Ke to do the work */
1753 KeSetDisableBoostProcess(&Process
->Pcb
, DisableBoost
);
1755 /* Loop the threads too */
1756 for (Next
= Process
->ThreadListHead
.Flink
;
1757 Next
!= &Process
->ThreadListHead
;
1760 /* Call Ke for the thread */
1761 Thread
= CONTAINING_RECORD(Next
, ETHREAD
, ThreadListEntry
);
1762 KeSetDisableBoostThread(&Thread
->Tcb
, DisableBoost
);
1765 /* Release the lock and rundown */
1766 ExReleasePushLockShared(&Process
->ProcessLock
);
1767 KeLeaveCriticalRegion();
1768 ExReleaseRundownProtection(&Process
->RundownProtect
);
1770 /* Set success code */
1771 Status
= STATUS_SUCCESS
;
1775 /* Avoid race conditions */
1776 Status
= STATUS_PROCESS_IS_TERMINATING
;
1780 case ProcessDebugFlags
:
1782 /* Check buffer length */
1783 if (ProcessInformationLength
!= sizeof(ULONG
))
1785 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1789 /* Enter SEH for direct buffer read */
1792 DebugFlags
= *(PULONG
)ProcessInformation
;
1794 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1796 /* Get exception code */
1797 Status
= _SEH2_GetExceptionCode();
1803 if (DebugFlags
& ~1)
1805 Status
= STATUS_INVALID_PARAMETER
;
1811 PspClearProcessFlag(Process
, PSF_NO_DEBUG_INHERIT_BIT
);
1815 PspSetProcessFlag(Process
, PSF_NO_DEBUG_INHERIT_BIT
);
1820 Status
= STATUS_SUCCESS
;
1823 case ProcessEnableAlignmentFaultFixup
:
1825 /* Check buffer length */
1826 if (ProcessInformationLength
!= sizeof(ULONG
))
1828 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1832 /* Enter SEH for direct buffer read */
1835 EnableFixup
= *(PULONG
)ProcessInformation
;
1837 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1839 /* Get exception code */
1840 Status
= _SEH2_GetExceptionCode();
1848 Process
->DefaultHardErrorProcessing
|= SEM_NOALIGNMENTFAULTEXCEPT
;
1852 Process
->DefaultHardErrorProcessing
&= ~SEM_NOALIGNMENTFAULTEXCEPT
;
1855 /* Call Ke for the update */
1856 KeSetAutoAlignmentProcess(&Process
->Pcb
, FALSE
);
1857 Status
= STATUS_SUCCESS
;
1860 case ProcessUserModeIOPL
:
1862 /* Only TCB can do this */
1863 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
1865 /* We don't hold the privilege, bail out */
1866 DPRINT1("Need TCB to set IOPL\n");
1867 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1871 /* Only supported on x86 */
1875 Status
= STATUS_NOT_IMPLEMENTED
;
1880 case ProcessExecuteFlags
:
1882 /* Check buffer length */
1883 if (ProcessInformationLength
!= sizeof(ULONG
))
1885 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1889 if (ProcessHandle
!= NtCurrentProcess())
1891 Status
= STATUS_INVALID_PARAMETER
;
1895 /* Enter SEH for direct buffer read */
1898 NoExecute
= *(PULONG
)ProcessInformation
;
1900 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1902 /* Get exception code */
1903 Status
= _SEH2_GetExceptionCode();
1908 /* Call Mm for the update */
1909 Status
= MmSetExecuteOptions(NoExecute
);
1912 /* We currently don't implement any of these */
1913 case ProcessLdtInformation
:
1914 case ProcessLdtSize
:
1915 case ProcessIoPortHandlers
:
1916 DPRINT1("VDM/16-bit Request not implemented: %lx\n", ProcessInformationClass
);
1917 Status
= STATUS_NOT_IMPLEMENTED
;
1920 case ProcessQuotaLimits
:
1922 Status
= PspSetQuotaLimits(Process
,
1925 ProcessInformationLength
,
1929 case ProcessWorkingSetWatch
:
1930 DPRINT1("WS watch not implemented\n");
1931 Status
= STATUS_NOT_IMPLEMENTED
;
1934 case ProcessDeviceMap
:
1935 DPRINT1("Device map not implemented\n");
1936 Status
= STATUS_NOT_IMPLEMENTED
;
1939 case ProcessHandleTracing
:
1940 DPRINT1("Handle tracing not implemented\n");
1941 Status
= STATUS_NOT_IMPLEMENTED
;
1944 /* Anything else is invalid */
1946 DPRINT1("Invalid Server 2003 Info Class: %lx\n", ProcessInformationClass
);
1947 Status
= STATUS_INVALID_INFO_CLASS
;
1950 /* Dereference and return status */
1951 ObDereferenceObject(Process
);
1960 NtSetInformationThread(IN HANDLE ThreadHandle
,
1961 IN THREADINFOCLASS ThreadInformationClass
,
1962 IN PVOID ThreadInformation
,
1963 IN ULONG ThreadInformationLength
)
1967 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1969 HANDLE TokenHandle
= NULL
;
1970 KPRIORITY Priority
= 0;
1971 KAFFINITY Affinity
= 0, CombinedAffinity
;
1972 PVOID Address
= NULL
;
1974 ULONG_PTR DisableBoost
= 0;
1975 ULONG_PTR IdealProcessor
= 0;
1976 ULONG_PTR Break
= 0;
1978 ULONG_PTR TlsIndex
= 0;
1979 PVOID
*ExpansionSlots
;
1980 PETHREAD ProcThread
;
1983 /* Verify Information Class validity */
1985 Status
= DefaultSetInfoBufferCheck(ThreadInformationClass
,
1987 RTL_NUMBER_OF(PsThreadInfoClass
),
1989 ThreadInformationLength
,
1991 if (!NT_SUCCESS(Status
)) return Status
;
1994 /* Check what class this is */
1995 Access
= THREAD_SET_INFORMATION
;
1996 if (ThreadInformationClass
== ThreadImpersonationToken
)
1998 /* Setting the impersonation token needs a special mask */
1999 Access
= THREAD_SET_THREAD_TOKEN
;
2002 /* Reference the thread */
2003 Status
= ObReferenceObjectByHandle(ThreadHandle
,
2009 if (!NT_SUCCESS(Status
)) return Status
;
2011 /* Check what kind of information class this is */
2012 switch (ThreadInformationClass
)
2014 /* Thread priority */
2015 case ThreadPriority
:
2017 /* Check buffer length */
2018 if (ThreadInformationLength
!= sizeof(KPRIORITY
))
2020 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2024 /* Use SEH for capture */
2027 /* Get the priority */
2028 Priority
= *(PLONG
)ThreadInformation
;
2030 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2032 /* Get the exception code */
2033 Status
= _SEH2_GetExceptionCode();
2039 if ((Priority
> HIGH_PRIORITY
) ||
2040 (Priority
<= LOW_PRIORITY
))
2043 Status
= STATUS_INVALID_PARAMETER
;
2047 /* Set the priority */
2048 KeSetPriorityThread(&Thread
->Tcb
, Priority
);
2051 case ThreadBasePriority
:
2053 /* Check buffer length */
2054 if (ThreadInformationLength
!= sizeof(LONG
))
2056 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2060 /* Use SEH for capture */
2063 /* Get the priority */
2064 Priority
= *(PLONG
)ThreadInformation
;
2066 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2068 /* Get the exception code */
2069 Status
= _SEH2_GetExceptionCode();
2075 if ((Priority
> THREAD_BASE_PRIORITY_MAX
) ||
2076 (Priority
< THREAD_BASE_PRIORITY_MIN
))
2078 /* These ones are OK */
2079 if ((Priority
!= THREAD_BASE_PRIORITY_LOWRT
+ 1) &&
2080 (Priority
!= THREAD_BASE_PRIORITY_IDLE
- 1))
2082 /* Check if the process is real time */
2083 if (PsGetCurrentProcess()->PriorityClass
!=
2084 PROCESS_PRIORITY_CLASS_REALTIME
)
2086 /* It isn't, fail */
2087 Status
= STATUS_INVALID_PARAMETER
;
2093 /* Set the base priority */
2094 KeSetBasePriorityThread(&Thread
->Tcb
, Priority
);
2097 case ThreadAffinityMask
:
2099 /* Check buffer length */
2100 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
2102 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2106 /* Use SEH for capture */
2109 /* Get the priority */
2110 Affinity
= *(PULONG_PTR
)ThreadInformation
;
2112 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2114 /* Get the exception code */
2115 Status
= _SEH2_GetExceptionCode();
2124 Status
= STATUS_INVALID_PARAMETER
;
2128 /* Get the process */
2129 Process
= Thread
->ThreadsProcess
;
2131 /* Try to acquire rundown */
2132 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
2135 KeEnterCriticalRegion();
2136 ExAcquirePushLockShared(&Process
->ProcessLock
);
2139 CombinedAffinity
= Affinity
& Process
->Pcb
.Affinity
;
2140 if (CombinedAffinity
!= Affinity
)
2143 Status
= STATUS_INVALID_PARAMETER
;
2147 /* Set the affinity */
2148 KeSetAffinityThread(&Thread
->Tcb
, CombinedAffinity
);
2151 /* Release the lock and rundown */
2152 ExReleasePushLockShared(&Process
->ProcessLock
);
2153 KeLeaveCriticalRegion();
2154 ExReleaseRundownProtection(&Process
->RundownProtect
);
2159 Status
= STATUS_PROCESS_IS_TERMINATING
;
2165 case ThreadImpersonationToken
:
2167 /* Check buffer length */
2168 if (ThreadInformationLength
!= sizeof(HANDLE
))
2170 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2174 /* Use SEH for capture */
2177 /* Save the token handle */
2178 TokenHandle
= *(PHANDLE
)ThreadInformation
;
2180 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2182 /* Get the exception code */
2183 Status
= _SEH2_GetExceptionCode();
2188 /* Assign the actual token */
2189 Status
= PsAssignImpersonationToken(Thread
, TokenHandle
);
2192 case ThreadQuerySetWin32StartAddress
:
2194 /* Check buffer length */
2195 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
2197 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2201 /* Use SEH for capture */
2204 /* Get the priority */
2205 Address
= *(PVOID
*)ThreadInformation
;
2207 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2209 /* Get the exception code */
2210 Status
= _SEH2_GetExceptionCode();
2215 /* Set the address */
2216 Thread
->Win32StartAddress
= Address
;
2219 case ThreadIdealProcessor
:
2221 /* Check buffer length */
2222 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
2224 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2228 /* Use SEH for capture */
2231 /* Get the priority */
2232 IdealProcessor
= *(PULONG_PTR
)ThreadInformation
;
2234 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2236 /* Get the exception code */
2237 Status
= _SEH2_GetExceptionCode();
2243 if (IdealProcessor
> MAXIMUM_PROCESSORS
)
2246 Status
= STATUS_INVALID_PARAMETER
;
2251 Status
= KeSetIdealProcessorThread(&Thread
->Tcb
,
2252 (CCHAR
)IdealProcessor
);
2254 /* Get the TEB and protect the thread */
2255 Teb
= Thread
->Tcb
.Teb
;
2256 if ((Teb
) && (ExAcquireRundownProtection(&Thread
->RundownProtect
)))
2258 /* Save the ideal processor */
2259 Teb
->IdealProcessor
= Thread
->Tcb
.IdealProcessor
;
2261 /* Release rundown protection */
2262 ExReleaseRundownProtection(&Thread
->RundownProtect
);
2267 case ThreadPriorityBoost
:
2269 /* Check buffer length */
2270 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
2272 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2276 /* Use SEH for capture */
2279 /* Get the priority */
2280 DisableBoost
= *(PULONG_PTR
)ThreadInformation
;
2282 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2284 /* Get the exception code */
2285 Status
= _SEH2_GetExceptionCode();
2290 /* Call the kernel */
2291 KeSetDisableBoostThread(&Thread
->Tcb
, (BOOLEAN
)DisableBoost
);
2294 case ThreadZeroTlsCell
:
2296 /* Check buffer length */
2297 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
2299 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2303 /* Use SEH for capture */
2306 /* Get the priority */
2307 TlsIndex
= *(PULONG_PTR
)ThreadInformation
;
2309 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2311 /* Get the exception code */
2312 Status
= _SEH2_GetExceptionCode();
2317 /* This is only valid for the current thread */
2318 if (Thread
!= PsGetCurrentThread())
2321 Status
= STATUS_INVALID_PARAMETER
;
2325 /* Get the process */
2326 Process
= Thread
->ThreadsProcess
;
2328 /* Loop the threads */
2329 ProcThread
= PsGetNextProcessThread(Process
, NULL
);
2332 /* Acquire rundown */
2333 if (ExAcquireRundownProtection(&ProcThread
->RundownProtect
))
2336 Teb
= ProcThread
->Tcb
.Teb
;
2339 /* Check if we're in the expansion range */
2340 if (TlsIndex
> TLS_MINIMUM_AVAILABLE
- 1)
2342 if (TlsIndex
< (TLS_MINIMUM_AVAILABLE
+
2343 TLS_EXPANSION_SLOTS
) - 1)
2345 /* Check if we have expansion slots */
2346 ExpansionSlots
= Teb
->TlsExpansionSlots
;
2349 /* Clear the index */
2350 ExpansionSlots
[TlsIndex
- TLS_MINIMUM_AVAILABLE
] = 0;
2356 /* Clear the index */
2357 Teb
->TlsSlots
[TlsIndex
] = NULL
;
2361 /* Release rundown */
2362 ExReleaseRundownProtection(&ProcThread
->RundownProtect
);
2365 /* Go to the next thread */
2366 ProcThread
= PsGetNextProcessThread(Process
, ProcThread
);
2372 case ThreadBreakOnTermination
:
2374 /* Check buffer length */
2375 if (ThreadInformationLength
!= sizeof(ULONG
))
2377 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2381 /* Enter SEH for direct buffer read */
2384 Break
= *(PULONG
)ThreadInformation
;
2386 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2388 /* Get exception code */
2390 Status
= _SEH2_GetExceptionCode();
2395 /* Setting 'break on termination' requires the SeDebugPrivilege */
2396 if (!SeSinglePrivilegeCheck(SeDebugPrivilege
, PreviousMode
))
2398 /* We don't hold the privilege, bail out */
2399 Status
= STATUS_PRIVILEGE_NOT_HELD
;
2403 /* Set or clear the flag */
2406 PspSetCrossThreadFlag(Thread
, CT_BREAK_ON_TERMINATION_BIT
);
2410 PspClearCrossThreadFlag(Thread
, CT_BREAK_ON_TERMINATION_BIT
);
2415 /* We don't implement it yet */
2416 DPRINT1("Not implemented: %d\n", ThreadInformationClass
);
2417 Status
= STATUS_NOT_IMPLEMENTED
;
2420 /* Dereference and return status */
2421 ObDereferenceObject(Thread
);
2430 NtQueryInformationThread(IN HANDLE ThreadHandle
,
2431 IN THREADINFOCLASS ThreadInformationClass
,
2432 OUT PVOID ThreadInformation
,
2433 IN ULONG ThreadInformationLength
,
2434 OUT PULONG ReturnLength OPTIONAL
)
2437 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2441 PTHREAD_BASIC_INFORMATION ThreadBasicInfo
=
2442 (PTHREAD_BASIC_INFORMATION
)ThreadInformation
;
2443 PKERNEL_USER_TIMES ThreadTime
= (PKERNEL_USER_TIMES
)ThreadInformation
;
2445 ULONG ThreadTerminated
;
2448 /* Check if we were called from user mode */
2449 if (PreviousMode
!= KernelMode
)
2454 /* Probe the buffer */
2455 ProbeForWrite(ThreadInformation
,
2456 ThreadInformationLength
,
2459 /* Probe the return length if required */
2460 if (ReturnLength
) ProbeForWriteUlong(ReturnLength
);
2462 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2464 /* Return the exception code */
2465 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2470 /* Check what class this is */
2471 Access
= THREAD_QUERY_INFORMATION
;
2473 /* Reference the process */
2474 Status
= ObReferenceObjectByHandle(ThreadHandle
,
2480 if (!NT_SUCCESS(Status
)) return Status
;
2482 /* Check what kind of information class this is */
2483 switch (ThreadInformationClass
)
2485 /* Basic thread information */
2486 case ThreadBasicInformation
:
2488 /* Set return length */
2489 Length
= sizeof(THREAD_BASIC_INFORMATION
);
2491 if (ThreadInformationLength
!= Length
)
2493 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2496 /* Protect writes with SEH */
2499 /* Write all the information from the ETHREAD/KTHREAD */
2500 ThreadBasicInfo
->ExitStatus
= Thread
->ExitStatus
;
2501 ThreadBasicInfo
->TebBaseAddress
= (PVOID
)Thread
->Tcb
.Teb
;
2502 ThreadBasicInfo
->ClientId
= Thread
->Cid
;
2503 ThreadBasicInfo
->AffinityMask
= Thread
->Tcb
.Affinity
;
2504 ThreadBasicInfo
->Priority
= Thread
->Tcb
.Priority
;
2505 ThreadBasicInfo
->BasePriority
= KeQueryBasePriorityThread(&Thread
->Tcb
);
2507 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2509 /* Get exception code */
2510 Status
= _SEH2_GetExceptionCode();
2515 /* Thread time information */
2518 /* Set the return length */
2519 Length
= sizeof(KERNEL_USER_TIMES
);
2521 if (ThreadInformationLength
!= Length
)
2523 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2526 /* Protect writes with SEH */
2529 /* Copy time information from ETHREAD/KTHREAD */
2530 ThreadTime
->KernelTime
.QuadPart
= Thread
->Tcb
.KernelTime
* KeMaximumIncrement
;
2531 ThreadTime
->UserTime
.QuadPart
= Thread
->Tcb
.UserTime
* KeMaximumIncrement
;
2532 ThreadTime
->CreateTime
= Thread
->CreateTime
;
2534 /* Exit time is in a union and only valid on actual exit! */
2535 if (KeReadStateThread(&Thread
->Tcb
))
2537 ThreadTime
->ExitTime
= Thread
->ExitTime
;
2541 ThreadTime
->ExitTime
.QuadPart
= 0;
2544 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2546 /* Get exception code */
2547 Status
= _SEH2_GetExceptionCode();
2552 case ThreadQuerySetWin32StartAddress
:
2554 /* Set the return length*/
2555 Length
= sizeof(PVOID
);
2557 if (ThreadInformationLength
!= Length
)
2559 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2562 /* Protect write with SEH */
2565 /* Return the Win32 Start Address */
2566 *(PVOID
*)ThreadInformation
= Thread
->Win32StartAddress
;
2568 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2570 /* Get exception code */
2571 Status
= _SEH2_GetExceptionCode();
2576 case ThreadPerformanceCount
:
2578 /* Set the return length*/
2579 Length
= sizeof(LARGE_INTEGER
);
2581 if (ThreadInformationLength
!= Length
)
2583 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2586 /* Protect write with SEH */
2590 (*(PLARGE_INTEGER
)ThreadInformation
).QuadPart
= 0;
2592 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2594 /* Get exception code */
2595 Status
= _SEH2_GetExceptionCode();
2600 case ThreadAmILastThread
:
2602 /* Set the return length*/
2603 Length
= sizeof(ULONG
);
2605 if (ThreadInformationLength
!= Length
)
2607 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2610 /* Protect write with SEH */
2613 /* Return whether or not we are the last thread */
2614 *(PULONG
)ThreadInformation
= ((Thread
->ThreadsProcess
->
2615 ThreadListHead
.Flink
->Flink
==
2616 &Thread
->ThreadsProcess
->
2620 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2622 /* Get exception code */
2623 Status
= _SEH2_GetExceptionCode();
2628 case ThreadIsIoPending
:
2630 /* Set the return length*/
2631 Length
= sizeof(ULONG
);
2633 if (ThreadInformationLength
!= Length
)
2635 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2638 /* Raise the IRQL to protect the IRP list */
2639 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2641 /* Protect write with SEH */
2644 /* Check if the IRP list is empty or not */
2645 *(PULONG
)ThreadInformation
= !IsListEmpty(&Thread
->IrpList
);
2647 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2649 /* Get exception code */
2650 Status
= _SEH2_GetExceptionCode();
2654 /* Lower IRQL back */
2655 KeLowerIrql(OldIrql
);
2658 /* LDT and GDT information */
2659 case ThreadDescriptorTableEntry
:
2662 /* Call the worker routine */
2663 Status
= PspQueryDescriptorThread(Thread
,
2665 ThreadInformationLength
,
2668 /* Only implemented on x86 */
2669 Status
= STATUS_NOT_IMPLEMENTED
;
2673 case ThreadPriorityBoost
:
2675 /* Set the return length*/
2676 Length
= sizeof(ULONG
);
2678 if (ThreadInformationLength
!= Length
)
2680 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2686 *(PULONG
)ThreadInformation
= Thread
->Tcb
.DisableBoost
? 1 : 0;
2688 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2690 Status
= _SEH2_GetExceptionCode();
2695 case ThreadIsTerminated
:
2697 /* Set the return length*/
2698 Length
= sizeof(ThreadTerminated
);
2700 if (ThreadInformationLength
!= Length
)
2702 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2706 ThreadTerminated
= PsIsThreadTerminating(Thread
);
2710 *(PULONG
)ThreadInformation
= ThreadTerminated
? 1 : 0;
2712 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2714 Status
= _SEH2_GetExceptionCode();
2723 /* Not yet implemented */
2724 DPRINT1("Not implemented: %lx\n", ThreadInformationClass
);
2725 Status
= STATUS_NOT_IMPLEMENTED
;
2728 /* Protect write with SEH */
2731 /* Check if caller wanted return length */
2732 if (ReturnLength
) *ReturnLength
= Length
;
2734 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2736 /* Get exception code */
2737 Status
= _SEH2_GetExceptionCode();
2741 /* Dereference the thread, and return */
2742 ObDereferenceObject(Thread
);