* PURPOSE: Process Manager: Thread/Process Query/Set Information
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* Thomas Weidenmueller (w3seek@reactos.org)
+ * Eric Kohl
*/
/* INCLUDES ******************************************************************/
{
PEPROCESS Process;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- NTSTATUS Status = STATUS_SUCCESS;
+ NTSTATUS Status;
ULONG Length = 0;
PPROCESS_BASIC_INFORMATION ProcessBasicInfo =
(PPROCESS_BASIC_INFORMATION)ProcessInformation;
PKERNEL_USER_TIMES ProcessTime = (PKERNEL_USER_TIMES)ProcessInformation;
+ PPROCESS_PRIORITY_CLASS PsPriorityClass = (PPROCESS_PRIORITY_CLASS)ProcessInformation;
ULONG HandleCount;
PPROCESS_SESSION_INFORMATION SessionInfo =
(PPROCESS_SESSION_INFORMATION)ProcessInformation;
PVM_COUNTERS VmCounters = (PVM_COUNTERS)ProcessInformation;
+ PIO_COUNTERS IoCounters = (PIO_COUNTERS)ProcessInformation;
+ PQUOTA_LIMITS QuotaLimits = (PQUOTA_LIMITS)ProcessInformation;
PROCESS_DEVICEMAP_INFORMATION DeviceMap;
PUNICODE_STRING ImageName;
ULONG Cookie;
PAGED_CODE();
- /* Check validity of Information Class */
-#if 0
- Status = DefaultQueryInfoBufferCheck(ProcessInformationClass,
- PsProcessInfoClass,
- RTL_NUMBER_OF(PsProcessInfoClass),
- ProcessInformation,
- ProcessInformationLength,
- ReturnLength,
- PreviousMode);
- if (!NT_SUCCESS(Status)) return Status;
-#endif
-
- /* Check if this isn't the cookie class */
- if(ProcessInformationClass != ProcessCookie)
+ /* Check for user-mode caller */
+ if (PreviousMode != KernelMode)
{
- /* Reference the process */
- Status = ObReferenceObjectByHandle(ProcessHandle,
- PROCESS_QUERY_INFORMATION,
- PsProcessType,
- PreviousMode,
- (PVOID*)&Process,
- NULL);
- if (!NT_SUCCESS(Status)) return Status;
+ /* Prepare to probe parameters */
+ _SEH2_TRY
+ {
+ /* Probe the buffer */
+ ProbeForWrite(ProcessInformation,
+ ProcessInformationLength,
+ sizeof(ULONG));
+
+ /* Probe the return length if required */
+ if (ReturnLength) ProbeForWriteUlong(ReturnLength);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Return the exception code */
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
}
- else if(ProcessHandle != NtCurrentProcess())
+
+ if((ProcessInformationClass == ProcessCookie) &&
+ (ProcessHandle != NtCurrentProcess()))
{
/*
* Retreiving the process cookie is only allowed for the calling process
/* Set return length */
Length = sizeof(PROCESS_BASIC_INFORMATION);
- if ( ProcessInformationLength != Length )
+ 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 writes with SEH */
_SEH2_TRY
{
ProcessBasicInfo->UniqueProcessId = (ULONG_PTR)Process->
UniqueProcessId;
ProcessBasicInfo->InheritedFromUniqueProcessId =
- (ULONG_PTR)Process->InheritedFromUniqueProcessId;
+ (ULONG)Process->InheritedFromUniqueProcessId;
ProcessBasicInfo->BasePriority = Process->Pcb.BasePriority;
}
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
+
+ /* Dereference the process */
+ ObDereferenceObject(Process);
break;
- /* Quote limits and I/O Counters: not implemented */
+ /* Process quota limits */
case ProcessQuotaLimits:
+
+ Length = sizeof(QUOTA_LIMITS);
+ 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;
+
+ /* Indicate success */
+ Status = STATUS_SUCCESS;
+
+ _SEH2_TRY
+ {
+ /* Set max/min working set sizes */
+ QuotaLimits->MaximumWorkingSetSize =
+ Process->Vm.MaximumWorkingSetSize << PAGE_SHIFT;
+ QuotaLimits->MinimumWorkingSetSize =
+ Process->Vm.MinimumWorkingSetSize << PAGE_SHIFT;
+
+ /* Set default time limits */
+ QuotaLimits->TimeLimit.LowPart = MAXULONG;
+ QuotaLimits->TimeLimit.HighPart = MAXULONG;
+
+ /* Is quota block a default one? */
+ if (Process->QuotaBlock == &PspDefaultQuotaBlock)
+ {
+ /* Set default pools and pagefile limits */
+ QuotaLimits->PagedPoolLimit = (SIZE_T)-1;
+ QuotaLimits->NonPagedPoolLimit = (SIZE_T)-1;
+ QuotaLimits->PagefileLimit = (SIZE_T)-1;
+ }
+ else
+ {
+ /* Get limits from non-default quota block */
+ QuotaLimits->PagedPoolLimit =
+ Process->QuotaBlock->QuotaEntry[PagedPool].Limit;
+ QuotaLimits->NonPagedPoolLimit =
+ Process->QuotaBlock->QuotaEntry[NonPagedPool].Limit;
+ QuotaLimits->PagefileLimit =
+ Process->QuotaBlock->QuotaEntry[2].Limit;
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ /* Dereference the process */
+ ObDereferenceObject(Process);
+ break;
+
case ProcessIoCounters:
Length = sizeof(IO_COUNTERS);
- if ( ProcessInformationLength != Length )
+ if (ProcessInformationLength != Length)
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
- Status = STATUS_NOT_IMPLEMENTED;
+ /* Reference the process */
+ Status = ObReferenceObjectByHandle(ProcessHandle,
+ PROCESS_QUERY_INFORMATION,
+ PsProcessType,
+ PreviousMode,
+ (PVOID*)&Process,
+ NULL);
+ if (!NT_SUCCESS(Status)) break;
+
+ _SEH2_TRY
+ {
+ 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;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Ignore exception */
+ }
+ _SEH2_END;
+
+ /* Set status to success in any case */
+ Status = STATUS_SUCCESS;
+
+ /* Dereference the process */
+ ObDereferenceObject(Process);
break;
/* Timing */
/* Set the return length */
Length = sizeof(KERNEL_USER_TIMES);
- if ( ProcessInformationLength != Length )
+ 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 writes with SEH */
_SEH2_TRY
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
+
+ /* Dereference the process */
+ ObDereferenceObject(Process);
break;
/* Process Debug Port */
case ProcessDebugPort:
+ /* Set 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;
+
/* Protect write with SEH */
_SEH2_TRY
{
/* Return whether or not we have a debug port */
*(PHANDLE)ProcessInformation = (Process->DebugPort ?
(HANDLE)-1 : NULL);
-
- /* Set the return length*/
- Length = sizeof(HANDLE);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
+
+ /* Dereference the process */
+ 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;
/* Set the return length*/
Length = sizeof(ULONG);
- if ( ProcessInformationLength != Length )
+ 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;
+
/* Count the number of handles this process has */
- HandleCount = ObpGetHandleCountByHandleTable(Process->ObjectTable);
+ HandleCount = ObGetProcessHandleCount(Process);
/* Protect write in SEH */
_SEH2_TRY
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
+
+ /* Dereference the process */
+ ObDereferenceObject(Process);
break;
/* Session ID for the process */
case ProcessSessionInformation:
+ /* Set the return length*/
+ Length = sizeof(PROCESS_SESSION_INFORMATION);
+
+ 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 write safety */
_SEH2_TRY
{
/* Write back the Session ID */
- SessionInfo->SessionId = PtrToUlong(Process->Session);
-
- /* Set the return length */
- Length = sizeof(PROCESS_SESSION_INFORMATION);
+ SessionInfo->SessionId = Process->Session;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
+
+ /* Dereference the process */
+ 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;
/* Set the return length */
Length = sizeof(VM_COUNTERS);
- if ( ProcessInformationLength != Length )
+ 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 write safety */
_SEH2_TRY
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
+
+ /* Dereference the process */
+ ObDereferenceObject(Process);
break;
/* Hard Error Processing Mode */
case ProcessDefaultHardErrorMode:
+ /* 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
{
/* Write the current processing mode */
*(PULONG)ProcessInformation = Process->
DefaultHardErrorProcessing;
-
- /* Set the return length */
- Length = sizeof(ULONG);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
+
+ /* Dereference the process */
+ ObDereferenceObject(Process);
break;
/* Priority Boosting status */
case ProcessPriorityBoost:
+ /* 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 boost status */
*(PULONG)ProcessInformation = Process->Pcb.DisableBoost ?
- FALSE : TRUE;
-
- /* Set the return length */
- Length = sizeof(ULONG);
+ TRUE : FALSE;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
+
+ /* Dereference the process */
+ ObDereferenceObject(Process);
break;
/* DOS Device Map */
case ProcessDeviceMap:
+ /* Set the return length*/
+ Length = sizeof(PROCESS_DEVICEMAP_INFORMATION);
+
+ 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;
+
/* Query the device map information */
ObQueryDeviceMapInformation(Process, &DeviceMap);
_SEH2_TRY
{
*(PPROCESS_DEVICEMAP_INFORMATION)ProcessInformation = DeviceMap;
-
- /* Set the return length */
- Length = sizeof(PROCESS_DEVICEMAP_INFORMATION);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
+
+ /* Dereference the process */
+ ObDereferenceObject(Process);
break;
/* Priority class */
case ProcessPriorityClass:
+ /* Set the return length*/
+ Length = sizeof(PROCESS_PRIORITY_CLASS);
+
+ 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 current priority class */
- *(PUSHORT)ProcessInformation = Process->PriorityClass;
-
- /* Set the return length */
- Length = sizeof(USHORT);
+ PsPriorityClass->PriorityClass = Process->PriorityClass;
+ PsPriorityClass->Foreground = FALSE;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
+
+ /* Dereference the process */
+ ObDereferenceObject(Process);
break;
case ProcessImageFileName:
+ /* Reference the process */
+ Status = ObReferenceObjectByHandle(ProcessHandle,
+ PROCESS_QUERY_INFORMATION,
+ PsProcessType,
+ PreviousMode,
+ (PVOID*)&Process,
+ NULL);
+ if (!NT_SUCCESS(Status)) break;
+
/* Get the image path */
Status = SeLocateProcessImageName(Process, &ImageName);
if (NT_SUCCESS(Status))
/* Free the image path */
ExFreePool(ImageName);
}
+ /* 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;
/* Per-process security cookie */
Length = sizeof(ULONG);
}
+ /* Indicate success */
+ Status = STATUS_SUCCESS;
+
/* Enter SEH to protect write */
_SEH2_TRY
{
case ProcessAffinityMask:
case ProcessForegroundInformation:
default:
+ DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass);
Status = STATUS_INVALID_INFO_CLASS;
}
}
_SEH2_END;
- /* If we referenced the process, dereference it */
- if(ProcessInformationClass != ProcessCookie) ObDereferenceObject(Process);
return Status;
}
HANDLE PortHandle = NULL;
HANDLE TokenHandle = NULL;
PROCESS_SESSION_INFORMATION SessionInfo = {0};
+ PROCESS_PRIORITY_CLASS PriorityClass = {0};
PVOID ExceptionPort;
+ ULONG Break;
PAGED_CODE();
/* Verify Information Class validity */
/* Check what kind of information class this is */
switch (ProcessInformationClass)
{
- /* Quotas and priorities: not implemented */
- case ProcessQuotaLimits:
- case ProcessBasePriority:
- case ProcessRaisePriority:
- Status = STATUS_NOT_IMPLEMENTED;
- 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
{
{
/* Get the exception code */
Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
}
_SEH2_END;
- if (!NT_SUCCESS(Status)) break;
/* Get the LPC Port */
Status = ObReferenceObjectByHandle(PortHandle,
/* Security Token */
case ProcessAccessToken:
+ /* Check buffer length */
+ if (ProcessInformationLength != sizeof(PROCESS_ACCESS_TOKEN))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
/* Use SEH for capture */
_SEH2_TRY
{
{
/* Get the exception code */
Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
}
_SEH2_END;
- if (!NT_SUCCESS(Status)) break;
/* Assign the actual token */
Status = PspSetPrimaryToken(Process, TokenHandle, NULL);
/* 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
{
/* 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
{
{
/* Get the exception code */
Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
}
_SEH2_END;
- if (!NT_SUCCESS(Status)) break;
/* Setting the session id requires the SeTcbPrivilege */
if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
//PsUnlockProcess(Process);
break;
- /* Priority class: HACK! */
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;
+ }
+
+ /* TODO: Check privileges */
+
+ /* 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 ? PsProcessPriorityBackground :
+ PsProcessPriorityForeground);
+
+ Status = STATUS_SUCCESS;
+ break;
+
+ case ProcessQuotaLimits:
+
+ /* Check buffer length */
+ if (ProcessInformationLength != sizeof(QUOTA_LIMITS))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ DPRINT1("Not implemented: ProcessQuotaLimits\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ case ProcessBasePriority:
+
+ /* Check buffer length */
+ if (ProcessInformationLength != sizeof(KPRIORITY))
+ {
+ 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))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ DPRINT1("Not implemented: ProcessRaisePriority\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ case ProcessWx86Information:
+
+ /* Check buffer length */
+ if (ProcessInformationLength != sizeof(HANDLE))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ DPRINT1("Not implemented: ProcessWx86Information\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ case ProcessDebugPort:
+
+ /* Check buffer length */
+ if (ProcessInformationLength != sizeof(HANDLE))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ DPRINT1("Not implemented: ProcessDebugPort\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ 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;
/* We currently don't implement any of these */
case ProcessUserModeIOPL:
case ProcessEnableAlignmentFaultFixup:
case ProcessAffinityMask:
+ DPRINT1("Not implemented: %lx\n", ProcessInformationClass);
Status = STATUS_NOT_IMPLEMENTED;
break;
case ProcessIoCounters:
case ProcessTimes:
case ProcessPooledUsageAndLimits:
- case ProcessWx86Information:
case ProcessHandleCount:
case ProcessWow64Information:
- case ProcessDebugPort:
default:
+ DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass);
Status = STATUS_INVALID_INFO_CLASS;
}
Access = THREAD_SET_THREAD_TOKEN;
}
- /* Reference the process */
+ /* Reference the thread */
Status = ObReferenceObjectByHandle(ThreadHandle,
Access,
PsThreadType,
/* Thread priority */
case ThreadPriority:
+ /* Check buffer length */
+ if (ThreadInformationLength != sizeof(KPRIORITY))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
/* Use SEH for capture */
_SEH2_TRY
{
{
/* Get the exception code */
Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
}
_SEH2_END;
- if (!NT_SUCCESS(Status)) break;
/* Validate it */
if ((Priority > HIGH_PRIORITY) ||
case ThreadBasePriority:
+ /* Check buffer length */
+ if (ThreadInformationLength != sizeof(LONG))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
/* Use SEH for capture */
_SEH2_TRY
{
{
/* Get the exception code */
Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
}
_SEH2_END;
- if (!NT_SUCCESS(Status)) break;
/* Validate it */
if ((Priority > THREAD_BASE_PRIORITY_MAX) ||
case ThreadAffinityMask:
+ /* Check buffer length */
+ if (ThreadInformationLength != sizeof(ULONG_PTR))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
/* Use SEH for capture */
_SEH2_TRY
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
- if (!NT_SUCCESS(Status)) break;
/* Validate it */
if (!Affinity)
case ThreadImpersonationToken:
+ /* Check buffer length */
+ if (ThreadInformationLength != sizeof(HANDLE))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
/* Use SEH for capture */
_SEH2_TRY
{
{
/* Get the exception code */
Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
}
_SEH2_END;
- if (!NT_SUCCESS(Status)) break;
/* Assign the actual token */
Status = PsAssignImpersonationToken(Thread, TokenHandle);
case ThreadQuerySetWin32StartAddress:
+ /* Check buffer length */
+ if (ThreadInformationLength != sizeof(ULONG_PTR))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
/* Use SEH for capture */
_SEH2_TRY
{
{
/* Get the exception code */
Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
}
_SEH2_END;
- if (!NT_SUCCESS(Status)) break;
/* Set the address */
Thread->Win32StartAddress = Address;
case ThreadIdealProcessor:
+ /* Check buffer length */
+ if (ThreadInformationLength != sizeof(ULONG_PTR))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
/* Use SEH for capture */
_SEH2_TRY
{
{
/* Get the exception code */
Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
}
_SEH2_END;
- if (!NT_SUCCESS(Status)) break;
/* Validate it */
if (IdealProcessor > MAXIMUM_PROCESSORS)
case ThreadPriorityBoost:
+ /* Check buffer length */
+ if (ThreadInformationLength != sizeof(ULONG_PTR))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
/* Use SEH for capture */
_SEH2_TRY
{
{
/* Get the exception code */
Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
}
_SEH2_END;
- if (!NT_SUCCESS(Status)) break;
/* Call the kernel */
KeSetDisableBoostThread(&Thread->Tcb, (BOOLEAN)DisableBoost);
case ThreadZeroTlsCell:
+ /* Check buffer length */
+ if (ThreadInformationLength != sizeof(ULONG_PTR))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
/* Use SEH for capture */
_SEH2_TRY
{
{
/* Get the exception code */
Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
}
_SEH2_END;
- if (!NT_SUCCESS(Status)) break;
/* This is only valid for the current thread */
if (Thread != PsGetCurrentThread())
{
PETHREAD Thread;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- NTSTATUS Status = STATUS_SUCCESS;
+ NTSTATUS Status;
ULONG Access;
ULONG Length = 0;
PTHREAD_BASIC_INFORMATION ThreadBasicInfo =
KIRQL OldIrql;
PAGED_CODE();
- /* Verify Information Class validity */
-#if 0
- Status = DefaultQueryInfoBufferCheck(ThreadInformationClass,
- PsThreadInfoClass,
- RTL_NUMBER_OF(PsThreadInfoClass),
- ThreadInformation,
- ThreadInformationLength,
- ReturnLength,
- PreviousMode);
- if (!NT_SUCCESS(Status)) return Status;
-#endif
+ /* Check if we were called from user mode */
+ if (PreviousMode != KernelMode)
+ {
+ /* Enter SEH */
+ _SEH2_TRY
+ {
+ /* Probe the buffer */
+ ProbeForWrite(ThreadInformation,
+ ThreadInformationLength,
+ sizeof(ULONG));
+
+ /* Probe the return length if required */
+ if (ReturnLength) ProbeForWriteUlong(ReturnLength);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Return the exception code */
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+ }
/* Check what class this is */
Access = THREAD_QUERY_INFORMATION;
/* Basic thread information */
case ThreadBasicInformation:
+ /* Set return length */
+ Length = sizeof(THREAD_BASIC_INFORMATION);
+
+ if (ThreadInformationLength != Length)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
/* Protect writes with SEH */
_SEH2_TRY
{
ThreadBasicInfo->AffinityMask = Thread->Tcb.Affinity;
ThreadBasicInfo->Priority = Thread->Tcb.Priority;
ThreadBasicInfo->BasePriority = KeQueryBasePriorityThread(&Thread->Tcb);
-
- /* Set return length */
- Length = sizeof(THREAD_BASIC_INFORMATION);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Thread time information */
case ThreadTimes:
+ /* Set the return length */
+ Length = sizeof(KERNEL_USER_TIMES);
+
+ if (ThreadInformationLength != Length)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
/* Protect writes with SEH */
_SEH2_TRY
{
100000LL;
ThreadTime->CreateTime = Thread->CreateTime;
ThreadTime->ExitTime = Thread->ExitTime;
-
- /* Set the return length */
- Length = sizeof(KERNEL_USER_TIMES);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
case ThreadQuerySetWin32StartAddress:
+ /* Set the return length*/
+ Length = sizeof(PVOID);
+
+ if (ThreadInformationLength != Length)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
/* Protect write with SEH */
_SEH2_TRY
{
/* Return the Win32 Start Address */
*(PVOID*)ThreadInformation = Thread->Win32StartAddress;
-
- /* Set the return length*/
- Length = sizeof(PVOID);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
case ThreadPerformanceCount:
+ /* Set the return length*/
+ Length = sizeof(LARGE_INTEGER);
+
+ if (ThreadInformationLength != Length)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
/* Protect write with SEH */
_SEH2_TRY
{
/* FIXME */
(*(PLARGE_INTEGER)ThreadInformation).QuadPart = 0;
-
- /* Set the return length*/
- Length = sizeof(LARGE_INTEGER);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
case ThreadAmILastThread:
+ /* Set the return length*/
+ Length = sizeof(ULONG);
+
+ if (ThreadInformationLength != Length)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
/* Protect write with SEH */
_SEH2_TRY
{
&Thread->ThreadsProcess->
ThreadListHead) ?
TRUE : FALSE);
-
- /* Set the return length*/
- Length = sizeof(ULONG);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
case ThreadIsIoPending:
+ /* Set the return length*/
+ Length = sizeof(ULONG);
+
+ if (ThreadInformationLength != Length)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
/* Raise the IRQL to protect the IRP list */
KeRaiseIrql(APC_LEVEL, &OldIrql);
{
/* Check if the IRP list is empty or not */
*(PULONG)ThreadInformation = !IsListEmpty(&Thread->IrpList);
-
- /* Set the return length*/
- Length = sizeof(ULONG);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
KeLowerIrql(OldIrql);
break;
+ /* LDT and GDT information */
+ case ThreadDescriptorTableEntry:
+
+#if defined(_X86_)
+ /* Call the worker routine */
+ Status = PspQueryDescriptorThread(Thread,
+ ThreadInformation,
+ ThreadInformationLength,
+ ReturnLength);
+#else
+ /* Only implemented on x86 */
+ Status = STATUS_NOT_IMPLEMENTED;
+#endif
+ break;
+
+ case ThreadPriorityBoost:
+
+ /* Set the return length*/
+ Length = sizeof(ULONG);
+
+ if (ThreadInformationLength != Length)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ _SEH2_TRY
+ {
+ *(PULONG)ThreadInformation = Thread->Tcb.DisableBoost ? 1 : 0;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+ break;
+
/* Anything else */
default: