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();
72 PPROCESS_BASIC_INFORMATION ProcessBasicInfo
=
73 (PPROCESS_BASIC_INFORMATION
)ProcessInformation
;
74 PKERNEL_USER_TIMES ProcessTime
= (PKERNEL_USER_TIMES
)ProcessInformation
;
75 PPROCESS_PRIORITY_CLASS PsPriorityClass
= (PPROCESS_PRIORITY_CLASS
)ProcessInformation
;
77 PPROCESS_SESSION_INFORMATION SessionInfo
=
78 (PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
79 PVM_COUNTERS VmCounters
= (PVM_COUNTERS
)ProcessInformation
;
80 PIO_COUNTERS IoCounters
= (PIO_COUNTERS
)ProcessInformation
;
81 PQUOTA_LIMITS QuotaLimits
= (PQUOTA_LIMITS
)ProcessInformation
;
82 PROCESS_DEVICEMAP_INFORMATION DeviceMap
;
83 PUNICODE_STRING ImageName
;
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 (ProcessHandle
!= NtCurrentProcess()))
113 * Retreiving the process cookie is only allowed for the calling process
114 * itself! XP only allowes NtCurrentProcess() as process handles even if
115 * a real handle actually represents the current process.
117 return STATUS_INVALID_PARAMETER
;
120 /* Check the information class */
121 switch (ProcessInformationClass
)
123 /* Basic process information */
124 case ProcessBasicInformation
:
126 /* Set return length */
127 Length
= sizeof(PROCESS_BASIC_INFORMATION
);
129 if (ProcessInformationLength
!= Length
)
131 Status
= STATUS_INFO_LENGTH_MISMATCH
;
135 /* Reference the process */
136 Status
= ObReferenceObjectByHandle(ProcessHandle
,
137 PROCESS_QUERY_INFORMATION
,
142 if (!NT_SUCCESS(Status
)) break;
144 /* Protect writes with SEH */
147 /* Write all the information from the EPROCESS/KPROCESS */
148 ProcessBasicInfo
->ExitStatus
= Process
->ExitStatus
;
149 ProcessBasicInfo
->PebBaseAddress
= Process
->Peb
;
150 ProcessBasicInfo
->AffinityMask
= Process
->Pcb
.Affinity
;
151 ProcessBasicInfo
->UniqueProcessId
= (ULONG_PTR
)Process
->
153 ProcessBasicInfo
->InheritedFromUniqueProcessId
=
154 (ULONG
)Process
->InheritedFromUniqueProcessId
;
155 ProcessBasicInfo
->BasePriority
= Process
->Pcb
.BasePriority
;
158 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
160 /* Get exception code */
161 Status
= _SEH2_GetExceptionCode();
165 /* Dereference the process */
166 ObDereferenceObject(Process
);
169 /* Process quota limits */
170 case ProcessQuotaLimits
:
172 Length
= sizeof(QUOTA_LIMITS
);
173 if (ProcessInformationLength
!= Length
)
175 Status
= STATUS_INFO_LENGTH_MISMATCH
;
179 /* Reference the process */
180 Status
= ObReferenceObjectByHandle(ProcessHandle
,
181 PROCESS_QUERY_INFORMATION
,
186 if (!NT_SUCCESS(Status
)) break;
188 /* Indicate success */
189 Status
= STATUS_SUCCESS
;
193 /* Set max/min working set sizes */
194 QuotaLimits
->MaximumWorkingSetSize
=
195 Process
->Vm
.MaximumWorkingSetSize
<< PAGE_SHIFT
;
196 QuotaLimits
->MinimumWorkingSetSize
=
197 Process
->Vm
.MinimumWorkingSetSize
<< PAGE_SHIFT
;
199 /* Set default time limits */
200 QuotaLimits
->TimeLimit
.LowPart
= MAXULONG
;
201 QuotaLimits
->TimeLimit
.HighPart
= MAXULONG
;
203 /* Is quota block a default one? */
204 if (Process
->QuotaBlock
== &PspDefaultQuotaBlock
)
206 /* Set default pools and pagefile limits */
207 QuotaLimits
->PagedPoolLimit
= (SIZE_T
)-1;
208 QuotaLimits
->NonPagedPoolLimit
= (SIZE_T
)-1;
209 QuotaLimits
->PagefileLimit
= (SIZE_T
)-1;
213 /* Get limits from non-default quota block */
214 QuotaLimits
->PagedPoolLimit
=
215 Process
->QuotaBlock
->QuotaEntry
[PagedPool
].Limit
;
216 QuotaLimits
->NonPagedPoolLimit
=
217 Process
->QuotaBlock
->QuotaEntry
[NonPagedPool
].Limit
;
218 QuotaLimits
->PagefileLimit
=
219 Process
->QuotaBlock
->QuotaEntry
[2].Limit
;
222 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
224 /* Get exception code */
225 Status
= _SEH2_GetExceptionCode();
229 /* Dereference the process */
230 ObDereferenceObject(Process
);
233 case ProcessIoCounters
:
235 Length
= sizeof(IO_COUNTERS
);
236 if (ProcessInformationLength
!= Length
)
238 Status
= STATUS_INFO_LENGTH_MISMATCH
;
242 /* Reference the process */
243 Status
= ObReferenceObjectByHandle(ProcessHandle
,
244 PROCESS_QUERY_INFORMATION
,
249 if (!NT_SUCCESS(Status
)) break;
253 /* FIXME: Call KeQueryValuesProcess */
254 IoCounters
->ReadOperationCount
= Process
->ReadOperationCount
.QuadPart
;
255 IoCounters
->ReadTransferCount
= Process
->ReadTransferCount
.QuadPart
;
256 IoCounters
->WriteOperationCount
= Process
->WriteOperationCount
.QuadPart
;
257 IoCounters
->WriteTransferCount
= Process
->WriteTransferCount
.QuadPart
;
258 IoCounters
->OtherOperationCount
= Process
->OtherOperationCount
.QuadPart
;
259 IoCounters
->OtherTransferCount
= Process
->OtherTransferCount
.QuadPart
;
261 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
263 /* Ignore exception */
267 /* Set status to success in any case */
268 Status
= STATUS_SUCCESS
;
270 /* Dereference the process */
271 ObDereferenceObject(Process
);
277 /* Set the return length */
278 Length
= sizeof(KERNEL_USER_TIMES
);
280 if (ProcessInformationLength
!= Length
)
282 Status
= STATUS_INFO_LENGTH_MISMATCH
;
286 /* Reference the process */
287 Status
= ObReferenceObjectByHandle(ProcessHandle
,
288 PROCESS_QUERY_INFORMATION
,
293 if (!NT_SUCCESS(Status
)) break;
295 /* Protect writes with SEH */
298 /* Copy time information from EPROCESS/KPROCESS */
299 /* FIXME: Call KeQueryRuntimeProcess */
300 ProcessTime
->CreateTime
= Process
->CreateTime
;
301 ProcessTime
->UserTime
.QuadPart
= Process
->Pcb
.UserTime
*
303 ProcessTime
->KernelTime
.QuadPart
= Process
->Pcb
.KernelTime
*
305 ProcessTime
->ExitTime
= Process
->ExitTime
;
307 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
309 /* Get exception code */
310 Status
= _SEH2_GetExceptionCode();
314 /* Dereference the process */
315 ObDereferenceObject(Process
);
318 /* Process Debug Port */
319 case ProcessDebugPort
:
321 /* Set return length */
322 Length
= sizeof(HANDLE
);
324 if (ProcessInformationLength
!= Length
)
326 Status
= STATUS_INFO_LENGTH_MISMATCH
;
330 /* Reference the process */
331 Status
= ObReferenceObjectByHandle(ProcessHandle
,
332 PROCESS_QUERY_INFORMATION
,
337 if (!NT_SUCCESS(Status
)) break;
339 /* Protect write with SEH */
342 /* Return whether or not we have a debug port */
343 *(PHANDLE
)ProcessInformation
= (Process
->DebugPort
?
346 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
348 /* Get exception code */
349 Status
= _SEH2_GetExceptionCode();
353 /* Dereference the process */
354 ObDereferenceObject(Process
);
357 case ProcessHandleCount
:
359 /* Set the return length*/
360 Length
= sizeof(ULONG
);
362 if (ProcessInformationLength
!= Length
)
364 Status
= STATUS_INFO_LENGTH_MISMATCH
;
368 /* Reference the process */
369 Status
= ObReferenceObjectByHandle(ProcessHandle
,
370 PROCESS_QUERY_INFORMATION
,
375 if (!NT_SUCCESS(Status
)) break;
377 /* Count the number of handles this process has */
378 HandleCount
= ObGetProcessHandleCount(Process
);
380 /* Protect write in SEH */
383 /* Return the count of handles */
384 *(PULONG
)ProcessInformation
= HandleCount
;
386 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
388 /* Get the exception code */
389 Status
= _SEH2_GetExceptionCode();
393 /* Dereference the process */
394 ObDereferenceObject(Process
);
397 /* Session ID for the process */
398 case ProcessSessionInformation
:
400 /* Set the return length*/
401 Length
= sizeof(PROCESS_SESSION_INFORMATION
);
403 if (ProcessInformationLength
!= Length
)
405 Status
= STATUS_INFO_LENGTH_MISMATCH
;
409 /* Reference the process */
410 Status
= ObReferenceObjectByHandle(ProcessHandle
,
411 PROCESS_QUERY_INFORMATION
,
416 if (!NT_SUCCESS(Status
)) break;
418 /* Enter SEH for write safety */
421 /* Write back the Session ID */
422 SessionInfo
->SessionId
= Process
->Session
; //MmGetSessionId(Process);
424 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
426 /* Get the exception code */
427 Status
= _SEH2_GetExceptionCode();
431 /* Dereference the process */
432 ObDereferenceObject(Process
);
435 /* Virtual Memory Statistics */
436 case ProcessVmCounters
:
438 /* Validate the input length */
439 if ((ProcessInformationLength
!= sizeof(VM_COUNTERS
)) &&
440 (ProcessInformationLength
!= sizeof(VM_COUNTERS_EX
)))
442 Status
= STATUS_INFO_LENGTH_MISMATCH
;
446 /* Set the return length */
447 Length
= ProcessInformationLength
;
449 /* Reference the process */
450 Status
= ObReferenceObjectByHandle(ProcessHandle
,
451 PROCESS_QUERY_INFORMATION
,
456 if (!NT_SUCCESS(Status
)) break;
458 /* Enter SEH for write safety */
461 /* Return data from EPROCESS */
462 VmCounters
->PeakVirtualSize
= Process
->PeakVirtualSize
;
463 VmCounters
->VirtualSize
= Process
->VirtualSize
;
464 VmCounters
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
465 VmCounters
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
466 VmCounters
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
467 VmCounters
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeak
[0];
468 VmCounters
->QuotaPagedPoolUsage
= Process
->QuotaUsage
[0];
469 VmCounters
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeak
[1];
470 VmCounters
->QuotaNonPagedPoolUsage
= Process
->QuotaUsage
[1];
471 VmCounters
->PagefileUsage
= Process
->QuotaUsage
[2] << PAGE_SHIFT
;
472 VmCounters
->PeakPagefileUsage
= Process
->QuotaPeak
[2] << PAGE_SHIFT
;
473 //VmCounters->PrivateUsage = Process->CommitCharge << PAGE_SHIFT;
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 ExFreePool(ImageName
);
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
:
823 DPRINT1("Image Information Query Not implemented: %lx\n", ProcessInformationClass
);
824 Status
= STATUS_NOT_IMPLEMENTED
;
827 case ProcessDebugObjectHandle
:
828 DPRINT1("Debug Object Query Not implemented: %lx\n", ProcessInformationClass
);
829 Status
= STATUS_NOT_IMPLEMENTED
;
832 case ProcessHandleTracing
:
833 DPRINT1("Handle tracing Not implemented: %lx\n", ProcessInformationClass
);
834 Status
= STATUS_NOT_IMPLEMENTED
;
837 case ProcessLUIDDeviceMapsEnabled
:
838 DPRINT1("LUID Device Maps Not implemented: %lx\n", ProcessInformationClass
);
839 Status
= STATUS_NOT_IMPLEMENTED
;
842 case ProcessExecuteFlags
:
843 DPRINT1("No execute Not implemented: %lx\n", ProcessInformationClass
);
844 Status
= STATUS_NOT_IMPLEMENTED
;
847 case ProcessWow64Information
:
848 case ProcessLdtInformation
:
849 case ProcessWx86Information
:
850 DPRINT1("VDM/16-bit implemented: %lx\n", ProcessInformationClass
);
851 Status
= STATUS_NOT_IMPLEMENTED
;
854 case ProcessWorkingSetWatch
:
855 DPRINT1("WS Watch Not implemented: %lx\n", ProcessInformationClass
);
856 Status
= STATUS_NOT_IMPLEMENTED
;
859 case ProcessPooledUsageAndLimits
:
860 DPRINT1("Pool limits Not implemented: %lx\n", ProcessInformationClass
);
861 Status
= STATUS_NOT_IMPLEMENTED
;
864 /* Not supported by Server 2003 */
866 DPRINT1("Unsupported info class: %lx\n", ProcessInformationClass
);
867 Status
= STATUS_INVALID_INFO_CLASS
;
870 /* Protect write with SEH */
873 /* Check if caller wanted return length */
874 if (ReturnLength
) *ReturnLength
= Length
;
876 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
878 /* Get exception code */
879 Status
= _SEH2_GetExceptionCode();
891 NtSetInformationProcess(IN HANDLE ProcessHandle
,
892 IN PROCESSINFOCLASS ProcessInformationClass
,
893 IN PVOID ProcessInformation
,
894 IN ULONG ProcessInformationLength
)
897 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
900 HANDLE PortHandle
= NULL
;
901 HANDLE TokenHandle
= NULL
;
902 PROCESS_SESSION_INFORMATION SessionInfo
= {0};
903 PROCESS_PRIORITY_CLASS PriorityClass
= {0};
904 PROCESS_FOREGROUND_BACKGROUND Foreground
= {0};
907 KAFFINITY ValidAffinity
, Affinity
= 0;
908 ULONG DefaultHardErrorMode
= 0, BasePriority
= 0, MemoryPriority
= 0;
909 ULONG DisableBoost
= 0, DebugFlags
= 0, EnableFixup
= 0, Boost
= 0;
914 /* Verify Information Class validity */
916 Status
= DefaultSetInfoBufferCheck(ProcessInformationClass
,
918 RTL_NUMBER_OF(PsProcessInfoClass
),
920 ProcessInformationLength
,
922 if (!NT_SUCCESS(Status
)) return Status
;
925 /* Check what class this is */
926 Access
= PROCESS_SET_INFORMATION
;
927 if (ProcessInformationClass
== ProcessSessionInformation
)
929 /* Setting the Session ID needs a special mask */
930 Access
|= PROCESS_SET_SESSIONID
;
932 else if (ProcessInformationClass
== ProcessExceptionPort
)
934 /* Setting the exception port needs a special mask */
935 Access
|= PROCESS_SUSPEND_RESUME
;
938 /* Reference the process */
939 Status
= ObReferenceObjectByHandle(ProcessHandle
,
945 if (!NT_SUCCESS(Status
)) return Status
;
947 /* Check what kind of information class this is */
948 switch (ProcessInformationClass
)
950 /* Error/Exception Port */
951 case ProcessExceptionPort
:
953 /* Check buffer length */
954 if (ProcessInformationLength
!= sizeof(HANDLE
))
956 Status
= STATUS_INFO_LENGTH_MISMATCH
;
960 /* Use SEH for capture */
963 /* Capture the handle */
964 PortHandle
= *(PHANDLE
)ProcessInformation
;
966 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
968 /* Get the exception code */
969 Status
= _SEH2_GetExceptionCode();
974 /* Setting the error port requires the SeTcbPrivilege */
975 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
977 /* Can't set the session ID, bail out. */
978 Status
= STATUS_PRIVILEGE_NOT_HELD
;
982 /* Get the LPC Port */
983 Status
= ObReferenceObjectByHandle(PortHandle
,
987 (PVOID
)&ExceptionPort
,
989 if (!NT_SUCCESS(Status
)) break;
991 /* Change the pointer */
992 if (InterlockedCompareExchangePointer(&Process
->ExceptionPort
,
996 /* We already had one, fail */
997 ObDereferenceObject(ExceptionPort
);
998 Status
= STATUS_PORT_ALREADY_SET
;
1002 /* Security Token */
1003 case ProcessAccessToken
:
1005 /* Check buffer length */
1006 if (ProcessInformationLength
!= sizeof(PROCESS_ACCESS_TOKEN
))
1008 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1012 /* Use SEH for capture */
1015 /* Save the token handle */
1016 TokenHandle
= ((PPROCESS_ACCESS_TOKEN
)ProcessInformation
)->
1019 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1021 /* Get the exception code */
1022 Status
= _SEH2_GetExceptionCode();
1027 /* Assign the actual token */
1028 Status
= PspSetPrimaryToken(Process
, TokenHandle
, NULL
);
1031 /* Hard error processing */
1032 case ProcessDefaultHardErrorMode
:
1034 /* Check buffer length */
1035 if (ProcessInformationLength
!= sizeof(ULONG
))
1037 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1041 /* Enter SEH for direct buffer read */
1044 DefaultHardErrorMode
= *(PULONG
)ProcessInformation
;
1046 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1048 /* Get exception code */
1049 Status
= _SEH2_GetExceptionCode();
1055 Process
->DefaultHardErrorProcessing
= DefaultHardErrorMode
;
1057 /* Call Ke for the update */
1058 if (DefaultHardErrorMode
& SEM_NOALIGNMENTFAULTEXCEPT
)
1060 KeSetAutoAlignmentProcess(&Process
->Pcb
, TRUE
);
1064 KeSetAutoAlignmentProcess(&Process
->Pcb
, FALSE
);
1066 Status
= STATUS_SUCCESS
;
1070 case ProcessSessionInformation
:
1072 /* Check buffer length */
1073 if (ProcessInformationLength
!= sizeof(PROCESS_SESSION_INFORMATION
))
1075 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1079 /* Enter SEH for capture */
1082 /* Capture the caller's buffer */
1083 SessionInfo
= *(PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
1085 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1087 /* Get the exception code */
1088 Status
= _SEH2_GetExceptionCode();
1093 /* Setting the session id requires the SeTcbPrivilege */
1094 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
1096 /* Can't set the session ID, bail out. */
1097 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1101 /* FIXME - update the session id for the process token */
1102 //Status = PsLockProcess(Process, FALSE);
1103 if (!NT_SUCCESS(Status
)) break;
1105 /* Write the session ID in the EPROCESS */
1106 Process
->Session
= SessionInfo
.SessionId
;
1108 /* Check if the process also has a PEB */
1112 * Attach to the process to make sure we're in the right
1113 * context to access the PEB structure
1115 KeAttachProcess(&Process
->Pcb
);
1117 /* Enter SEH for write to user-mode PEB */
1120 /* Write the session ID */
1121 Process
->Peb
->SessionId
= SessionInfo
.SessionId
;
1123 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1125 /* Get exception code */
1126 Status
= _SEH2_GetExceptionCode();
1130 /* Detach from the process */
1134 /* Unlock the process */
1135 //PsUnlockProcess(Process);
1138 case ProcessPriorityClass
:
1140 /* Check buffer length */
1141 if (ProcessInformationLength
!= sizeof(PROCESS_PRIORITY_CLASS
))
1143 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1147 /* Enter SEH for capture */
1150 /* Capture the caller's buffer */
1151 PriorityClass
= *(PPROCESS_PRIORITY_CLASS
)ProcessInformation
;
1153 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1155 /* Return the exception code */
1156 Status
= _SEH2_GetExceptionCode();
1161 /* Check for invalid PriorityClass value */
1162 if (PriorityClass
.PriorityClass
> PROCESS_PRIORITY_CLASS_ABOVE_NORMAL
)
1164 Status
= STATUS_INVALID_PARAMETER
;
1168 if ((PriorityClass
.PriorityClass
!= Process
->PriorityClass
) &&
1169 (PriorityClass
.PriorityClass
== PROCESS_PRIORITY_CLASS_REALTIME
))
1171 /* TODO: Check privileges */
1172 DPRINT1("Should check privilege\n");
1175 /* Check if we have a job */
1178 DPRINT1("Jobs not yet supported\n");
1181 /* Set process priority class */
1182 Process
->PriorityClass
= PriorityClass
.PriorityClass
;
1184 /* Set process priority mode (foreground or background) */
1185 PsSetProcessPriorityByClass(Process
,
1186 PriorityClass
.Foreground
?
1187 PsProcessPriorityForeground
:
1188 PsProcessPriorityBackground
);
1189 Status
= STATUS_SUCCESS
;
1192 case ProcessForegroundInformation
:
1194 /* Check buffer length */
1195 if (ProcessInformationLength
!= sizeof(PROCESS_FOREGROUND_BACKGROUND
))
1197 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1201 /* Enter SEH for capture */
1204 /* Capture the caller's buffer */
1205 Foreground
= *(PPROCESS_FOREGROUND_BACKGROUND
)ProcessInformation
;
1207 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1209 /* Return the exception code */
1210 Status
= _SEH2_GetExceptionCode();
1215 /* Set process priority mode (foreground or background) */
1216 PsSetProcessPriorityByClass(Process
,
1217 Foreground
.Foreground
?
1218 PsProcessPriorityForeground
:
1219 PsProcessPriorityBackground
);
1220 Status
= STATUS_SUCCESS
;
1223 case ProcessBasePriority
:
1225 /* Validate input length */
1226 if (ProcessInformationLength
!= sizeof(KPRIORITY
))
1228 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1232 /* Enter SEH for direct buffer read */
1235 BasePriority
= *(PULONG
)ProcessInformation
;
1237 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1239 /* Get exception code */
1241 Status
= _SEH2_GetExceptionCode();
1246 /* Extract the memory priority out of there */
1247 if (BasePriority
& 0x80000000)
1249 MemoryPriority
= MEMORY_PRIORITY_FOREGROUND
;
1250 BasePriority
&= ~0x80000000;
1254 MemoryPriority
= MEMORY_PRIORITY_BACKGROUND
;
1257 /* Validate the number */
1258 if ((BasePriority
> HIGH_PRIORITY
) || (BasePriority
<= LOW_PRIORITY
))
1260 return STATUS_INVALID_PARAMETER
;
1263 /* Check if the new base is higher */
1264 if (BasePriority
> Process
->Pcb
.BasePriority
)
1266 DPRINT1("Should check privilege\n");
1270 KeSetPriorityAndQuantumProcess(&Process
->Pcb
, BasePriority
, 0);
1272 /* Now set the memory priority */
1273 MmSetMemoryPriorityProcess(Process
, MemoryPriority
);
1274 Status
= STATUS_SUCCESS
;
1277 case ProcessRaisePriority
:
1279 /* Validate input length */
1280 if (ProcessInformationLength
!= sizeof(ULONG
))
1282 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1286 /* Enter SEH for direct buffer read */
1289 Boost
= *(PULONG
)ProcessInformation
;
1291 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1293 /* Get exception code */
1295 Status
= _SEH2_GetExceptionCode();
1300 /* Make sure the process isn't dying */
1301 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1304 KeEnterCriticalRegion();
1305 ExAcquirePushLockShared(&Process
->ProcessLock
);
1307 /* Loop the threads */
1308 for (Next
= Process
->ThreadListHead
.Flink
;
1309 Next
!= &Process
->ThreadListHead
;
1312 /* Call Ke for the thread */
1313 Thread
= CONTAINING_RECORD(Next
, ETHREAD
, ThreadListEntry
);
1314 KeBoostPriorityThread(&Thread
->Tcb
, Boost
);
1317 /* Release the lock and rundown */
1318 ExReleasePushLockShared(&Process
->ProcessLock
);
1319 KeLeaveCriticalRegion();
1320 ExReleaseRundownProtection(&Process
->RundownProtect
);
1322 /* Set success code */
1323 Status
= STATUS_SUCCESS
;
1327 /* Avoid race conditions */
1328 Status
= STATUS_PROCESS_IS_TERMINATING
;
1332 case ProcessBreakOnTermination
:
1334 /* Check buffer length */
1335 if (ProcessInformationLength
!= sizeof(ULONG
))
1337 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1341 /* Enter SEH for direct buffer read */
1344 Break
= *(PULONG
)ProcessInformation
;
1346 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1348 /* Get exception code */
1350 Status
= _SEH2_GetExceptionCode();
1355 /* Setting 'break on termination' requires the SeDebugPrivilege */
1356 if (!SeSinglePrivilegeCheck(SeDebugPrivilege
, PreviousMode
))
1358 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1362 /* Set or clear the flag */
1365 PspSetProcessFlag(Process
, PSF_BREAK_ON_TERMINATION_BIT
);
1369 PspClearProcessFlag(Process
, PSF_BREAK_ON_TERMINATION_BIT
);
1374 case ProcessAffinityMask
:
1376 /* Check buffer length */
1377 if (ProcessInformationLength
!= sizeof(KAFFINITY
))
1379 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1383 /* Enter SEH for direct buffer read */
1386 Affinity
= *(PKAFFINITY
)ProcessInformation
;
1388 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1390 /* Get exception code */
1392 Status
= _SEH2_GetExceptionCode();
1397 /* Make sure it's valid for the CPUs present */
1398 ValidAffinity
= Affinity
& KeActiveProcessors
;
1399 if (!Affinity
|| (ValidAffinity
!= Affinity
))
1401 Status
= STATUS_INVALID_PARAMETER
;
1405 /* Check if it's within job affinity limits */
1408 /* Not yet implemented */
1410 Status
= STATUS_NOT_IMPLEMENTED
;
1414 /* Make sure the process isn't dying */
1415 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1418 KeEnterCriticalRegion();
1419 ExAcquirePushLockShared(&Process
->ProcessLock
);
1421 /* Call Ke to do the work */
1422 KeSetAffinityProcess(&Process
->Pcb
, ValidAffinity
);
1424 /* Release the lock and rundown */
1425 ExReleasePushLockShared(&Process
->ProcessLock
);
1426 KeLeaveCriticalRegion();
1427 ExReleaseRundownProtection(&Process
->RundownProtect
);
1429 /* Set success code */
1430 Status
= STATUS_SUCCESS
;
1434 /* Avoid race conditions */
1435 Status
= STATUS_PROCESS_IS_TERMINATING
;
1439 /* Priority Boosting status */
1440 case ProcessPriorityBoost
:
1442 /* Validate input length */
1443 if (ProcessInformationLength
!= sizeof(ULONG
))
1445 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1449 /* Enter SEH for direct buffer read */
1452 DisableBoost
= *(PULONG
)ProcessInformation
;
1454 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1456 /* Get exception code */
1458 Status
= _SEH2_GetExceptionCode();
1463 /* Make sure the process isn't dying */
1464 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1467 KeEnterCriticalRegion();
1468 ExAcquirePushLockShared(&Process
->ProcessLock
);
1470 /* Call Ke to do the work */
1471 KeSetDisableBoostProcess(&Process
->Pcb
, DisableBoost
);
1473 /* Loop the threads too */
1474 for (Next
= Process
->ThreadListHead
.Flink
;
1475 Next
!= &Process
->ThreadListHead
;
1478 /* Call Ke for the thread */
1479 Thread
= CONTAINING_RECORD(Next
, ETHREAD
, ThreadListEntry
);
1480 KeSetDisableBoostThread(&Thread
->Tcb
, DisableBoost
);
1483 /* Release the lock and rundown */
1484 ExReleasePushLockShared(&Process
->ProcessLock
);
1485 KeLeaveCriticalRegion();
1486 ExReleaseRundownProtection(&Process
->RundownProtect
);
1488 /* Set success code */
1489 Status
= STATUS_SUCCESS
;
1493 /* Avoid race conditions */
1494 Status
= STATUS_PROCESS_IS_TERMINATING
;
1498 case ProcessDebugFlags
:
1500 /* Check buffer length */
1501 if (ProcessInformationLength
!= sizeof(ULONG
))
1503 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1507 /* Enter SEH for direct buffer read */
1510 DebugFlags
= *(PULONG
)ProcessInformation
;
1512 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1514 /* Get exception code */
1515 Status
= _SEH2_GetExceptionCode();
1521 if (DebugFlags
& ~1)
1523 Status
= STATUS_INVALID_PARAMETER
;
1529 PspClearProcessFlag(Process
, PSF_NO_DEBUG_INHERIT_BIT
);
1533 PspSetProcessFlag(Process
, PSF_NO_DEBUG_INHERIT_BIT
);
1538 Status
= STATUS_SUCCESS
;
1541 case ProcessEnableAlignmentFaultFixup
:
1543 /* Check buffer length */
1544 if (ProcessInformationLength
!= sizeof(ULONG
))
1546 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1550 /* Enter SEH for direct buffer read */
1553 EnableFixup
= *(PULONG
)ProcessInformation
;
1555 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1557 /* Get exception code */
1558 Status
= _SEH2_GetExceptionCode();
1566 Process
->DefaultHardErrorProcessing
|= SEM_NOALIGNMENTFAULTEXCEPT
;
1570 Process
->DefaultHardErrorProcessing
&= ~SEM_NOALIGNMENTFAULTEXCEPT
;
1573 /* Call Ke for the update */
1574 KeSetAutoAlignmentProcess(&Process
->Pcb
, FALSE
);
1575 Status
= STATUS_SUCCESS
;
1578 /* We currently don't implement any of these */
1579 case ProcessLdtInformation
:
1580 case ProcessLdtSize
:
1581 case ProcessIoPortHandlers
:
1582 case ProcessUserModeIOPL
:
1583 case ProcessWx86Information
:
1584 DPRINT1("VDM/16-bit Request not implemented: %lx\n", ProcessInformationClass
);
1585 Status
= STATUS_NOT_IMPLEMENTED
;
1588 case ProcessQuotaLimits
:
1589 DPRINT1("Quota Limits not implemented\n");
1590 Status
= STATUS_NOT_IMPLEMENTED
;
1593 case ProcessWorkingSetWatch
:
1594 DPRINT1("WS watch not implemented\n");
1595 Status
= STATUS_NOT_IMPLEMENTED
;
1598 case ProcessDeviceMap
:
1599 DPRINT1("Device map not implemented\n");
1600 Status
= STATUS_NOT_IMPLEMENTED
;
1603 case ProcessHandleTracing
:
1604 DPRINT1("Handle tracing not implemented\n");
1605 Status
= STATUS_NOT_IMPLEMENTED
;
1608 case ProcessExecuteFlags
:
1609 DPRINT1("No execute support not implemented\n");
1610 Status
= STATUS_NOT_IMPLEMENTED
;
1613 /* Anything else is invalid */
1615 DPRINT1("Invalid Server 2003 Info Class: %lx\n", ProcessInformationClass
);
1616 Status
= STATUS_INVALID_INFO_CLASS
;
1619 /* Dereference and return status */
1620 ObDereferenceObject(Process
);
1629 NtSetInformationThread(IN HANDLE ThreadHandle
,
1630 IN THREADINFOCLASS ThreadInformationClass
,
1631 IN PVOID ThreadInformation
,
1632 IN ULONG ThreadInformationLength
)
1636 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1638 HANDLE TokenHandle
= NULL
;
1639 KPRIORITY Priority
= 0;
1640 KAFFINITY Affinity
= 0, CombinedAffinity
;
1641 PVOID Address
= NULL
;
1643 ULONG_PTR DisableBoost
= 0;
1644 ULONG_PTR IdealProcessor
= 0;
1646 ULONG_PTR TlsIndex
= 0;
1647 PVOID
*ExpansionSlots
;
1648 PETHREAD ProcThread
;
1651 /* Verify Information Class validity */
1653 Status
= DefaultSetInfoBufferCheck(ThreadInformationClass
,
1655 RTL_NUMBER_OF(PsThreadInfoClass
),
1657 ThreadInformationLength
,
1659 if (!NT_SUCCESS(Status
)) return Status
;
1662 /* Check what class this is */
1663 Access
= THREAD_SET_INFORMATION
;
1664 if (ThreadInformationClass
== ThreadImpersonationToken
)
1666 /* Setting the impersonation token needs a special mask */
1667 Access
= THREAD_SET_THREAD_TOKEN
;
1670 /* Reference the thread */
1671 Status
= ObReferenceObjectByHandle(ThreadHandle
,
1677 if (!NT_SUCCESS(Status
)) return Status
;
1679 /* Check what kind of information class this is */
1680 switch (ThreadInformationClass
)
1682 /* Thread priority */
1683 case ThreadPriority
:
1685 /* Check buffer length */
1686 if (ThreadInformationLength
!= sizeof(KPRIORITY
))
1688 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1692 /* Use SEH for capture */
1695 /* Get the priority */
1696 Priority
= *(PLONG
)ThreadInformation
;
1698 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1700 /* Get the exception code */
1701 Status
= _SEH2_GetExceptionCode();
1707 if ((Priority
> HIGH_PRIORITY
) ||
1708 (Priority
<= LOW_PRIORITY
))
1711 Status
= STATUS_INVALID_PARAMETER
;
1715 /* Set the priority */
1716 KeSetPriorityThread(&Thread
->Tcb
, Priority
);
1719 case ThreadBasePriority
:
1721 /* Check buffer length */
1722 if (ThreadInformationLength
!= sizeof(LONG
))
1724 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1728 /* Use SEH for capture */
1731 /* Get the priority */
1732 Priority
= *(PLONG
)ThreadInformation
;
1734 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1736 /* Get the exception code */
1737 Status
= _SEH2_GetExceptionCode();
1743 if ((Priority
> THREAD_BASE_PRIORITY_MAX
) ||
1744 (Priority
< THREAD_BASE_PRIORITY_MIN
))
1746 /* These ones are OK */
1747 if ((Priority
!= THREAD_BASE_PRIORITY_LOWRT
+ 1) &&
1748 (Priority
!= THREAD_BASE_PRIORITY_IDLE
- 1))
1750 /* Check if the process is real time */
1751 if (PsGetCurrentProcess()->PriorityClass
!=
1752 PROCESS_PRIORITY_CLASS_REALTIME
)
1754 /* It isn't, fail */
1755 Status
= STATUS_INVALID_PARAMETER
;
1761 /* Set the base priority */
1762 KeSetBasePriorityThread(&Thread
->Tcb
, Priority
);
1765 case ThreadAffinityMask
:
1767 /* Check buffer length */
1768 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1770 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1774 /* Use SEH for capture */
1777 /* Get the priority */
1778 Affinity
= *(PULONG_PTR
)ThreadInformation
;
1780 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1782 /* Get the exception code */
1783 Status
= _SEH2_GetExceptionCode();
1792 Status
= STATUS_INVALID_PARAMETER
;
1796 /* Get the process */
1797 Process
= Thread
->ThreadsProcess
;
1799 /* Try to acquire rundown */
1800 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1803 KeEnterCriticalRegion();
1804 ExAcquirePushLockShared(&Process
->ProcessLock
);
1807 CombinedAffinity
= Affinity
& Process
->Pcb
.Affinity
;
1808 if (CombinedAffinity
!= Affinity
)
1811 Status
= STATUS_INVALID_PARAMETER
;
1815 /* Set the affinity */
1816 KeSetAffinityThread(&Thread
->Tcb
, CombinedAffinity
);
1819 /* Release the lock and rundown */
1820 ExReleasePushLockShared(&Process
->ProcessLock
);
1821 KeLeaveCriticalRegion();
1822 ExReleaseRundownProtection(&Process
->RundownProtect
);
1827 Status
= STATUS_PROCESS_IS_TERMINATING
;
1833 case ThreadImpersonationToken
:
1835 /* Check buffer length */
1836 if (ThreadInformationLength
!= sizeof(HANDLE
))
1838 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1842 /* Use SEH for capture */
1845 /* Save the token handle */
1846 TokenHandle
= *(PHANDLE
)ThreadInformation
;
1848 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1850 /* Get the exception code */
1851 Status
= _SEH2_GetExceptionCode();
1856 /* Assign the actual token */
1857 Status
= PsAssignImpersonationToken(Thread
, TokenHandle
);
1860 case ThreadQuerySetWin32StartAddress
:
1862 /* Check buffer length */
1863 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1865 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1869 /* Use SEH for capture */
1872 /* Get the priority */
1873 Address
= *(PVOID
*)ThreadInformation
;
1875 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1877 /* Get the exception code */
1878 Status
= _SEH2_GetExceptionCode();
1883 /* Set the address */
1884 Thread
->Win32StartAddress
= Address
;
1887 case ThreadIdealProcessor
:
1889 /* Check buffer length */
1890 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1892 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1896 /* Use SEH for capture */
1899 /* Get the priority */
1900 IdealProcessor
= *(PULONG_PTR
)ThreadInformation
;
1902 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1904 /* Get the exception code */
1905 Status
= _SEH2_GetExceptionCode();
1911 if (IdealProcessor
> MAXIMUM_PROCESSORS
)
1914 Status
= STATUS_INVALID_PARAMETER
;
1919 Status
= KeSetIdealProcessorThread(&Thread
->Tcb
,
1920 (CCHAR
)IdealProcessor
);
1922 /* Get the TEB and protect the thread */
1923 Teb
= Thread
->Tcb
.Teb
;
1924 if ((Teb
) && (ExAcquireRundownProtection(&Thread
->RundownProtect
)))
1926 /* Save the ideal processor */
1927 Teb
->IdealProcessor
= Thread
->Tcb
.IdealProcessor
;
1929 /* Release rundown protection */
1930 ExReleaseRundownProtection(&Thread
->RundownProtect
);
1935 case ThreadPriorityBoost
:
1937 /* Check buffer length */
1938 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1940 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1944 /* Use SEH for capture */
1947 /* Get the priority */
1948 DisableBoost
= *(PULONG_PTR
)ThreadInformation
;
1950 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1952 /* Get the exception code */
1953 Status
= _SEH2_GetExceptionCode();
1958 /* Call the kernel */
1959 KeSetDisableBoostThread(&Thread
->Tcb
, (BOOLEAN
)DisableBoost
);
1962 case ThreadZeroTlsCell
:
1964 /* Check buffer length */
1965 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1967 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1971 /* Use SEH for capture */
1974 /* Get the priority */
1975 TlsIndex
= *(PULONG_PTR
)ThreadInformation
;
1977 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1979 /* Get the exception code */
1980 Status
= _SEH2_GetExceptionCode();
1985 /* This is only valid for the current thread */
1986 if (Thread
!= PsGetCurrentThread())
1989 Status
= STATUS_INVALID_PARAMETER
;
1993 /* Get the process */
1994 Process
= Thread
->ThreadsProcess
;
1996 /* Loop the threads */
1997 ProcThread
= PsGetNextProcessThread(Process
, NULL
);
2000 /* Acquire rundown */
2001 if (ExAcquireRundownProtection(&ProcThread
->RundownProtect
))
2004 Teb
= ProcThread
->Tcb
.Teb
;
2007 /* Check if we're in the expansion range */
2008 if (TlsIndex
> TLS_MINIMUM_AVAILABLE
- 1)
2010 if (TlsIndex
< (TLS_MINIMUM_AVAILABLE
+
2011 TLS_EXPANSION_SLOTS
) - 1)
2013 /* Check if we have expansion slots */
2014 ExpansionSlots
= Teb
->TlsExpansionSlots
;
2017 /* Clear the index */
2018 ExpansionSlots
[TlsIndex
- TLS_MINIMUM_AVAILABLE
] = 0;
2024 /* Clear the index */
2025 Teb
->TlsSlots
[TlsIndex
] = NULL
;
2029 /* Release rundown */
2030 ExReleaseRundownProtection(&ProcThread
->RundownProtect
);
2033 /* Go to the next thread */
2034 ProcThread
= PsGetNextProcessThread(Process
, ProcThread
);
2041 /* We don't implement it yet */
2042 DPRINT1("Not implemented: %lx\n", ThreadInformationClass
);
2043 Status
= STATUS_NOT_IMPLEMENTED
;
2046 /* Dereference and return status */
2047 ObDereferenceObject(Thread
);
2056 NtQueryInformationThread(IN HANDLE ThreadHandle
,
2057 IN THREADINFOCLASS ThreadInformationClass
,
2058 OUT PVOID ThreadInformation
,
2059 IN ULONG ThreadInformationLength
,
2060 OUT PULONG ReturnLength OPTIONAL
)
2063 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2067 PTHREAD_BASIC_INFORMATION ThreadBasicInfo
=
2068 (PTHREAD_BASIC_INFORMATION
)ThreadInformation
;
2069 PKERNEL_USER_TIMES ThreadTime
= (PKERNEL_USER_TIMES
)ThreadInformation
;
2073 /* Check if we were called from user mode */
2074 if (PreviousMode
!= KernelMode
)
2079 /* Probe the buffer */
2080 ProbeForWrite(ThreadInformation
,
2081 ThreadInformationLength
,
2084 /* Probe the return length if required */
2085 if (ReturnLength
) ProbeForWriteUlong(ReturnLength
);
2087 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2089 /* Return the exception code */
2090 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2095 /* Check what class this is */
2096 Access
= THREAD_QUERY_INFORMATION
;
2098 /* Reference the process */
2099 Status
= ObReferenceObjectByHandle(ThreadHandle
,
2105 if (!NT_SUCCESS(Status
)) return Status
;
2107 /* Check what kind of information class this is */
2108 switch (ThreadInformationClass
)
2110 /* Basic thread information */
2111 case ThreadBasicInformation
:
2113 /* Set return length */
2114 Length
= sizeof(THREAD_BASIC_INFORMATION
);
2116 if (ThreadInformationLength
!= Length
)
2118 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2121 /* Protect writes with SEH */
2124 /* Write all the information from the ETHREAD/KTHREAD */
2125 ThreadBasicInfo
->ExitStatus
= Thread
->ExitStatus
;
2126 ThreadBasicInfo
->TebBaseAddress
= (PVOID
)Thread
->Tcb
.Teb
;
2127 ThreadBasicInfo
->ClientId
= Thread
->Cid
;
2128 ThreadBasicInfo
->AffinityMask
= Thread
->Tcb
.Affinity
;
2129 ThreadBasicInfo
->Priority
= Thread
->Tcb
.Priority
;
2130 ThreadBasicInfo
->BasePriority
= KeQueryBasePriorityThread(&Thread
->Tcb
);
2132 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2134 /* Get exception code */
2135 Status
= _SEH2_GetExceptionCode();
2140 /* Thread time information */
2143 /* Set the return length */
2144 Length
= sizeof(KERNEL_USER_TIMES
);
2146 if (ThreadInformationLength
!= Length
)
2148 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2151 /* Protect writes with SEH */
2154 /* Copy time information from ETHREAD/KTHREAD */
2155 ThreadTime
->KernelTime
.QuadPart
= Thread
->Tcb
.KernelTime
*
2157 ThreadTime
->UserTime
.QuadPart
= Thread
->Tcb
.UserTime
*
2159 ThreadTime
->CreateTime
= Thread
->CreateTime
;
2160 ThreadTime
->ExitTime
= Thread
->ExitTime
;
2162 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2164 /* Get exception code */
2165 Status
= _SEH2_GetExceptionCode();
2170 case ThreadQuerySetWin32StartAddress
:
2172 /* Set the return length*/
2173 Length
= sizeof(PVOID
);
2175 if (ThreadInformationLength
!= Length
)
2177 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2180 /* Protect write with SEH */
2183 /* Return the Win32 Start Address */
2184 *(PVOID
*)ThreadInformation
= Thread
->Win32StartAddress
;
2186 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2188 /* Get exception code */
2189 Status
= _SEH2_GetExceptionCode();
2194 case ThreadPerformanceCount
:
2196 /* Set the return length*/
2197 Length
= sizeof(LARGE_INTEGER
);
2199 if (ThreadInformationLength
!= Length
)
2201 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2204 /* Protect write with SEH */
2208 (*(PLARGE_INTEGER
)ThreadInformation
).QuadPart
= 0;
2210 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2212 /* Get exception code */
2213 Status
= _SEH2_GetExceptionCode();
2218 case ThreadAmILastThread
:
2220 /* Set the return length*/
2221 Length
= sizeof(ULONG
);
2223 if (ThreadInformationLength
!= Length
)
2225 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2228 /* Protect write with SEH */
2231 /* Return whether or not we are the last thread */
2232 *(PULONG
)ThreadInformation
= ((Thread
->ThreadsProcess
->
2233 ThreadListHead
.Flink
->Flink
==
2234 &Thread
->ThreadsProcess
->
2238 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2240 /* Get exception code */
2241 Status
= _SEH2_GetExceptionCode();
2246 case ThreadIsIoPending
:
2248 /* Set the return length*/
2249 Length
= sizeof(ULONG
);
2251 if (ThreadInformationLength
!= Length
)
2253 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2256 /* Raise the IRQL to protect the IRP list */
2257 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2259 /* Protect write with SEH */
2262 /* Check if the IRP list is empty or not */
2263 *(PULONG
)ThreadInformation
= !IsListEmpty(&Thread
->IrpList
);
2265 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2267 /* Get exception code */
2268 Status
= _SEH2_GetExceptionCode();
2272 /* Lower IRQL back */
2273 KeLowerIrql(OldIrql
);
2276 /* LDT and GDT information */
2277 case ThreadDescriptorTableEntry
:
2280 /* Call the worker routine */
2281 Status
= PspQueryDescriptorThread(Thread
,
2283 ThreadInformationLength
,
2286 /* Only implemented on x86 */
2287 Status
= STATUS_NOT_IMPLEMENTED
;
2291 case ThreadPriorityBoost
:
2293 /* Set the return length*/
2294 Length
= sizeof(ULONG
);
2296 if (ThreadInformationLength
!= Length
)
2298 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2304 *(PULONG
)ThreadInformation
= Thread
->Tcb
.DisableBoost
? 1 : 0;
2306 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2308 Status
= _SEH2_GetExceptionCode();
2316 /* Not yet implemented */
2317 DPRINT1("Not implemented: %lx\n", ThreadInformationClass
);
2318 Status
= STATUS_NOT_IMPLEMENTED
;
2321 /* Protect write with SEH */
2324 /* Check if caller wanted return length */
2325 if (ReturnLength
) *ReturnLength
= Length
;
2327 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2329 /* Get exception code */
2330 Status
= _SEH2_GetExceptionCode();
2334 /* Dereference the thread, and return */
2335 ObDereferenceObject(Thread
);