- Major formatting cleanup and optimizations to NtQueryInformationProcess so that it does not burn the eyes of anyone that might attempt to read it.

svn path=/trunk/; revision=23175
This commit is contained in:
Alex Ionescu 2006-07-20 00:13:09 +00:00
parent 69995705e9
commit 2278c2914f

View file

@ -16,10 +16,65 @@
/* Include Information Class Tables */ /* Include Information Class Tables */
#include "internal/ps_i.h" #include "internal/ps_i.h"
/* FUNCTIONS *****************************************************************/ /* PRIVATE FUNCTIONS *********************************************************/
/* FIXME:
* This entire API is messed up because:
* 1) Directly pokes SECTION_OBJECT/FILE_OBJECT without special reffing.
* 2) Ignores SeAuditProcessImageFileName stuff added in XP (and ROS).
* 3) Doesn't use ObQueryNameString.
*/
NTSTATUS
NTAPI
PspGetImagePath(IN PEPROCESS Process,
OUT PUNICODE_STRING DstPath,
IN ULONG ProcessInformationLength)
{
NTSTATUS Status;
ULONG ImagePathLen = 0;
PROS_SECTION_OBJECT Section;
PWSTR SrcBuffer = NULL, DstBuffer = (PWSTR)(DstPath + 1);
Section = (PROS_SECTION_OBJECT)Process->SectionObject;
if ((Section)&& (Section->FileObject))
{
/* FIXME - check for SEC_IMAGE and/or SEC_FILE instead
of relying on FileObject being != NULL? */
SrcBuffer = Section->FileObject->FileName.Buffer;
if (SrcBuffer) ImagePathLen = Section->FileObject->FileName.Length;
}
if (ProcessInformationLength < (sizeof(UNICODE_STRING) +
ImagePathLen +
sizeof(WCHAR)))
{
return STATUS_INFO_LENGTH_MISMATCH;
}
Status = STATUS_SUCCESS;
_SEH_TRY
{
/* copy the string manually, don't use RtlCopyUnicodeString with DstPath! */
DstPath->Length = ImagePathLen;
DstPath->MaximumLength = ImagePathLen + sizeof(WCHAR);
DstPath->Buffer = DstBuffer;
if (ImagePathLen) RtlCopyMemory(DstBuffer, SrcBuffer, ImagePathLen);
DstBuffer[ImagePathLen / sizeof(WCHAR)] = L'\0';
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
/* Return status */
return Status;
}
/* PUBLIC FUNCTIONS **********************************************************/
/* /*
* @unimplemented * @implemented
*/ */
NTSTATUS NTSTATUS
NTAPI NTAPI
@ -27,11 +82,21 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
IN PROCESSINFOCLASS ProcessInformationClass, IN PROCESSINFOCLASS ProcessInformationClass,
OUT PVOID ProcessInformation, OUT PVOID ProcessInformation,
IN ULONG ProcessInformationLength, IN ULONG ProcessInformationLength,
OUT PULONG ReturnLength OPTIONAL) OUT PULONG ReturnLength OPTIONAL)
{ {
PEPROCESS Process; PEPROCESS Process;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
ULONG Length = 0;
PPROCESS_BASIC_INFORMATION ProcessBasicInfo =
(PPROCESS_BASIC_INFORMATION)ProcessInformation;
PKERNEL_USER_TIMES ProcessTime = (PKERNEL_USER_TIMES)ProcessInformation;
ULONG HandleCount;
PPROCESS_SESSION_INFORMATION SessionInfo =
(PPROCESS_SESSION_INFORMATION)ProcessInformation;
PVM_COUNTERS VmCounters = (PVM_COUNTERS)ProcessInformation;
PROCESS_DEVICEMAP_INFORMATION DeviceMap;
ULONG Cookie;
PAGED_CODE(); PAGED_CODE();
/* Check validity of Information Class */ /* Check validity of Information Class */
@ -42,108 +107,113 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
ProcessInformationLength, ProcessInformationLength,
ReturnLength, ReturnLength,
PreviousMode); PreviousMode);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status)) return Status;
{
DPRINT1("NtQueryInformationProcess() failed, Status: 0x%x\n", Status);
return Status;
}
/* Check if this isn't the cookie class */
if(ProcessInformationClass != ProcessCookie) if(ProcessInformationClass != ProcessCookie)
{ {
/* Reference the process */
Status = ObReferenceObjectByHandle(ProcessHandle, Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_QUERY_INFORMATION, PROCESS_QUERY_INFORMATION,
PsProcessType, PsProcessType,
PreviousMode, PreviousMode,
(PVOID*)&Process, (PVOID*)&Process,
NULL); NULL);
if (!NT_SUCCESS(Status)) return(Status); if (!NT_SUCCESS(Status)) return Status;
} }
else if(ProcessHandle != NtCurrentProcess()) else if(ProcessHandle != NtCurrentProcess())
{ {
/* retreiving the process cookie is only allowed for the calling process /*
itself! XP only allowes NtCurrentProcess() as process handles even if a * Retreiving the process cookie is only allowed for the calling process
real handle actually represents the current process. */ * itself! XP only allowes NtCurrentProcess() as process handles even if
* a real handle actually represents the current process.
*/
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
/* Check the information class */
switch (ProcessInformationClass) switch (ProcessInformationClass)
{ {
/* Basic process information */
case ProcessBasicInformation: case ProcessBasicInformation:
/* Protect writes with SEH */
_SEH_TRY
{ {
PPROCESS_BASIC_INFORMATION ProcessBasicInformationP = /* Write all the information from the EPROCESS/KPROCESS */
(PPROCESS_BASIC_INFORMATION)ProcessInformation; ProcessBasicInfo->ExitStatus = Process->ExitStatus;
ProcessBasicInfo->PebBaseAddress = Process->Peb;
ProcessBasicInfo->AffinityMask = Process->Pcb.Affinity;
ProcessBasicInfo->UniqueProcessId = (ULONG)Process->
UniqueProcessId;
ProcessBasicInfo->InheritedFromUniqueProcessId =
(ULONG)Process->InheritedFromUniqueProcessId;
ProcessBasicInfo->BasePriority = Process->Pcb.BasePriority;
_SEH_TRY /* Set return length */
{ Length = sizeof(PROCESS_BASIC_INFORMATION);
ProcessBasicInformationP->ExitStatus = Process->ExitStatus;
ProcessBasicInformationP->PebBaseAddress = Process->Peb;
ProcessBasicInformationP->AffinityMask = Process->Pcb.Affinity;
ProcessBasicInformationP->UniqueProcessId =
(ULONG)Process->UniqueProcessId;
ProcessBasicInformationP->InheritedFromUniqueProcessId =
(ULONG)Process->InheritedFromUniqueProcessId;
ProcessBasicInformationP->BasePriority =
Process->Pcb.BasePriority;
if (ReturnLength)
{
*ReturnLength = sizeof(PROCESS_BASIC_INFORMATION);
}
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
break;
} }
_SEH_HANDLE
{
/* Get exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
break;
/* Quote limits and I/O Counters: not implemented */
case ProcessQuotaLimits: case ProcessQuotaLimits:
case ProcessIoCounters: case ProcessIoCounters:
Status = STATUS_NOT_IMPLEMENTED; Status = STATUS_NOT_IMPLEMENTED;
break; break;
/* Timing */
case ProcessTimes: case ProcessTimes:
/* Protect writes with SEH */
_SEH_TRY
{ {
PKERNEL_USER_TIMES ProcessTimeP = (PKERNEL_USER_TIMES)ProcessInformation; /* Copy time information from EPROCESS/KPROCESS */
_SEH_TRY ProcessTime->CreateTime = Process->CreateTime;
{ ProcessTime->UserTime.QuadPart = Process->Pcb.UserTime *
ProcessTimeP->CreateTime = Process->CreateTime; 100000LL;
ProcessTimeP->UserTime.QuadPart = Process->Pcb.UserTime * 100000LL; ProcessTime->KernelTime.QuadPart = Process->Pcb.KernelTime *
ProcessTimeP->KernelTime.QuadPart = Process->Pcb.KernelTime * 100000LL; 100000LL;
ProcessTimeP->ExitTime = Process->ExitTime; ProcessTime->ExitTime = Process->ExitTime;
if (ReturnLength) /* Set the return length */
{ Length = sizeof(KERNEL_USER_TIMES);
*ReturnLength = sizeof(KERNEL_USER_TIMES);
}
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
break;
} }
_SEH_HANDLE
{
/* Get exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
break;
/* Process Debug Port */
case ProcessDebugPort: case ProcessDebugPort:
{
_SEH_TRY
{
*(PHANDLE)ProcessInformation = (Process->DebugPort != NULL ? (HANDLE)-1 : NULL);
if (ReturnLength)
{
*ReturnLength = sizeof(HANDLE);
}
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
break;
}
/* Protect write with SEH */
_SEH_TRY
{
/* Return whether or not we have a debug port */
*(PHANDLE)ProcessInformation = (Process->DebugPort ?
(HANDLE)-1 : NULL);
/* Set the return length*/
Length = sizeof(HANDLE);
}
_SEH_HANDLE
{
/* Get exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
break;
/* LDT, WS and VDM Information: not implemented */
case ProcessLdtInformation: case ProcessLdtInformation:
case ProcessWorkingSetWatch: case ProcessWorkingSetWatch:
case ProcessWx86Information: case ProcessWx86Information:
@ -151,278 +221,217 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
break; break;
case ProcessHandleCount: case ProcessHandleCount:
/* Count the number of handles this process has */
HandleCount = ObpGetHandleCountByHandleTable(Process->ObjectTable);
/* Protect write in SEH */
_SEH_TRY
{ {
ULONG HandleCount = ObpGetHandleCountByHandleTable(Process->ObjectTable); /* Return the count of handles */
*(PULONG)ProcessInformation = HandleCount;
_SEH_TRY /* Set the return length*/
{ Length = sizeof(ULONG);
*(PULONG)ProcessInformation = HandleCount;
if (ReturnLength)
{
*ReturnLength = sizeof(ULONG);
}
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
break;
} }
_SEH_HANDLE
{
/* Get the exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
break;
/* Session ID for the process */
case ProcessSessionInformation: case ProcessSessionInformation:
/* Enter SEH for write safety */
_SEH_TRY
{ {
PPROCESS_SESSION_INFORMATION SessionInfo = (PPROCESS_SESSION_INFORMATION)ProcessInformation; /* Write back the Session ID */
SessionInfo->SessionId = Process->Session;
_SEH_TRY /* Set the return length */
{ Length = sizeof(PROCESS_SESSION_INFORMATION);
SessionInfo->SessionId = Process->Session;
if (ReturnLength)
{
*ReturnLength = sizeof(PROCESS_SESSION_INFORMATION);
}
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
break;
} }
_SEH_HANDLE
{
/* Get the exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
break;
/* WOW64: Not implemented */
case ProcessWow64Information: case ProcessWow64Information:
DPRINT1("We currently don't support the ProcessWow64Information information class!\n");
Status = STATUS_NOT_IMPLEMENTED; Status = STATUS_NOT_IMPLEMENTED;
break; break;
/* Virtual Memory Statistics */
case ProcessVmCounters: case ProcessVmCounters:
/* Enter SEH for write safety */
_SEH_TRY
{ {
PVM_COUNTERS pOut = (PVM_COUNTERS)ProcessInformation; /* Return data from EPROCESS */
VmCounters->PeakVirtualSize = Process->PeakVirtualSize;
VmCounters->VirtualSize = Process->VirtualSize;
VmCounters->PageFaultCount = Process->Vm.PageFaultCount;
VmCounters->PeakWorkingSetSize = Process->Vm.PeakWorkingSetSize;
VmCounters->WorkingSetSize = Process->Vm.WorkingSetSize;
VmCounters->QuotaPeakPagedPoolUsage = Process->QuotaPeak[0];
VmCounters->QuotaPagedPoolUsage = Process->QuotaUsage[0];
VmCounters->QuotaPeakNonPagedPoolUsage = Process->QuotaPeak[1];
VmCounters->QuotaNonPagedPoolUsage = Process->QuotaUsage[1];
VmCounters->PagefileUsage = Process->QuotaUsage[2];
VmCounters->PeakPagefileUsage = Process->QuotaPeak[2];
_SEH_TRY /* Set the return length */
{ *ReturnLength = sizeof(VM_COUNTERS);
pOut->PeakVirtualSize = Process->PeakVirtualSize;
/*
* Here we should probably use VirtualSize.LowPart, but due to
* incompatibilities in current headers (no unnamed union),
* I opted for cast.
*/
pOut->VirtualSize = (ULONG)Process->VirtualSize;
pOut->PageFaultCount = Process->Vm.PageFaultCount;
pOut->PeakWorkingSetSize = Process->Vm.PeakWorkingSetSize;
pOut->WorkingSetSize = Process->Vm.WorkingSetSize;
pOut->QuotaPeakPagedPoolUsage = Process->QuotaPeak[0]; // TODO: Verify!
pOut->QuotaPagedPoolUsage = Process->QuotaUsage[0]; // TODO: Verify!
pOut->QuotaPeakNonPagedPoolUsage = Process->QuotaPeak[1]; // TODO: Verify!
pOut->QuotaNonPagedPoolUsage = Process->QuotaUsage[1]; // TODO: Verify!
pOut->PagefileUsage = Process->QuotaUsage[2];
pOut->PeakPagefileUsage = Process->QuotaPeak[2];
if (ReturnLength)
{
*ReturnLength = sizeof(VM_COUNTERS);
}
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
break;
} }
_SEH_HANDLE
{
/* Get the exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
break;
/* Hard Error Processing Mode */
case ProcessDefaultHardErrorMode: case ProcessDefaultHardErrorMode:
{
PULONG HardErrMode = (PULONG)ProcessInformation;
_SEH_TRY
{
*HardErrMode = Process->DefaultHardErrorProcessing;
if (ReturnLength)
{
*ReturnLength = sizeof(ULONG);
}
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
break;
}
/* Enter SEH for writing back data */
_SEH_TRY
{
/* Write the current processing mode */
*(PULONG)ProcessInformation = Process->
DefaultHardErrorProcessing;
/* Set the return length */
Length = sizeof(ULONG);
}
_SEH_HANDLE
{
/* Get the exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
break;
/* Priority Boosting status */
case ProcessPriorityBoost: case ProcessPriorityBoost:
/* Enter SEH for writing back data */
_SEH_TRY
{ {
PULONG BoostEnabled = (PULONG)ProcessInformation; /* Return boost status */
*(PULONG)ProcessInformation = Process->Pcb.DisableBoost ?
FALSE : TRUE;
_SEH_TRY /* Set the return length */
{ Length = sizeof(ULONG);
*BoostEnabled = Process->Pcb.DisableBoost ? FALSE : TRUE;
if (ReturnLength)
{
*ReturnLength = sizeof(ULONG);
}
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
break;
} }
_SEH_HANDLE
{
/* Get the exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
break;
/* DOS Device Map */
case ProcessDeviceMap: case ProcessDeviceMap:
/* Query the device map information */
ObQueryDeviceMapInformation(Process, &DeviceMap);
/* Enter SEH for writing back data */
_SEH_TRY
{ {
PROCESS_DEVICEMAP_INFORMATION DeviceMap; *(PPROCESS_DEVICEMAP_INFORMATION)ProcessInformation = DeviceMap;
ObQueryDeviceMapInformation(Process, &DeviceMap); /* Set the return length */
Length = sizeof(PROCESS_DEVICEMAP_INFORMATION);
_SEH_TRY
{
*(PPROCESS_DEVICEMAP_INFORMATION)ProcessInformation = DeviceMap;
if (ReturnLength)
{
*ReturnLength = sizeof(PROCESS_DEVICEMAP_INFORMATION);
}
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
break;
} }
_SEH_HANDLE
{
/* Get the exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
break;
/* Priority class */
case ProcessPriorityClass: case ProcessPriorityClass:
/* Enter SEH for writing back data */
_SEH_TRY
{ {
PUSHORT Priority = (PUSHORT)ProcessInformation; /* Return current priority class */
*(PUSHORT)ProcessInformation = Process->PriorityClass;
_SEH_TRY /* Set the return length */
{ Length = sizeof(USHORT);
*Priority = Process->PriorityClass;
if (ReturnLength)
{
*ReturnLength = sizeof(USHORT);
}
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
break;
} }
_SEH_HANDLE
{
/* Get the exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
break;
case ProcessImageFileName: case ProcessImageFileName:
{
ULONG ImagePathLen = 0;
PROS_SECTION_OBJECT Section;
PUNICODE_STRING DstPath = (PUNICODE_STRING)ProcessInformation;
PWSTR SrcBuffer = NULL, DstBuffer = (PWSTR)(DstPath + 1);
Section = (PROS_SECTION_OBJECT)Process->SectionObject; /* Get the image path */
Status = PspGetImagePath(Process,
if (Section != NULL && Section->FileObject != NULL) (PUNICODE_STRING)ProcessInformation,
{ ProcessInformationLength);
/* FIXME - check for SEC_IMAGE and/or SEC_FILE instead break;
of relying on FileObject being != NULL? */
SrcBuffer = Section->FileObject->FileName.Buffer;
if (SrcBuffer != NULL)
{
ImagePathLen = Section->FileObject->FileName.Length;
}
}
if(ProcessInformationLength < sizeof(UNICODE_STRING) + ImagePathLen + sizeof(WCHAR))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
}
else
{
_SEH_TRY
{
/* copy the string manually, don't use RtlCopyUnicodeString with DstPath! */
DstPath->Length = ImagePathLen;
DstPath->MaximumLength = ImagePathLen + sizeof(WCHAR);
DstPath->Buffer = DstBuffer;
if (ImagePathLen != 0)
{
RtlCopyMemory(DstBuffer,
SrcBuffer,
ImagePathLen);
}
DstBuffer[ImagePathLen / sizeof(WCHAR)] = L'\0';
Status = STATUS_SUCCESS;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
break;
}
/* Per-process security cookie */
case ProcessCookie: case ProcessCookie:
/* Get the current process and cookie */
Process = PsGetCurrentProcess();
Cookie = Process->Cookie;
if(!Cookie)
{ {
ULONG Cookie; LARGE_INTEGER SystemTime;
ULONG NewCookie;
PKPRCB Prcb;
/* receive the process cookie, this is only allowed for the current /* Generate a new cookie */
process! */ KeQuerySystemTime(&SystemTime);
Prcb = KeGetCurrentPrcb();
NewCookie = Prcb->KeSystemCalls ^ Prcb->InterruptTime ^
SystemTime.u.LowPart ^ SystemTime.u.HighPart;
Process = PsGetCurrentProcess(); /* Set the new cookie or return the current one */
Cookie = InterlockedCompareExchange((LONG*)&Process->Cookie,
NewCookie,
Cookie);
if(!Cookie) Cookie = NewCookie;
Cookie = Process->Cookie; /* Set return length */
if(Cookie == 0) Length = sizeof(ULONG);
{
LARGE_INTEGER SystemTime;
ULONG NewCookie;
PKPRCB Prcb;
/* generate a new cookie */
KeQuerySystemTime(&SystemTime);
Prcb = KeGetCurrentPrcb();
NewCookie = Prcb->KeSystemCalls ^ Prcb->InterruptTime ^
SystemTime.u.LowPart ^ SystemTime.u.HighPart;
/* try to set the new cookie, return the current one if another thread
set it in the meanwhile */
Cookie = InterlockedCompareExchange((LONG*)&Process->Cookie,
NewCookie,
Cookie);
if(Cookie == 0)
{
/* successfully set the cookie */
Cookie = NewCookie;
}
}
_SEH_TRY
{
*(PULONG)ProcessInformation = Cookie;
if (ReturnLength)
{
*ReturnLength = sizeof(ULONG);
}
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
break;
} }
/* /* Enter SEH to protect write */
* Note: The following 10 information classes are verified to not be _SEH_TRY
* implemented on NT, and do indeed return STATUS_INVALID_INFO_CLASS; {
*/ /* Write back the cookie */
*(PULONG)ProcessInformation = Cookie;
}
_SEH_HANDLE
{
/* Get the exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
break;
/* Not yet implemented, or unknown */
case ProcessBasePriority: case ProcessBasePriority:
case ProcessRaisePriority: case ProcessRaisePriority:
case ProcessExceptionPort: case ProcessExceptionPort:
@ -437,6 +446,20 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
Status = STATUS_INVALID_INFO_CLASS; Status = STATUS_INVALID_INFO_CLASS;
} }
/* Protect write with SEH */
_SEH_TRY
{
/* Check if caller wanted return length */
if (ReturnLength) *ReturnLength = Length;
}
_SEH_HANDLE
{
/* Get exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
/* If we referenced the process, dereference it */
if(ProcessInformationClass != ProcessCookie) ObDereferenceObject(Process); if(ProcessInformationClass != ProcessCookie) ObDereferenceObject(Process);
return Status; return Status;
} }