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 /* Get the exception code */
929 Status
= _SEH2_GetExceptionCode();
933 if (!NT_SUCCESS(Status
)) break;
935 /* Get the LPC Port */
936 Status
= ObReferenceObjectByHandle(PortHandle
,
940 (PVOID
)&ExceptionPort
,
942 if (!NT_SUCCESS(Status
)) break;
944 /* Change the pointer */
945 if (InterlockedCompareExchangePointer(&Process
->ExceptionPort
,
949 /* We already had one, fail */
950 ObDereferenceObject(ExceptionPort
);
951 Status
= STATUS_PORT_ALREADY_SET
;
956 case ProcessAccessToken
:
958 /* Check buffer length */
959 if (ProcessInformationLength
!= sizeof(PROCESS_ACCESS_TOKEN
))
961 Status
= STATUS_INFO_LENGTH_MISMATCH
;
965 /* Use SEH for capture */
968 /* Save the token handle */
969 TokenHandle
= ((PPROCESS_ACCESS_TOKEN
)ProcessInformation
)->
972 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
974 /* Get the exception code */
975 Status
= _SEH2_GetExceptionCode();
979 if (!NT_SUCCESS(Status
)) break;
981 /* Assign the actual token */
982 Status
= PspSetPrimaryToken(Process
, TokenHandle
, NULL
);
985 /* Hard error processing */
986 case ProcessDefaultHardErrorMode
:
988 /* Check buffer length */
989 if (ProcessInformationLength
!= sizeof(ULONG
))
991 Status
= STATUS_INFO_LENGTH_MISMATCH
;
995 /* Enter SEH for direct buffer read */
998 /* Update the current mode abd return the previous one */
999 InterlockedExchange((LONG
*)&Process
->DefaultHardErrorProcessing
,
1000 *(PLONG
)ProcessInformation
);
1002 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1004 /* Get exception code */
1005 Status
= _SEH2_GetExceptionCode();
1011 case ProcessSessionInformation
:
1013 /* Check buffer length */
1014 if (ProcessInformationLength
!= sizeof(PROCESS_SESSION_INFORMATION
))
1016 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1020 /* Enter SEH for capture */
1023 /* Capture the caller's buffer */
1024 SessionInfo
= *(PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
1026 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1028 /* Get the exception code */
1029 Status
= _SEH2_GetExceptionCode();
1033 if (!NT_SUCCESS(Status
)) break;
1035 /* Setting the session id requires the SeTcbPrivilege */
1036 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
1038 /* Can't set the session ID, bail out. */
1039 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1043 /* FIXME - update the session id for the process token */
1044 //Status = PsLockProcess(Process, FALSE);
1045 if (!NT_SUCCESS(Status
)) break;
1047 /* Write the session ID in the EPROCESS */
1048 Process
->Session
= SessionInfo
.SessionId
;
1050 /* Check if the process also has a PEB */
1054 * Attach to the process to make sure we're in the right
1055 * context to access the PEB structure
1057 KeAttachProcess(&Process
->Pcb
);
1059 /* Enter SEH for write to user-mode PEB */
1062 /* Write the session ID */
1063 Process
->Peb
->SessionId
= SessionInfo
.SessionId
;
1065 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1067 /* Get exception code */
1068 Status
= _SEH2_GetExceptionCode();
1072 /* Detach from the process */
1076 /* Unlock the process */
1077 //PsUnlockProcess(Process);
1080 case ProcessPriorityClass
:
1082 /* Check buffer length */
1083 if (ProcessInformationLength
!= sizeof(PROCESS_PRIORITY_CLASS
))
1085 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1089 /* Enter SEH for capture */
1092 /* Capture the caller's buffer */
1093 PriorityClass
= *(PPROCESS_PRIORITY_CLASS
)ProcessInformation
;
1095 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1097 /* Return the exception code */
1098 Status
= _SEH2_GetExceptionCode();
1102 if (!NT_SUCCESS(Status
)) break;
1104 /* Check for invalid PriorityClass value */
1105 if (PriorityClass
.PriorityClass
> PROCESS_PRIORITY_CLASS_ABOVE_NORMAL
)
1107 Status
= STATUS_INVALID_PARAMETER
;
1111 /* TODO: Check privileges */
1113 /* Check if we have a job */
1116 DPRINT1("Jobs not yet supported\n");
1119 /* Set process priority class */
1120 Process
->PriorityClass
= PriorityClass
.PriorityClass
;
1122 /* Set process priority mode (foreground or background) */
1123 PsSetProcessPriorityByClass(Process
,
1124 !PriorityClass
.Foreground
? PsProcessPriorityBackground
:
1125 PsProcessPriorityForeground
);
1127 Status
= STATUS_SUCCESS
;
1130 case ProcessQuotaLimits
:
1132 /* Check buffer length */
1133 if (ProcessInformationLength
!= sizeof(QUOTA_LIMITS
))
1135 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1139 DPRINT1("Not implemented: ProcessQuotaLimits\n");
1140 Status
= STATUS_NOT_IMPLEMENTED
;
1143 case ProcessBasePriority
:
1145 /* Check buffer length */
1146 if (ProcessInformationLength
!= sizeof(KPRIORITY
))
1148 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1152 DPRINT1("Not implemented: ProcessBasePriority\n");
1153 Status
= STATUS_NOT_IMPLEMENTED
;
1156 case ProcessRaisePriority
:
1158 /* Check buffer length */
1159 if (ProcessInformationLength
!= sizeof(ULONG
))
1161 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1165 DPRINT1("Not implemented: ProcessRaisePriority\n");
1166 Status
= STATUS_NOT_IMPLEMENTED
;
1169 case ProcessWx86Information
:
1171 /* Check buffer length */
1172 if (ProcessInformationLength
!= sizeof(HANDLE
))
1174 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1178 DPRINT1("Not implemented: ProcessWx86Information\n");
1179 Status
= STATUS_NOT_IMPLEMENTED
;
1182 case ProcessDebugPort
:
1184 /* Check buffer length */
1185 if (ProcessInformationLength
!= sizeof(HANDLE
))
1187 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1191 DPRINT1("Not implemented: ProcessDebugPort\n");
1192 Status
= STATUS_NOT_IMPLEMENTED
;
1195 case ProcessBreakOnTermination
:
1197 /* Check buffer length */
1198 if (ProcessInformationLength
!= sizeof(ULONG
))
1200 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1204 /* Setting 'break on termination' requires the SeDebugPrivilege */
1205 if (!SeSinglePrivilegeCheck(SeDebugPrivilege
, PreviousMode
))
1207 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1211 /* Enter SEH for direct buffer read */
1214 Process
->BreakOnTermination
= *(PULONG
)ProcessInformation
;
1216 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1218 /* Get exception code */
1219 Status
= _SEH2_GetExceptionCode();
1224 /* We currently don't implement any of these */
1225 case ProcessLdtInformation
:
1226 case ProcessLdtSize
:
1227 case ProcessIoPortHandlers
:
1228 case ProcessWorkingSetWatch
:
1229 case ProcessUserModeIOPL
:
1230 case ProcessEnableAlignmentFaultFixup
:
1231 case ProcessAffinityMask
:
1232 DPRINT1("Not implemented: %lx\n", ProcessInformationClass
);
1233 Status
= STATUS_NOT_IMPLEMENTED
;
1236 /* Supposedly these are invalid...!? verify! */
1237 case ProcessBasicInformation
:
1238 case ProcessIoCounters
:
1240 case ProcessPooledUsageAndLimits
:
1241 case ProcessHandleCount
:
1242 case ProcessWow64Information
:
1244 DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass
);
1245 Status
= STATUS_INVALID_INFO_CLASS
;
1248 /* Dereference and return status */
1249 ObDereferenceObject(Process
);
1258 NtSetInformationThread(IN HANDLE ThreadHandle
,
1259 IN THREADINFOCLASS ThreadInformationClass
,
1260 IN PVOID ThreadInformation
,
1261 IN ULONG ThreadInformationLength
)
1265 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1267 HANDLE TokenHandle
= NULL
;
1268 KPRIORITY Priority
= 0;
1269 KAFFINITY Affinity
= 0, CombinedAffinity
;
1270 PVOID Address
= NULL
;
1272 ULONG DisableBoost
= 0;
1273 ULONG IdealProcessor
= 0;
1276 PVOID
*ExpansionSlots
;
1277 PETHREAD ProcThread
;
1280 /* Verify Information Class validity */
1282 Status
= DefaultSetInfoBufferCheck(ThreadInformationClass
,
1284 RTL_NUMBER_OF(PsThreadInfoClass
),
1286 ThreadInformationLength
,
1288 if (!NT_SUCCESS(Status
)) return Status
;
1291 /* Check what class this is */
1292 Access
= THREAD_SET_INFORMATION
;
1293 if (ThreadInformationClass
== ThreadImpersonationToken
)
1295 /* Setting the impersonation token needs a special mask */
1296 Access
= THREAD_SET_THREAD_TOKEN
;
1299 /* Reference the thread */
1300 Status
= ObReferenceObjectByHandle(ThreadHandle
,
1306 if (!NT_SUCCESS(Status
)) return Status
;
1308 /* Check what kind of information class this is */
1309 switch (ThreadInformationClass
)
1311 /* Thread priority */
1312 case ThreadPriority
:
1314 /* Check buffer length */
1315 if (ThreadInformationLength
!= sizeof(KPRIORITY
))
1317 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1321 /* Use SEH for capture */
1324 /* Get the priority */
1325 Priority
= *(PLONG
)ThreadInformation
;
1327 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1329 /* Get the exception code */
1330 Status
= _SEH2_GetExceptionCode();
1334 if (!NT_SUCCESS(Status
)) break;
1337 if ((Priority
> HIGH_PRIORITY
) ||
1338 (Priority
<= LOW_PRIORITY
))
1341 Status
= STATUS_INVALID_PARAMETER
;
1345 /* Set the priority */
1346 KeSetPriorityThread(&Thread
->Tcb
, Priority
);
1349 case ThreadBasePriority
:
1351 /* Check buffer length */
1352 if (ThreadInformationLength
!= sizeof(LONG
))
1354 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1358 /* Use SEH for capture */
1361 /* Get the priority */
1362 Priority
= *(PLONG
)ThreadInformation
;
1364 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1366 /* Get the exception code */
1367 Status
= _SEH2_GetExceptionCode();
1371 if (!NT_SUCCESS(Status
)) break;
1374 if ((Priority
> THREAD_BASE_PRIORITY_MAX
) ||
1375 (Priority
< THREAD_BASE_PRIORITY_MIN
))
1377 /* These ones are OK */
1378 if ((Priority
!= THREAD_BASE_PRIORITY_LOWRT
+ 1) &&
1379 (Priority
!= THREAD_BASE_PRIORITY_IDLE
- 1))
1381 /* Check if the process is real time */
1382 if (PsGetCurrentProcess()->PriorityClass
!=
1383 PROCESS_PRIORITY_CLASS_REALTIME
)
1385 /* It isn't, fail */
1386 Status
= STATUS_INVALID_PARAMETER
;
1392 /* Set the base priority */
1393 KeSetBasePriorityThread(&Thread
->Tcb
, Priority
);
1396 case ThreadAffinityMask
:
1398 /* Check buffer length */
1399 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1401 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1405 /* Use SEH for capture */
1408 /* Get the priority */
1409 Affinity
= *(PULONG_PTR
)ThreadInformation
;
1411 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1413 /* Get the exception code */
1414 Status
= _SEH2_GetExceptionCode();
1422 Status
= STATUS_INVALID_PARAMETER
;
1426 /* Get the process */
1427 Process
= Thread
->ThreadsProcess
;
1429 /* Try to acquire rundown */
1430 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1433 KeEnterCriticalRegion();
1434 ExAcquirePushLockShared(&Process
->ProcessLock
);
1437 CombinedAffinity
= Affinity
& Process
->Pcb
.Affinity
;
1438 if (CombinedAffinity
!= Affinity
)
1441 Status
= STATUS_INVALID_PARAMETER
;
1445 /* Set the affinity */
1446 KeSetAffinityThread(&Thread
->Tcb
, CombinedAffinity
);
1449 /* Release the lock and rundown */
1450 ExReleasePushLockShared(&Process
->ProcessLock
);
1451 KeLeaveCriticalRegion();
1452 ExReleaseRundownProtection(&Process
->RundownProtect
);
1457 Status
= STATUS_PROCESS_IS_TERMINATING
;
1463 case ThreadImpersonationToken
:
1465 /* Check buffer length */
1466 if (ThreadInformationLength
!= sizeof(HANDLE
))
1468 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1472 /* Use SEH for capture */
1475 /* Save the token handle */
1476 TokenHandle
= *(PHANDLE
)ThreadInformation
;
1478 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1480 /* Get the exception code */
1481 Status
= _SEH2_GetExceptionCode();
1485 if (!NT_SUCCESS(Status
)) break;
1487 /* Assign the actual token */
1488 Status
= PsAssignImpersonationToken(Thread
, TokenHandle
);
1491 case ThreadQuerySetWin32StartAddress
:
1493 /* Check buffer length */
1494 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1496 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1500 /* Use SEH for capture */
1503 /* Get the priority */
1504 Address
= *(PVOID
*)ThreadInformation
;
1506 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1508 /* Get the exception code */
1509 Status
= _SEH2_GetExceptionCode();
1513 if (!NT_SUCCESS(Status
)) break;
1515 /* Set the address */
1516 Thread
->Win32StartAddress
= Address
;
1519 case ThreadIdealProcessor
:
1521 /* Check buffer length */
1522 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1524 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1528 /* Use SEH for capture */
1531 /* Get the priority */
1532 IdealProcessor
= *(PULONG_PTR
)ThreadInformation
;
1534 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1536 /* Get the exception code */
1537 Status
= _SEH2_GetExceptionCode();
1541 if (!NT_SUCCESS(Status
)) break;
1544 if (IdealProcessor
> MAXIMUM_PROCESSORS
)
1547 Status
= STATUS_INVALID_PARAMETER
;
1552 Status
= KeSetIdealProcessorThread(&Thread
->Tcb
,
1553 (CCHAR
)IdealProcessor
);
1555 /* Get the TEB and protect the thread */
1556 Teb
= Thread
->Tcb
.Teb
;
1557 if ((Teb
) && (ExAcquireRundownProtection(&Thread
->RundownProtect
)))
1559 /* Save the ideal processor */
1560 Teb
->IdealProcessor
= Thread
->Tcb
.IdealProcessor
;
1562 /* Release rundown protection */
1563 ExReleaseRundownProtection(&Thread
->RundownProtect
);
1568 case ThreadPriorityBoost
:
1570 /* Check buffer length */
1571 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1573 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1577 /* Use SEH for capture */
1580 /* Get the priority */
1581 DisableBoost
= *(PULONG_PTR
)ThreadInformation
;
1583 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1585 /* Get the exception code */
1586 Status
= _SEH2_GetExceptionCode();
1590 if (!NT_SUCCESS(Status
)) break;
1592 /* Call the kernel */
1593 KeSetDisableBoostThread(&Thread
->Tcb
, (BOOLEAN
)DisableBoost
);
1596 case ThreadZeroTlsCell
:
1598 /* Check buffer length */
1599 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1601 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1605 /* Use SEH for capture */
1608 /* Get the priority */
1609 TlsIndex
= *(PULONG_PTR
)ThreadInformation
;
1611 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1613 /* Get the exception code */
1614 Status
= _SEH2_GetExceptionCode();
1618 if (!NT_SUCCESS(Status
)) break;
1620 /* This is only valid for the current thread */
1621 if (Thread
!= PsGetCurrentThread())
1624 Status
= STATUS_INVALID_PARAMETER
;
1628 /* Get the process */
1629 Process
= Thread
->ThreadsProcess
;
1631 /* Loop the threads */
1632 ProcThread
= PsGetNextProcessThread(Process
, NULL
);
1635 /* Acquire rundown */
1636 if (ExAcquireRundownProtection(&ProcThread
->RundownProtect
))
1639 Teb
= ProcThread
->Tcb
.Teb
;
1642 /* Check if we're in the expansion range */
1643 if (TlsIndex
> TLS_MINIMUM_AVAILABLE
- 1)
1645 if (TlsIndex
< (TLS_MINIMUM_AVAILABLE
+
1646 TLS_EXPANSION_SLOTS
) - 1)
1648 /* Check if we have expansion slots */
1649 ExpansionSlots
= Teb
->TlsExpansionSlots
;
1652 /* Clear the index */
1653 ExpansionSlots
[TlsIndex
- TLS_MINIMUM_AVAILABLE
] = 0;
1659 /* Clear the index */
1660 Teb
->TlsSlots
[TlsIndex
] = NULL
;
1664 /* Release rundown */
1665 ExReleaseRundownProtection(&ProcThread
->RundownProtect
);
1668 /* Go to the next thread */
1669 ProcThread
= PsGetNextProcessThread(Process
, ProcThread
);
1676 /* We don't implement it yet */
1677 DPRINT1("Not implemented: %lx\n", ThreadInformationClass
);
1678 Status
= STATUS_NOT_IMPLEMENTED
;
1681 /* Dereference and return status */
1682 ObDereferenceObject(Thread
);
1691 NtQueryInformationThread(IN HANDLE ThreadHandle
,
1692 IN THREADINFOCLASS ThreadInformationClass
,
1693 OUT PVOID ThreadInformation
,
1694 IN ULONG ThreadInformationLength
,
1695 OUT PULONG ReturnLength OPTIONAL
)
1698 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1702 PTHREAD_BASIC_INFORMATION ThreadBasicInfo
=
1703 (PTHREAD_BASIC_INFORMATION
)ThreadInformation
;
1704 PKERNEL_USER_TIMES ThreadTime
= (PKERNEL_USER_TIMES
)ThreadInformation
;
1708 /* Check if we were called from user mode */
1709 if (PreviousMode
!= KernelMode
)
1714 /* Probe the buffer */
1715 ProbeForWrite(ThreadInformation
,
1716 ThreadInformationLength
,
1719 /* Probe the return length if required */
1720 if (ReturnLength
) ProbeForWriteUlong(ReturnLength
);
1722 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1724 /* Return the exception code */
1725 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1730 /* Check what class this is */
1731 Access
= THREAD_QUERY_INFORMATION
;
1733 /* Reference the process */
1734 Status
= ObReferenceObjectByHandle(ThreadHandle
,
1740 if (!NT_SUCCESS(Status
)) return Status
;
1742 /* Check what kind of information class this is */
1743 switch (ThreadInformationClass
)
1745 /* Basic thread information */
1746 case ThreadBasicInformation
:
1748 /* Set return length */
1749 Length
= sizeof(THREAD_BASIC_INFORMATION
);
1751 if (ThreadInformationLength
!= Length
)
1753 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1756 /* Protect writes with SEH */
1759 /* Write all the information from the ETHREAD/KTHREAD */
1760 ThreadBasicInfo
->ExitStatus
= Thread
->ExitStatus
;
1761 ThreadBasicInfo
->TebBaseAddress
= (PVOID
)Thread
->Tcb
.Teb
;
1762 ThreadBasicInfo
->ClientId
= Thread
->Cid
;
1763 ThreadBasicInfo
->AffinityMask
= Thread
->Tcb
.Affinity
;
1764 ThreadBasicInfo
->Priority
= Thread
->Tcb
.Priority
;
1765 ThreadBasicInfo
->BasePriority
= KeQueryBasePriorityThread(&Thread
->Tcb
);
1767 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1769 /* Get exception code */
1770 Status
= _SEH2_GetExceptionCode();
1775 /* Thread time information */
1778 /* Set the return length */
1779 Length
= sizeof(KERNEL_USER_TIMES
);
1781 if (ThreadInformationLength
!= Length
)
1783 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1786 /* Protect writes with SEH */
1789 /* Copy time information from ETHREAD/KTHREAD */
1790 ThreadTime
->KernelTime
.QuadPart
= Thread
->Tcb
.KernelTime
*
1792 ThreadTime
->UserTime
.QuadPart
= Thread
->Tcb
.UserTime
*
1794 ThreadTime
->CreateTime
= Thread
->CreateTime
;
1795 ThreadTime
->ExitTime
= Thread
->ExitTime
;
1797 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1799 /* Get exception code */
1800 Status
= _SEH2_GetExceptionCode();
1805 case ThreadQuerySetWin32StartAddress
:
1807 /* Set the return length*/
1808 Length
= sizeof(PVOID
);
1810 if (ThreadInformationLength
!= Length
)
1812 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1815 /* Protect write with SEH */
1818 /* Return the Win32 Start Address */
1819 *(PVOID
*)ThreadInformation
= Thread
->Win32StartAddress
;
1821 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1823 /* Get exception code */
1824 Status
= _SEH2_GetExceptionCode();
1829 case ThreadPerformanceCount
:
1831 /* Set the return length*/
1832 Length
= sizeof(LARGE_INTEGER
);
1834 if (ThreadInformationLength
!= Length
)
1836 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1839 /* Protect write with SEH */
1843 (*(PLARGE_INTEGER
)ThreadInformation
).QuadPart
= 0;
1845 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1847 /* Get exception code */
1848 Status
= _SEH2_GetExceptionCode();
1853 case ThreadAmILastThread
:
1855 /* Set the return length*/
1856 Length
= sizeof(ULONG
);
1858 if (ThreadInformationLength
!= Length
)
1860 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1863 /* Protect write with SEH */
1866 /* Return whether or not we are the last thread */
1867 *(PULONG
)ThreadInformation
= ((Thread
->ThreadsProcess
->
1868 ThreadListHead
.Flink
->Flink
==
1869 &Thread
->ThreadsProcess
->
1873 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1875 /* Get exception code */
1876 Status
= _SEH2_GetExceptionCode();
1881 case ThreadIsIoPending
:
1883 /* Set the return length*/
1884 Length
= sizeof(ULONG
);
1886 if (ThreadInformationLength
!= Length
)
1888 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1891 /* Raise the IRQL to protect the IRP list */
1892 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1894 /* Protect write with SEH */
1897 /* Check if the IRP list is empty or not */
1898 *(PULONG
)ThreadInformation
= !IsListEmpty(&Thread
->IrpList
);
1900 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1902 /* Get exception code */
1903 Status
= _SEH2_GetExceptionCode();
1907 /* Lower IRQL back */
1908 KeLowerIrql(OldIrql
);
1911 /* LDT and GDT information */
1912 case ThreadDescriptorTableEntry
:
1915 /* Call the worker routine */
1916 Status
= PspQueryDescriptorThread(Thread
,
1918 ThreadInformationLength
,
1921 /* Only implemented on x86 */
1922 Status
= STATUS_NOT_IMPLEMENTED
;
1926 case ThreadPriorityBoost
:
1928 /* Set the return length*/
1929 Length
= sizeof(ULONG
);
1931 if (ThreadInformationLength
!= Length
)
1933 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1939 *(PULONG
)ThreadInformation
= Thread
->Tcb
.DisableBoost
? 1 : 0;
1941 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1943 Status
= _SEH2_GetExceptionCode();
1951 /* Not yet implemented */
1952 DPRINT1("Not implemented: %lx\n", ThreadInformationClass
);
1953 Status
= STATUS_NOT_IMPLEMENTED
;
1956 /* Protect write with SEH */
1959 /* Check if caller wanted return length */
1960 if (ReturnLength
) *ReturnLength
= Length
;
1962 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1964 /* Get exception code */
1965 Status
= _SEH2_GetExceptionCode();
1969 /* Dereference the thread, and return */
1970 ObDereferenceObject(Thread
);