/* 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;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status;
ULONG Length = 0;
+ HANDLE DebugPort = 0;
PPROCESS_BASIC_INFORMATION ProcessBasicInfo =
(PPROCESS_BASIC_INFORMATION)ProcessInformation;
PKERNEL_USER_TIMES ProcessTime = (PKERNEL_USER_TIMES)ProcessInformation;
PQUOTA_LIMITS QuotaLimits = (PQUOTA_LIMITS)ProcessInformation;
PROCESS_DEVICEMAP_INFORMATION DeviceMap;
PUNICODE_STRING ImageName;
- ULONG Cookie;
+ ULONG Cookie, ExecuteOptions = 0;
+ ULONG_PTR Wow64 = 0;
PAGED_CODE();
/* Check for user-mode caller */
_SEH2_END;
}
- if((ProcessInformationClass == ProcessCookie) &&
+ if (((ProcessInformationClass == ProcessCookie) ||
+ (ProcessInformationClass == ProcessImageInformation)) &&
(ProcessHandle != NtCurrentProcess()))
{
/*
ProcessBasicInfo->UniqueProcessId = (ULONG_PTR)Process->
UniqueProcessId;
ProcessBasicInfo->InheritedFromUniqueProcessId =
- (ULONG)Process->InheritedFromUniqueProcessId;
+ (ULONG_PTR)Process->InheritedFromUniqueProcessId;
ProcessBasicInfo->BasePriority = Process->Pcb.BasePriority;
}
_SEH2_TRY
{
/* Write back the Session ID */
- SessionInfo->SessionId = PtrToUlong(PsGetProcessSessionId(Process));
+ SessionInfo->SessionId = PsGetProcessSessionId(Process);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
break;
}
- /* Set the return length */
- Length = ProcessInformationLength;
-
/* Reference the process */
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_QUERY_INFORMATION,
VmCounters->PagefileUsage = Process->QuotaUsage[2] << PAGE_SHIFT;
VmCounters->PeakPagefileUsage = Process->QuotaPeak[2] << PAGE_SHIFT;
//VmCounters->PrivateUsage = Process->CommitCharge << PAGE_SHIFT;
+ //
+
+ /* Set the return length */
+ Length = ProcessInformationLength;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
}
/* Free the image path */
- ExFreePool(ImageName);
+ ExFreePoolWithTag(ImageName, TAG_SEPA);
}
/* Dereference the process */
ObDereferenceObject(Process);
break;
case ProcessImageInformation:
- DPRINT1("Image Information Query Not implemented: %lx\n", ProcessInformationClass);
- Status = STATUS_NOT_IMPLEMENTED;
+
+ /* Set the length required and validate it */
+ Length = sizeof(SECTION_IMAGE_INFORMATION);
+ if (ProcessInformationLength != Length)
+ {
+ /* Break out */
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* 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:
- DPRINT1("Debug Object Query Not implemented: %lx\n", ProcessInformationClass);
- Status = STATUS_NOT_IMPLEMENTED;
+
+ /* Set the return length */
+ Length = sizeof(HANDLE);
+ if (ProcessInformationLength != Length)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* Reference the process */
+ Status = ObReferenceObjectByHandle(ProcessHandle,
+ PROCESS_QUERY_INFORMATION,
+ PsProcessType,
+ PreviousMode,
+ (PVOID*)&Process,
+ NULL);
+ if (!NT_SUCCESS(Status)) break;
+
+ /* Get the debug port */
+ Status = DbgkOpenProcessDebugPort(Process, PreviousMode, &DebugPort);
+
+ /* Let go of the process */
+ ObDereferenceObject(Process);
+
+ /* Protect write in SEH */
+ _SEH2_TRY
+ {
+ /* Return debug port's handle */
+ *(PHANDLE)ProcessInformation = DebugPort;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
break;
case ProcessHandleTracing:
break;
case ProcessLUIDDeviceMapsEnabled:
- DPRINT1("LUID Device Maps Not implemented: %lx\n", ProcessInformationClass);
- Status = STATUS_NOT_IMPLEMENTED;
+
+ /* Set the return length */
+ Length = sizeof(ULONG);
+ if (ProcessInformationLength != Length)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* Indicate success */
+ Status = STATUS_SUCCESS;
+
+ /* Protect write in SEH */
+ _SEH2_TRY
+ {
+ /* Return FALSE -- we don't support this */
+ *(PULONG)ProcessInformation = FALSE;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
break;
- case ProcessExecuteFlags:
- DPRINT1("No execute Not implemented: %lx\n", ProcessInformationClass);
- Status = STATUS_NOT_IMPLEMENTED;
+ case ProcessWx86Information:
+
+ /* Set the return length */
+ Length = sizeof(ULONG);
+ if (ProcessInformationLength != Length)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* Reference the process */
+ Status = ObReferenceObjectByHandle(ProcessHandle,
+ PROCESS_QUERY_INFORMATION,
+ PsProcessType,
+ PreviousMode,
+ (PVOID*)&Process,
+ NULL);
+ if (!NT_SUCCESS(Status)) break;
+
+ /* Protect write in SEH */
+ _SEH2_TRY
+ {
+ /* Return if the flag is set */
+ *(PULONG)ProcessInformation = (ULONG)Process->VdmAllowed;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ /* Dereference the process */
+ ObDereferenceObject(Process);
break;
case ProcessWow64Information:
+
+ /* Set return length */
+ Length = sizeof(ULONG_PTR);
+ if (ProcessInformationLength != Length)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* Reference the process */
+ Status = ObReferenceObjectByHandle(ProcessHandle,
+ PROCESS_QUERY_INFORMATION,
+ PsProcessType,
+ PreviousMode,
+ (PVOID*)&Process,
+ NULL);
+ if (!NT_SUCCESS(Status)) break;
+
+ /* Make sure the process isn't dying */
+ if (ExAcquireRundownProtection(&Process->RundownProtect))
+ {
+ /* Get the WOW64 process structure */
+#ifdef _WIN64
+ Wow64 = (ULONG_PTR)Process->Wow64Process;
+#else
+ Wow64 = 0;
+#endif
+ /* Release the lock */
+ ExReleaseRundownProtection(&Process->RundownProtect);
+ }
+
+ /* Protect write with SEH */
+ _SEH2_TRY
+ {
+ /* Return whether or not we have a debug port */
+ *(PULONG_PTR)ProcessInformation = Wow64;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ /* Dereference the process */
+ ObDereferenceObject(Process);
+ break;
+
+ case ProcessExecuteFlags:
+
+ /* Set return length */
+ Length = sizeof(ULONG);
+ if (ProcessInformationLength != Length)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ if (ProcessHandle != NtCurrentProcess())
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Get the options */
+ Status = MmGetExecuteOptions(&ExecuteOptions);
+ if (NT_SUCCESS(Status))
+ {
+ /* Protect write with SEH */
+ _SEH2_TRY
+ {
+ /* Return them */
+ *(PULONG)ProcessInformation = ExecuteOptions;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+ }
+ break;
+
case ProcessLdtInformation:
- case ProcessWx86Information:
- DPRINT1("VDM/16-bit implemented: %lx\n", ProcessInformationClass);
+ DPRINT1("VDM/16-bit not implemented: %lx\n", ProcessInformationClass);
Status = STATUS_NOT_IMPLEMENTED;
break;
_SEH2_TRY
{
/* Check if caller wanted return length */
- if (ReturnLength) *ReturnLength = Length;
+ if ((ReturnLength) && (Length)) *ReturnLength = Length;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
PVOID ExceptionPort;
ULONG Break;
KAFFINITY ValidAffinity, Affinity = 0;
- ULONG DefaultHardErrorMode = 0, BasePriority = 0, MemoryPriority = 0;
- ULONG DisableBoost = 0, DebugFlags = 0, EnableFixup = 0, Boost = 0;
+ KPRIORITY BasePriority = 0;
+ UCHAR MemoryPriority = 0;
+ BOOLEAN DisableBoost = 0;
+ ULONG DefaultHardErrorMode = 0;
+ ULONG DebugFlags = 0, EnableFixup = 0, Boost = 0;
+ ULONG NoExecute = 0, VdmPower = 0;
+ BOOLEAN HasPrivilege;
PLIST_ENTRY Next;
PETHREAD Thread;
PAGED_CODE();
/* Check what kind of information class this is */
switch (ProcessInformationClass)
{
+ case ProcessWx86Information:
+
+ /* Check buffer length */
+ if (ProcessInformationLength != sizeof(HANDLE))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* Use SEH for capture */
+ _SEH2_TRY
+ {
+ /* Capture the boolean */
+ VdmPower = *(PULONG)ProcessInformation;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
+ }
+ _SEH2_END;
+
+ /* Getting VDM powers requires the SeTcbPrivilege */
+ if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
+ {
+ /* We don't hold the privilege, bail out */
+ Status = STATUS_PRIVILEGE_NOT_HELD;
+ DPRINT1("Need TCB privilege\n");
+ break;
+ }
+
+ /* Set or clear the flag */
+ if (VdmPower)
+ {
+ PspSetProcessFlag(Process, PSF_VDM_ALLOWED_BIT);
+ }
+ else
+ {
+ PspClearProcessFlag(Process, PSF_VDM_ALLOWED_BIT);
+ }
+ break;
+
/* Error/Exception Port */
case ProcessExceptionPort:
/* 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;
/* Write the session ID in the EPROCESS */
- Process->Session = SessionInfo.SessionId;
+ Process->Session = UlongToPtr(SessionInfo.SessionId); // HACK!!!
/* Check if the process also has a PEB */
if (Process->Peb)
/* 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:
if ((PriorityClass.PriorityClass != Process->PriorityClass) &&
(PriorityClass.PriorityClass == PROCESS_PRIORITY_CLASS_REALTIME))
{
- /* TODO: Check privileges */
- DPRINT1("Should check privilege\n");
+ /* Check the privilege */
+ HasPrivilege = SeCheckPrivilegedObject(SeIncreaseBasePriorityPrivilege,
+ ProcessHandle,
+ PROCESS_SET_INFORMATION,
+ PreviousMode);
+ if (!HasPrivilege)
+ {
+ ObDereferenceObject(Process);
+ DPRINT1("Privilege to change priority to realtime lacking\n");
+ return STATUS_PRIVILEGE_NOT_HELD;
+ }
}
/* Check if we have a job */
/* Enter SEH for direct buffer read */
_SEH2_TRY
{
- BasePriority = *(PULONG)ProcessInformation;
+ BasePriority = *(KPRIORITY*)ProcessInformation;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Check if the new base is higher */
if (BasePriority > Process->Pcb.BasePriority)
{
- DPRINT1("Should check privilege\n");
+ HasPrivilege = SeCheckPrivilegedObject(SeIncreaseBasePriorityPrivilege,
+ ProcessHandle,
+ PROCESS_SET_INFORMATION,
+ PreviousMode);
+ if (!HasPrivilege)
+ {
+ ObDereferenceObject(Process);
+ DPRINT1("Privilege to change priority from %lx to %lx lacking\n", BasePriority, Process->Pcb.BasePriority);
+ return STATUS_PRIVILEGE_NOT_HELD;
+ }
}
/* Call Ke */
/* 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;
}
/* Enter SEH for direct buffer read */
_SEH2_TRY
{
- DisableBoost = *(PULONG)ProcessInformation;
+ DisableBoost = *(PBOOLEAN)ProcessInformation;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = STATUS_SUCCESS;
break;
+ case ProcessUserModeIOPL:
+
+ /* Only TCB can do this */
+ if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
+ {
+ /* We don't hold the privilege, bail out */
+ DPRINT1("Need TCB to set IOPL\n");
+ Status = STATUS_PRIVILEGE_NOT_HELD;
+ break;
+ }
+
+ /* Only supported on x86 */
+#if defined (_X86_)
+ Ke386SetIOPL();
+#else
+ Status = STATUS_NOT_IMPLEMENTED;
+#endif
+ /* Done */
+ break;
+
+ case ProcessExecuteFlags:
+
+ /* Check buffer length */
+ if (ProcessInformationLength != sizeof(ULONG))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ if (ProcessHandle != NtCurrentProcess())
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ /* Enter SEH for direct buffer read */
+ _SEH2_TRY
+ {
+ NoExecute = *(PULONG)ProcessInformation;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get exception code */
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
+ }
+ _SEH2_END;
+
+ /* Call Mm for the update */
+ Status = MmSetExecuteOptions(NoExecute);
+ break;
+
/* We currently don't implement any of these */
case ProcessLdtInformation:
case ProcessLdtSize:
case ProcessIoPortHandlers:
- case ProcessUserModeIOPL:
- case ProcessWx86Information:
DPRINT1("VDM/16-bit Request not implemented: %lx\n", ProcessInformationClass);
Status = STATUS_NOT_IMPLEMENTED;
break;
case ProcessQuotaLimits:
- DPRINT1("Quota Limits not implemented\n");
- Status = STATUS_NOT_IMPLEMENTED;
- break;
+
+ return PspSetQuotaLimits(ProcessHandle,
+ 1,
+ ProcessInformation,
+ ProcessInformationLength,
+ PreviousMode);
case ProcessWorkingSetWatch:
DPRINT1("WS watch not implemented\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
- case ProcessExecuteFlags:
- DPRINT1("No execute support not implemented\n");
- Status = STATUS_NOT_IMPLEMENTED;
- break;
-
/* Anything else is invalid */
default:
DPRINT1("Invalid Server 2003 Info Class: %lx\n", ProcessInformationClass);
PEPROCESS Process;
ULONG_PTR DisableBoost = 0;
ULONG_PTR IdealProcessor = 0;
+ ULONG_PTR Break = 0;
PTEB Teb;
ULONG_PTR TlsIndex = 0;
PVOID *ExpansionSlots;
/* All done */
break;
+ case ThreadBreakOnTermination:
+
+ /* Check buffer length */
+ if (ThreadInformationLength != sizeof(ULONG))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* Enter SEH for direct buffer read */
+ _SEH2_TRY
+ {
+ Break = *(PULONG)ThreadInformation;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get exception code */
+ Break = 0;
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
+ }
+ _SEH2_END;
+
+ /* 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;
+ }
+
+ /* Set or clear the flag */
+ if (Break)
+ {
+ PspSetCrossThreadFlag(Thread, CT_BREAK_ON_TERMINATION_BIT);
+ }
+ else
+ {
+ PspClearCrossThreadFlag(Thread, CT_BREAK_ON_TERMINATION_BIT);
+ }
+ break;
+
default:
/* We don't implement it yet */
- DPRINT1("Not implemented: %lx\n", ThreadInformationClass);
+ DPRINT1("Not implemented: %d\n", ThreadInformationClass);
Status = STATUS_NOT_IMPLEMENTED;
}
(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_TRY
{
/* Copy time information from ETHREAD/KTHREAD */
- ThreadTime->KernelTime.QuadPart = Thread->Tcb.KernelTime *
- 100000LL;
- ThreadTime->UserTime.QuadPart = Thread->Tcb.UserTime *
- 100000LL;
+ ThreadTime->KernelTime.QuadPart = Thread->Tcb.KernelTime * KeMaximumIncrement;
+ ThreadTime->UserTime.QuadPart = Thread->Tcb.UserTime * KeMaximumIncrement;
ThreadTime->CreateTime = Thread->CreateTime;
- ThreadTime->ExitTime = Thread->ExitTime;
+
+ /* Exit time is in a union and only valid on actual exit! */
+ if (KeReadStateThread(&Thread->Tcb))
+ {
+ ThreadTime->ExitTime = Thread->ExitTime;
+ }
+ else
+ {
+ ThreadTime->ExitTime.QuadPart = 0;
+ }
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
_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: