[NTOSKRNL]: An old patch that implements most of the Query/Set classes for processes, and cleans up those that aren't yet implemented. Adds support for KeBoostPriorityThread, KeSetDisableBoostProcess, KeSetAutoAlignmentProcess, KeSetAffinityProcess and the scheduling impact of these APIs. Also fixes some bugs in existing classes.

svn path=/trunk/; revision=54681
This commit is contained in:
Alex Ionescu 2011-12-18 04:27:20 +00:00
parent 48b3130f83
commit 58e95a8607
5 changed files with 659 additions and 141 deletions

View file

@ -222,6 +222,12 @@ Author:
#define STA_ADDRESS_SPACE_OWNER_BIT 0x4 #define STA_ADDRESS_SPACE_OWNER_BIT 0x4
#define STA_OWNS_WORKING_SET_BITS 0x1F8 #define STA_OWNS_WORKING_SET_BITS 0x1F8
//
// Kernel Process flags (maybe in ketypes.h?)
//
#define KPSF_AUTO_ALIGNMENT_BIT 0
#define KPSF_DISABLE_BOOST_BIT 1
// //
// Process Flags // Process Flags
// //
@ -762,6 +768,11 @@ typedef struct _PROCESS_PRIORITY_CLASS
UCHAR PriorityClass; UCHAR PriorityClass;
} PROCESS_PRIORITY_CLASS, *PPROCESS_PRIORITY_CLASS; } PROCESS_PRIORITY_CLASS, *PPROCESS_PRIORITY_CLASS;
typedef struct _PROCESS_FOREGROUND_BACKGROUND
{
BOOLEAN Foreground;
} PROCESS_FOREGROUND_BACKGROUND, *PPROCESS_FOREGROUND_BACKGROUND;
// //
// Thread Information Structures for NtQueryProcessInformation // Thread Information Structures for NtQueryProcessInformation
// //

View file

@ -269,6 +269,34 @@ KeSetDisableBoostThread(
IN BOOLEAN Disable IN BOOLEAN Disable
); );
BOOLEAN
NTAPI
KeSetDisableBoostProcess(
IN PKPROCESS Process,
IN BOOLEAN Disable
);
BOOLEAN
NTAPI
KeSetAutoAlignmentProcess(
IN PKPROCESS Process,
IN BOOLEAN Enable
);
KAFFINITY
NTAPI
KeSetAffinityProcess(
IN PKPROCESS Process,
IN KAFFINITY Affinity
);
VOID
NTAPI
KeBoostPriorityThread(
IN PKTHREAD Thread,
IN KPRIORITY Increment
);
VOID VOID
NTAPI NTAPI
KeBalanceSetManager(IN PVOID Context); KeBalanceSetManager(IN PVOID Context);

View file

@ -260,6 +260,90 @@ KeSetQuantumProcess(IN PKPROCESS Process,
KiReleaseProcessLock(&ProcessLock); KiReleaseProcessLock(&ProcessLock);
} }
KAFFINITY
NTAPI
KeSetAffinityProcess(IN PKPROCESS Process,
IN KAFFINITY Affinity)
{
KLOCK_QUEUE_HANDLE ProcessLock;
PLIST_ENTRY NextEntry, ListHead;
KAFFINITY OldAffinity;
PKTHREAD Thread;
ASSERT_PROCESS(Process);
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
ASSERT((Affinity & KeActiveProcessors) != 0);
/* Lock the process */
KiAcquireProcessLock(Process, &ProcessLock);
/* Acquire the dispatcher lock */
KiAcquireDispatcherLockAtDpcLevel();
/* Capture old affinity and update it */
OldAffinity = Process->Affinity;
Process->Affinity = Affinity;
/* Loop all child threads */
ListHead = &Process->ThreadListHead;
NextEntry = ListHead->Flink;
while (ListHead != NextEntry)
{
/* Get the thread */
Thread = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry);
/* Set affinity on it */
KiSetAffinityThread(Thread, Affinity);
NextEntry = NextEntry->Flink;
}
/* Release Dispatcher Database */
KiReleaseDispatcherLockFromDpcLevel();
/* Release the process lock */
KiReleaseProcessLockFromDpcLevel(&ProcessLock);
KiExitDispatcher(ProcessLock.OldIrql);
/* Return previous affinity */
return OldAffinity;
}
BOOLEAN
NTAPI
KeSetAutoAlignmentProcess(IN PKPROCESS Process,
IN BOOLEAN Enable)
{
/* Set or reset the bit depending on what the enable flag says */
if (Enable)
{
return InterlockedBitTestAndSet(&Process->ProcessFlags,
KPSF_AUTO_ALIGNMENT_BIT);
}
else
{
return InterlockedBitTestAndReset(&Process->ProcessFlags,
KPSF_AUTO_ALIGNMENT_BIT);
}
}
BOOLEAN
NTAPI
KeSetDisableBoostProcess(IN PKPROCESS Process,
IN BOOLEAN Disable)
{
/* Set or reset the bit depending on what the disable flag says */
if (Disable)
{
return InterlockedBitTestAndSet(&Process->ProcessFlags,
KPSF_DISABLE_BOOST_BIT);
}
else
{
return InterlockedBitTestAndReset(&Process->ProcessFlags,
KPSF_DISABLE_BOOST_BIT);
}
}
KPRIORITY KPRIORITY
NTAPI NTAPI
KeSetPriorityAndQuantumProcess(IN PKPROCESS Process, KeSetPriorityAndQuantumProcess(IN PKPROCESS Process,

View file

@ -224,6 +224,53 @@ KeAlertThread(IN PKTHREAD Thread,
return PreviousState; return PreviousState;
} }
VOID
NTAPI
KeBoostPriorityThread(IN PKTHREAD Thread,
IN KPRIORITY Increment)
{
KIRQL OldIrql;
KPRIORITY Priority;
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
/* Lock the Dispatcher Database */
OldIrql = KiAcquireDispatcherLock();
/* Only threads in the dynamic range get boosts */
if (Thread->Priority < LOW_REALTIME_PRIORITY)
{
/* Lock the thread */
KiAcquireThreadLock(Thread);
/* Check again, and make sure there's not already a boost */
if ((Thread->Priority < LOW_REALTIME_PRIORITY) &&
!(Thread->PriorityDecrement))
{
/* Compute the new priority and see if it's higher */
Priority = Thread->BasePriority + Increment;
if (Priority > Thread->Priority)
{
if (Priority >= LOW_REALTIME_PRIORITY)
{
Priority = LOW_REALTIME_PRIORITY - 1;
}
/* Reset the quantum */
Thread->Quantum = Thread->QuantumReset;
/* Set the new Priority */
KiSetPriorityThread(Thread, Priority);
}
}
/* Release thread lock */
KiReleaseThreadLock(Thread);
}
/* Release the dispatcher lokc */
KiReleaseDispatcherLock(OldIrql);
}
ULONG ULONG
NTAPI NTAPI
KeForceResumeThread(IN PKTHREAD Thread) KeForceResumeThread(IN PKTHREAD Thread)

View file

@ -14,6 +14,9 @@
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
/* FIXME: From winbase.h... what to do? */
#define SEM_NOALIGNMENTFAULTEXCEPT 0x04
/* Include Information Class Tables */ /* Include Information Class Tables */
#include "internal/ps_i.h" #include "internal/ps_i.h"
@ -247,6 +250,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
_SEH2_TRY _SEH2_TRY
{ {
/* FIXME: Call KeQueryValuesProcess */
IoCounters->ReadOperationCount = Process->ReadOperationCount.QuadPart; IoCounters->ReadOperationCount = Process->ReadOperationCount.QuadPart;
IoCounters->ReadTransferCount = Process->ReadTransferCount.QuadPart; IoCounters->ReadTransferCount = Process->ReadTransferCount.QuadPart;
IoCounters->WriteOperationCount = Process->WriteOperationCount.QuadPart; IoCounters->WriteOperationCount = Process->WriteOperationCount.QuadPart;
@ -292,11 +296,12 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
_SEH2_TRY _SEH2_TRY
{ {
/* Copy time information from EPROCESS/KPROCESS */ /* Copy time information from EPROCESS/KPROCESS */
/* FIXME: Call KeQueryRuntimeProcess */
ProcessTime->CreateTime = Process->CreateTime; ProcessTime->CreateTime = Process->CreateTime;
ProcessTime->UserTime.QuadPart = Process->Pcb.UserTime * ProcessTime->UserTime.QuadPart = Process->Pcb.UserTime *
100000LL; KeMaximumIncrement;
ProcessTime->KernelTime.QuadPart = Process->Pcb.KernelTime * ProcessTime->KernelTime.QuadPart = Process->Pcb.KernelTime *
100000LL; KeMaximumIncrement;
ProcessTime->ExitTime = Process->ExitTime; ProcessTime->ExitTime = Process->ExitTime;
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
@ -349,27 +354,6 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
ObDereferenceObject(Process); ObDereferenceObject(Process);
break; 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: case ProcessHandleCount:
/* Set the return length*/ /* Set the return length*/
@ -435,50 +419,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
_SEH2_TRY _SEH2_TRY
{ {
/* Write back the Session ID */ /* Write back the Session ID */
SessionInfo->SessionId = Process->Session; SessionInfo->SessionId = Process->Session; //MmGetSessionId(Process);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get the exception code */
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;
/* Protect write in SEH */
_SEH2_TRY
{
#ifdef _WIN64
DPRINT1("Not implemented: ProcessWow64Information\n");
Status = STATUS_NOT_IMPLEMENTED;
#else
/* Wow64 not present */
*(PULONG_PTR)ProcessInformation = 0;
#endif
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{ {
@ -494,15 +435,17 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
/* Virtual Memory Statistics */ /* Virtual Memory Statistics */
case ProcessVmCounters: case ProcessVmCounters:
/* Set the return length */ /* Validate the input length */
Length = sizeof(VM_COUNTERS); if ((ProcessInformationLength != sizeof(VM_COUNTERS)) &&
(ProcessInformationLength != sizeof(VM_COUNTERS_EX)))
if (ProcessInformationLength != Length)
{ {
Status = STATUS_INFO_LENGTH_MISMATCH; Status = STATUS_INFO_LENGTH_MISMATCH;
break; break;
} }
/* Set the return length */
Length = ProcessInformationLength;
/* Reference the process */ /* Reference the process */
Status = ObReferenceObjectByHandle(ProcessHandle, Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_QUERY_INFORMATION, PROCESS_QUERY_INFORMATION,
@ -525,9 +468,9 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
VmCounters->QuotaPagedPoolUsage = Process->QuotaUsage[0]; VmCounters->QuotaPagedPoolUsage = Process->QuotaUsage[0];
VmCounters->QuotaPeakNonPagedPoolUsage = Process->QuotaPeak[1]; VmCounters->QuotaPeakNonPagedPoolUsage = Process->QuotaPeak[1];
VmCounters->QuotaNonPagedPoolUsage = Process->QuotaUsage[1]; VmCounters->QuotaNonPagedPoolUsage = Process->QuotaUsage[1];
VmCounters->PagefileUsage = Process->QuotaUsage[2]; VmCounters->PagefileUsage = Process->QuotaUsage[2] << PAGE_SHIFT;
VmCounters->PeakPagefileUsage = Process->QuotaPeak[2]; VmCounters->PeakPagefileUsage = Process->QuotaPeak[2] << PAGE_SHIFT;
//VmCounters->PrivateUsage = Process->CommitCharge << PAGE_SHIFT;
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{ {
@ -582,7 +525,7 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
/* Priority Boosting status */ /* Priority Boosting status */
case ProcessPriorityBoost: case ProcessPriorityBoost:
/* Set the return length*/ /* Set the return length */
Length = sizeof(ULONG); Length = sizeof(ULONG);
if (ProcessInformationLength != Length) if (ProcessInformationLength != Length)
@ -621,12 +564,20 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
/* DOS Device Map */ /* DOS Device Map */
case ProcessDeviceMap: case ProcessDeviceMap:
/* Set the return length*/ /* Set the return length */
Length = sizeof(PROCESS_DEVICEMAP_INFORMATION); Length = sizeof(PROCESS_DEVICEMAP_INFORMATION);
if (ProcessInformationLength != Length) 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; break;
} }
@ -751,6 +702,42 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
ObDereferenceObject(Process); ObDereferenceObject(Process);
break; 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: case ProcessBreakOnTermination:
/* Set the return length*/ /* Set the return length*/
@ -831,20 +818,52 @@ NtQueryInformationProcess(IN HANDLE ProcessHandle,
} }
_SEH2_END; _SEH2_END;
break; break;
case ProcessImageInformation:
DPRINT1("Image Information Query Not implemented: %lx\n", ProcessInformationClass);
Status = STATUS_NOT_IMPLEMENTED;
break;
case ProcessDebugObjectHandle:
DPRINT1("Debug Object Query Not implemented: %lx\n", ProcessInformationClass);
Status = STATUS_NOT_IMPLEMENTED;
break;
case ProcessHandleTracing:
DPRINT1("Handle tracing Not implemented: %lx\n", ProcessInformationClass);
Status = STATUS_NOT_IMPLEMENTED;
break;
case ProcessLUIDDeviceMapsEnabled:
DPRINT1("LUID Device Maps Not implemented: %lx\n", ProcessInformationClass);
Status = STATUS_NOT_IMPLEMENTED;
break;
case ProcessExecuteFlags:
DPRINT1("No execute Not implemented: %lx\n", ProcessInformationClass);
Status = STATUS_NOT_IMPLEMENTED;
break;
case ProcessWow64Information:
case ProcessLdtInformation:
case ProcessWx86Information:
DPRINT1("VDM/16-bit implemented: %lx\n", ProcessInformationClass);
Status = STATUS_NOT_IMPLEMENTED;
break;
/* Not yet implemented, or unknown */ case ProcessWorkingSetWatch:
case ProcessBasePriority: DPRINT1("WS Watch Not implemented: %lx\n", ProcessInformationClass);
case ProcessRaisePriority: Status = STATUS_NOT_IMPLEMENTED;
case ProcessExceptionPort: break;
case ProcessAccessToken:
case ProcessLdtSize: case ProcessPooledUsageAndLimits:
case ProcessIoPortHandlers: DPRINT1("Pool limits Not implemented: %lx\n", ProcessInformationClass);
case ProcessUserModeIOPL: Status = STATUS_NOT_IMPLEMENTED;
case ProcessEnableAlignmentFaultFixup: break;
case ProcessAffinityMask:
case ProcessForegroundInformation: /* Not supported by Server 2003 */
default: default:
DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass); DPRINT1("Unsupported info class: %lx\n", ProcessInformationClass);
Status = STATUS_INVALID_INFO_CLASS; Status = STATUS_INVALID_INFO_CLASS;
} }
@ -882,8 +901,14 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
HANDLE TokenHandle = NULL; HANDLE TokenHandle = NULL;
PROCESS_SESSION_INFORMATION SessionInfo = {0}; PROCESS_SESSION_INFORMATION SessionInfo = {0};
PROCESS_PRIORITY_CLASS PriorityClass = {0}; PROCESS_PRIORITY_CLASS PriorityClass = {0};
PROCESS_FOREGROUND_BACKGROUND Foreground = {0};
PVOID ExceptionPort; PVOID ExceptionPort;
ULONG Break; ULONG Break;
KAFFINITY ValidAffinity, Affinity = 0;
ULONG DefaultHardErrorMode = 0, BasePriority = 0, MemoryPriority = 0;
ULONG DisableBoost = 0, DebugFlags = 0, EnableFixup = 0, Boost = 0;
PLIST_ENTRY Next;
PETHREAD Thread;
PAGED_CODE(); PAGED_CODE();
/* Verify Information Class validity */ /* Verify Information Class validity */
@ -946,6 +971,14 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
} }
_SEH2_END; _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 */ /* Get the LPC Port */
Status = ObReferenceObjectByHandle(PortHandle, Status = ObReferenceObjectByHandle(PortHandle,
0, 0,
@ -1008,16 +1041,29 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
/* Enter SEH for direct buffer read */ /* Enter SEH for direct buffer read */
_SEH2_TRY _SEH2_TRY
{ {
/* Update the current mode abd return the previous one */ DefaultHardErrorMode = *(PULONG)ProcessInformation;
InterlockedExchange((LONG*)&Process->DefaultHardErrorProcessing,
*(PLONG)ProcessInformation);
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{ {
/* Get exception code */ /* Get exception code */
Status = _SEH2_GetExceptionCode(); Status = _SEH2_GetExceptionCode();
_SEH2_YIELD(break);
} }
_SEH2_END; _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; break;
/* Session ID */ /* Session ID */
@ -1119,7 +1165,12 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
break; break;
} }
/* TODO: Check privileges */ if ((PriorityClass.PriorityClass != Process->PriorityClass) &&
(PriorityClass.PriorityClass == PROCESS_PRIORITY_CLASS_REALTIME))
{
/* TODO: Check privileges */
DPRINT1("Should check privilege\n");
}
/* Check if we have a job */ /* Check if we have a job */
if (Process->Job) if (Process->Job)
@ -1132,75 +1183,150 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
/* Set process priority mode (foreground or background) */ /* Set process priority mode (foreground or background) */
PsSetProcessPriorityByClass(Process, PsSetProcessPriorityByClass(Process,
!PriorityClass.Foreground ? PsProcessPriorityBackground : PriorityClass.Foreground ?
PsProcessPriorityForeground); PsProcessPriorityForeground :
PsProcessPriorityBackground);
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
break; break;
case ProcessQuotaLimits: case ProcessForegroundInformation:
/* Check buffer length */ /* Check buffer length */
if (ProcessInformationLength != sizeof(QUOTA_LIMITS)) if (ProcessInformationLength != sizeof(PROCESS_FOREGROUND_BACKGROUND))
{ {
Status = STATUS_INFO_LENGTH_MISMATCH; Status = STATUS_INFO_LENGTH_MISMATCH;
break; break;
} }
DPRINT1("Not implemented: ProcessQuotaLimits\n"); /* Enter SEH for capture */
Status = STATUS_NOT_IMPLEMENTED; _SEH2_TRY
break; {
/* 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: case ProcessBasePriority:
/* Check buffer length */ /* Validate input length */
if (ProcessInformationLength != sizeof(KPRIORITY)) if (ProcessInformationLength != sizeof(KPRIORITY))
{ {
Status = STATUS_INFO_LENGTH_MISMATCH; Status = STATUS_INFO_LENGTH_MISMATCH;
break; break;
} }
DPRINT1("Not implemented: ProcessBasePriority\n"); /* Enter SEH for direct buffer read */
Status = STATUS_NOT_IMPLEMENTED; _SEH2_TRY
{
BasePriority = *(PULONG)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)
{
DPRINT1("Should check privilege\n");
}
/* Call Ke */
KeSetPriorityAndQuantumProcess(&Process->Pcb, BasePriority, 0);
/* Now set the memory priority */
MmSetMemoryPriorityProcess(Process, MemoryPriority);
Status = STATUS_SUCCESS;
break; break;
case ProcessRaisePriority: case ProcessRaisePriority:
/* Check buffer length */ /* Validate input length */
if (ProcessInformationLength != sizeof(ULONG)) if (ProcessInformationLength != sizeof(ULONG))
{ {
Status = STATUS_INFO_LENGTH_MISMATCH; Status = STATUS_INFO_LENGTH_MISMATCH;
break; break;
} }
DPRINT1("Not implemented: ProcessRaisePriority\n"); /* Enter SEH for direct buffer read */
Status = STATUS_NOT_IMPLEMENTED; _SEH2_TRY
break;
case ProcessWx86Information:
/* Check buffer length */
if (ProcessInformationLength != sizeof(HANDLE))
{ {
Status = STATUS_INFO_LENGTH_MISMATCH; Boost = *(PULONG)ProcessInformation;
break;
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
DPRINT1("Not implemented: ProcessWx86Information\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
case ProcessDebugPort:
/* Check buffer length */
if (ProcessInformationLength != sizeof(HANDLE))
{ {
Status = STATUS_INFO_LENGTH_MISMATCH; /* Get exception code */
break; Break = 0;
Status = _SEH2_GetExceptionCode();
_SEH2_YIELD(break);
} }
_SEH2_END;
DPRINT1("Not implemented: ProcessDebugPort\n"); /* Make sure the process isn't dying */
Status = STATUS_NOT_IMPLEMENTED; 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; break;
case ProcessBreakOnTermination: case ProcessBreakOnTermination:
@ -1244,28 +1370,249 @@ NtSetInformationProcess(IN HANDLE ProcessHandle,
} }
break; 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;
}
/* Make sure the process isn't dying */
if (ExAcquireRundownProtection(&Process->RundownProtect))
{
/* 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;
}
else
{
/* Avoid race conditions */
Status = STATUS_PROCESS_IS_TERMINATING;
}
break;
/* Priority Boosting status */
case ProcessPriorityBoost:
/* Validate input length */
if (ProcessInformationLength != sizeof(ULONG))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
/* Enter SEH for direct buffer read */
_SEH2_TRY
{
DisableBoost = *(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);
/* 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;
case ProcessDebugFlags:
/* Check buffer length */
if (ProcessInformationLength != sizeof(ULONG))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
/* Enter SEH for direct buffer read */
_SEH2_TRY
{
DebugFlags = *(PULONG)ProcessInformation;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get exception code */
Status = _SEH2_GetExceptionCode();
_SEH2_YIELD(break);
}
_SEH2_END;
/* Set the mode */
if (DebugFlags & ~1)
{
Status = STATUS_INVALID_PARAMETER;
}
else
{
if (DebugFlags & 1)
{
PspClearProcessFlag(Process, PSF_NO_DEBUG_INHERIT_BIT);
}
else
{
PspSetProcessFlag(Process, PSF_NO_DEBUG_INHERIT_BIT);
}
}
/* Done */
Status = STATUS_SUCCESS;
break;
case ProcessEnableAlignmentFaultFixup:
/* Check buffer length */
if (ProcessInformationLength != sizeof(ULONG))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
/* Enter SEH for direct buffer read */
_SEH2_TRY
{
EnableFixup = *(PULONG)ProcessInformation;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get exception code */
Status = _SEH2_GetExceptionCode();
_SEH2_YIELD(break);
}
_SEH2_END;
/* Set the mode */
if (EnableFixup)
{
Process->DefaultHardErrorProcessing |= SEM_NOALIGNMENTFAULTEXCEPT;
}
else
{
Process->DefaultHardErrorProcessing &= ~SEM_NOALIGNMENTFAULTEXCEPT;
}
/* Call Ke for the update */
KeSetAutoAlignmentProcess(&Process->Pcb, FALSE);
Status = STATUS_SUCCESS;
break;
/* We currently don't implement any of these */ /* We currently don't implement any of these */
case ProcessLdtInformation: case ProcessLdtInformation:
case ProcessLdtSize: case ProcessLdtSize:
case ProcessIoPortHandlers: case ProcessIoPortHandlers:
case ProcessWorkingSetWatch:
case ProcessUserModeIOPL: case ProcessUserModeIOPL:
case ProcessEnableAlignmentFaultFixup: case ProcessWx86Information:
case ProcessAffinityMask: DPRINT1("VDM/16-bit Request not implemented: %lx\n", ProcessInformationClass);
DPRINT1("Not implemented: %lx\n", ProcessInformationClass); Status = STATUS_NOT_IMPLEMENTED;
break;
case ProcessQuotaLimits:
DPRINT1("Quota Limits not implemented\n");
Status = STATUS_NOT_IMPLEMENTED; Status = STATUS_NOT_IMPLEMENTED;
break; break;
/* Supposedly these are invalid...!? verify! */ case ProcessWorkingSetWatch:
case ProcessBasicInformation: DPRINT1("WS watch not implemented\n");
case ProcessIoCounters: Status = STATUS_NOT_IMPLEMENTED;
case ProcessTimes: break;
case ProcessPooledUsageAndLimits:
case ProcessHandleCount: case ProcessDeviceMap:
case ProcessWow64Information: DPRINT1("Device map not implemented\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
case ProcessHandleTracing:
DPRINT1("Handle tracing 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: default:
DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass); DPRINT1("Invalid Server 2003 Info Class: %lx\n", ProcessInformationClass);
Status = STATUS_INVALID_INFO_CLASS; Status = STATUS_INVALID_INFO_CLASS;
} }
@ -1434,6 +1781,7 @@ NtSetInformationThread(IN HANDLE ThreadHandle,
{ {
/* Get the exception code */ /* Get the exception code */
Status = _SEH2_GetExceptionCode(); Status = _SEH2_GetExceptionCode();
_SEH2_YIELD(break);
} }
_SEH2_END; _SEH2_END;