Author: ion
Date: Sun Dec 18 04:27:20 2011
New Revision: 54681
URL:
http://svn.reactos.org/svn/reactos?rev=54681&view=rev
Log:
[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.
Modified:
trunk/reactos/include/ndk/pstypes.h
trunk/reactos/ntoskrnl/include/internal/ke.h
trunk/reactos/ntoskrnl/ke/procobj.c
trunk/reactos/ntoskrnl/ke/thrdobj.c
trunk/reactos/ntoskrnl/ps/query.c
Modified: trunk/reactos/include/ndk/pstypes.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/pstypes.h?rev=…
==============================================================================
--- trunk/reactos/include/ndk/pstypes.h [iso-8859-1] (original)
+++ trunk/reactos/include/ndk/pstypes.h [iso-8859-1] Sun Dec 18 04:27:20 2011
@@ -221,6 +221,12 @@
#define STA_LPC_EXIT_THREAD_CALLED_BIT 0x2
#define STA_ADDRESS_SPACE_OWNER_BIT 0x4
#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
@@ -762,6 +768,11 @@
UCHAR PriorityClass;
} PROCESS_PRIORITY_CLASS, *PPROCESS_PRIORITY_CLASS;
+typedef struct _PROCESS_FOREGROUND_BACKGROUND
+{
+ BOOLEAN Foreground;
+} PROCESS_FOREGROUND_BACKGROUND, *PPROCESS_FOREGROUND_BACKGROUND;
+
//
// Thread Information Structures for NtQueryProcessInformation
//
Modified: trunk/reactos/ntoskrnl/include/internal/ke.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ke.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/ke.h [iso-8859-1] Sun Dec 18 04:27:20 2011
@@ -269,6 +269,34 @@
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
NTAPI
KeBalanceSetManager(IN PVOID Context);
Modified: trunk/reactos/ntoskrnl/ke/procobj.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/procobj.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/procobj.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/procobj.c [iso-8859-1] Sun Dec 18 04:27:20 2011
@@ -258,6 +258,90 @@
/* Release lock */
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
Modified: trunk/reactos/ntoskrnl/ke/thrdobj.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/thrdobj.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/thrdobj.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/thrdobj.c [iso-8859-1] Sun Dec 18 04:27:20 2011
@@ -222,6 +222,53 @@
/* Return the old state */
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
Modified: trunk/reactos/ntoskrnl/ps/query.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ps/query.c?rev=54…
==============================================================================
--- trunk/reactos/ntoskrnl/ps/query.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ps/query.c [iso-8859-1] Sun Dec 18 04:27:20 2011
@@ -13,6 +13,9 @@
#include <ntoskrnl.h>
#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"
@@ -247,6 +250,7 @@
_SEH2_TRY
{
+ /* FIXME: Call KeQueryValuesProcess */
IoCounters->ReadOperationCount =
Process->ReadOperationCount.QuadPart;
IoCounters->ReadTransferCount =
Process->ReadTransferCount.QuadPart;
IoCounters->WriteOperationCount =
Process->WriteOperationCount.QuadPart;
@@ -292,11 +296,12 @@
_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)
@@ -349,10 +354,16 @@
ObDereferenceObject(Process);
break;
- /* LDT, WS and VDM Information: not implemented */
- case ProcessLdtInformation:
- case ProcessWorkingSetWatch:
- case ProcessWx86Information:
+ case ProcessHandleCount:
+
+ /* Set the return length*/
+ Length = sizeof(ULONG);
+
+ if (ProcessInformationLength != Length)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
/* Reference the process */
Status = ObReferenceObjectByHandle(ProcessHandle,
@@ -363,17 +374,31 @@
NULL);
if (!NT_SUCCESS(Status)) break;
- DPRINT1("Not implemented: %lx\n", ProcessInformationClass);
+ /* Count the number of handles this process has */
+ HandleCount = ObGetProcessHandleCount(Process);
+
+ /* Protect write in SEH */
+ _SEH2_TRY
+ {
+ /* Return the count of handles */
+ *(PULONG)ProcessInformation = HandleCount;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
/* Dereference the process */
ObDereferenceObject(Process);
- Status = STATUS_NOT_IMPLEMENTED;
- break;
-
- case ProcessHandleCount:
+ break;
+
+ /* Session ID for the process */
+ case ProcessSessionInformation:
/* Set the return length*/
- Length = sizeof(ULONG);
+ Length = sizeof(PROCESS_SESSION_INFORMATION);
if (ProcessInformationLength != Length)
{
@@ -390,14 +415,11 @@
NULL);
if (!NT_SUCCESS(Status)) break;
- /* Count the number of handles this process has */
- HandleCount = ObGetProcessHandleCount(Process);
-
- /* Protect write in SEH */
- _SEH2_TRY
- {
- /* Return the count of handles */
- *(PULONG)ProcessInformation = HandleCount;
+ /* Enter SEH for write safety */
+ _SEH2_TRY
+ {
+ /* Write back the Session ID */
+ SessionInfo->SessionId = Process->Session;
//MmGetSessionId(Process);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
@@ -410,98 +432,19 @@
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 = Process->Session;
- }
- _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)
- {
- /* Get the exception code */
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END;
-
- /* Dereference the process */
- ObDereferenceObject(Process);
- break;
-
/* Virtual Memory Statistics */
case ProcessVmCounters:
+ /* Validate the input length */
+ if ((ProcessInformationLength != sizeof(VM_COUNTERS)) &&
+ (ProcessInformationLength != sizeof(VM_COUNTERS_EX)))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
/* Set the return length */
- Length = sizeof(VM_COUNTERS);
-
- if (ProcessInformationLength != Length)
- {
- Status = STATUS_INFO_LENGTH_MISMATCH;
- break;
- }
+ Length = ProcessInformationLength;
/* Reference the process */
Status = ObReferenceObjectByHandle(ProcessHandle,
@@ -525,9 +468,9 @@
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;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
@@ -582,7 +525,7 @@
/* Priority Boosting status */
case ProcessPriorityBoost:
- /* Set the return length*/
+ /* Set the return length */
Length = sizeof(ULONG);
if (ProcessInformationLength != Length)
@@ -621,12 +564,20 @@
/* 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;
}
@@ -751,7 +702,7 @@
ObDereferenceObject(Process);
break;
- case ProcessBreakOnTermination:
+ case ProcessDebugFlags:
/* Set the return length*/
Length = sizeof(ULONG);
@@ -773,6 +724,42 @@
/* 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;
}
@@ -831,20 +818,52 @@
}
_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:
+
+ 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;
+
+ 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 or unimplemented: %lx\n",
ProcessInformationClass);
+ DPRINT1("Unsupported info class: %lx\n", ProcessInformationClass);
Status = STATUS_INVALID_INFO_CLASS;
}
@@ -882,8 +901,14 @@
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;
+ ULONG DefaultHardErrorMode = 0, BasePriority = 0, MemoryPriority = 0;
+ ULONG DisableBoost = 0, DebugFlags = 0, EnableFixup = 0, Boost = 0;
+ PLIST_ENTRY Next;
+ PETHREAD Thread;
PAGED_CODE();
/* Verify Information Class validity */
@@ -946,6 +971,14 @@
}
_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,
0,
@@ -1008,16 +1041,29 @@
/* Enter SEH for direct buffer read */
_SEH2_TRY
{
- /* Update the current mode abd return the previous one */
- InterlockedExchange((LONG*)&Process->DefaultHardErrorProcessing,
- *(PLONG)ProcessInformation);
+ DefaultHardErrorMode = *(PULONG)ProcessInformation;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get exception code */
Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END;
+ _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 */
@@ -1119,7 +1165,12 @@
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 */
if (Process->Job)
@@ -1132,39 +1183,153 @@
/* Set process priority mode (foreground or background) */
PsSetProcessPriorityByClass(Process,
- !PriorityClass.Foreground ?
PsProcessPriorityBackground :
- PsProcessPriorityForeground);
-
+ PriorityClass.Foreground ?
+ PsProcessPriorityForeground :
+ PsProcessPriorityBackground);
Status = STATUS_SUCCESS;
break;
- case ProcessQuotaLimits:
+ case ProcessForegroundInformation:
/* Check buffer length */
- if (ProcessInformationLength != sizeof(QUOTA_LIMITS))
- {
- Status = STATUS_INFO_LENGTH_MISMATCH;
- break;
- }
-
- DPRINT1("Not implemented: ProcessQuotaLimits\n");
- Status = STATUS_NOT_IMPLEMENTED;
- break;
-
+ 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:
- /* Check buffer length */
+ /* Validate input length */
if (ProcessInformationLength != sizeof(KPRIORITY))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
- DPRINT1("Not implemented: ProcessBasePriority\n");
- Status = STATUS_NOT_IMPLEMENTED;
+ /* Enter SEH for direct buffer read */
+ _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;
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))
@@ -1173,37 +1338,164 @@
break;
}
- DPRINT1("Not implemented: ProcessRaisePriority\n");
- Status = STATUS_NOT_IMPLEMENTED;
- break;
-
- case ProcessWx86Information:
-
+ /* 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(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:
+ 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))
@@ -1215,57 +1507,112 @@
/* Enter SEH for direct buffer read */
_SEH2_TRY
{
- Break = *(PULONG)ProcessInformation;
+ DebugFlags = *(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);
+ /* Set the mode */
+ if (DebugFlags & ~1)
+ {
+ Status = STATUS_INVALID_PARAMETER;
}
else
{
- PspClearProcessFlag(Process, PSF_BREAK_ON_TERMINATION_BIT);
- }
-
- break;
-
+ 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 */
case ProcessLdtInformation:
case ProcessLdtSize:
case ProcessIoPortHandlers:
+ case ProcessUserModeIOPL:
+ case ProcessWx86Information:
+ DPRINT1("VDM/16-bit Request not implemented: %lx\n",
ProcessInformationClass);
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ case ProcessQuotaLimits:
+ DPRINT1("Quota Limits not implemented\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+
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;
+
+ case ProcessExecuteFlags:
+ DPRINT1("No execute support 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;
}
@@ -1434,6 +1781,7 @@
{
/* Get the exception code */
Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(break);
}
_SEH2_END;