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 /* Include Information Class Tables */
18 #include "internal/ps_i.h"
21 ULONG PspTraceLevel
= 0;
23 /* PRIVATE FUNCTIONS *********************************************************/
27 PsReferenceProcessFilePointer(IN PEPROCESS Process
,
28 OUT PFILE_OBJECT
*FileObject
)
33 /* Lock the process */
34 ExAcquireRundownProtection(&Process
->RundownProtect
);
37 Section
= Process
->SectionObject
;
40 /* Get the file object and reference it */
41 *FileObject
= MmGetFileObjectForSection((PVOID
)Section
);
42 ObReferenceObject(*FileObject
);
45 /* Release the protection */
46 ExReleaseRundownProtection(&Process
->RundownProtect
);
49 return Section
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
;
52 /* PUBLIC FUNCTIONS **********************************************************/
59 NtQueryInformationProcess(IN HANDLE ProcessHandle
,
60 IN PROCESSINFOCLASS ProcessInformationClass
,
61 OUT PVOID ProcessInformation
,
62 IN ULONG ProcessInformationLength
,
63 OUT PULONG ReturnLength OPTIONAL
)
66 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
69 PPROCESS_BASIC_INFORMATION ProcessBasicInfo
=
70 (PPROCESS_BASIC_INFORMATION
)ProcessInformation
;
71 PKERNEL_USER_TIMES ProcessTime
= (PKERNEL_USER_TIMES
)ProcessInformation
;
72 PPROCESS_PRIORITY_CLASS PsPriorityClass
= (PPROCESS_PRIORITY_CLASS
)ProcessInformation
;
74 PPROCESS_SESSION_INFORMATION SessionInfo
=
75 (PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
76 PVM_COUNTERS VmCounters
= (PVM_COUNTERS
)ProcessInformation
;
77 PIO_COUNTERS IoCounters
= (PIO_COUNTERS
)ProcessInformation
;
78 PQUOTA_LIMITS QuotaLimits
= (PQUOTA_LIMITS
)ProcessInformation
;
79 PROCESS_DEVICEMAP_INFORMATION DeviceMap
;
80 PUNICODE_STRING ImageName
;
84 /* Check for user-mode caller */
85 if (PreviousMode
!= KernelMode
)
87 /* Prepare to probe parameters */
90 /* Probe the buffer */
91 ProbeForWrite(ProcessInformation
,
92 ProcessInformationLength
,
95 /* Probe the return length if required */
96 if (ReturnLength
) ProbeForWriteUlong(ReturnLength
);
98 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
100 /* Return the exception code */
101 _SEH2_YIELD(return _SEH2_GetExceptionCode());
106 if((ProcessInformationClass
== ProcessCookie
) &&
107 (ProcessHandle
!= NtCurrentProcess()))
110 * Retreiving the process cookie is only allowed for the calling process
111 * itself! XP only allowes NtCurrentProcess() as process handles even if
112 * a real handle actually represents the current process.
114 return STATUS_INVALID_PARAMETER
;
117 /* Check the information class */
118 switch (ProcessInformationClass
)
120 /* Basic process information */
121 case ProcessBasicInformation
:
123 /* Set return length */
124 Length
= sizeof(PROCESS_BASIC_INFORMATION
);
126 if (ProcessInformationLength
!= Length
)
128 Status
= STATUS_INFO_LENGTH_MISMATCH
;
132 /* Reference the process */
133 Status
= ObReferenceObjectByHandle(ProcessHandle
,
134 PROCESS_QUERY_INFORMATION
,
139 if (!NT_SUCCESS(Status
)) break;
141 /* Protect writes with SEH */
144 /* Write all the information from the EPROCESS/KPROCESS */
145 ProcessBasicInfo
->ExitStatus
= Process
->ExitStatus
;
146 ProcessBasicInfo
->PebBaseAddress
= Process
->Peb
;
147 ProcessBasicInfo
->AffinityMask
= Process
->Pcb
.Affinity
;
148 ProcessBasicInfo
->UniqueProcessId
= (ULONG_PTR
)Process
->
150 ProcessBasicInfo
->InheritedFromUniqueProcessId
=
151 (ULONG
)Process
->InheritedFromUniqueProcessId
;
152 ProcessBasicInfo
->BasePriority
= Process
->Pcb
.BasePriority
;
155 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
157 /* Get exception code */
158 Status
= _SEH2_GetExceptionCode();
162 /* Dereference the process */
163 ObDereferenceObject(Process
);
166 /* Process quota limits */
167 case ProcessQuotaLimits
:
169 Length
= sizeof(QUOTA_LIMITS
);
170 if (ProcessInformationLength
!= Length
)
172 Status
= STATUS_INFO_LENGTH_MISMATCH
;
176 /* Reference the process */
177 Status
= ObReferenceObjectByHandle(ProcessHandle
,
178 PROCESS_QUERY_INFORMATION
,
183 if (!NT_SUCCESS(Status
)) break;
185 /* Indicate success */
186 Status
= STATUS_SUCCESS
;
190 /* Set max/min working set sizes */
191 QuotaLimits
->MaximumWorkingSetSize
=
192 Process
->Vm
.MaximumWorkingSetSize
<< PAGE_SHIFT
;
193 QuotaLimits
->MinimumWorkingSetSize
=
194 Process
->Vm
.MinimumWorkingSetSize
<< PAGE_SHIFT
;
196 /* Set default time limits */
197 QuotaLimits
->TimeLimit
.LowPart
= MAXULONG
;
198 QuotaLimits
->TimeLimit
.HighPart
= MAXULONG
;
200 /* Is quota block a default one? */
201 if (Process
->QuotaBlock
== &PspDefaultQuotaBlock
)
203 /* Set default pools and pagefile limits */
204 QuotaLimits
->PagedPoolLimit
= (SIZE_T
)-1;
205 QuotaLimits
->NonPagedPoolLimit
= (SIZE_T
)-1;
206 QuotaLimits
->PagefileLimit
= (SIZE_T
)-1;
210 /* Get limits from non-default quota block */
211 QuotaLimits
->PagedPoolLimit
=
212 Process
->QuotaBlock
->QuotaEntry
[PagedPool
].Limit
;
213 QuotaLimits
->NonPagedPoolLimit
=
214 Process
->QuotaBlock
->QuotaEntry
[NonPagedPool
].Limit
;
215 QuotaLimits
->PagefileLimit
=
216 Process
->QuotaBlock
->QuotaEntry
[2].Limit
;
219 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
221 /* Get exception code */
222 Status
= _SEH2_GetExceptionCode();
226 /* Dereference the process */
227 ObDereferenceObject(Process
);
230 case ProcessIoCounters
:
232 Length
= sizeof(IO_COUNTERS
);
233 if (ProcessInformationLength
!= Length
)
235 Status
= STATUS_INFO_LENGTH_MISMATCH
;
239 /* Reference the process */
240 Status
= ObReferenceObjectByHandle(ProcessHandle
,
241 PROCESS_QUERY_INFORMATION
,
246 if (!NT_SUCCESS(Status
)) break;
250 IoCounters
->ReadOperationCount
= Process
->ReadOperationCount
.QuadPart
;
251 IoCounters
->ReadTransferCount
= Process
->ReadTransferCount
.QuadPart
;
252 IoCounters
->WriteOperationCount
= Process
->WriteOperationCount
.QuadPart
;
253 IoCounters
->WriteTransferCount
= Process
->WriteTransferCount
.QuadPart
;
254 IoCounters
->OtherOperationCount
= Process
->OtherOperationCount
.QuadPart
;
255 IoCounters
->OtherTransferCount
= Process
->OtherTransferCount
.QuadPart
;
257 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
259 /* Ignore exception */
263 /* Set status to success in any case */
264 Status
= STATUS_SUCCESS
;
266 /* Dereference the process */
267 ObDereferenceObject(Process
);
273 /* Set the return length */
274 Length
= sizeof(KERNEL_USER_TIMES
);
276 if (ProcessInformationLength
!= Length
)
278 Status
= STATUS_INFO_LENGTH_MISMATCH
;
282 /* Reference the process */
283 Status
= ObReferenceObjectByHandle(ProcessHandle
,
284 PROCESS_QUERY_INFORMATION
,
289 if (!NT_SUCCESS(Status
)) break;
291 /* Protect writes with SEH */
294 /* Copy time information from EPROCESS/KPROCESS */
295 ProcessTime
->CreateTime
= Process
->CreateTime
;
296 ProcessTime
->UserTime
.QuadPart
= Process
->Pcb
.UserTime
*
298 ProcessTime
->KernelTime
.QuadPart
= Process
->Pcb
.KernelTime
*
300 ProcessTime
->ExitTime
= Process
->ExitTime
;
302 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
304 /* Get exception code */
305 Status
= _SEH2_GetExceptionCode();
309 /* Dereference the process */
310 ObDereferenceObject(Process
);
313 /* Process Debug Port */
314 case ProcessDebugPort
:
316 /* Set return length */
317 Length
= sizeof(HANDLE
);
319 if (ProcessInformationLength
!= Length
)
321 Status
= STATUS_INFO_LENGTH_MISMATCH
;
325 /* Reference the process */
326 Status
= ObReferenceObjectByHandle(ProcessHandle
,
327 PROCESS_QUERY_INFORMATION
,
332 if (!NT_SUCCESS(Status
)) break;
334 /* Protect write with SEH */
337 /* Return whether or not we have a debug port */
338 *(PHANDLE
)ProcessInformation
= (Process
->DebugPort
?
341 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
343 /* Get exception code */
344 Status
= _SEH2_GetExceptionCode();
348 /* Dereference the process */
349 ObDereferenceObject(Process
);
352 /* LDT, WS and VDM Information: not implemented */
353 case ProcessLdtInformation
:
354 case ProcessWorkingSetWatch
:
355 case ProcessWx86Information
:
357 /* Reference the process */
358 Status
= ObReferenceObjectByHandle(ProcessHandle
,
359 PROCESS_QUERY_INFORMATION
,
364 if (!NT_SUCCESS(Status
)) break;
366 DPRINT1("Not implemented: %lx\n", ProcessInformationClass
);
368 /* Dereference the process */
369 ObDereferenceObject(Process
);
370 Status
= STATUS_NOT_IMPLEMENTED
;
373 case ProcessHandleCount
:
375 /* Set the return length*/
376 Length
= sizeof(ULONG
);
378 if (ProcessInformationLength
!= Length
)
380 Status
= STATUS_INFO_LENGTH_MISMATCH
;
384 /* Reference the process */
385 Status
= ObReferenceObjectByHandle(ProcessHandle
,
386 PROCESS_QUERY_INFORMATION
,
391 if (!NT_SUCCESS(Status
)) break;
393 /* Count the number of handles this process has */
394 HandleCount
= ObGetProcessHandleCount(Process
);
396 /* Protect write in SEH */
399 /* Return the count of handles */
400 *(PULONG
)ProcessInformation
= HandleCount
;
402 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
404 /* Get the exception code */
405 Status
= _SEH2_GetExceptionCode();
409 /* Dereference the process */
410 ObDereferenceObject(Process
);
413 /* Session ID for the process */
414 case ProcessSessionInformation
:
416 /* Set the return length*/
417 Length
= sizeof(PROCESS_SESSION_INFORMATION
);
419 if (ProcessInformationLength
!= Length
)
421 Status
= STATUS_INFO_LENGTH_MISMATCH
;
425 /* Reference the process */
426 Status
= ObReferenceObjectByHandle(ProcessHandle
,
427 PROCESS_QUERY_INFORMATION
,
432 if (!NT_SUCCESS(Status
)) break;
434 /* Enter SEH for write safety */
437 /* Write back the Session ID */
438 SessionInfo
->SessionId
= Process
->Session
;
440 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
442 /* Get the exception code */
443 Status
= _SEH2_GetExceptionCode();
447 /* Dereference the process */
448 ObDereferenceObject(Process
);
451 /* WOW64: Not implemented */
452 case ProcessWow64Information
:
454 /* Set the return length */
455 Length
= sizeof(ULONG_PTR
);
457 if (ProcessInformationLength
!= Length
)
459 Status
= STATUS_INFO_LENGTH_MISMATCH
;
463 /* Reference the process */
464 Status
= ObReferenceObjectByHandle(ProcessHandle
,
465 PROCESS_QUERY_INFORMATION
,
470 if (!NT_SUCCESS(Status
)) break;
472 DPRINT1("Not implemented: ProcessWow64Information\n");
474 /* Dereference the process */
475 ObDereferenceObject(Process
);
476 Status
= STATUS_NOT_IMPLEMENTED
;
479 /* Virtual Memory Statistics */
480 case ProcessVmCounters
:
482 /* Set the return length */
483 Length
= sizeof(VM_COUNTERS
);
485 if (ProcessInformationLength
!= Length
)
487 Status
= STATUS_INFO_LENGTH_MISMATCH
;
491 /* Reference the process */
492 Status
= ObReferenceObjectByHandle(ProcessHandle
,
493 PROCESS_QUERY_INFORMATION
,
498 if (!NT_SUCCESS(Status
)) break;
500 /* Enter SEH for write safety */
503 /* Return data from EPROCESS */
504 VmCounters
->PeakVirtualSize
= Process
->PeakVirtualSize
;
505 VmCounters
->VirtualSize
= Process
->VirtualSize
;
506 VmCounters
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
507 VmCounters
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
508 VmCounters
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
509 VmCounters
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeak
[0];
510 VmCounters
->QuotaPagedPoolUsage
= Process
->QuotaUsage
[0];
511 VmCounters
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeak
[1];
512 VmCounters
->QuotaNonPagedPoolUsage
= Process
->QuotaUsage
[1];
513 VmCounters
->PagefileUsage
= Process
->QuotaUsage
[2];
514 VmCounters
->PeakPagefileUsage
= Process
->QuotaPeak
[2];
517 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
519 /* Get the exception code */
520 Status
= _SEH2_GetExceptionCode();
524 /* Dereference the process */
525 ObDereferenceObject(Process
);
528 /* Hard Error Processing Mode */
529 case ProcessDefaultHardErrorMode
:
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 /* Write the current processing mode */
553 *(PULONG
)ProcessInformation
= Process
->
554 DefaultHardErrorProcessing
;
556 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
558 /* Get the exception code */
559 Status
= _SEH2_GetExceptionCode();
563 /* Dereference the process */
564 ObDereferenceObject(Process
);
567 /* Priority Boosting status */
568 case ProcessPriorityBoost
:
570 /* Set the return length*/
571 Length
= sizeof(ULONG
);
573 if (ProcessInformationLength
!= Length
)
575 Status
= STATUS_INFO_LENGTH_MISMATCH
;
579 /* Reference the process */
580 Status
= ObReferenceObjectByHandle(ProcessHandle
,
581 PROCESS_QUERY_INFORMATION
,
586 if (!NT_SUCCESS(Status
)) break;
588 /* Enter SEH for writing back data */
591 /* Return boost status */
592 *(PULONG
)ProcessInformation
= Process
->Pcb
.DisableBoost
?
595 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
597 /* Get the exception code */
598 Status
= _SEH2_GetExceptionCode();
602 /* Dereference the process */
603 ObDereferenceObject(Process
);
607 case ProcessDeviceMap
:
609 /* Set the return length*/
610 Length
= sizeof(PROCESS_DEVICEMAP_INFORMATION
);
612 if (ProcessInformationLength
!= Length
)
614 Status
= STATUS_INFO_LENGTH_MISMATCH
;
618 /* Reference the process */
619 Status
= ObReferenceObjectByHandle(ProcessHandle
,
620 PROCESS_QUERY_INFORMATION
,
625 if (!NT_SUCCESS(Status
)) break;
627 /* Query the device map information */
628 ObQueryDeviceMapInformation(Process
, &DeviceMap
);
630 /* Enter SEH for writing back data */
633 *(PPROCESS_DEVICEMAP_INFORMATION
)ProcessInformation
= DeviceMap
;
635 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
637 /* Get the exception code */
638 Status
= _SEH2_GetExceptionCode();
642 /* Dereference the process */
643 ObDereferenceObject(Process
);
647 case ProcessPriorityClass
:
649 /* Set the return length*/
650 Length
= sizeof(PROCESS_PRIORITY_CLASS
);
652 if (ProcessInformationLength
!= Length
)
654 Status
= STATUS_INFO_LENGTH_MISMATCH
;
658 /* Reference the process */
659 Status
= ObReferenceObjectByHandle(ProcessHandle
,
660 PROCESS_QUERY_INFORMATION
,
665 if (!NT_SUCCESS(Status
)) break;
667 /* Enter SEH for writing back data */
670 /* Return current priority class */
671 PsPriorityClass
->PriorityClass
= Process
->PriorityClass
;
672 PsPriorityClass
->Foreground
= FALSE
;
674 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
676 /* Get the exception code */
677 Status
= _SEH2_GetExceptionCode();
681 /* Dereference the process */
682 ObDereferenceObject(Process
);
685 case ProcessImageFileName
:
687 /* Reference the process */
688 Status
= ObReferenceObjectByHandle(ProcessHandle
,
689 PROCESS_QUERY_INFORMATION
,
694 if (!NT_SUCCESS(Status
)) break;
696 /* Get the image path */
697 Status
= SeLocateProcessImageName(Process
, &ImageName
);
698 if (NT_SUCCESS(Status
))
700 /* Set return length */
701 Length
= ImageName
->MaximumLength
+
702 sizeof(OBJECT_NAME_INFORMATION
);
704 /* Make sure it's large enough */
705 if (Length
<= ProcessInformationLength
)
707 /* Enter SEH to protect write */
711 RtlCopyMemory(ProcessInformation
,
716 ((PUNICODE_STRING
)ProcessInformation
)->Buffer
=
717 (PWSTR
)((PUNICODE_STRING
)ProcessInformation
+ 1);
719 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
721 /* Get the exception code */
722 Status
= _SEH2_GetExceptionCode();
728 /* Buffer too small */
729 Status
= STATUS_INFO_LENGTH_MISMATCH
;
732 /* Free the image path */
733 ExFreePool(ImageName
);
735 /* Dereference the process */
736 ObDereferenceObject(Process
);
739 case ProcessBreakOnTermination
:
741 /* Set the return length*/
742 Length
= sizeof(ULONG
);
743 if (ProcessInformationLength
!= Length
)
745 Status
= STATUS_INFO_LENGTH_MISMATCH
;
749 /* Reference the process */
750 Status
= ObReferenceObjectByHandle(ProcessHandle
,
751 PROCESS_QUERY_INFORMATION
,
756 if (!NT_SUCCESS(Status
))
759 /* Enter SEH for writing back data */
762 /* Return the BreakOnTermination state */
763 *(PULONG
)ProcessInformation
= Process
->BreakOnTermination
;
765 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
767 /* Get the exception code */
768 Status
= _SEH2_GetExceptionCode();
772 /* Dereference the process */
773 ObDereferenceObject(Process
);
776 /* Per-process security cookie */
779 /* Get the current process and cookie */
780 Process
= PsGetCurrentProcess();
781 Cookie
= Process
->Cookie
;
784 LARGE_INTEGER SystemTime
;
788 /* Generate a new cookie */
789 KeQuerySystemTime(&SystemTime
);
790 Prcb
= KeGetCurrentPrcb();
791 NewCookie
= Prcb
->KeSystemCalls
^ Prcb
->InterruptTime
^
792 SystemTime
.u
.LowPart
^ SystemTime
.u
.HighPart
;
794 /* Set the new cookie or return the current one */
795 Cookie
= InterlockedCompareExchange((LONG
*)&Process
->Cookie
,
798 if (!Cookie
) Cookie
= NewCookie
;
800 /* Set return length */
801 Length
= sizeof(ULONG
);
804 /* Indicate success */
805 Status
= STATUS_SUCCESS
;
807 /* Enter SEH to protect write */
810 /* Write back the cookie */
811 *(PULONG
)ProcessInformation
= Cookie
;
813 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
815 /* Get the exception code */
816 Status
= _SEH2_GetExceptionCode();
821 /* Not yet implemented, or unknown */
822 case ProcessBasePriority
:
823 case ProcessRaisePriority
:
824 case ProcessExceptionPort
:
825 case ProcessAccessToken
:
827 case ProcessIoPortHandlers
:
828 case ProcessUserModeIOPL
:
829 case ProcessEnableAlignmentFaultFixup
:
830 case ProcessAffinityMask
:
831 case ProcessForegroundInformation
:
833 DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass
);
834 Status
= STATUS_INVALID_INFO_CLASS
;
837 /* Protect write with SEH */
840 /* Check if caller wanted return length */
841 if (ReturnLength
) *ReturnLength
= Length
;
843 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
845 /* Get exception code */
846 Status
= _SEH2_GetExceptionCode();
858 NtSetInformationProcess(IN HANDLE ProcessHandle
,
859 IN PROCESSINFOCLASS ProcessInformationClass
,
860 IN PVOID ProcessInformation
,
861 IN ULONG ProcessInformationLength
)
864 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
867 HANDLE PortHandle
= NULL
;
868 HANDLE TokenHandle
= NULL
;
869 PROCESS_SESSION_INFORMATION SessionInfo
= {0};
870 PROCESS_PRIORITY_CLASS PriorityClass
= {0};
874 /* Verify Information Class validity */
876 Status
= DefaultSetInfoBufferCheck(ProcessInformationClass
,
878 RTL_NUMBER_OF(PsProcessInfoClass
),
880 ProcessInformationLength
,
882 if (!NT_SUCCESS(Status
)) return Status
;
885 /* Check what class this is */
886 Access
= PROCESS_SET_INFORMATION
;
887 if (ProcessInformationClass
== ProcessSessionInformation
)
889 /* Setting the Session ID needs a special mask */
890 Access
|= PROCESS_SET_SESSIONID
;
892 else if (ProcessInformationClass
== ProcessExceptionPort
)
894 /* Setting the exception port needs a special mask */
895 Access
|= PROCESS_SUSPEND_RESUME
;
898 /* Reference the process */
899 Status
= ObReferenceObjectByHandle(ProcessHandle
,
905 if (!NT_SUCCESS(Status
)) return Status
;
907 /* Check what kind of information class this is */
908 switch (ProcessInformationClass
)
910 /* Error/Exception Port */
911 case ProcessExceptionPort
:
913 /* Check buffer length */
914 if (ProcessInformationLength
!= sizeof(HANDLE
))
916 Status
= STATUS_INFO_LENGTH_MISMATCH
;
920 /* Use SEH for capture */
923 /* Capture the handle */
924 PortHandle
= *(PHANDLE
)ProcessInformation
;
926 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
928 /* Return the exception code */
929 _SEH2_YIELD(return _SEH2_GetExceptionCode());
933 /* Get the LPC Port */
934 Status
= ObReferenceObjectByHandle(PortHandle
,
938 (PVOID
)&ExceptionPort
,
940 if (!NT_SUCCESS(Status
)) break;
942 /* Change the pointer */
943 if (InterlockedCompareExchangePointer(&Process
->ExceptionPort
,
947 /* We already had one, fail */
948 ObDereferenceObject(ExceptionPort
);
949 Status
= STATUS_PORT_ALREADY_SET
;
954 case ProcessAccessToken
:
956 /* Check buffer length */
957 if (ProcessInformationLength
!= sizeof(PROCESS_ACCESS_TOKEN
))
959 Status
= STATUS_INFO_LENGTH_MISMATCH
;
963 /* Use SEH for capture */
966 /* Save the token handle */
967 TokenHandle
= ((PPROCESS_ACCESS_TOKEN
)ProcessInformation
)->
970 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
972 /* Return the exception code */
973 _SEH2_YIELD(return _SEH2_GetExceptionCode());
977 /* Assign the actual token */
978 Status
= PspSetPrimaryToken(Process
, TokenHandle
, NULL
);
981 /* Hard error processing */
982 case ProcessDefaultHardErrorMode
:
984 /* Check buffer length */
985 if (ProcessInformationLength
!= sizeof(ULONG
))
987 Status
= STATUS_INFO_LENGTH_MISMATCH
;
991 /* Enter SEH for direct buffer read */
994 /* Update the current mode abd return the previous one */
995 InterlockedExchange((LONG
*)&Process
->DefaultHardErrorProcessing
,
996 *(PLONG
)ProcessInformation
);
998 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1000 /* Get exception code */
1001 Status
= _SEH2_GetExceptionCode();
1007 case ProcessSessionInformation
:
1009 /* Check buffer length */
1010 if (ProcessInformationLength
!= sizeof(PROCESS_SESSION_INFORMATION
))
1012 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1016 /* Enter SEH for capture */
1019 /* Capture the caller's buffer */
1020 SessionInfo
= *(PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
1022 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1024 /* Return the exception code */
1025 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1029 /* Setting the session id requires the SeTcbPrivilege */
1030 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
1032 /* Can't set the session ID, bail out. */
1033 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1037 /* FIXME - update the session id for the process token */
1038 //Status = PsLockProcess(Process, FALSE);
1039 if (!NT_SUCCESS(Status
)) break;
1041 /* Write the session ID in the EPROCESS */
1042 Process
->Session
= SessionInfo
.SessionId
;
1044 /* Check if the process also has a PEB */
1048 * Attach to the process to make sure we're in the right
1049 * context to access the PEB structure
1051 KeAttachProcess(&Process
->Pcb
);
1053 /* Enter SEH for write to user-mode PEB */
1056 /* Write the session ID */
1057 Process
->Peb
->SessionId
= SessionInfo
.SessionId
;
1059 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1061 /* Get exception code */
1062 Status
= _SEH2_GetExceptionCode();
1066 /* Detach from the process */
1070 /* Unlock the process */
1071 //PsUnlockProcess(Process);
1074 case ProcessPriorityClass
:
1076 /* Check buffer length */
1077 if (ProcessInformationLength
!= sizeof(PROCESS_PRIORITY_CLASS
))
1079 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1083 /* Enter SEH for capture */
1086 /* Capture the caller's buffer */
1087 PriorityClass
= *(PPROCESS_PRIORITY_CLASS
)ProcessInformation
;
1089 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1091 /* Return the exception code */
1092 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1096 /* Check for invalid PriorityClass value */
1097 if (PriorityClass
.PriorityClass
> PROCESS_PRIORITY_CLASS_ABOVE_NORMAL
)
1099 Status
= STATUS_INVALID_PARAMETER
;
1103 /* TODO: Check privileges */
1105 /* Check if we have a job */
1108 DPRINT1("Jobs not yet supported\n");
1111 /* Set process priority class */
1112 Process
->PriorityClass
= PriorityClass
.PriorityClass
;
1114 /* Set process priority mode (foreground or background) */
1115 PsSetProcessPriorityByClass(Process
,
1116 !PriorityClass
.Foreground
? PsProcessPriorityBackground
:
1117 PsProcessPriorityForeground
);
1119 Status
= STATUS_SUCCESS
;
1122 case ProcessQuotaLimits
:
1124 /* Check buffer length */
1125 if (ProcessInformationLength
!= sizeof(QUOTA_LIMITS
))
1127 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1131 DPRINT1("Not implemented: ProcessQuotaLimits\n");
1132 Status
= STATUS_NOT_IMPLEMENTED
;
1135 case ProcessBasePriority
:
1137 /* Check buffer length */
1138 if (ProcessInformationLength
!= sizeof(KPRIORITY
))
1140 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1144 DPRINT1("Not implemented: ProcessBasePriority\n");
1145 Status
= STATUS_NOT_IMPLEMENTED
;
1148 case ProcessRaisePriority
:
1150 /* Check buffer length */
1151 if (ProcessInformationLength
!= sizeof(ULONG
))
1153 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1157 DPRINT1("Not implemented: ProcessRaisePriority\n");
1158 Status
= STATUS_NOT_IMPLEMENTED
;
1161 case ProcessWx86Information
:
1163 /* Check buffer length */
1164 if (ProcessInformationLength
!= sizeof(HANDLE
))
1166 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1170 DPRINT1("Not implemented: ProcessWx86Information\n");
1171 Status
= STATUS_NOT_IMPLEMENTED
;
1174 case ProcessDebugPort
:
1176 /* Check buffer length */
1177 if (ProcessInformationLength
!= sizeof(HANDLE
))
1179 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1183 DPRINT1("Not implemented: ProcessDebugPort\n");
1184 Status
= STATUS_NOT_IMPLEMENTED
;
1187 case ProcessBreakOnTermination
:
1189 /* Check buffer length */
1190 if (ProcessInformationLength
!= sizeof(ULONG
))
1192 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1196 /* Setting 'break on termination' requires the SeDebugPrivilege */
1197 if (!SeSinglePrivilegeCheck(SeDebugPrivilege
, PreviousMode
))
1199 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1203 /* Enter SEH for direct buffer read */
1206 Process
->BreakOnTermination
= *(PULONG
)ProcessInformation
;
1208 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1210 /* Get exception code */
1211 Status
= _SEH2_GetExceptionCode();
1216 /* We currently don't implement any of these */
1217 case ProcessLdtInformation
:
1218 case ProcessLdtSize
:
1219 case ProcessIoPortHandlers
:
1220 case ProcessWorkingSetWatch
:
1221 case ProcessUserModeIOPL
:
1222 case ProcessEnableAlignmentFaultFixup
:
1223 case ProcessAffinityMask
:
1224 DPRINT1("Not implemented: %lx\n", ProcessInformationClass
);
1225 Status
= STATUS_NOT_IMPLEMENTED
;
1228 /* Supposedly these are invalid...!? verify! */
1229 case ProcessBasicInformation
:
1230 case ProcessIoCounters
:
1232 case ProcessPooledUsageAndLimits
:
1233 case ProcessHandleCount
:
1234 case ProcessWow64Information
:
1236 DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass
);
1237 Status
= STATUS_INVALID_INFO_CLASS
;
1240 /* Dereference and return status */
1241 ObDereferenceObject(Process
);
1250 NtSetInformationThread(IN HANDLE ThreadHandle
,
1251 IN THREADINFOCLASS ThreadInformationClass
,
1252 IN PVOID ThreadInformation
,
1253 IN ULONG ThreadInformationLength
)
1257 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1259 HANDLE TokenHandle
= NULL
;
1260 KPRIORITY Priority
= 0;
1261 KAFFINITY Affinity
= 0, CombinedAffinity
;
1262 PVOID Address
= NULL
;
1264 ULONG DisableBoost
= 0;
1265 ULONG IdealProcessor
= 0;
1268 PVOID
*ExpansionSlots
;
1269 PETHREAD ProcThread
;
1272 /* Verify Information Class validity */
1274 Status
= DefaultSetInfoBufferCheck(ThreadInformationClass
,
1276 RTL_NUMBER_OF(PsThreadInfoClass
),
1278 ThreadInformationLength
,
1280 if (!NT_SUCCESS(Status
)) return Status
;
1283 /* Check what class this is */
1284 Access
= THREAD_SET_INFORMATION
;
1285 if (ThreadInformationClass
== ThreadImpersonationToken
)
1287 /* Setting the impersonation token needs a special mask */
1288 Access
= THREAD_SET_THREAD_TOKEN
;
1291 /* Reference the process */
1292 Status
= ObReferenceObjectByHandle(ThreadHandle
,
1298 if (!NT_SUCCESS(Status
)) return Status
;
1300 /* Check what kind of information class this is */
1301 switch (ThreadInformationClass
)
1303 /* Thread priority */
1304 case ThreadPriority
:
1306 /* Check buffer length */
1307 if (ThreadInformationLength
!= sizeof(KPRIORITY
))
1309 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1313 /* Use SEH for capture */
1316 /* Get the priority */
1317 Priority
= *(PLONG
)ThreadInformation
;
1319 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1321 /* Return the exception code */
1322 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1327 if ((Priority
> HIGH_PRIORITY
) ||
1328 (Priority
<= LOW_PRIORITY
))
1331 Status
= STATUS_INVALID_PARAMETER
;
1335 /* Set the priority */
1336 KeSetPriorityThread(&Thread
->Tcb
, Priority
);
1339 case ThreadBasePriority
:
1341 /* Check buffer length */
1342 if (ThreadInformationLength
!= sizeof(LONG
))
1344 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1348 /* Use SEH for capture */
1351 /* Get the priority */
1352 Priority
= *(PLONG
)ThreadInformation
;
1354 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1356 /* Return the exception code */
1357 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1362 if ((Priority
> THREAD_BASE_PRIORITY_MAX
) ||
1363 (Priority
< THREAD_BASE_PRIORITY_MIN
))
1365 /* These ones are OK */
1366 if ((Priority
!= THREAD_BASE_PRIORITY_LOWRT
+ 1) &&
1367 (Priority
!= THREAD_BASE_PRIORITY_IDLE
- 1))
1369 /* Check if the process is real time */
1370 if (PsGetCurrentProcess()->PriorityClass
!=
1371 PROCESS_PRIORITY_CLASS_REALTIME
)
1373 /* It isn't, fail */
1374 Status
= STATUS_INVALID_PARAMETER
;
1380 /* Set the base priority */
1381 KeSetBasePriorityThread(&Thread
->Tcb
, Priority
);
1384 case ThreadAffinityMask
:
1386 /* Check buffer length */
1387 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1389 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1393 /* Use SEH for capture */
1396 /* Get the priority */
1397 Affinity
= *(PULONG_PTR
)ThreadInformation
;
1399 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1401 /* Return the exception code */
1402 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1410 Status
= STATUS_INVALID_PARAMETER
;
1414 /* Get the process */
1415 Process
= Thread
->ThreadsProcess
;
1417 /* Try to acquire rundown */
1418 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1421 KeEnterCriticalRegion();
1422 ExAcquirePushLockShared(&Process
->ProcessLock
);
1425 CombinedAffinity
= Affinity
& Process
->Pcb
.Affinity
;
1426 if (CombinedAffinity
!= Affinity
)
1429 Status
= STATUS_INVALID_PARAMETER
;
1433 /* Set the affinity */
1434 KeSetAffinityThread(&Thread
->Tcb
, CombinedAffinity
);
1437 /* Release the lock and rundown */
1438 ExReleasePushLockShared(&Process
->ProcessLock
);
1439 KeLeaveCriticalRegion();
1440 ExReleaseRundownProtection(&Process
->RundownProtect
);
1445 Status
= STATUS_PROCESS_IS_TERMINATING
;
1451 case ThreadImpersonationToken
:
1453 /* Check buffer length */
1454 if (ThreadInformationLength
!= sizeof(HANDLE
))
1456 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1460 /* Use SEH for capture */
1463 /* Save the token handle */
1464 TokenHandle
= *(PHANDLE
)ThreadInformation
;
1466 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1468 /* Return the exception code */
1469 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1473 /* Assign the actual token */
1474 Status
= PsAssignImpersonationToken(Thread
, TokenHandle
);
1477 case ThreadQuerySetWin32StartAddress
:
1479 /* Check buffer length */
1480 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1482 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1486 /* Use SEH for capture */
1489 /* Get the priority */
1490 Address
= *(PVOID
*)ThreadInformation
;
1492 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1494 /* Return the exception code */
1495 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1499 /* Set the address */
1500 Thread
->Win32StartAddress
= Address
;
1503 case ThreadIdealProcessor
:
1505 /* Check buffer length */
1506 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1508 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1512 /* Use SEH for capture */
1515 /* Get the priority */
1516 IdealProcessor
= *(PULONG_PTR
)ThreadInformation
;
1518 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1520 /* Return the exception code */
1521 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1526 if (IdealProcessor
> MAXIMUM_PROCESSORS
)
1529 Status
= STATUS_INVALID_PARAMETER
;
1534 Status
= KeSetIdealProcessorThread(&Thread
->Tcb
,
1535 (CCHAR
)IdealProcessor
);
1537 /* Get the TEB and protect the thread */
1538 Teb
= Thread
->Tcb
.Teb
;
1539 if ((Teb
) && (ExAcquireRundownProtection(&Thread
->RundownProtect
)))
1541 /* Save the ideal processor */
1542 Teb
->IdealProcessor
= Thread
->Tcb
.IdealProcessor
;
1544 /* Release rundown protection */
1545 ExReleaseRundownProtection(&Thread
->RundownProtect
);
1550 case ThreadPriorityBoost
:
1552 /* Check buffer length */
1553 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1555 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1559 /* Use SEH for capture */
1562 /* Get the priority */
1563 DisableBoost
= *(PULONG_PTR
)ThreadInformation
;
1565 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1567 /* Return the exception code */
1568 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1572 /* Call the kernel */
1573 KeSetDisableBoostThread(&Thread
->Tcb
, (BOOLEAN
)DisableBoost
);
1576 case ThreadZeroTlsCell
:
1578 /* Check buffer length */
1579 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1581 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1585 /* Use SEH for capture */
1588 /* Get the priority */
1589 TlsIndex
= *(PULONG_PTR
)ThreadInformation
;
1591 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1593 /* Return the exception code */
1594 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1598 /* This is only valid for the current thread */
1599 if (Thread
!= PsGetCurrentThread())
1602 Status
= STATUS_INVALID_PARAMETER
;
1606 /* Get the process */
1607 Process
= Thread
->ThreadsProcess
;
1609 /* Loop the threads */
1610 ProcThread
= PsGetNextProcessThread(Process
, NULL
);
1613 /* Acquire rundown */
1614 if (ExAcquireRundownProtection(&ProcThread
->RundownProtect
))
1617 Teb
= ProcThread
->Tcb
.Teb
;
1620 /* Check if we're in the expansion range */
1621 if (TlsIndex
> TLS_MINIMUM_AVAILABLE
- 1)
1623 if (TlsIndex
< (TLS_MINIMUM_AVAILABLE
+
1624 TLS_EXPANSION_SLOTS
) - 1)
1626 /* Check if we have expansion slots */
1627 ExpansionSlots
= Teb
->TlsExpansionSlots
;
1630 /* Clear the index */
1631 ExpansionSlots
[TlsIndex
- TLS_MINIMUM_AVAILABLE
] = 0;
1637 /* Clear the index */
1638 Teb
->TlsSlots
[TlsIndex
] = NULL
;
1642 /* Release rundown */
1643 ExReleaseRundownProtection(&ProcThread
->RundownProtect
);
1646 /* Go to the next thread */
1647 ProcThread
= PsGetNextProcessThread(Process
, ProcThread
);
1654 /* We don't implement it yet */
1655 DPRINT1("Not implemented: %lx\n", ThreadInformationClass
);
1656 Status
= STATUS_NOT_IMPLEMENTED
;
1659 /* Dereference and return status */
1660 ObDereferenceObject(Thread
);
1669 NtQueryInformationThread(IN HANDLE ThreadHandle
,
1670 IN THREADINFOCLASS ThreadInformationClass
,
1671 OUT PVOID ThreadInformation
,
1672 IN ULONG ThreadInformationLength
,
1673 OUT PULONG ReturnLength OPTIONAL
)
1676 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1680 PTHREAD_BASIC_INFORMATION ThreadBasicInfo
=
1681 (PTHREAD_BASIC_INFORMATION
)ThreadInformation
;
1682 PKERNEL_USER_TIMES ThreadTime
= (PKERNEL_USER_TIMES
)ThreadInformation
;
1686 /* Check if we were called from user mode */
1687 if (PreviousMode
!= KernelMode
)
1692 /* Probe the buffer */
1693 ProbeForWrite(ThreadInformation
,
1694 ThreadInformationLength
,
1697 /* Probe the return length if required */
1698 if (ReturnLength
) ProbeForWriteUlong(ReturnLength
);
1700 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1702 /* Return the exception code */
1703 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1708 /* Check what class this is */
1709 Access
= THREAD_QUERY_INFORMATION
;
1711 /* Reference the process */
1712 Status
= ObReferenceObjectByHandle(ThreadHandle
,
1718 if (!NT_SUCCESS(Status
)) return Status
;
1720 /* Check what kind of information class this is */
1721 switch (ThreadInformationClass
)
1723 /* Basic thread information */
1724 case ThreadBasicInformation
:
1726 /* Set return length */
1727 Length
= sizeof(THREAD_BASIC_INFORMATION
);
1729 if (ThreadInformationLength
!= Length
)
1731 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1734 /* Protect writes with SEH */
1737 /* Write all the information from the ETHREAD/KTHREAD */
1738 ThreadBasicInfo
->ExitStatus
= Thread
->ExitStatus
;
1739 ThreadBasicInfo
->TebBaseAddress
= (PVOID
)Thread
->Tcb
.Teb
;
1740 ThreadBasicInfo
->ClientId
= Thread
->Cid
;
1741 ThreadBasicInfo
->AffinityMask
= Thread
->Tcb
.Affinity
;
1742 ThreadBasicInfo
->Priority
= Thread
->Tcb
.Priority
;
1743 ThreadBasicInfo
->BasePriority
= KeQueryBasePriorityThread(&Thread
->Tcb
);
1745 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1747 /* Get exception code */
1748 Status
= _SEH2_GetExceptionCode();
1753 /* Thread time information */
1756 /* Set the return length */
1757 Length
= sizeof(KERNEL_USER_TIMES
);
1759 if (ThreadInformationLength
!= Length
)
1761 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1764 /* Protect writes with SEH */
1767 /* Copy time information from ETHREAD/KTHREAD */
1768 ThreadTime
->KernelTime
.QuadPart
= Thread
->Tcb
.KernelTime
*
1770 ThreadTime
->UserTime
.QuadPart
= Thread
->Tcb
.UserTime
*
1772 ThreadTime
->CreateTime
= Thread
->CreateTime
;
1773 ThreadTime
->ExitTime
= Thread
->ExitTime
;
1775 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1777 /* Get exception code */
1778 Status
= _SEH2_GetExceptionCode();
1783 case ThreadQuerySetWin32StartAddress
:
1785 /* Set the return length*/
1786 Length
= sizeof(PVOID
);
1788 if (ThreadInformationLength
!= Length
)
1790 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1793 /* Protect write with SEH */
1796 /* Return the Win32 Start Address */
1797 *(PVOID
*)ThreadInformation
= Thread
->Win32StartAddress
;
1799 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1801 /* Get exception code */
1802 Status
= _SEH2_GetExceptionCode();
1807 case ThreadPerformanceCount
:
1809 /* Set the return length*/
1810 Length
= sizeof(LARGE_INTEGER
);
1812 if (ThreadInformationLength
!= Length
)
1814 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1817 /* Protect write with SEH */
1821 (*(PLARGE_INTEGER
)ThreadInformation
).QuadPart
= 0;
1823 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1825 /* Get exception code */
1826 Status
= _SEH2_GetExceptionCode();
1831 case ThreadAmILastThread
:
1833 /* Set the return length*/
1834 Length
= sizeof(ULONG
);
1836 if (ThreadInformationLength
!= Length
)
1838 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1841 /* Protect write with SEH */
1844 /* Return whether or not we are the last thread */
1845 *(PULONG
)ThreadInformation
= ((Thread
->ThreadsProcess
->
1846 ThreadListHead
.Flink
->Flink
==
1847 &Thread
->ThreadsProcess
->
1851 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1853 /* Get exception code */
1854 Status
= _SEH2_GetExceptionCode();
1859 case ThreadIsIoPending
:
1861 /* Set the return length*/
1862 Length
= sizeof(ULONG
);
1864 if (ThreadInformationLength
!= Length
)
1866 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1869 /* Raise the IRQL to protect the IRP list */
1870 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1872 /* Protect write with SEH */
1875 /* Check if the IRP list is empty or not */
1876 *(PULONG
)ThreadInformation
= !IsListEmpty(&Thread
->IrpList
);
1878 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1880 /* Get exception code */
1881 Status
= _SEH2_GetExceptionCode();
1885 /* Lower IRQL back */
1886 KeLowerIrql(OldIrql
);
1889 /* LDT and GDT information */
1890 case ThreadDescriptorTableEntry
:
1893 /* Call the worker routine */
1894 Status
= PspQueryDescriptorThread(Thread
,
1896 ThreadInformationLength
,
1899 /* Only implemented on x86 */
1900 Status
= STATUS_NOT_IMPLEMENTED
;
1904 case ThreadPriorityBoost
:
1906 /* Set the return length*/
1907 Length
= sizeof(ULONG
);
1909 if (ThreadInformationLength
!= Length
)
1911 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1917 *(PULONG
)ThreadInformation
= Thread
->Tcb
.DisableBoost
? 1 : 0;
1919 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1921 Status
= _SEH2_GetExceptionCode();
1929 /* Not yet implemented */
1930 DPRINT1("Not implemented: %lx\n", ThreadInformationClass
);
1931 Status
= STATUS_NOT_IMPLEMENTED
;
1934 /* Protect write with SEH */
1937 /* Check if caller wanted return length */
1938 if (ReturnLength
) *ReturnLength
= Length
;
1940 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1942 /* Get exception code */
1943 Status
= _SEH2_GetExceptionCode();
1947 /* Dereference the thread, and return */
1948 ObDereferenceObject(Thread
);