#define NDEBUG
#include <debug.h>
-/* FIXME: From winbase.h... what to do? */
-#define SEM_NOALIGNMENTFAULTEXCEPT 0x04
-
-/* Include Information Class Tables */
-#include "internal/ps_i.h"
-
/* Debugging Level */
ULONG PspTraceLevel = 0;
PAGED_CODE();
/* Lock the process */
- ExAcquireRundownProtection(&Process->RundownProtect);
+ if (!ExAcquireRundownProtection(&Process->RundownProtect))
+ {
+ return STATUS_PROCESS_IS_TERMINATING;
+ }
/* Get the section */
Section = Process->SectionObject;
PPROCESS_BASIC_INFORMATION ProcessBasicInfo =
(PPROCESS_BASIC_INFORMATION)ProcessInformation;
PKERNEL_USER_TIMES ProcessTime = (PKERNEL_USER_TIMES)ProcessInformation;
+ ULONG UserTime, KernelTime;
PPROCESS_PRIORITY_CLASS PsPriorityClass = (PPROCESS_PRIORITY_CLASS)ProcessInformation;
ULONG HandleCount;
PPROCESS_SESSION_INFORMATION SessionInfo =
PUNICODE_STRING ImageName;
ULONG Cookie, ExecuteOptions = 0;
ULONG_PTR Wow64 = 0;
+ PROCESS_VALUES ProcessValues;
PAGED_CODE();
/* Check for user-mode caller */
_SEH2_TRY
{
/* Probe the buffer */
- ProbeForWrite(ProcessInformation,
- ProcessInformationLength,
- sizeof(ULONG));
+ ProbeForRead(ProcessInformation,
+ ProcessInformationLength,
+ sizeof(ULONG));
/* Probe the return length if required */
if (ReturnLength) ProbeForWriteUlong(ReturnLength);
_SEH2_END;
}
- if((ProcessInformationClass == ProcessCookie) &&
+ if (((ProcessInformationClass == ProcessCookie) ||
+ (ProcessInformationClass == ProcessImageInformation)) &&
(ProcessHandle != NtCurrentProcess()))
{
/*
- * Retreiving the process cookie is only allowed for the calling process
- * itself! XP only allowes NtCurrentProcess() as process handles even if
+ * Retrieving the process cookie is only allowed for the calling process
+ * itself! XP only allows NtCurrentProcess() as process handles even if
* a real handle actually represents the current process.
*/
return STATUS_INVALID_PARAMETER;
/* Basic process information */
case ProcessBasicInformation:
- /* Set return length */
- Length = sizeof(PROCESS_BASIC_INFORMATION);
-
- if (ProcessInformationLength != Length)
+ if (ProcessInformationLength != sizeof(PROCESS_BASIC_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
+ /* Set return length */
+ Length = sizeof(PROCESS_BASIC_INFORMATION);
+
/* Reference the process */
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_QUERY_INFORMATION,
ProcessBasicInfo->UniqueProcessId = (ULONG_PTR)Process->
UniqueProcessId;
ProcessBasicInfo->InheritedFromUniqueProcessId =
- (ULONG)Process->InheritedFromUniqueProcessId;
+ (ULONG_PTR)Process->InheritedFromUniqueProcessId;
ProcessBasicInfo->BasePriority = Process->Pcb.BasePriority;
}
/* Process quota limits */
case ProcessQuotaLimits:
- Length = sizeof(QUOTA_LIMITS);
- if (ProcessInformationLength != Length)
+ if (ProcessInformationLength != sizeof(QUOTA_LIMITS))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
+ Length = sizeof(QUOTA_LIMITS);
+
/* Reference the process */
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_QUERY_INFORMATION,
case ProcessIoCounters:
- Length = sizeof(IO_COUNTERS);
- if (ProcessInformationLength != Length)
+ if (ProcessInformationLength != sizeof(IO_COUNTERS))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
+ Length = sizeof(IO_COUNTERS);
+
/* Reference the process */
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_QUERY_INFORMATION,
NULL);
if (!NT_SUCCESS(Status)) break;
+ /* Query IO counters from the process */
+ KeQueryValuesProcess(&Process->Pcb, &ProcessValues);
+
_SEH2_TRY
{
- /* FIXME: Call KeQueryValuesProcess */
- IoCounters->ReadOperationCount = Process->ReadOperationCount.QuadPart;
- IoCounters->ReadTransferCount = Process->ReadTransferCount.QuadPart;
- IoCounters->WriteOperationCount = Process->WriteOperationCount.QuadPart;
- IoCounters->WriteTransferCount = Process->WriteTransferCount.QuadPart;
- IoCounters->OtherOperationCount = Process->OtherOperationCount.QuadPart;
- IoCounters->OtherTransferCount = Process->OtherTransferCount.QuadPart;
+ RtlCopyMemory(IoCounters, &ProcessValues.IoInfo, sizeof(IO_COUNTERS));
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
case ProcessTimes:
/* Set the return length */
- Length = sizeof(KERNEL_USER_TIMES);
-
- if (ProcessInformationLength != Length)
+ if (ProcessInformationLength != sizeof(KERNEL_USER_TIMES))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
+ Length = sizeof(KERNEL_USER_TIMES);
+
/* Reference the process */
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_QUERY_INFORMATION,
_SEH2_TRY
{
/* Copy time information from EPROCESS/KPROCESS */
- /* FIXME: Call KeQueryRuntimeProcess */
+ KernelTime = KeQueryRuntimeProcess(&Process->Pcb, &UserTime);
ProcessTime->CreateTime = Process->CreateTime;
- ProcessTime->UserTime.QuadPart = Process->Pcb.UserTime *
- KeMaximumIncrement;
- ProcessTime->KernelTime.QuadPart = Process->Pcb.KernelTime *
- KeMaximumIncrement;
+ ProcessTime->UserTime.QuadPart = (LONGLONG)UserTime * KeMaximumIncrement;
+ ProcessTime->KernelTime.QuadPart = (LONGLONG)KernelTime * KeMaximumIncrement;
ProcessTime->ExitTime = Process->ExitTime;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
/* Process Debug Port */
case ProcessDebugPort:
- /* Set return length */
- Length = sizeof(HANDLE);
-
- if (ProcessInformationLength != Length)
+ if (ProcessInformationLength != sizeof(HANDLE))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
+ /* Set return length */
+ Length = sizeof(HANDLE);
+
/* Reference the process */
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_QUERY_INFORMATION,
case ProcessHandleCount:
- /* Set the return length*/
- Length = sizeof(ULONG);
-
- if (ProcessInformationLength != Length)
+ if (ProcessInformationLength != sizeof(ULONG))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
+ /* Set the return length*/
+ Length = sizeof(ULONG);
+
/* Reference the process */
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_QUERY_INFORMATION,
/* Session ID for the process */
case ProcessSessionInformation:
- /* Set the return length*/
- Length = sizeof(PROCESS_SESSION_INFORMATION);
-
- if (ProcessInformationLength != Length)
+ if (ProcessInformationLength != sizeof(PROCESS_SESSION_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
+ /* Set the return length*/
+ Length = sizeof(PROCESS_SESSION_INFORMATION);
+
/* Reference the process */
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_QUERY_INFORMATION,
_SEH2_TRY
{
/* Write back the Session ID */
- SessionInfo->SessionId = PtrToUlong(PsGetProcessSessionId(Process));
+ SessionInfo->SessionId = PsGetProcessSessionId(Process);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Hard Error Processing Mode */
case ProcessDefaultHardErrorMode:
- /* Set the return length*/
- Length = sizeof(ULONG);
-
- if (ProcessInformationLength != Length)
+ if (ProcessInformationLength != sizeof(ULONG))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
+ /* Set the return length*/
+ Length = sizeof(ULONG);
+
/* Reference the process */
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_QUERY_INFORMATION,
/* Priority Boosting status */
case ProcessPriorityBoost:
- /* Set the return length */
- Length = sizeof(ULONG);
-
- if (ProcessInformationLength != Length)
+ if (ProcessInformationLength != sizeof(ULONG))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
+ /* Set the return length */
+ Length = sizeof(ULONG);
+
/* Reference the process */
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_QUERY_INFORMATION,
/* DOS Device Map */
case ProcessDeviceMap:
- /* Set the return length */
- Length = sizeof(PROCESS_DEVICEMAP_INFORMATION);
-
- if (ProcessInformationLength != Length)
+ if (ProcessInformationLength != sizeof(PROCESS_DEVICEMAP_INFORMATION))
{
if (ProcessInformationLength == sizeof(PROCESS_DEVICEMAP_INFORMATION_EX))
{
break;
}
+ /* Set the return length */
+ Length = sizeof(PROCESS_DEVICEMAP_INFORMATION);
+
/* Reference the process */
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_QUERY_INFORMATION,
/* Priority class */
case ProcessPriorityClass:
- /* Set the return length*/
- Length = sizeof(PROCESS_PRIORITY_CLASS);
-
- if (ProcessInformationLength != Length)
+ if (ProcessInformationLength != sizeof(PROCESS_PRIORITY_CLASS))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
+ /* Set the return length*/
+ Length = sizeof(PROCESS_PRIORITY_CLASS);
+
/* Reference the process */
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_QUERY_INFORMATION,
}
/* Free the image path */
- ExFreePool(ImageName);
+ ExFreePoolWithTag(ImageName, TAG_SEPA);
}
/* Dereference the process */
ObDereferenceObject(Process);
case ProcessDebugFlags:
- /* Set the return length*/
- Length = sizeof(ULONG);
- if (ProcessInformationLength != Length)
+ if (ProcessInformationLength != sizeof(ULONG))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
+ /* Set the return length*/
+ Length = sizeof(ULONG);
+
/* Reference the process */
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_QUERY_INFORMATION,
case ProcessBreakOnTermination:
- /* Set the return length*/
- Length = sizeof(ULONG);
- if (ProcessInformationLength != Length)
+ if (ProcessInformationLength != sizeof(ULONG))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
+ /* Set the return length */
+ Length = sizeof(ULONG);
+
/* Reference the process */
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_QUERY_INFORMATION,
break;
case ProcessImageInformation:
- DPRINT1("Image Information Query Not implemented: %lx\n", ProcessInformationClass);
- Status = STATUS_NOT_IMPLEMENTED;
+
+ if (ProcessInformationLength != sizeof(SECTION_IMAGE_INFORMATION))
+ {
+ /* Break out */
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* Set the length required and validate it */
+ Length = sizeof(SECTION_IMAGE_INFORMATION);
+
+ /* Enter SEH to protect write */
+ _SEH2_TRY
+ {
+ MmGetImageInformation((PSECTION_IMAGE_INFORMATION)ProcessInformation);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ /* Indicate success */
+ Status = STATUS_SUCCESS;
break;
case ProcessDebugObjectHandle:
- /* Set the return length */
- Length = sizeof(HANDLE);
- if (ProcessInformationLength != Length)
+ if (ProcessInformationLength != sizeof(HANDLE))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
+ /* Set the return length */
+ Length = sizeof(HANDLE);
+
/* Reference the process */
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_QUERY_INFORMATION,
case ProcessLUIDDeviceMapsEnabled:
- /* Set the return length */
- Length = sizeof(ULONG);
- if (ProcessInformationLength != Length)
+ if (ProcessInformationLength != sizeof(ULONG))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
+ /* Set the return length */
+ Length = sizeof(ULONG);
+
/* Indicate success */
Status = STATUS_SUCCESS;
case ProcessWx86Information:
- /* Set the return length */
- Length = sizeof(ULONG);
- if (ProcessInformationLength != Length)
+ if (ProcessInformationLength != sizeof(ULONG))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
+ /* Set the return length */
+ Length = sizeof(ULONG);
+
/* Reference the process */
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_QUERY_INFORMATION,
case ProcessWow64Information:
- /* Set return length */
- Length = sizeof(ULONG_PTR);
- if (ProcessInformationLength != Length)
+ if (ProcessInformationLength != sizeof(ULONG_PTR))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
+ /* Set return length */
+ Length = sizeof(ULONG_PTR);
+
/* Reference the process */
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_QUERY_INFORMATION,
case ProcessExecuteFlags:
- /* Set return length */
- Length = sizeof(ULONG);
- if (ProcessInformationLength != Length)
+ if (ProcessInformationLength != sizeof(ULONG))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
+ /* Set return length */
+ Length = sizeof(ULONG);
+
if (ProcessHandle != NtCurrentProcess())
{
return STATUS_INVALID_PARAMETER;
/* Getting VDM powers requires the SeTcbPrivilege */
if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
{
- /* Bail out */
+ /* We don't hold the privilege, bail out */
Status = STATUS_PRIVILEGE_NOT_HELD;
DPRINT1("Need TCB privilege\n");
break;
/* Setting the error port requires the SeTcbPrivilege */
if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
{
- /* Can't set the session ID, bail out. */
+ /* We don't hold the privilege, bail out */
Status = STATUS_PRIVILEGE_NOT_HELD;
break;
}
/* Setting the session id requires the SeTcbPrivilege */
if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
{
- /* Can't set the session ID, bail out. */
+ /* We don't hold the privilege, bail out */
Status = STATUS_PRIVILEGE_NOT_HELD;
break;
}
+#if 0 // OLD AND DEPRECATED CODE!!!!
+
/* FIXME - update the session id for the process token */
//Status = PsLockProcess(Process, FALSE);
if (!NT_SUCCESS(Status)) break;
/* Unlock the process */
//PsUnlockProcess(Process);
+
+#endif
+
+ /*
+ * Since we cannot change the session ID of the given
+ * process anymore because it is set once and for all
+ * at process creation time and because it is stored
+ * inside the Process->Session structure managed by MM,
+ * we fake changing it: we just return success if the
+ * user-defined value is the same as the session ID of
+ * the process, and otherwise we fail.
+ */
+ if (SessionInfo.SessionId == PsGetProcessSessionId(Process))
+ {
+ Status = STATUS_SUCCESS;
+ }
+ else
+ {
+ Status = STATUS_ACCESS_DENIED;
+ }
+
break;
case ProcessPriorityClass:
/* Validate the number */
if ((BasePriority > HIGH_PRIORITY) || (BasePriority <= LOW_PRIORITY))
{
+ ObDereferenceObject(Process);
return STATUS_INVALID_PARAMETER;
}
/* Setting 'break on termination' requires the SeDebugPrivilege */
if (!SeSinglePrivilegeCheck(SeDebugPrivilege, PreviousMode))
{
+ /* We don't hold the privilege, bail out */
Status = STATUS_PRIVILEGE_NOT_HELD;
break;
}
/* Only TCB can do this */
if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
{
- /* Fail */
+ /* We don't hold the privilege, bail out */
DPRINT1("Need TCB to set IOPL\n");
Status = STATUS_PRIVILEGE_NOT_HELD;
break;
break;
case ProcessQuotaLimits:
- DPRINT1("Quota Limits not implemented\n");
- Status = STATUS_NOT_IMPLEMENTED;
+
+ Status = PspSetQuotaLimits(Process,
+ 1,
+ ProcessInformation,
+ ProcessInformationLength,
+ PreviousMode);
break;
case ProcessWorkingSetWatch:
/* Setting 'break on termination' requires the SeDebugPrivilege */
if (!SeSinglePrivilegeCheck(SeDebugPrivilege, PreviousMode))
{
+ /* We don't hold the privilege, bail out */
Status = STATUS_PRIVILEGE_NOT_HELD;
break;
}
}
break;
+ case ThreadHideFromDebugger:
+
+ /* Check buffer length */
+ if (ThreadInformationLength != 0)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* Set the flag */
+ PspSetCrossThreadFlag(Thread, CT_HIDE_FROM_DEBUGGER_BIT);
+ break;
+
default:
/* We don't implement it yet */
DPRINT1("Not implemented: %d\n", ThreadInformationClass);
(PTHREAD_BASIC_INFORMATION)ThreadInformation;
PKERNEL_USER_TIMES ThreadTime = (PKERNEL_USER_TIMES)ThreadInformation;
KIRQL OldIrql;
+ ULONG ThreadTerminated;
PAGED_CODE();
/* Check if we were called from user mode */
_SEH2_END;
break;
+ case ThreadIsTerminated:
+
+ /* Set the return length*/
+ Length = sizeof(ThreadTerminated);
+
+ if (ThreadInformationLength != Length)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ ThreadTerminated = PsIsThreadTerminating(Thread);
+
+ _SEH2_TRY
+ {
+ *(PULONG)ThreadInformation = ThreadTerminated ? 1 : 0;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ break;
+
/* Anything else */
default: