* PURPOSE: Process Manager: Thread/Process Query/Set Information
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* Thomas Weidenmueller (w3seek@reactos.org)
+ * Eric Kohl
*/
/* INCLUDES ******************************************************************/
#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"
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_TRY
{
+ /* FIXME: Call KeQueryValuesProcess */
IoCounters->ReadOperationCount = Process->ReadOperationCount.QuadPart;
IoCounters->ReadTransferCount = Process->ReadTransferCount.QuadPart;
IoCounters->WriteOperationCount = Process->WriteOperationCount.QuadPart;
_SEH2_TRY
{
/* Copy time information from EPROCESS/KPROCESS */
+ /* FIXME: Call KeQueryRuntimeProcess */
ProcessTime->CreateTime = Process->CreateTime;
ProcessTime->UserTime.QuadPart = Process->Pcb.UserTime *
- 100000LL;
+ KeMaximumIncrement;
ProcessTime->KernelTime.QuadPart = Process->Pcb.KernelTime *
- 100000LL;
+ KeMaximumIncrement;
ProcessTime->ExitTime = Process->ExitTime;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
ObDereferenceObject(Process);
break;
- /* LDT, WS and VDM Information: not implemented */
- case ProcessLdtInformation:
- case ProcessWorkingSetWatch:
- case ProcessWx86Information:
-
- /* Reference the process */
- Status = ObReferenceObjectByHandle(ProcessHandle,
- PROCESS_QUERY_INFORMATION,
- PsProcessType,
- PreviousMode,
- (PVOID*)&Process,
- NULL);
- if (!NT_SUCCESS(Status)) break;
-
- DPRINT1("Not implemented: %lx\n", ProcessInformationClass);
-
- /* Dereference the process */
- ObDereferenceObject(Process);
- Status = STATUS_NOT_IMPLEMENTED;
- break;
-
case ProcessHandleCount:
/* Set the return length*/
_SEH2_TRY
{
/* Write back the Session ID */
- SessionInfo->SessionId = Process->Session;
+ SessionInfo->SessionId = PtrToUlong(PsGetProcessSessionId(Process));
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
ObDereferenceObject(Process);
break;
- /* WOW64: Not implemented */
- case ProcessWow64Information:
-
- /* Set the 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;
-
- DPRINT1("Not implemented: ProcessWow64Information\n");
-
- /* Dereference the process */
- ObDereferenceObject(Process);
- Status = STATUS_NOT_IMPLEMENTED;
- break;
-
/* Virtual Memory Statistics */
case ProcessVmCounters:
- /* Set the return length */
- Length = sizeof(VM_COUNTERS);
-
- if (ProcessInformationLength != Length)
+ /* Validate the input length */
+ if ((ProcessInformationLength != sizeof(VM_COUNTERS)) &&
+ (ProcessInformationLength != sizeof(VM_COUNTERS_EX)))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
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];
+ 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)
{
/* Priority Boosting status */
case ProcessPriorityBoost:
- /* Set the return length*/
+ /* Set the return length */
Length = sizeof(ULONG);
if (ProcessInformationLength != Length)
/* DOS Device Map */
case ProcessDeviceMap:
- /* Set the return length*/
+ /* Set the return length */
Length = sizeof(PROCESS_DEVICEMAP_INFORMATION);
if (ProcessInformationLength != Length)
{
- Status = STATUS_INFO_LENGTH_MISMATCH;
+ if (ProcessInformationLength == sizeof(PROCESS_DEVICEMAP_INFORMATION_EX))
+ {
+ DPRINT1("PROCESS_DEVICEMAP_INFORMATION_EX not supported!\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ }
+ else
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ }
break;
}
}
/* Free the image path */
- ExFreePool(ImageName);
+ ExFreePoolWithTag(ImageName, TAG_SEPA);
+ }
+ /* Dereference the process */
+ ObDereferenceObject(Process);
+ break;
+
+ case ProcessDebugFlags:
+
+ /* 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;
+
+ /* Enter SEH for writing back data */
+ _SEH2_TRY
+ {
+ /* Return the debug flag state */
+ *(PULONG)ProcessInformation = Process->NoDebugInherit ? 0 : 1;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ /* Dereference the process */
+ ObDereferenceObject(Process);
+ break;
+
+ case ProcessBreakOnTermination:
+
+ /* 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;
+
+ /* Enter SEH for writing back data */
+ _SEH2_TRY
+ {
+ /* Return the BreakOnTermination state */
+ *(PULONG)ProcessInformation = Process->BreakOnTermination;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
}
+ _SEH2_END;
+
/* Dereference the process */
ObDereferenceObject(Process);
break;
_SEH2_END;
break;
- /* Not yet implemented, or unknown */
- case ProcessBasePriority:
- case ProcessRaisePriority:
- case ProcessExceptionPort:
- case ProcessAccessToken:
- case ProcessLdtSize:
- case ProcessIoPortHandlers:
- case ProcessUserModeIOPL:
- case ProcessEnableAlignmentFaultFixup:
- case ProcessAffinityMask:
- case ProcessForegroundInformation:
- default:
- DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass);
- Status = STATUS_INVALID_INFO_CLASS;
- }
+ case ProcessImageInformation:
+ DPRINT1("Image Information Query Not implemented: %lx\n", ProcessInformationClass);
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
- /* Protect write with SEH */
- _SEH2_TRY
- {
- /* Check if caller wanted return length */
- if (ReturnLength) *ReturnLength = Length;
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- /* Get exception code */
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END;
+ case ProcessDebugObjectHandle:
- return Status;
-}
+ /* Set the return length */
+ Length = sizeof(HANDLE);
+ if (ProcessInformationLength != Length)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
-/*
- * @implemented
- */
-NTSTATUS
-NTAPI
-NtSetInformationProcess(IN HANDLE ProcessHandle,
- IN PROCESSINFOCLASS ProcessInformationClass,
- IN PVOID ProcessInformation,
- IN ULONG ProcessInformationLength)
-{
- PEPROCESS Process;
- KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- ACCESS_MASK Access;
- NTSTATUS Status;
- HANDLE PortHandle = NULL;
- HANDLE TokenHandle = NULL;
- PROCESS_SESSION_INFORMATION SessionInfo = {0};
- PROCESS_PRIORITY_CLASS PriorityClass = {0};
- PVOID ExceptionPort;
- PAGED_CODE();
+ /* Reference the process */
+ Status = ObReferenceObjectByHandle(ProcessHandle,
+ PROCESS_QUERY_INFORMATION,
+ PsProcessType,
+ PreviousMode,
+ (PVOID*)&Process,
+ NULL);
+ if (!NT_SUCCESS(Status)) break;
- /* Verify Information Class validity */
-#if 0
- Status = DefaultSetInfoBufferCheck(ProcessInformationClass,
- PsProcessInfoClass,
- RTL_NUMBER_OF(PsProcessInfoClass),
- ProcessInformation,
- ProcessInformationLength,
- PreviousMode);
- if (!NT_SUCCESS(Status)) return Status;
-#endif
+ /* Get the debug port */
+ Status = DbgkOpenProcessDebugPort(Process, PreviousMode, &DebugPort);
- /* Check what class this is */
- Access = PROCESS_SET_INFORMATION;
- if (ProcessInformationClass == ProcessSessionInformation)
- {
- /* Setting the Session ID needs a special mask */
- Access |= PROCESS_SET_SESSIONID;
- }
- else if (ProcessInformationClass == ProcessExceptionPort)
- {
- /* Setting the exception port needs a special mask */
- Access |= PROCESS_SUSPEND_RESUME;
- }
+ /* Let go of the process */
+ ObDereferenceObject(Process);
- /* Reference the process */
- Status = ObReferenceObjectByHandle(ProcessHandle,
- Access,
- PsProcessType,
- PreviousMode,
- (PVOID*)&Process,
- NULL);
- if (!NT_SUCCESS(Status)) return Status;
+ /* 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;
- /* Check what kind of information class this is */
- switch (ProcessInformationClass)
- {
- /* Error/Exception Port */
- case ProcessExceptionPort:
+ case ProcessHandleTracing:
+ DPRINT1("Handle tracing Not implemented: %lx\n", ProcessInformationClass);
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
- /* Check buffer length */
- if (ProcessInformationLength != sizeof(HANDLE))
+ case ProcessLUIDDeviceMapsEnabled:
+
+ /* Set the return length */
+ Length = sizeof(ULONG);
+ if (ProcessInformationLength != Length)
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
- /* Use SEH for capture */
+ /* Indicate success */
+ Status = STATUS_SUCCESS;
+
+ /* Protect write in SEH */
_SEH2_TRY
{
- /* Capture the handle */
- PortHandle = *(PHANDLE)ProcessInformation;
+ /* Return FALSE -- we don't support this */
+ *(PULONG)ProcessInformation = FALSE;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- /* Return the exception code */
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
+ break;
+
+ 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:
+ DPRINT1("VDM/16-bit not implemented: %lx\n", ProcessInformationClass);
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ case ProcessWorkingSetWatch:
+ DPRINT1("WS Watch Not implemented: %lx\n", ProcessInformationClass);
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ case ProcessPooledUsageAndLimits:
+ DPRINT1("Pool limits Not implemented: %lx\n", ProcessInformationClass);
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ /* Not supported by Server 2003 */
+ default:
+ DPRINT1("Unsupported info class: %lx\n", ProcessInformationClass);
+ Status = STATUS_INVALID_INFO_CLASS;
+ }
+
+ /* Protect write with SEH */
+ _SEH2_TRY
+ {
+ /* Check if caller wanted return length */
+ if ((ReturnLength) && (Length)) *ReturnLength = Length;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ return Status;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+NtSetInformationProcess(IN HANDLE ProcessHandle,
+ IN PROCESSINFOCLASS ProcessInformationClass,
+ IN PVOID ProcessInformation,
+ IN ULONG ProcessInformationLength)
+{
+ PEPROCESS Process;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ ACCESS_MASK Access;
+ NTSTATUS Status;
+ HANDLE PortHandle = NULL;
+ HANDLE TokenHandle = NULL;
+ PROCESS_SESSION_INFORMATION SessionInfo = {0};
+ PROCESS_PRIORITY_CLASS PriorityClass = {0};
+ PROCESS_FOREGROUND_BACKGROUND Foreground = {0};
+ PVOID ExceptionPort;
+ ULONG Break;
+ KAFFINITY ValidAffinity, Affinity = 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();
+
+ /* Verify Information Class validity */
+#if 0
+ Status = DefaultSetInfoBufferCheck(ProcessInformationClass,
+ PsProcessInfoClass,
+ RTL_NUMBER_OF(PsProcessInfoClass),
+ ProcessInformation,
+ ProcessInformationLength,
+ PreviousMode);
+ if (!NT_SUCCESS(Status)) return Status;
+#endif
+
+ /* Check what class this is */
+ Access = PROCESS_SET_INFORMATION;
+ if (ProcessInformationClass == ProcessSessionInformation)
+ {
+ /* Setting the Session ID needs a special mask */
+ Access |= PROCESS_SET_SESSIONID;
+ }
+ else if (ProcessInformationClass == ProcessExceptionPort)
+ {
+ /* Setting the exception port needs a special mask */
+ Access |= PROCESS_SUSPEND_RESUME;
+ }
+
+ /* Reference the process */
+ Status = ObReferenceObjectByHandle(ProcessHandle,
+ Access,
+ PsProcessType,
+ PreviousMode,
+ (PVOID*)&Process,
+ NULL);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* 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))
+ {
+ /* 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:
+
+ /* Check buffer length */
+ if (ProcessInformationLength != sizeof(HANDLE))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* Use SEH for capture */
+ _SEH2_TRY
+ {
+ /* Capture the handle */
+ PortHandle = *(PHANDLE)ProcessInformation;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
+ }
+ _SEH2_END;
+
+ /* Setting the error port requires the SeTcbPrivilege */
+ if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
+ {
+ /* Can't set the session ID, bail out. */
+ Status = STATUS_PRIVILEGE_NOT_HELD;
+ break;
+ }
/* Get the LPC Port */
Status = ObReferenceObjectByHandle(PortHandle,
/* Check buffer length */
if (ProcessInformationLength != sizeof(PROCESS_ACCESS_TOKEN))
{
- Status = STATUS_INFO_LENGTH_MISMATCH;
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* Use SEH for capture */
+ _SEH2_TRY
+ {
+ /* Save the token handle */
+ TokenHandle = ((PPROCESS_ACCESS_TOKEN)ProcessInformation)->
+ Token;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
+ }
+ _SEH2_END;
+
+ /* Assign the actual token */
+ Status = PspSetPrimaryToken(Process, TokenHandle, NULL);
+ break;
+
+ /* Hard error processing */
+ case ProcessDefaultHardErrorMode:
+
+ /* Check buffer length */
+ if (ProcessInformationLength != sizeof(ULONG))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* Enter SEH for direct buffer read */
+ _SEH2_TRY
+ {
+ DefaultHardErrorMode = *(PULONG)ProcessInformation;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get exception code */
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
+ }
+ _SEH2_END;
+
+ /* Set the mode */
+ Process->DefaultHardErrorProcessing = DefaultHardErrorMode;
+
+ /* Call Ke for the update */
+ if (DefaultHardErrorMode & SEM_NOALIGNMENTFAULTEXCEPT)
+ {
+ KeSetAutoAlignmentProcess(&Process->Pcb, TRUE);
+ }
+ else
+ {
+ KeSetAutoAlignmentProcess(&Process->Pcb, FALSE);
+ }
+ Status = STATUS_SUCCESS;
+ break;
+
+ /* Session ID */
+ case ProcessSessionInformation:
+
+ /* Check buffer length */
+ if (ProcessInformationLength != sizeof(PROCESS_SESSION_INFORMATION))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* Enter SEH for capture */
+ _SEH2_TRY
+ {
+ /* Capture the caller's buffer */
+ SessionInfo = *(PPROCESS_SESSION_INFORMATION)ProcessInformation;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
+ }
+ _SEH2_END;
+
+ /* Setting the session id requires the SeTcbPrivilege */
+ if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
+ {
+ /* Can't set the session ID, bail out. */
+ Status = STATUS_PRIVILEGE_NOT_HELD;
+ break;
+ }
+
+ /* 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 = UlongToPtr(SessionInfo.SessionId); // HACK!!!
+
+ /* Check if the process also has a PEB */
+ if (Process->Peb)
+ {
+ /*
+ * Attach to the process to make sure we're in the right
+ * context to access the PEB structure
+ */
+ KeAttachProcess(&Process->Pcb);
+
+ /* Enter SEH for write to user-mode PEB */
+ _SEH2_TRY
+ {
+ /* Write the session ID */
+ Process->Peb->SessionId = SessionInfo.SessionId;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ /* Detach from the process */
+ KeDetachProcess();
+ }
+
+ /* Unlock the process */
+ //PsUnlockProcess(Process);
+ break;
+
+ case ProcessPriorityClass:
+
+ /* Check buffer length */
+ if (ProcessInformationLength != sizeof(PROCESS_PRIORITY_CLASS))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* Enter SEH for capture */
+ _SEH2_TRY
+ {
+ /* Capture the caller's buffer */
+ PriorityClass = *(PPROCESS_PRIORITY_CLASS)ProcessInformation;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Return the exception code */
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
+ }
+ _SEH2_END;
+
+ /* Check for invalid PriorityClass value */
+ if (PriorityClass.PriorityClass > PROCESS_PRIORITY_CLASS_ABOVE_NORMAL)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ if ((PriorityClass.PriorityClass != Process->PriorityClass) &&
+ (PriorityClass.PriorityClass == PROCESS_PRIORITY_CLASS_REALTIME))
+ {
+ /* 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 */
+ if (Process->Job)
+ {
+ DPRINT1("Jobs not yet supported\n");
+ }
+
+ /* Set process priority class */
+ Process->PriorityClass = PriorityClass.PriorityClass;
+
+ /* Set process priority mode (foreground or background) */
+ PsSetProcessPriorityByClass(Process,
+ PriorityClass.Foreground ?
+ PsProcessPriorityForeground :
+ PsProcessPriorityBackground);
+ Status = STATUS_SUCCESS;
+ break;
+
+ case ProcessForegroundInformation:
+
+ /* Check buffer length */
+ if (ProcessInformationLength != sizeof(PROCESS_FOREGROUND_BACKGROUND))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* Enter SEH for capture */
+ _SEH2_TRY
+ {
+ /* Capture the caller's buffer */
+ Foreground = *(PPROCESS_FOREGROUND_BACKGROUND)ProcessInformation;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Return the exception code */
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
+ }
+ _SEH2_END;
+
+ /* Set process priority mode (foreground or background) */
+ PsSetProcessPriorityByClass(Process,
+ Foreground.Foreground ?
+ PsProcessPriorityForeground :
+ PsProcessPriorityBackground);
+ Status = STATUS_SUCCESS;
+ break;
+
+ case ProcessBasePriority:
+
+ /* Validate input length */
+ if (ProcessInformationLength != sizeof(KPRIORITY))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* Enter SEH for direct buffer read */
+ _SEH2_TRY
+ {
+ BasePriority = *(KPRIORITY*)ProcessInformation;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get exception code */
+ Break = 0;
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
+ }
+ _SEH2_END;
+
+ /* Extract the memory priority out of there */
+ if (BasePriority & 0x80000000)
+ {
+ MemoryPriority = MEMORY_PRIORITY_FOREGROUND;
+ BasePriority &= ~0x80000000;
+ }
+ else
+ {
+ MemoryPriority = MEMORY_PRIORITY_BACKGROUND;
+ }
+
+ /* Validate the number */
+ if ((BasePriority > HIGH_PRIORITY) || (BasePriority <= LOW_PRIORITY))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Check if the new base is higher */
+ if (BasePriority > Process->Pcb.BasePriority)
+ {
+ 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 */
+ KeSetPriorityAndQuantumProcess(&Process->Pcb, BasePriority, 0);
+
+ /* Now set the memory priority */
+ MmSetMemoryPriorityProcess(Process, MemoryPriority);
+ Status = STATUS_SUCCESS;
+ break;
+
+ case ProcessRaisePriority:
+
+ /* Validate input length */
+ if (ProcessInformationLength != sizeof(ULONG))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* Enter SEH for direct buffer read */
+ _SEH2_TRY
+ {
+ Boost = *(PULONG)ProcessInformation;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get exception code */
+ Break = 0;
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
+ }
+ _SEH2_END;
+
+ /* Make sure the process isn't dying */
+ if (ExAcquireRundownProtection(&Process->RundownProtect))
+ {
+ /* Lock it */
+ KeEnterCriticalRegion();
+ ExAcquirePushLockShared(&Process->ProcessLock);
+
+ /* Loop the threads */
+ for (Next = Process->ThreadListHead.Flink;
+ Next != &Process->ThreadListHead;
+ Next = Next->Flink)
+ {
+ /* Call Ke for the thread */
+ Thread = CONTAINING_RECORD(Next, ETHREAD, ThreadListEntry);
+ KeBoostPriorityThread(&Thread->Tcb, Boost);
+ }
+
+ /* Release the lock and rundown */
+ ExReleasePushLockShared(&Process->ProcessLock);
+ KeLeaveCriticalRegion();
+ ExReleaseRundownProtection(&Process->RundownProtect);
+
+ /* Set success code */
+ Status = STATUS_SUCCESS;
+ }
+ else
+ {
+ /* Avoid race conditions */
+ Status = STATUS_PROCESS_IS_TERMINATING;
+ }
+ break;
+
+ case ProcessBreakOnTermination:
+
+ /* Check buffer length */
+ if (ProcessInformationLength != sizeof(ULONG))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* Enter SEH for direct buffer read */
+ _SEH2_TRY
+ {
+ Break = *(PULONG)ProcessInformation;
+ }
+ _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))
+ {
+ Status = STATUS_PRIVILEGE_NOT_HELD;
+ break;
+ }
+
+ /* Set or clear the flag */
+ if (Break)
+ {
+ PspSetProcessFlag(Process, PSF_BREAK_ON_TERMINATION_BIT);
+ }
+ else
+ {
+ PspClearProcessFlag(Process, PSF_BREAK_ON_TERMINATION_BIT);
+ }
+
+ break;
+
+ case ProcessAffinityMask:
+
+ /* Check buffer length */
+ if (ProcessInformationLength != sizeof(KAFFINITY))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* Enter SEH for direct buffer read */
+ _SEH2_TRY
+ {
+ Affinity = *(PKAFFINITY)ProcessInformation;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get exception code */
+ Break = 0;
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
+ }
+ _SEH2_END;
+
+ /* Make sure it's valid for the CPUs present */
+ ValidAffinity = Affinity & KeActiveProcessors;
+ if (!Affinity || (ValidAffinity != Affinity))
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ /* Check if it's within job affinity limits */
+ if (Process->Job)
+ {
+ /* Not yet implemented */
+ UNIMPLEMENTED;
+ Status = STATUS_NOT_IMPLEMENTED;
break;
}
- /* Use SEH for capture */
- _SEH2_TRY
+ /* Make sure the process isn't dying */
+ if (ExAcquireRundownProtection(&Process->RundownProtect))
{
- /* Save the token handle */
- TokenHandle = ((PPROCESS_ACCESS_TOKEN)ProcessInformation)->
- Token;
+ /* Lock it */
+ KeEnterCriticalRegion();
+ ExAcquirePushLockShared(&Process->ProcessLock);
+
+ /* Call Ke to do the work */
+ KeSetAffinityProcess(&Process->Pcb, ValidAffinity);
+
+ /* Release the lock and rundown */
+ ExReleasePushLockShared(&Process->ProcessLock);
+ KeLeaveCriticalRegion();
+ ExReleaseRundownProtection(&Process->RundownProtect);
+
+ /* Set success code */
+ Status = STATUS_SUCCESS;
}
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ else
{
- /* Return the exception code */
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ /* Avoid race conditions */
+ Status = STATUS_PROCESS_IS_TERMINATING;
}
- _SEH2_END;
-
- /* Assign the actual token */
- Status = PspSetPrimaryToken(Process, TokenHandle, NULL);
break;
- /* Hard error processing */
- case ProcessDefaultHardErrorMode:
+ /* Priority Boosting status */
+ case ProcessPriorityBoost:
- /* Check buffer length */
+ /* Validate input length */
if (ProcessInformationLength != sizeof(ULONG))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
/* Enter SEH for direct buffer read */
_SEH2_TRY
{
- /* Update the current mode abd return the previous one */
- InterlockedExchange((LONG*)&Process->DefaultHardErrorProcessing,
- *(PLONG)ProcessInformation);
+ DisableBoost = *(PBOOLEAN)ProcessInformation;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get exception code */
+ Break = 0;
Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
}
_SEH2_END;
+
+ /* Make sure the process isn't dying */
+ if (ExAcquireRundownProtection(&Process->RundownProtect))
+ {
+ /* Lock it */
+ KeEnterCriticalRegion();
+ ExAcquirePushLockShared(&Process->ProcessLock);
+
+ /* Call Ke to do the work */
+ KeSetDisableBoostProcess(&Process->Pcb, DisableBoost);
+
+ /* Loop the threads too */
+ for (Next = Process->ThreadListHead.Flink;
+ Next != &Process->ThreadListHead;
+ Next = Next->Flink)
+ {
+ /* Call Ke for the thread */
+ Thread = CONTAINING_RECORD(Next, ETHREAD, ThreadListEntry);
+ KeSetDisableBoostThread(&Thread->Tcb, DisableBoost);
+ }
+
+ /* Release the lock and rundown */
+ ExReleasePushLockShared(&Process->ProcessLock);
+ KeLeaveCriticalRegion();
+ ExReleaseRundownProtection(&Process->RundownProtect);
+
+ /* Set success code */
+ Status = STATUS_SUCCESS;
+ }
+ else
+ {
+ /* Avoid race conditions */
+ Status = STATUS_PROCESS_IS_TERMINATING;
+ }
break;
- /* Session ID */
- case ProcessSessionInformation:
+ case ProcessDebugFlags:
/* Check buffer length */
- if (ProcessInformationLength != sizeof(PROCESS_SESSION_INFORMATION))
+ if (ProcessInformationLength != sizeof(ULONG))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
- /* Enter SEH for capture */
+ /* Enter SEH for direct buffer read */
_SEH2_TRY
{
- /* Capture the caller's buffer */
- SessionInfo = *(PPROCESS_SESSION_INFORMATION)ProcessInformation;
+ DebugFlags = *(PULONG)ProcessInformation;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- /* Return the exception code */
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ /* Get exception code */
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
}
_SEH2_END;
- /* Setting the session id requires the SeTcbPrivilege */
- if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
+ /* Set the mode */
+ if (DebugFlags & ~1)
{
- /* Can't set the session ID, bail out. */
- Status = STATUS_PRIVILEGE_NOT_HELD;
- break;
+ Status = STATUS_INVALID_PARAMETER;
}
-
- /* 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;
-
- /* Check if the process also has a PEB */
- if (Process->Peb)
+ else
{
- /*
- * Attach to the process to make sure we're in the right
- * context to access the PEB structure
- */
- KeAttachProcess(&Process->Pcb);
-
- /* Enter SEH for write to user-mode PEB */
- _SEH2_TRY
+ if (DebugFlags & 1)
{
- /* Write the session ID */
- Process->Peb->SessionId = SessionInfo.SessionId;
+ PspClearProcessFlag(Process, PSF_NO_DEBUG_INHERIT_BIT);
}
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ else
{
- /* Get exception code */
- Status = _SEH2_GetExceptionCode();
+ PspSetProcessFlag(Process, PSF_NO_DEBUG_INHERIT_BIT);
}
- _SEH2_END;
-
- /* Detach from the process */
- KeDetachProcess();
}
- /* Unlock the process */
- //PsUnlockProcess(Process);
+ /* Done */
+ Status = STATUS_SUCCESS;
break;
- case ProcessPriorityClass:
+ case ProcessEnableAlignmentFaultFixup:
/* Check buffer length */
- if (ProcessInformationLength != sizeof(PROCESS_PRIORITY_CLASS))
+ if (ProcessInformationLength != sizeof(ULONG))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
- /* Enter SEH for capture */
+ /* Enter SEH for direct buffer read */
_SEH2_TRY
{
- /* Capture the caller's buffer */
- PriorityClass = *(PPROCESS_PRIORITY_CLASS)ProcessInformation;
+ EnableFixup = *(PULONG)ProcessInformation;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- /* Return the exception code */
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ /* Get exception code */
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
}
_SEH2_END;
- /* Check for invalid PriorityClass value */
- if (PriorityClass.PriorityClass > PROCESS_PRIORITY_CLASS_ABOVE_NORMAL)
+ /* Set the mode */
+ if (EnableFixup)
{
- Status = STATUS_INVALID_PARAMETER;
- break;
+ Process->DefaultHardErrorProcessing |= SEM_NOALIGNMENTFAULTEXCEPT;
}
-
- /* TODO: Check privileges */
-
- /* Check if we have a job */
- if (Process->Job)
+ else
{
- DPRINT1("Jobs not yet supported\n");
+ Process->DefaultHardErrorProcessing &= ~SEM_NOALIGNMENTFAULTEXCEPT;
}
- /* Set process priority class */
- Process->PriorityClass = PriorityClass.PriorityClass;
-
- /* Set process priority mode (foreground or background) */
- PsSetProcessPriorityByClass(Process,
- !PriorityClass.Foreground ? PsProcessPriorityBackground :
- PsProcessPriorityForeground);
-
+ /* Call Ke for the update */
+ KeSetAutoAlignmentProcess(&Process->Pcb, FALSE);
Status = STATUS_SUCCESS;
break;
- case ProcessQuotaLimits:
+ case ProcessUserModeIOPL:
- /* Check buffer length */
- if (ProcessInformationLength != sizeof(QUOTA_LIMITS))
+ /* Only TCB can do this */
+ if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
{
- Status = STATUS_INFO_LENGTH_MISMATCH;
+ /* Fail */
+ DPRINT1("Need TCB to set IOPL\n");
+ Status = STATUS_PRIVILEGE_NOT_HELD;
break;
}
- DPRINT1("Not implemented: ProcessQuotaLimits\n");
+ /* Only supported on x86 */
+#if defined (_X86_)
+ Ke386SetIOPL();
+#else
Status = STATUS_NOT_IMPLEMENTED;
+#endif
+ /* Done */
break;
- case ProcessBasePriority:
+ case ProcessExecuteFlags:
/* Check buffer length */
- if (ProcessInformationLength != sizeof(KPRIORITY))
+ if (ProcessInformationLength != sizeof(ULONG))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
- DPRINT1("Not implemented: ProcessBasePriority\n");
- Status = STATUS_NOT_IMPLEMENTED;
- break;
-
- case ProcessRaisePriority:
-
- /* Check buffer length */
- if (ProcessInformationLength != sizeof(ULONG))
+ if (ProcessHandle != NtCurrentProcess())
{
- Status = STATUS_INFO_LENGTH_MISMATCH;
+ Status = STATUS_INVALID_PARAMETER;
break;
}
- DPRINT1("Not implemented: ProcessRaisePriority\n");
- Status = STATUS_NOT_IMPLEMENTED;
- break;
-
- case ProcessWx86Information:
-
- /* Check buffer length */
- if (ProcessInformationLength != sizeof(HANDLE))
+ /* Enter SEH for direct buffer read */
+ _SEH2_TRY
{
- Status = STATUS_INFO_LENGTH_MISMATCH;
- break;
+ NoExecute = *(PULONG)ProcessInformation;
}
-
- DPRINT1("Not implemented: ProcessWx86Information\n");
- Status = STATUS_NOT_IMPLEMENTED;
- break;
-
- case ProcessDebugPort:
-
- /* Check buffer length */
- if (ProcessInformationLength != sizeof(HANDLE))
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- Status = STATUS_INFO_LENGTH_MISMATCH;
- break;
+ /* Get exception code */
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
}
+ _SEH2_END;
- DPRINT1("Not implemented: ProcessDebugPort\n");
- Status = STATUS_NOT_IMPLEMENTED;
+ /* Call Mm for the update */
+ Status = MmSetExecuteOptions(NoExecute);
break;
/* We currently don't implement any of these */
case ProcessLdtInformation:
case ProcessLdtSize:
case ProcessIoPortHandlers:
+ 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;
+
case ProcessWorkingSetWatch:
- case ProcessUserModeIOPL:
- case ProcessEnableAlignmentFaultFixup:
- case ProcessAffinityMask:
- DPRINT1("Not implemented: %lx\n", ProcessInformationClass);
+ DPRINT1("WS watch not implemented\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
- /* Supposedly these are invalid...!? verify! */
- case ProcessBasicInformation:
- case ProcessIoCounters:
- case ProcessTimes:
- case ProcessPooledUsageAndLimits:
- case ProcessHandleCount:
- case ProcessWow64Information:
+ case ProcessDeviceMap:
+ DPRINT1("Device map not implemented\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ case ProcessHandleTracing:
+ DPRINT1("Handle tracing not implemented\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ /* Anything else is invalid */
default:
- DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass);
+ DPRINT1("Invalid Server 2003 Info Class: %lx\n", ProcessInformationClass);
Status = STATUS_INVALID_INFO_CLASS;
}
KAFFINITY Affinity = 0, CombinedAffinity;
PVOID Address = NULL;
PEPROCESS Process;
- ULONG DisableBoost = 0;
- ULONG IdealProcessor = 0;
+ ULONG_PTR DisableBoost = 0;
+ ULONG_PTR IdealProcessor = 0;
+ ULONG_PTR Break = 0;
PTEB Teb;
- ULONG TlsIndex = 0;
+ ULONG_PTR TlsIndex = 0;
PVOID *ExpansionSlots;
PETHREAD ProcThread;
PAGED_CODE();
Access = THREAD_SET_THREAD_TOKEN;
}
- /* Reference the process */
+ /* Reference the thread */
Status = ObReferenceObjectByHandle(ThreadHandle,
Access,
PsThreadType,
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- /* Return the exception code */
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
}
_SEH2_END;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- /* Return the exception code */
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
}
_SEH2_END;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- /* Return the exception code */
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
}
_SEH2_END;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- /* Return the exception code */
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
}
_SEH2_END;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- /* Return the exception code */
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
}
_SEH2_END;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- /* Return the exception code */
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
}
_SEH2_END;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- /* Return the exception code */
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
}
_SEH2_END;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- /* Return the exception code */
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
}
_SEH2_END;
/* 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))
+ {
+ 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;
}
_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)
{