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
20 /* Include Information Class Tables */
21 #include "internal/ps_i.h"
24 ULONG PspTraceLevel
= 0;
26 /* PRIVATE FUNCTIONS *********************************************************/
30 PsReferenceProcessFilePointer(IN PEPROCESS Process
,
31 OUT PFILE_OBJECT
*FileObject
)
36 /* Lock the process */
37 ExAcquireRundownProtection(&Process
->RundownProtect
);
40 Section
= Process
->SectionObject
;
43 /* Get the file object and reference it */
44 *FileObject
= MmGetFileObjectForSection((PVOID
)Section
);
45 ObReferenceObject(*FileObject
);
48 /* Release the protection */
49 ExReleaseRundownProtection(&Process
->RundownProtect
);
52 return Section
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
;
55 /* PUBLIC FUNCTIONS **********************************************************/
62 NtQueryInformationProcess(IN HANDLE ProcessHandle
,
63 IN PROCESSINFOCLASS ProcessInformationClass
,
64 OUT PVOID ProcessInformation
,
65 IN ULONG ProcessInformationLength
,
66 OUT PULONG ReturnLength OPTIONAL
)
69 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
73 PPROCESS_BASIC_INFORMATION ProcessBasicInfo
=
74 (PPROCESS_BASIC_INFORMATION
)ProcessInformation
;
75 PKERNEL_USER_TIMES ProcessTime
= (PKERNEL_USER_TIMES
)ProcessInformation
;
76 PPROCESS_PRIORITY_CLASS PsPriorityClass
= (PPROCESS_PRIORITY_CLASS
)ProcessInformation
;
78 PPROCESS_SESSION_INFORMATION SessionInfo
=
79 (PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
80 PVM_COUNTERS VmCounters
= (PVM_COUNTERS
)ProcessInformation
;
81 PIO_COUNTERS IoCounters
= (PIO_COUNTERS
)ProcessInformation
;
82 PQUOTA_LIMITS QuotaLimits
= (PQUOTA_LIMITS
)ProcessInformation
;
83 PROCESS_DEVICEMAP_INFORMATION DeviceMap
;
84 PUNICODE_STRING ImageName
;
85 ULONG Cookie
, ExecuteOptions
= 0;
89 /* Check for user-mode caller */
90 if (PreviousMode
!= KernelMode
)
92 /* Prepare to probe parameters */
95 /* Probe the buffer */
96 ProbeForWrite(ProcessInformation
,
97 ProcessInformationLength
,
100 /* Probe the return length if required */
101 if (ReturnLength
) ProbeForWriteUlong(ReturnLength
);
103 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
105 /* Return the exception code */
106 _SEH2_YIELD(return _SEH2_GetExceptionCode());
111 if((ProcessInformationClass
== ProcessCookie
) &&
112 (ProcessHandle
!= NtCurrentProcess()))
115 * Retreiving the process cookie is only allowed for the calling process
116 * itself! XP only allowes NtCurrentProcess() as process handles even if
117 * a real handle actually represents the current process.
119 return STATUS_INVALID_PARAMETER
;
122 /* Check the information class */
123 switch (ProcessInformationClass
)
125 /* Basic process information */
126 case ProcessBasicInformation
:
128 /* Set return length */
129 Length
= sizeof(PROCESS_BASIC_INFORMATION
);
131 if (ProcessInformationLength
!= Length
)
133 Status
= STATUS_INFO_LENGTH_MISMATCH
;
137 /* Reference the process */
138 Status
= ObReferenceObjectByHandle(ProcessHandle
,
139 PROCESS_QUERY_INFORMATION
,
144 if (!NT_SUCCESS(Status
)) break;
146 /* Protect writes with SEH */
149 /* Write all the information from the EPROCESS/KPROCESS */
150 ProcessBasicInfo
->ExitStatus
= Process
->ExitStatus
;
151 ProcessBasicInfo
->PebBaseAddress
= Process
->Peb
;
152 ProcessBasicInfo
->AffinityMask
= Process
->Pcb
.Affinity
;
153 ProcessBasicInfo
->UniqueProcessId
= (ULONG_PTR
)Process
->
155 ProcessBasicInfo
->InheritedFromUniqueProcessId
=
156 (ULONG
)Process
->InheritedFromUniqueProcessId
;
157 ProcessBasicInfo
->BasePriority
= Process
->Pcb
.BasePriority
;
160 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
162 /* Get exception code */
163 Status
= _SEH2_GetExceptionCode();
167 /* Dereference the process */
168 ObDereferenceObject(Process
);
171 /* Process quota limits */
172 case ProcessQuotaLimits
:
174 Length
= sizeof(QUOTA_LIMITS
);
175 if (ProcessInformationLength
!= Length
)
177 Status
= STATUS_INFO_LENGTH_MISMATCH
;
181 /* Reference the process */
182 Status
= ObReferenceObjectByHandle(ProcessHandle
,
183 PROCESS_QUERY_INFORMATION
,
188 if (!NT_SUCCESS(Status
)) break;
190 /* Indicate success */
191 Status
= STATUS_SUCCESS
;
195 /* Set max/min working set sizes */
196 QuotaLimits
->MaximumWorkingSetSize
=
197 Process
->Vm
.MaximumWorkingSetSize
<< PAGE_SHIFT
;
198 QuotaLimits
->MinimumWorkingSetSize
=
199 Process
->Vm
.MinimumWorkingSetSize
<< PAGE_SHIFT
;
201 /* Set default time limits */
202 QuotaLimits
->TimeLimit
.LowPart
= MAXULONG
;
203 QuotaLimits
->TimeLimit
.HighPart
= MAXULONG
;
205 /* Is quota block a default one? */
206 if (Process
->QuotaBlock
== &PspDefaultQuotaBlock
)
208 /* Set default pools and pagefile limits */
209 QuotaLimits
->PagedPoolLimit
= (SIZE_T
)-1;
210 QuotaLimits
->NonPagedPoolLimit
= (SIZE_T
)-1;
211 QuotaLimits
->PagefileLimit
= (SIZE_T
)-1;
215 /* Get limits from non-default quota block */
216 QuotaLimits
->PagedPoolLimit
=
217 Process
->QuotaBlock
->QuotaEntry
[PagedPool
].Limit
;
218 QuotaLimits
->NonPagedPoolLimit
=
219 Process
->QuotaBlock
->QuotaEntry
[NonPagedPool
].Limit
;
220 QuotaLimits
->PagefileLimit
=
221 Process
->QuotaBlock
->QuotaEntry
[2].Limit
;
224 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
226 /* Get exception code */
227 Status
= _SEH2_GetExceptionCode();
231 /* Dereference the process */
232 ObDereferenceObject(Process
);
235 case ProcessIoCounters
:
237 Length
= sizeof(IO_COUNTERS
);
238 if (ProcessInformationLength
!= Length
)
240 Status
= STATUS_INFO_LENGTH_MISMATCH
;
244 /* Reference the process */
245 Status
= ObReferenceObjectByHandle(ProcessHandle
,
246 PROCESS_QUERY_INFORMATION
,
251 if (!NT_SUCCESS(Status
)) break;
255 /* FIXME: Call KeQueryValuesProcess */
256 IoCounters
->ReadOperationCount
= Process
->ReadOperationCount
.QuadPart
;
257 IoCounters
->ReadTransferCount
= Process
->ReadTransferCount
.QuadPart
;
258 IoCounters
->WriteOperationCount
= Process
->WriteOperationCount
.QuadPart
;
259 IoCounters
->WriteTransferCount
= Process
->WriteTransferCount
.QuadPart
;
260 IoCounters
->OtherOperationCount
= Process
->OtherOperationCount
.QuadPart
;
261 IoCounters
->OtherTransferCount
= Process
->OtherTransferCount
.QuadPart
;
263 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
265 /* Ignore exception */
269 /* Set status to success in any case */
270 Status
= STATUS_SUCCESS
;
272 /* Dereference the process */
273 ObDereferenceObject(Process
);
279 /* Set the return length */
280 Length
= sizeof(KERNEL_USER_TIMES
);
282 if (ProcessInformationLength
!= Length
)
284 Status
= STATUS_INFO_LENGTH_MISMATCH
;
288 /* Reference the process */
289 Status
= ObReferenceObjectByHandle(ProcessHandle
,
290 PROCESS_QUERY_INFORMATION
,
295 if (!NT_SUCCESS(Status
)) break;
297 /* Protect writes with SEH */
300 /* Copy time information from EPROCESS/KPROCESS */
301 /* FIXME: Call KeQueryRuntimeProcess */
302 ProcessTime
->CreateTime
= Process
->CreateTime
;
303 ProcessTime
->UserTime
.QuadPart
= Process
->Pcb
.UserTime
*
305 ProcessTime
->KernelTime
.QuadPart
= Process
->Pcb
.KernelTime
*
307 ProcessTime
->ExitTime
= Process
->ExitTime
;
309 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
311 /* Get exception code */
312 Status
= _SEH2_GetExceptionCode();
316 /* Dereference the process */
317 ObDereferenceObject(Process
);
320 /* Process Debug Port */
321 case ProcessDebugPort
:
323 /* Set return length */
324 Length
= sizeof(HANDLE
);
326 if (ProcessInformationLength
!= Length
)
328 Status
= STATUS_INFO_LENGTH_MISMATCH
;
332 /* Reference the process */
333 Status
= ObReferenceObjectByHandle(ProcessHandle
,
334 PROCESS_QUERY_INFORMATION
,
339 if (!NT_SUCCESS(Status
)) break;
341 /* Protect write with SEH */
344 /* Return whether or not we have a debug port */
345 *(PHANDLE
)ProcessInformation
= (Process
->DebugPort
?
348 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
350 /* Get exception code */
351 Status
= _SEH2_GetExceptionCode();
355 /* Dereference the process */
356 ObDereferenceObject(Process
);
359 case ProcessHandleCount
:
361 /* Set the return length*/
362 Length
= sizeof(ULONG
);
364 if (ProcessInformationLength
!= Length
)
366 Status
= STATUS_INFO_LENGTH_MISMATCH
;
370 /* Reference the process */
371 Status
= ObReferenceObjectByHandle(ProcessHandle
,
372 PROCESS_QUERY_INFORMATION
,
377 if (!NT_SUCCESS(Status
)) break;
379 /* Count the number of handles this process has */
380 HandleCount
= ObGetProcessHandleCount(Process
);
382 /* Protect write in SEH */
385 /* Return the count of handles */
386 *(PULONG
)ProcessInformation
= HandleCount
;
388 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
390 /* Get the exception code */
391 Status
= _SEH2_GetExceptionCode();
395 /* Dereference the process */
396 ObDereferenceObject(Process
);
399 /* Session ID for the process */
400 case ProcessSessionInformation
:
402 /* Set the return length*/
403 Length
= sizeof(PROCESS_SESSION_INFORMATION
);
405 if (ProcessInformationLength
!= Length
)
407 Status
= STATUS_INFO_LENGTH_MISMATCH
;
411 /* Reference the process */
412 Status
= ObReferenceObjectByHandle(ProcessHandle
,
413 PROCESS_QUERY_INFORMATION
,
418 if (!NT_SUCCESS(Status
)) break;
420 /* Enter SEH for write safety */
423 /* Write back the Session ID */
424 SessionInfo
->SessionId
= PtrToUlong(PsGetProcessSessionId(Process
));
426 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
428 /* Get the exception code */
429 Status
= _SEH2_GetExceptionCode();
433 /* Dereference the process */
434 ObDereferenceObject(Process
);
437 /* Virtual Memory Statistics */
438 case ProcessVmCounters
:
440 /* Validate the input length */
441 if ((ProcessInformationLength
!= sizeof(VM_COUNTERS
)) &&
442 (ProcessInformationLength
!= sizeof(VM_COUNTERS_EX
)))
444 Status
= STATUS_INFO_LENGTH_MISMATCH
;
448 /* Reference the process */
449 Status
= ObReferenceObjectByHandle(ProcessHandle
,
450 PROCESS_QUERY_INFORMATION
,
455 if (!NT_SUCCESS(Status
)) break;
457 /* Enter SEH for write safety */
460 /* Return data from EPROCESS */
461 VmCounters
->PeakVirtualSize
= Process
->PeakVirtualSize
;
462 VmCounters
->VirtualSize
= Process
->VirtualSize
;
463 VmCounters
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
464 VmCounters
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
465 VmCounters
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
466 VmCounters
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeak
[0];
467 VmCounters
->QuotaPagedPoolUsage
= Process
->QuotaUsage
[0];
468 VmCounters
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeak
[1];
469 VmCounters
->QuotaNonPagedPoolUsage
= Process
->QuotaUsage
[1];
470 VmCounters
->PagefileUsage
= Process
->QuotaUsage
[2] << PAGE_SHIFT
;
471 VmCounters
->PeakPagefileUsage
= Process
->QuotaPeak
[2] << PAGE_SHIFT
;
472 //VmCounters->PrivateUsage = Process->CommitCharge << PAGE_SHIFT;
475 /* Set the return length */
476 Length
= ProcessInformationLength
;
478 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
480 /* Get the exception code */
481 Status
= _SEH2_GetExceptionCode();
485 /* Dereference the process */
486 ObDereferenceObject(Process
);
489 /* Hard Error Processing Mode */
490 case ProcessDefaultHardErrorMode
:
492 /* Set the return length*/
493 Length
= sizeof(ULONG
);
495 if (ProcessInformationLength
!= Length
)
497 Status
= STATUS_INFO_LENGTH_MISMATCH
;
501 /* Reference the process */
502 Status
= ObReferenceObjectByHandle(ProcessHandle
,
503 PROCESS_QUERY_INFORMATION
,
508 if (!NT_SUCCESS(Status
)) break;
510 /* Enter SEH for writing back data */
513 /* Write the current processing mode */
514 *(PULONG
)ProcessInformation
= Process
->
515 DefaultHardErrorProcessing
;
517 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
519 /* Get the exception code */
520 Status
= _SEH2_GetExceptionCode();
524 /* Dereference the process */
525 ObDereferenceObject(Process
);
528 /* Priority Boosting status */
529 case ProcessPriorityBoost
:
531 /* Set the return length */
532 Length
= sizeof(ULONG
);
534 if (ProcessInformationLength
!= Length
)
536 Status
= STATUS_INFO_LENGTH_MISMATCH
;
540 /* Reference the process */
541 Status
= ObReferenceObjectByHandle(ProcessHandle
,
542 PROCESS_QUERY_INFORMATION
,
547 if (!NT_SUCCESS(Status
)) break;
549 /* Enter SEH for writing back data */
552 /* Return boost status */
553 *(PULONG
)ProcessInformation
= Process
->Pcb
.DisableBoost
?
556 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
558 /* Get the exception code */
559 Status
= _SEH2_GetExceptionCode();
563 /* Dereference the process */
564 ObDereferenceObject(Process
);
568 case ProcessDeviceMap
:
570 /* Set the return length */
571 Length
= sizeof(PROCESS_DEVICEMAP_INFORMATION
);
573 if (ProcessInformationLength
!= Length
)
575 if (ProcessInformationLength
== sizeof(PROCESS_DEVICEMAP_INFORMATION_EX
))
577 DPRINT1("PROCESS_DEVICEMAP_INFORMATION_EX not supported!\n");
578 Status
= STATUS_NOT_IMPLEMENTED
;
582 Status
= STATUS_INFO_LENGTH_MISMATCH
;
587 /* Reference the process */
588 Status
= ObReferenceObjectByHandle(ProcessHandle
,
589 PROCESS_QUERY_INFORMATION
,
594 if (!NT_SUCCESS(Status
)) break;
596 /* Query the device map information */
597 ObQueryDeviceMapInformation(Process
, &DeviceMap
);
599 /* Enter SEH for writing back data */
602 *(PPROCESS_DEVICEMAP_INFORMATION
)ProcessInformation
= DeviceMap
;
604 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
606 /* Get the exception code */
607 Status
= _SEH2_GetExceptionCode();
611 /* Dereference the process */
612 ObDereferenceObject(Process
);
616 case ProcessPriorityClass
:
618 /* Set the return length*/
619 Length
= sizeof(PROCESS_PRIORITY_CLASS
);
621 if (ProcessInformationLength
!= Length
)
623 Status
= STATUS_INFO_LENGTH_MISMATCH
;
627 /* Reference the process */
628 Status
= ObReferenceObjectByHandle(ProcessHandle
,
629 PROCESS_QUERY_INFORMATION
,
634 if (!NT_SUCCESS(Status
)) break;
636 /* Enter SEH for writing back data */
639 /* Return current priority class */
640 PsPriorityClass
->PriorityClass
= Process
->PriorityClass
;
641 PsPriorityClass
->Foreground
= FALSE
;
643 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
645 /* Get the exception code */
646 Status
= _SEH2_GetExceptionCode();
650 /* Dereference the process */
651 ObDereferenceObject(Process
);
654 case ProcessImageFileName
:
656 /* Reference the process */
657 Status
= ObReferenceObjectByHandle(ProcessHandle
,
658 PROCESS_QUERY_INFORMATION
,
663 if (!NT_SUCCESS(Status
)) break;
665 /* Get the image path */
666 Status
= SeLocateProcessImageName(Process
, &ImageName
);
667 if (NT_SUCCESS(Status
))
669 /* Set return length */
670 Length
= ImageName
->MaximumLength
+
671 sizeof(OBJECT_NAME_INFORMATION
);
673 /* Make sure it's large enough */
674 if (Length
<= ProcessInformationLength
)
676 /* Enter SEH to protect write */
680 RtlCopyMemory(ProcessInformation
,
685 ((PUNICODE_STRING
)ProcessInformation
)->Buffer
=
686 (PWSTR
)((PUNICODE_STRING
)ProcessInformation
+ 1);
688 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
690 /* Get the exception code */
691 Status
= _SEH2_GetExceptionCode();
697 /* Buffer too small */
698 Status
= STATUS_INFO_LENGTH_MISMATCH
;
701 /* Free the image path */
702 ExFreePoolWithTag(ImageName
, TAG_SEPA
);
704 /* Dereference the process */
705 ObDereferenceObject(Process
);
708 case ProcessDebugFlags
:
710 /* Set the return length*/
711 Length
= sizeof(ULONG
);
712 if (ProcessInformationLength
!= Length
)
714 Status
= STATUS_INFO_LENGTH_MISMATCH
;
718 /* Reference the process */
719 Status
= ObReferenceObjectByHandle(ProcessHandle
,
720 PROCESS_QUERY_INFORMATION
,
725 if (!NT_SUCCESS(Status
)) break;
727 /* Enter SEH for writing back data */
730 /* Return the debug flag state */
731 *(PULONG
)ProcessInformation
= Process
->NoDebugInherit
? 0 : 1;
733 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
735 /* Get the exception code */
736 Status
= _SEH2_GetExceptionCode();
740 /* Dereference the process */
741 ObDereferenceObject(Process
);
744 case ProcessBreakOnTermination
:
746 /* Set the return length*/
747 Length
= sizeof(ULONG
);
748 if (ProcessInformationLength
!= Length
)
750 Status
= STATUS_INFO_LENGTH_MISMATCH
;
754 /* Reference the process */
755 Status
= ObReferenceObjectByHandle(ProcessHandle
,
756 PROCESS_QUERY_INFORMATION
,
761 if (!NT_SUCCESS(Status
)) break;
763 /* Enter SEH for writing back data */
766 /* Return the BreakOnTermination state */
767 *(PULONG
)ProcessInformation
= Process
->BreakOnTermination
;
769 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
771 /* Get the exception code */
772 Status
= _SEH2_GetExceptionCode();
776 /* Dereference the process */
777 ObDereferenceObject(Process
);
780 /* Per-process security cookie */
783 /* Get the current process and cookie */
784 Process
= PsGetCurrentProcess();
785 Cookie
= Process
->Cookie
;
788 LARGE_INTEGER SystemTime
;
792 /* Generate a new cookie */
793 KeQuerySystemTime(&SystemTime
);
794 Prcb
= KeGetCurrentPrcb();
795 NewCookie
= Prcb
->KeSystemCalls
^ Prcb
->InterruptTime
^
796 SystemTime
.u
.LowPart
^ SystemTime
.u
.HighPart
;
798 /* Set the new cookie or return the current one */
799 Cookie
= InterlockedCompareExchange((LONG
*)&Process
->Cookie
,
802 if (!Cookie
) Cookie
= NewCookie
;
804 /* Set return length */
805 Length
= sizeof(ULONG
);
808 /* Indicate success */
809 Status
= STATUS_SUCCESS
;
811 /* Enter SEH to protect write */
814 /* Write back the cookie */
815 *(PULONG
)ProcessInformation
= Cookie
;
817 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
819 /* Get the exception code */
820 Status
= _SEH2_GetExceptionCode();
825 case ProcessImageInformation
:
826 DPRINT1("Image Information Query Not implemented: %lx\n", ProcessInformationClass
);
827 Status
= STATUS_NOT_IMPLEMENTED
;
830 case ProcessDebugObjectHandle
:
832 /* Set the return length */
833 Length
= sizeof(HANDLE
);
834 if (ProcessInformationLength
!= Length
)
836 Status
= STATUS_INFO_LENGTH_MISMATCH
;
840 /* Reference the process */
841 Status
= ObReferenceObjectByHandle(ProcessHandle
,
842 PROCESS_QUERY_INFORMATION
,
847 if (!NT_SUCCESS(Status
)) break;
849 /* Get the debug port */
850 Status
= DbgkOpenProcessDebugPort(Process
, PreviousMode
, &DebugPort
);
852 /* Let go of the process */
853 ObDereferenceObject(Process
);
855 /* Protect write in SEH */
858 /* Return debug port's handle */
859 *(PHANDLE
)ProcessInformation
= DebugPort
;
861 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
863 /* Get the exception code */
864 Status
= _SEH2_GetExceptionCode();
869 case ProcessHandleTracing
:
870 DPRINT1("Handle tracing Not implemented: %lx\n", ProcessInformationClass
);
871 Status
= STATUS_NOT_IMPLEMENTED
;
874 case ProcessLUIDDeviceMapsEnabled
:
876 /* Set the return length */
877 Length
= sizeof(ULONG
);
878 if (ProcessInformationLength
!= Length
)
880 Status
= STATUS_INFO_LENGTH_MISMATCH
;
884 /* Indicate success */
885 Status
= STATUS_SUCCESS
;
887 /* Protect write in SEH */
890 /* Return FALSE -- we don't support this */
891 *(PULONG
)ProcessInformation
= FALSE
;
893 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
895 /* Get the exception code */
896 Status
= _SEH2_GetExceptionCode();
901 case ProcessWx86Information
:
903 /* Set the return length */
904 Length
= sizeof(ULONG
);
905 if (ProcessInformationLength
!= Length
)
907 Status
= STATUS_INFO_LENGTH_MISMATCH
;
911 /* Reference the process */
912 Status
= ObReferenceObjectByHandle(ProcessHandle
,
913 PROCESS_QUERY_INFORMATION
,
918 if (!NT_SUCCESS(Status
)) break;
920 /* Protect write in SEH */
923 /* Return if the flag is set */
924 *(PULONG
)ProcessInformation
= (ULONG
)Process
->VdmAllowed
;
926 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
928 /* Get the exception code */
929 Status
= _SEH2_GetExceptionCode();
933 /* Dereference the process */
934 ObDereferenceObject(Process
);
937 case ProcessWow64Information
:
939 /* Set return length */
940 Length
= sizeof(ULONG_PTR
);
941 if (ProcessInformationLength
!= Length
)
943 Status
= STATUS_INFO_LENGTH_MISMATCH
;
947 /* Reference the process */
948 Status
= ObReferenceObjectByHandle(ProcessHandle
,
949 PROCESS_QUERY_INFORMATION
,
954 if (!NT_SUCCESS(Status
)) break;
956 /* Make sure the process isn't dying */
957 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
959 /* Get the WOW64 process structure */
961 Wow64
= (ULONG_PTR
)Process
->Wow64Process
;
965 /* Release the lock */
966 ExReleaseRundownProtection(&Process
->RundownProtect
);
969 /* Protect write with SEH */
972 /* Return whether or not we have a debug port */
973 *(PULONG_PTR
)ProcessInformation
= Wow64
;
975 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
977 /* Get exception code */
978 Status
= _SEH2_GetExceptionCode();
982 /* Dereference the process */
983 ObDereferenceObject(Process
);
986 case ProcessExecuteFlags
:
988 /* Set return length */
989 Length
= sizeof(ULONG
);
990 if (ProcessInformationLength
!= Length
)
992 Status
= STATUS_INFO_LENGTH_MISMATCH
;
996 if (ProcessHandle
!= NtCurrentProcess())
998 return STATUS_INVALID_PARAMETER
;
1001 /* Get the options */
1002 Status
= MmGetExecuteOptions(&ExecuteOptions
);
1003 if (NT_SUCCESS(Status
))
1005 /* Protect write with SEH */
1009 *(PULONG
)ProcessInformation
= ExecuteOptions
;
1011 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1013 /* Get exception code */
1014 Status
= _SEH2_GetExceptionCode();
1020 case ProcessLdtInformation
:
1021 DPRINT1("VDM/16-bit not implemented: %lx\n", ProcessInformationClass
);
1022 Status
= STATUS_NOT_IMPLEMENTED
;
1025 case ProcessWorkingSetWatch
:
1026 DPRINT1("WS Watch Not implemented: %lx\n", ProcessInformationClass
);
1027 Status
= STATUS_NOT_IMPLEMENTED
;
1030 case ProcessPooledUsageAndLimits
:
1031 DPRINT1("Pool limits Not implemented: %lx\n", ProcessInformationClass
);
1032 Status
= STATUS_NOT_IMPLEMENTED
;
1035 /* Not supported by Server 2003 */
1037 DPRINT1("Unsupported info class: %lx\n", ProcessInformationClass
);
1038 Status
= STATUS_INVALID_INFO_CLASS
;
1041 /* Protect write with SEH */
1044 /* Check if caller wanted return length */
1045 if ((ReturnLength
) && (Length
)) *ReturnLength
= Length
;
1047 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1049 /* Get exception code */
1050 Status
= _SEH2_GetExceptionCode();
1062 NtSetInformationProcess(IN HANDLE ProcessHandle
,
1063 IN PROCESSINFOCLASS ProcessInformationClass
,
1064 IN PVOID ProcessInformation
,
1065 IN ULONG ProcessInformationLength
)
1068 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1071 HANDLE PortHandle
= NULL
;
1072 HANDLE TokenHandle
= NULL
;
1073 PROCESS_SESSION_INFORMATION SessionInfo
= {0};
1074 PROCESS_PRIORITY_CLASS PriorityClass
= {0};
1075 PROCESS_FOREGROUND_BACKGROUND Foreground
= {0};
1076 PVOID ExceptionPort
;
1078 KAFFINITY ValidAffinity
, Affinity
= 0;
1079 KPRIORITY BasePriority
= 0;
1080 UCHAR MemoryPriority
= 0;
1081 BOOLEAN DisableBoost
= 0;
1082 ULONG DefaultHardErrorMode
= 0;
1083 ULONG DebugFlags
= 0, EnableFixup
= 0, Boost
= 0;
1084 ULONG NoExecute
= 0, VdmPower
= 0;
1085 BOOLEAN HasPrivilege
;
1090 /* Verify Information Class validity */
1092 Status
= DefaultSetInfoBufferCheck(ProcessInformationClass
,
1094 RTL_NUMBER_OF(PsProcessInfoClass
),
1096 ProcessInformationLength
,
1098 if (!NT_SUCCESS(Status
)) return Status
;
1101 /* Check what class this is */
1102 Access
= PROCESS_SET_INFORMATION
;
1103 if (ProcessInformationClass
== ProcessSessionInformation
)
1105 /* Setting the Session ID needs a special mask */
1106 Access
|= PROCESS_SET_SESSIONID
;
1108 else if (ProcessInformationClass
== ProcessExceptionPort
)
1110 /* Setting the exception port needs a special mask */
1111 Access
|= PROCESS_SUSPEND_RESUME
;
1114 /* Reference the process */
1115 Status
= ObReferenceObjectByHandle(ProcessHandle
,
1121 if (!NT_SUCCESS(Status
)) return Status
;
1123 /* Check what kind of information class this is */
1124 switch (ProcessInformationClass
)
1126 case ProcessWx86Information
:
1128 /* Check buffer length */
1129 if (ProcessInformationLength
!= sizeof(HANDLE
))
1131 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1135 /* Use SEH for capture */
1138 /* Capture the boolean */
1139 VdmPower
= *(PULONG
)ProcessInformation
;
1141 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1143 /* Get the exception code */
1144 Status
= _SEH2_GetExceptionCode();
1149 /* Getting VDM powers requires the SeTcbPrivilege */
1150 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
1153 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1154 DPRINT1("Need TCB privilege\n");
1158 /* Set or clear the flag */
1161 PspSetProcessFlag(Process
, PSF_VDM_ALLOWED_BIT
);
1165 PspClearProcessFlag(Process
, PSF_VDM_ALLOWED_BIT
);
1169 /* Error/Exception Port */
1170 case ProcessExceptionPort
:
1172 /* Check buffer length */
1173 if (ProcessInformationLength
!= sizeof(HANDLE
))
1175 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1179 /* Use SEH for capture */
1182 /* Capture the handle */
1183 PortHandle
= *(PHANDLE
)ProcessInformation
;
1185 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1187 /* Get the exception code */
1188 Status
= _SEH2_GetExceptionCode();
1193 /* Setting the error port requires the SeTcbPrivilege */
1194 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
1196 /* Can't set the session ID, bail out. */
1197 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1201 /* Get the LPC Port */
1202 Status
= ObReferenceObjectByHandle(PortHandle
,
1206 (PVOID
)&ExceptionPort
,
1208 if (!NT_SUCCESS(Status
)) break;
1210 /* Change the pointer */
1211 if (InterlockedCompareExchangePointer(&Process
->ExceptionPort
,
1215 /* We already had one, fail */
1216 ObDereferenceObject(ExceptionPort
);
1217 Status
= STATUS_PORT_ALREADY_SET
;
1221 /* Security Token */
1222 case ProcessAccessToken
:
1224 /* Check buffer length */
1225 if (ProcessInformationLength
!= sizeof(PROCESS_ACCESS_TOKEN
))
1227 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1231 /* Use SEH for capture */
1234 /* Save the token handle */
1235 TokenHandle
= ((PPROCESS_ACCESS_TOKEN
)ProcessInformation
)->
1238 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1240 /* Get the exception code */
1241 Status
= _SEH2_GetExceptionCode();
1246 /* Assign the actual token */
1247 Status
= PspSetPrimaryToken(Process
, TokenHandle
, NULL
);
1250 /* Hard error processing */
1251 case ProcessDefaultHardErrorMode
:
1253 /* Check buffer length */
1254 if (ProcessInformationLength
!= sizeof(ULONG
))
1256 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1260 /* Enter SEH for direct buffer read */
1263 DefaultHardErrorMode
= *(PULONG
)ProcessInformation
;
1265 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1267 /* Get exception code */
1268 Status
= _SEH2_GetExceptionCode();
1274 Process
->DefaultHardErrorProcessing
= DefaultHardErrorMode
;
1276 /* Call Ke for the update */
1277 if (DefaultHardErrorMode
& SEM_NOALIGNMENTFAULTEXCEPT
)
1279 KeSetAutoAlignmentProcess(&Process
->Pcb
, TRUE
);
1283 KeSetAutoAlignmentProcess(&Process
->Pcb
, FALSE
);
1285 Status
= STATUS_SUCCESS
;
1289 case ProcessSessionInformation
:
1291 /* Check buffer length */
1292 if (ProcessInformationLength
!= sizeof(PROCESS_SESSION_INFORMATION
))
1294 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1298 /* Enter SEH for capture */
1301 /* Capture the caller's buffer */
1302 SessionInfo
= *(PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
1304 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1306 /* Get the exception code */
1307 Status
= _SEH2_GetExceptionCode();
1312 /* Setting the session id requires the SeTcbPrivilege */
1313 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
1315 /* Can't set the session ID, bail out. */
1316 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1320 /* FIXME - update the session id for the process token */
1321 //Status = PsLockProcess(Process, FALSE);
1322 if (!NT_SUCCESS(Status
)) break;
1324 /* Write the session ID in the EPROCESS */
1325 Process
->Session
= UlongToPtr(SessionInfo
.SessionId
); // HACK!!!
1327 /* Check if the process also has a PEB */
1331 * Attach to the process to make sure we're in the right
1332 * context to access the PEB structure
1334 KeAttachProcess(&Process
->Pcb
);
1336 /* Enter SEH for write to user-mode PEB */
1339 /* Write the session ID */
1340 Process
->Peb
->SessionId
= SessionInfo
.SessionId
;
1342 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1344 /* Get exception code */
1345 Status
= _SEH2_GetExceptionCode();
1349 /* Detach from the process */
1353 /* Unlock the process */
1354 //PsUnlockProcess(Process);
1357 case ProcessPriorityClass
:
1359 /* Check buffer length */
1360 if (ProcessInformationLength
!= sizeof(PROCESS_PRIORITY_CLASS
))
1362 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1366 /* Enter SEH for capture */
1369 /* Capture the caller's buffer */
1370 PriorityClass
= *(PPROCESS_PRIORITY_CLASS
)ProcessInformation
;
1372 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1374 /* Return the exception code */
1375 Status
= _SEH2_GetExceptionCode();
1380 /* Check for invalid PriorityClass value */
1381 if (PriorityClass
.PriorityClass
> PROCESS_PRIORITY_CLASS_ABOVE_NORMAL
)
1383 Status
= STATUS_INVALID_PARAMETER
;
1387 if ((PriorityClass
.PriorityClass
!= Process
->PriorityClass
) &&
1388 (PriorityClass
.PriorityClass
== PROCESS_PRIORITY_CLASS_REALTIME
))
1390 /* Check the privilege */
1391 HasPrivilege
= SeCheckPrivilegedObject(SeIncreaseBasePriorityPrivilege
,
1393 PROCESS_SET_INFORMATION
,
1397 ObDereferenceObject(Process
);
1398 DPRINT1("Privilege to change priority to realtime lacking\n");
1399 return STATUS_PRIVILEGE_NOT_HELD
;
1403 /* Check if we have a job */
1406 DPRINT1("Jobs not yet supported\n");
1409 /* Set process priority class */
1410 Process
->PriorityClass
= PriorityClass
.PriorityClass
;
1412 /* Set process priority mode (foreground or background) */
1413 PsSetProcessPriorityByClass(Process
,
1414 PriorityClass
.Foreground
?
1415 PsProcessPriorityForeground
:
1416 PsProcessPriorityBackground
);
1417 Status
= STATUS_SUCCESS
;
1420 case ProcessForegroundInformation
:
1422 /* Check buffer length */
1423 if (ProcessInformationLength
!= sizeof(PROCESS_FOREGROUND_BACKGROUND
))
1425 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1429 /* Enter SEH for capture */
1432 /* Capture the caller's buffer */
1433 Foreground
= *(PPROCESS_FOREGROUND_BACKGROUND
)ProcessInformation
;
1435 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1437 /* Return the exception code */
1438 Status
= _SEH2_GetExceptionCode();
1443 /* Set process priority mode (foreground or background) */
1444 PsSetProcessPriorityByClass(Process
,
1445 Foreground
.Foreground
?
1446 PsProcessPriorityForeground
:
1447 PsProcessPriorityBackground
);
1448 Status
= STATUS_SUCCESS
;
1451 case ProcessBasePriority
:
1453 /* Validate input length */
1454 if (ProcessInformationLength
!= sizeof(KPRIORITY
))
1456 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1460 /* Enter SEH for direct buffer read */
1463 BasePriority
= *(KPRIORITY
*)ProcessInformation
;
1465 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1467 /* Get exception code */
1469 Status
= _SEH2_GetExceptionCode();
1474 /* Extract the memory priority out of there */
1475 if (BasePriority
& 0x80000000)
1477 MemoryPriority
= MEMORY_PRIORITY_FOREGROUND
;
1478 BasePriority
&= ~0x80000000;
1482 MemoryPriority
= MEMORY_PRIORITY_BACKGROUND
;
1485 /* Validate the number */
1486 if ((BasePriority
> HIGH_PRIORITY
) || (BasePriority
<= LOW_PRIORITY
))
1488 return STATUS_INVALID_PARAMETER
;
1491 /* Check if the new base is higher */
1492 if (BasePriority
> Process
->Pcb
.BasePriority
)
1494 HasPrivilege
= SeCheckPrivilegedObject(SeIncreaseBasePriorityPrivilege
,
1496 PROCESS_SET_INFORMATION
,
1500 ObDereferenceObject(Process
);
1501 DPRINT1("Privilege to change priority from %lx to %lx lacking\n", BasePriority
, Process
->Pcb
.BasePriority
);
1502 return STATUS_PRIVILEGE_NOT_HELD
;
1507 KeSetPriorityAndQuantumProcess(&Process
->Pcb
, BasePriority
, 0);
1509 /* Now set the memory priority */
1510 MmSetMemoryPriorityProcess(Process
, MemoryPriority
);
1511 Status
= STATUS_SUCCESS
;
1514 case ProcessRaisePriority
:
1516 /* Validate input length */
1517 if (ProcessInformationLength
!= sizeof(ULONG
))
1519 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1523 /* Enter SEH for direct buffer read */
1526 Boost
= *(PULONG
)ProcessInformation
;
1528 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1530 /* Get exception code */
1532 Status
= _SEH2_GetExceptionCode();
1537 /* Make sure the process isn't dying */
1538 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1541 KeEnterCriticalRegion();
1542 ExAcquirePushLockShared(&Process
->ProcessLock
);
1544 /* Loop the threads */
1545 for (Next
= Process
->ThreadListHead
.Flink
;
1546 Next
!= &Process
->ThreadListHead
;
1549 /* Call Ke for the thread */
1550 Thread
= CONTAINING_RECORD(Next
, ETHREAD
, ThreadListEntry
);
1551 KeBoostPriorityThread(&Thread
->Tcb
, Boost
);
1554 /* Release the lock and rundown */
1555 ExReleasePushLockShared(&Process
->ProcessLock
);
1556 KeLeaveCriticalRegion();
1557 ExReleaseRundownProtection(&Process
->RundownProtect
);
1559 /* Set success code */
1560 Status
= STATUS_SUCCESS
;
1564 /* Avoid race conditions */
1565 Status
= STATUS_PROCESS_IS_TERMINATING
;
1569 case ProcessBreakOnTermination
:
1571 /* Check buffer length */
1572 if (ProcessInformationLength
!= sizeof(ULONG
))
1574 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1578 /* Enter SEH for direct buffer read */
1581 Break
= *(PULONG
)ProcessInformation
;
1583 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1585 /* Get exception code */
1587 Status
= _SEH2_GetExceptionCode();
1592 /* Setting 'break on termination' requires the SeDebugPrivilege */
1593 if (!SeSinglePrivilegeCheck(SeDebugPrivilege
, PreviousMode
))
1595 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1599 /* Set or clear the flag */
1602 PspSetProcessFlag(Process
, PSF_BREAK_ON_TERMINATION_BIT
);
1606 PspClearProcessFlag(Process
, PSF_BREAK_ON_TERMINATION_BIT
);
1611 case ProcessAffinityMask
:
1613 /* Check buffer length */
1614 if (ProcessInformationLength
!= sizeof(KAFFINITY
))
1616 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1620 /* Enter SEH for direct buffer read */
1623 Affinity
= *(PKAFFINITY
)ProcessInformation
;
1625 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1627 /* Get exception code */
1629 Status
= _SEH2_GetExceptionCode();
1634 /* Make sure it's valid for the CPUs present */
1635 ValidAffinity
= Affinity
& KeActiveProcessors
;
1636 if (!Affinity
|| (ValidAffinity
!= Affinity
))
1638 Status
= STATUS_INVALID_PARAMETER
;
1642 /* Check if it's within job affinity limits */
1645 /* Not yet implemented */
1647 Status
= STATUS_NOT_IMPLEMENTED
;
1651 /* Make sure the process isn't dying */
1652 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1655 KeEnterCriticalRegion();
1656 ExAcquirePushLockShared(&Process
->ProcessLock
);
1658 /* Call Ke to do the work */
1659 KeSetAffinityProcess(&Process
->Pcb
, ValidAffinity
);
1661 /* Release the lock and rundown */
1662 ExReleasePushLockShared(&Process
->ProcessLock
);
1663 KeLeaveCriticalRegion();
1664 ExReleaseRundownProtection(&Process
->RundownProtect
);
1666 /* Set success code */
1667 Status
= STATUS_SUCCESS
;
1671 /* Avoid race conditions */
1672 Status
= STATUS_PROCESS_IS_TERMINATING
;
1676 /* Priority Boosting status */
1677 case ProcessPriorityBoost
:
1679 /* Validate input length */
1680 if (ProcessInformationLength
!= sizeof(ULONG
))
1682 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1686 /* Enter SEH for direct buffer read */
1689 DisableBoost
= *(PBOOLEAN
)ProcessInformation
;
1691 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1693 /* Get exception code */
1695 Status
= _SEH2_GetExceptionCode();
1700 /* Make sure the process isn't dying */
1701 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1704 KeEnterCriticalRegion();
1705 ExAcquirePushLockShared(&Process
->ProcessLock
);
1707 /* Call Ke to do the work */
1708 KeSetDisableBoostProcess(&Process
->Pcb
, DisableBoost
);
1710 /* Loop the threads too */
1711 for (Next
= Process
->ThreadListHead
.Flink
;
1712 Next
!= &Process
->ThreadListHead
;
1715 /* Call Ke for the thread */
1716 Thread
= CONTAINING_RECORD(Next
, ETHREAD
, ThreadListEntry
);
1717 KeSetDisableBoostThread(&Thread
->Tcb
, DisableBoost
);
1720 /* Release the lock and rundown */
1721 ExReleasePushLockShared(&Process
->ProcessLock
);
1722 KeLeaveCriticalRegion();
1723 ExReleaseRundownProtection(&Process
->RundownProtect
);
1725 /* Set success code */
1726 Status
= STATUS_SUCCESS
;
1730 /* Avoid race conditions */
1731 Status
= STATUS_PROCESS_IS_TERMINATING
;
1735 case ProcessDebugFlags
:
1737 /* Check buffer length */
1738 if (ProcessInformationLength
!= sizeof(ULONG
))
1740 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1744 /* Enter SEH for direct buffer read */
1747 DebugFlags
= *(PULONG
)ProcessInformation
;
1749 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1751 /* Get exception code */
1752 Status
= _SEH2_GetExceptionCode();
1758 if (DebugFlags
& ~1)
1760 Status
= STATUS_INVALID_PARAMETER
;
1766 PspClearProcessFlag(Process
, PSF_NO_DEBUG_INHERIT_BIT
);
1770 PspSetProcessFlag(Process
, PSF_NO_DEBUG_INHERIT_BIT
);
1775 Status
= STATUS_SUCCESS
;
1778 case ProcessEnableAlignmentFaultFixup
:
1780 /* Check buffer length */
1781 if (ProcessInformationLength
!= sizeof(ULONG
))
1783 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1787 /* Enter SEH for direct buffer read */
1790 EnableFixup
= *(PULONG
)ProcessInformation
;
1792 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1794 /* Get exception code */
1795 Status
= _SEH2_GetExceptionCode();
1803 Process
->DefaultHardErrorProcessing
|= SEM_NOALIGNMENTFAULTEXCEPT
;
1807 Process
->DefaultHardErrorProcessing
&= ~SEM_NOALIGNMENTFAULTEXCEPT
;
1810 /* Call Ke for the update */
1811 KeSetAutoAlignmentProcess(&Process
->Pcb
, FALSE
);
1812 Status
= STATUS_SUCCESS
;
1815 case ProcessUserModeIOPL
:
1817 /* Only TCB can do this */
1818 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
1821 DPRINT1("Need TCB to set IOPL\n");
1822 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1826 /* Only supported on x86 */
1830 Status
= STATUS_NOT_IMPLEMENTED
;
1835 case ProcessExecuteFlags
:
1837 /* Check buffer length */
1838 if (ProcessInformationLength
!= sizeof(ULONG
))
1840 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1844 if (ProcessHandle
!= NtCurrentProcess())
1846 Status
= STATUS_INVALID_PARAMETER
;
1850 /* Enter SEH for direct buffer read */
1853 NoExecute
= *(PULONG
)ProcessInformation
;
1855 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1857 /* Get exception code */
1858 Status
= _SEH2_GetExceptionCode();
1863 /* Call Mm for the update */
1864 Status
= MmSetExecuteOptions(NoExecute
);
1867 /* We currently don't implement any of these */
1868 case ProcessLdtInformation
:
1869 case ProcessLdtSize
:
1870 case ProcessIoPortHandlers
:
1871 DPRINT1("VDM/16-bit Request not implemented: %lx\n", ProcessInformationClass
);
1872 Status
= STATUS_NOT_IMPLEMENTED
;
1875 case ProcessQuotaLimits
:
1876 DPRINT1("Quota Limits not implemented\n");
1877 Status
= STATUS_NOT_IMPLEMENTED
;
1880 case ProcessWorkingSetWatch
:
1881 DPRINT1("WS watch not implemented\n");
1882 Status
= STATUS_NOT_IMPLEMENTED
;
1885 case ProcessDeviceMap
:
1886 DPRINT1("Device map not implemented\n");
1887 Status
= STATUS_NOT_IMPLEMENTED
;
1890 case ProcessHandleTracing
:
1891 DPRINT1("Handle tracing not implemented\n");
1892 Status
= STATUS_NOT_IMPLEMENTED
;
1895 /* Anything else is invalid */
1897 DPRINT1("Invalid Server 2003 Info Class: %lx\n", ProcessInformationClass
);
1898 Status
= STATUS_INVALID_INFO_CLASS
;
1901 /* Dereference and return status */
1902 ObDereferenceObject(Process
);
1911 NtSetInformationThread(IN HANDLE ThreadHandle
,
1912 IN THREADINFOCLASS ThreadInformationClass
,
1913 IN PVOID ThreadInformation
,
1914 IN ULONG ThreadInformationLength
)
1918 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1920 HANDLE TokenHandle
= NULL
;
1921 KPRIORITY Priority
= 0;
1922 KAFFINITY Affinity
= 0, CombinedAffinity
;
1923 PVOID Address
= NULL
;
1925 ULONG_PTR DisableBoost
= 0;
1926 ULONG_PTR IdealProcessor
= 0;
1927 ULONG_PTR Break
= 0;
1929 ULONG_PTR TlsIndex
= 0;
1930 PVOID
*ExpansionSlots
;
1931 PETHREAD ProcThread
;
1934 /* Verify Information Class validity */
1936 Status
= DefaultSetInfoBufferCheck(ThreadInformationClass
,
1938 RTL_NUMBER_OF(PsThreadInfoClass
),
1940 ThreadInformationLength
,
1942 if (!NT_SUCCESS(Status
)) return Status
;
1945 /* Check what class this is */
1946 Access
= THREAD_SET_INFORMATION
;
1947 if (ThreadInformationClass
== ThreadImpersonationToken
)
1949 /* Setting the impersonation token needs a special mask */
1950 Access
= THREAD_SET_THREAD_TOKEN
;
1953 /* Reference the thread */
1954 Status
= ObReferenceObjectByHandle(ThreadHandle
,
1960 if (!NT_SUCCESS(Status
)) return Status
;
1962 /* Check what kind of information class this is */
1963 switch (ThreadInformationClass
)
1965 /* Thread priority */
1966 case ThreadPriority
:
1968 /* Check buffer length */
1969 if (ThreadInformationLength
!= sizeof(KPRIORITY
))
1971 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1975 /* Use SEH for capture */
1978 /* Get the priority */
1979 Priority
= *(PLONG
)ThreadInformation
;
1981 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1983 /* Get the exception code */
1984 Status
= _SEH2_GetExceptionCode();
1990 if ((Priority
> HIGH_PRIORITY
) ||
1991 (Priority
<= LOW_PRIORITY
))
1994 Status
= STATUS_INVALID_PARAMETER
;
1998 /* Set the priority */
1999 KeSetPriorityThread(&Thread
->Tcb
, Priority
);
2002 case ThreadBasePriority
:
2004 /* Check buffer length */
2005 if (ThreadInformationLength
!= sizeof(LONG
))
2007 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2011 /* Use SEH for capture */
2014 /* Get the priority */
2015 Priority
= *(PLONG
)ThreadInformation
;
2017 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2019 /* Get the exception code */
2020 Status
= _SEH2_GetExceptionCode();
2026 if ((Priority
> THREAD_BASE_PRIORITY_MAX
) ||
2027 (Priority
< THREAD_BASE_PRIORITY_MIN
))
2029 /* These ones are OK */
2030 if ((Priority
!= THREAD_BASE_PRIORITY_LOWRT
+ 1) &&
2031 (Priority
!= THREAD_BASE_PRIORITY_IDLE
- 1))
2033 /* Check if the process is real time */
2034 if (PsGetCurrentProcess()->PriorityClass
!=
2035 PROCESS_PRIORITY_CLASS_REALTIME
)
2037 /* It isn't, fail */
2038 Status
= STATUS_INVALID_PARAMETER
;
2044 /* Set the base priority */
2045 KeSetBasePriorityThread(&Thread
->Tcb
, Priority
);
2048 case ThreadAffinityMask
:
2050 /* Check buffer length */
2051 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
2053 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2057 /* Use SEH for capture */
2060 /* Get the priority */
2061 Affinity
= *(PULONG_PTR
)ThreadInformation
;
2063 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2065 /* Get the exception code */
2066 Status
= _SEH2_GetExceptionCode();
2075 Status
= STATUS_INVALID_PARAMETER
;
2079 /* Get the process */
2080 Process
= Thread
->ThreadsProcess
;
2082 /* Try to acquire rundown */
2083 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
2086 KeEnterCriticalRegion();
2087 ExAcquirePushLockShared(&Process
->ProcessLock
);
2090 CombinedAffinity
= Affinity
& Process
->Pcb
.Affinity
;
2091 if (CombinedAffinity
!= Affinity
)
2094 Status
= STATUS_INVALID_PARAMETER
;
2098 /* Set the affinity */
2099 KeSetAffinityThread(&Thread
->Tcb
, CombinedAffinity
);
2102 /* Release the lock and rundown */
2103 ExReleasePushLockShared(&Process
->ProcessLock
);
2104 KeLeaveCriticalRegion();
2105 ExReleaseRundownProtection(&Process
->RundownProtect
);
2110 Status
= STATUS_PROCESS_IS_TERMINATING
;
2116 case ThreadImpersonationToken
:
2118 /* Check buffer length */
2119 if (ThreadInformationLength
!= sizeof(HANDLE
))
2121 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2125 /* Use SEH for capture */
2128 /* Save the token handle */
2129 TokenHandle
= *(PHANDLE
)ThreadInformation
;
2131 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2133 /* Get the exception code */
2134 Status
= _SEH2_GetExceptionCode();
2139 /* Assign the actual token */
2140 Status
= PsAssignImpersonationToken(Thread
, TokenHandle
);
2143 case ThreadQuerySetWin32StartAddress
:
2145 /* Check buffer length */
2146 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
2148 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2152 /* Use SEH for capture */
2155 /* Get the priority */
2156 Address
= *(PVOID
*)ThreadInformation
;
2158 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2160 /* Get the exception code */
2161 Status
= _SEH2_GetExceptionCode();
2166 /* Set the address */
2167 Thread
->Win32StartAddress
= Address
;
2170 case ThreadIdealProcessor
:
2172 /* Check buffer length */
2173 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
2175 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2179 /* Use SEH for capture */
2182 /* Get the priority */
2183 IdealProcessor
= *(PULONG_PTR
)ThreadInformation
;
2185 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2187 /* Get the exception code */
2188 Status
= _SEH2_GetExceptionCode();
2194 if (IdealProcessor
> MAXIMUM_PROCESSORS
)
2197 Status
= STATUS_INVALID_PARAMETER
;
2202 Status
= KeSetIdealProcessorThread(&Thread
->Tcb
,
2203 (CCHAR
)IdealProcessor
);
2205 /* Get the TEB and protect the thread */
2206 Teb
= Thread
->Tcb
.Teb
;
2207 if ((Teb
) && (ExAcquireRundownProtection(&Thread
->RundownProtect
)))
2209 /* Save the ideal processor */
2210 Teb
->IdealProcessor
= Thread
->Tcb
.IdealProcessor
;
2212 /* Release rundown protection */
2213 ExReleaseRundownProtection(&Thread
->RundownProtect
);
2218 case ThreadPriorityBoost
:
2220 /* Check buffer length */
2221 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
2223 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2227 /* Use SEH for capture */
2230 /* Get the priority */
2231 DisableBoost
= *(PULONG_PTR
)ThreadInformation
;
2233 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2235 /* Get the exception code */
2236 Status
= _SEH2_GetExceptionCode();
2241 /* Call the kernel */
2242 KeSetDisableBoostThread(&Thread
->Tcb
, (BOOLEAN
)DisableBoost
);
2245 case ThreadZeroTlsCell
:
2247 /* Check buffer length */
2248 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
2250 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2254 /* Use SEH for capture */
2257 /* Get the priority */
2258 TlsIndex
= *(PULONG_PTR
)ThreadInformation
;
2260 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2262 /* Get the exception code */
2263 Status
= _SEH2_GetExceptionCode();
2268 /* This is only valid for the current thread */
2269 if (Thread
!= PsGetCurrentThread())
2272 Status
= STATUS_INVALID_PARAMETER
;
2276 /* Get the process */
2277 Process
= Thread
->ThreadsProcess
;
2279 /* Loop the threads */
2280 ProcThread
= PsGetNextProcessThread(Process
, NULL
);
2283 /* Acquire rundown */
2284 if (ExAcquireRundownProtection(&ProcThread
->RundownProtect
))
2287 Teb
= ProcThread
->Tcb
.Teb
;
2290 /* Check if we're in the expansion range */
2291 if (TlsIndex
> TLS_MINIMUM_AVAILABLE
- 1)
2293 if (TlsIndex
< (TLS_MINIMUM_AVAILABLE
+
2294 TLS_EXPANSION_SLOTS
) - 1)
2296 /* Check if we have expansion slots */
2297 ExpansionSlots
= Teb
->TlsExpansionSlots
;
2300 /* Clear the index */
2301 ExpansionSlots
[TlsIndex
- TLS_MINIMUM_AVAILABLE
] = 0;
2307 /* Clear the index */
2308 Teb
->TlsSlots
[TlsIndex
] = NULL
;
2312 /* Release rundown */
2313 ExReleaseRundownProtection(&ProcThread
->RundownProtect
);
2316 /* Go to the next thread */
2317 ProcThread
= PsGetNextProcessThread(Process
, ProcThread
);
2323 case ThreadBreakOnTermination
:
2325 /* Check buffer length */
2326 if (ThreadInformationLength
!= sizeof(ULONG
))
2328 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2332 /* Enter SEH for direct buffer read */
2335 Break
= *(PULONG
)ThreadInformation
;
2337 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2339 /* Get exception code */
2341 Status
= _SEH2_GetExceptionCode();
2346 /* Setting 'break on termination' requires the SeDebugPrivilege */
2347 if (!SeSinglePrivilegeCheck(SeDebugPrivilege
, PreviousMode
))
2349 Status
= STATUS_PRIVILEGE_NOT_HELD
;
2353 /* Set or clear the flag */
2356 PspSetCrossThreadFlag(Thread
, CT_BREAK_ON_TERMINATION_BIT
);
2360 PspClearCrossThreadFlag(Thread
, CT_BREAK_ON_TERMINATION_BIT
);
2365 /* We don't implement it yet */
2366 DPRINT1("Not implemented: %d\n", ThreadInformationClass
);
2367 Status
= STATUS_NOT_IMPLEMENTED
;
2370 /* Dereference and return status */
2371 ObDereferenceObject(Thread
);
2380 NtQueryInformationThread(IN HANDLE ThreadHandle
,
2381 IN THREADINFOCLASS ThreadInformationClass
,
2382 OUT PVOID ThreadInformation
,
2383 IN ULONG ThreadInformationLength
,
2384 OUT PULONG ReturnLength OPTIONAL
)
2387 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2391 PTHREAD_BASIC_INFORMATION ThreadBasicInfo
=
2392 (PTHREAD_BASIC_INFORMATION
)ThreadInformation
;
2393 PKERNEL_USER_TIMES ThreadTime
= (PKERNEL_USER_TIMES
)ThreadInformation
;
2397 /* Check if we were called from user mode */
2398 if (PreviousMode
!= KernelMode
)
2403 /* Probe the buffer */
2404 ProbeForWrite(ThreadInformation
,
2405 ThreadInformationLength
,
2408 /* Probe the return length if required */
2409 if (ReturnLength
) ProbeForWriteUlong(ReturnLength
);
2411 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2413 /* Return the exception code */
2414 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2419 /* Check what class this is */
2420 Access
= THREAD_QUERY_INFORMATION
;
2422 /* Reference the process */
2423 Status
= ObReferenceObjectByHandle(ThreadHandle
,
2429 if (!NT_SUCCESS(Status
)) return Status
;
2431 /* Check what kind of information class this is */
2432 switch (ThreadInformationClass
)
2434 /* Basic thread information */
2435 case ThreadBasicInformation
:
2437 /* Set return length */
2438 Length
= sizeof(THREAD_BASIC_INFORMATION
);
2440 if (ThreadInformationLength
!= Length
)
2442 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2445 /* Protect writes with SEH */
2448 /* Write all the information from the ETHREAD/KTHREAD */
2449 ThreadBasicInfo
->ExitStatus
= Thread
->ExitStatus
;
2450 ThreadBasicInfo
->TebBaseAddress
= (PVOID
)Thread
->Tcb
.Teb
;
2451 ThreadBasicInfo
->ClientId
= Thread
->Cid
;
2452 ThreadBasicInfo
->AffinityMask
= Thread
->Tcb
.Affinity
;
2453 ThreadBasicInfo
->Priority
= Thread
->Tcb
.Priority
;
2454 ThreadBasicInfo
->BasePriority
= KeQueryBasePriorityThread(&Thread
->Tcb
);
2456 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2458 /* Get exception code */
2459 Status
= _SEH2_GetExceptionCode();
2464 /* Thread time information */
2467 /* Set the return length */
2468 Length
= sizeof(KERNEL_USER_TIMES
);
2470 if (ThreadInformationLength
!= Length
)
2472 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2475 /* Protect writes with SEH */
2478 /* Copy time information from ETHREAD/KTHREAD */
2479 ThreadTime
->KernelTime
.QuadPart
= Thread
->Tcb
.KernelTime
* KeMaximumIncrement
;
2480 ThreadTime
->UserTime
.QuadPart
= Thread
->Tcb
.UserTime
* KeMaximumIncrement
;
2481 ThreadTime
->CreateTime
= Thread
->CreateTime
;
2483 /* Exit time is in a union and only valid on actual exit! */
2484 if (KeReadStateThread(&Thread
->Tcb
))
2486 ThreadTime
->ExitTime
= Thread
->ExitTime
;
2490 ThreadTime
->ExitTime
.QuadPart
= 0;
2493 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2495 /* Get exception code */
2496 Status
= _SEH2_GetExceptionCode();
2501 case ThreadQuerySetWin32StartAddress
:
2503 /* Set the return length*/
2504 Length
= sizeof(PVOID
);
2506 if (ThreadInformationLength
!= Length
)
2508 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2511 /* Protect write with SEH */
2514 /* Return the Win32 Start Address */
2515 *(PVOID
*)ThreadInformation
= Thread
->Win32StartAddress
;
2517 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2519 /* Get exception code */
2520 Status
= _SEH2_GetExceptionCode();
2525 case ThreadPerformanceCount
:
2527 /* Set the return length*/
2528 Length
= sizeof(LARGE_INTEGER
);
2530 if (ThreadInformationLength
!= Length
)
2532 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2535 /* Protect write with SEH */
2539 (*(PLARGE_INTEGER
)ThreadInformation
).QuadPart
= 0;
2541 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2543 /* Get exception code */
2544 Status
= _SEH2_GetExceptionCode();
2549 case ThreadAmILastThread
:
2551 /* Set the return length*/
2552 Length
= sizeof(ULONG
);
2554 if (ThreadInformationLength
!= Length
)
2556 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2559 /* Protect write with SEH */
2562 /* Return whether or not we are the last thread */
2563 *(PULONG
)ThreadInformation
= ((Thread
->ThreadsProcess
->
2564 ThreadListHead
.Flink
->Flink
==
2565 &Thread
->ThreadsProcess
->
2569 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2571 /* Get exception code */
2572 Status
= _SEH2_GetExceptionCode();
2577 case ThreadIsIoPending
:
2579 /* Set the return length*/
2580 Length
= sizeof(ULONG
);
2582 if (ThreadInformationLength
!= Length
)
2584 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2587 /* Raise the IRQL to protect the IRP list */
2588 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2590 /* Protect write with SEH */
2593 /* Check if the IRP list is empty or not */
2594 *(PULONG
)ThreadInformation
= !IsListEmpty(&Thread
->IrpList
);
2596 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2598 /* Get exception code */
2599 Status
= _SEH2_GetExceptionCode();
2603 /* Lower IRQL back */
2604 KeLowerIrql(OldIrql
);
2607 /* LDT and GDT information */
2608 case ThreadDescriptorTableEntry
:
2611 /* Call the worker routine */
2612 Status
= PspQueryDescriptorThread(Thread
,
2614 ThreadInformationLength
,
2617 /* Only implemented on x86 */
2618 Status
= STATUS_NOT_IMPLEMENTED
;
2622 case ThreadPriorityBoost
:
2624 /* Set the return length*/
2625 Length
= sizeof(ULONG
);
2627 if (ThreadInformationLength
!= Length
)
2629 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2635 *(PULONG
)ThreadInformation
= Thread
->Tcb
.DisableBoost
? 1 : 0;
2637 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2639 Status
= _SEH2_GetExceptionCode();
2647 /* Not yet implemented */
2648 DPRINT1("Not implemented: %lx\n", ThreadInformationClass
);
2649 Status
= STATUS_NOT_IMPLEMENTED
;
2652 /* Protect write with SEH */
2655 /* Check if caller wanted return length */
2656 if (ReturnLength
) *ReturnLength
= Length
;
2658 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2660 /* Get exception code */
2661 Status
= _SEH2_GetExceptionCode();
2665 /* Dereference the thread, and return */
2666 ObDereferenceObject(Thread
);