|
|
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
psinit.c
Abstract:
Process Structure Initialization.
Author:
Mark Lucovsky (markl) 20-Apr-1989
Revision History:
--*/
#include "psp.h"
#define ROUND_UP(VALUE,ROUND) ((ULONG)(((ULONG)VALUE + \
((ULONG)ROUND - 1L)) & (~((ULONG)ROUND - 1L))))
extern ULONG PsMinimumWorkingSet; extern ULONG PsMaximumWorkingSet; #ifdef ALLOC_DATA_PRAGMA
#pragma const_seg("PAGECONST")
#pragma data_seg("PAGEDATA")
#endif
#define NTDLL_PATH_NAME L"\\SystemRoot\\System32\\ntdll.dll"
const UNICODE_STRING PsNtDllPathName = { sizeof(NTDLL_PATH_NAME) - sizeof(UNICODE_NULL), sizeof(NTDLL_PATH_NAME), NTDLL_PATH_NAME };
ULONG PsPrioritySeperation; // nonpaged
BOOLEAN PspUseJobSchedulingClasses = FALSE; PACCESS_TOKEN PspBootAccessToken = NULL; HANDLE PspInitialSystemProcessHandle = NULL; PHANDLE_TABLE PspCidTable; // nonpaged
SYSTEM_DLL PspSystemDll = {NULL}; #ifdef ALLOC_DATA_PRAGMA
#pragma const_seg("INITCONST")
#pragma data_seg("INITDATA")
#endif
ULONG PsRawPrioritySeparation = 0; ULONG PsEmbeddedNTMask = 0;
NTSTATUS MmCheckSystemImage( IN HANDLE ImageFileHandle, IN LOGICAL PurgeSection );
NTSTATUS LookupEntryPoint ( IN PVOID DllBase, IN PSZ NameOfEntryPoint, OUT PVOID *AddressOfEntryPoint );
const GENERIC_MAPPING PspProcessMapping = { STANDARD_RIGHTS_READ | PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, STANDARD_RIGHTS_WRITE | PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_DUP_HANDLE | PROCESS_TERMINATE | PROCESS_SET_QUOTA | PROCESS_SET_INFORMATION | PROCESS_SET_PORT, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE, PROCESS_ALL_ACCESS };
const GENERIC_MAPPING PspThreadMapping = { STANDARD_RIGHTS_READ | THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION, STANDARD_RIGHTS_WRITE | THREAD_TERMINATE | THREAD_SUSPEND_RESUME | THREAD_ALERT | THREAD_SET_INFORMATION | THREAD_SET_CONTEXT, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE, THREAD_ALL_ACCESS };
const GENERIC_MAPPING PspJobMapping = { STANDARD_RIGHTS_READ | JOB_OBJECT_QUERY, STANDARD_RIGHTS_WRITE | JOB_OBJECT_ASSIGN_PROCESS | JOB_OBJECT_SET_ATTRIBUTES | JOB_OBJECT_TERMINATE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE, THREAD_ALL_ACCESS }; #ifdef ALLOC_DATA_PRAGMA
#pragma data_seg()
#pragma const_seg("PAGECONST")
#endif
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT,PsInitSystem)
#pragma alloc_text(INIT,PspInitPhase0)
#pragma alloc_text(INIT,PspInitPhase1)
#pragma alloc_text(INIT,PsLocateSystemDll)
#pragma alloc_text(INIT,PspInitializeSystemDll)
#pragma alloc_text(INIT,PspLookupSystemDllEntryPoint)
#pragma alloc_text(INIT,PspNameToOrdinal)
#pragma alloc_text(PAGE,PspMapSystemDll)
#pragma alloc_text(PAGE,PsChangeQuantumTable)
#endif
//
// Process Structure Global Data
//
POBJECT_TYPE PsThreadType; POBJECT_TYPE PsProcessType; PEPROCESS PsInitialSystemProcess; PVOID PsSystemDllDllBase; ULONG PspDefaultPagedLimit; ULONG PspDefaultNonPagedLimit; ULONG PspDefaultPagefileLimit; SCHAR PspForegroundQuantum[3];
EPROCESS_QUOTA_BLOCK PspDefaultQuotaBlock; BOOLEAN PspDoingGiveBacks; POBJECT_TYPE PsJobType; FAST_MUTEX PspJobListLock; KSPIN_LOCK PspQuotaLock; LIST_ENTRY PspJobList;
BOOLEAN PsReaperActive; PETHREAD PsReaperList; WORK_QUEUE_ITEM PsReaperWorkItem; PVOID PsSystemDllBase; #define PSP_1MB (1024*1024)
//
// List head and mutex that links all processes that have been initialized
//
FAST_MUTEX PspActiveProcessMutex; LIST_ENTRY PsActiveProcessHead; //extern PIMAGE_FILE_HEADER _header;
PEPROCESS PsIdleProcess; PETHREAD PspShutdownThread;
BOOLEAN PsInitSystem ( IN ULONG Phase, IN PLOADER_PARAMETER_BLOCK LoaderBlock )
/*++
Routine Description:
This function performs process structure initialization. It is called during phase 0 and phase 1 initialization. Its function is to dispatch to the appropriate phase initialization routine.
Arguments:
Phase - Supplies the initialization phase number.
LoaderBlock - Supplies a pointer to a loader parameter block.
Return Value:
TRUE - Initialization succeeded.
FALSE - Initialization failed.
--*/
{ UNREFERENCED_PARAMETER (Phase);
switch ( InitializationPhase ) {
case 0 : return PspInitPhase0(LoaderBlock); case 1 : return PspInitPhase1(LoaderBlock); default: KeBugCheckEx(UNEXPECTED_INITIALIZATION_CALL, 1, InitializationPhase, 0, 0); } // return 0; // Not reachable, quiet compiler
}
BOOLEAN PspInitPhase0 ( IN PLOADER_PARAMETER_BLOCK LoaderBlock )
/*++
Routine Description:
This routine performs phase 0 process structure initialization. During this phase, the initial system process, phase 1 initialization thread, and reaper threads are created. All object types and other process structures are created and initialized.
Arguments:
None.
Return Value:
TRUE - Initialization was successful.
FALSE - Initialization Failed.
--*/
{
UNICODE_STRING NameString; OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; HANDLE ThreadHandle; PETHREAD Thread; MM_SYSTEMSIZE SystemSize; ULONG i; #if DBG
NTSTATUS Status; #endif
SystemSize = MmQuerySystemSize(); PspDefaultPagefileLimit = (ULONG)-1;
#ifdef _WIN64
if ( sizeof(TEB) > 8192 || sizeof(PEB) > 4096 ) { #else
if ( sizeof(TEB) > 4096 || sizeof(PEB) > 4096 ) { #endif
KeBugCheckEx(PROCESS_INITIALIZATION_FAILED,99,sizeof(TEB),sizeof(PEB),99); }
switch ( SystemSize ) {
case MmMediumSystem : PsMinimumWorkingSet += 10; PsMaximumWorkingSet += 100; break;
case MmLargeSystem : PsMinimumWorkingSet += 30; PsMaximumWorkingSet += 300; break;
case MmSmallSystem : default: break; }
//
// Initialize all the callback structures
//
for (i = 0; i < PSP_MAX_CREATE_THREAD_NOTIFY; i++) { ExInitializeCallBack (&PspCreateThreadNotifyRoutine[i]); }
for (i = 0; i < PSP_MAX_CREATE_PROCESS_NOTIFY; i++) { ExInitializeCallBack (&PspCreateProcessNotifyRoutine[i]); }
for (i = 0; i < PSP_MAX_LOAD_IMAGE_NOTIFY; i++) { ExInitializeCallBack (&PspLoadImageNotifyRoutine[i]); }
PsChangeQuantumTable(FALSE,PsRawPrioritySeparation);
//
// Quotas grow as needed automatically
//
// if ( !PspDefaultPagedLimit ) {
// PspDefaultPagedLimit = 0;
// }
// if ( !PspDefaultNonPagedLimit ) {
// PspDefaultNonPagedLimit = 0;
// }
if (PspDefaultNonPagedLimit == 0 && PspDefaultPagedLimit == 0) { PspDoingGiveBacks = TRUE; } else { PspDoingGiveBacks = FALSE; }
PspDefaultPagedLimit *= PSP_1MB; PspDefaultNonPagedLimit *= PSP_1MB;
if (PspDefaultPagefileLimit != -1) { PspDefaultPagefileLimit *= PSP_1MB; }
//
// Initialize active process list head and mutex
//
InitializeListHead(&PsActiveProcessHead); ExInitializeFastMutex(&PspActiveProcessMutex);
//
// Initialize the process security fields lock
//
PsIdleProcess = PsGetCurrentProcess();
PspInitializeProcessLock (PsIdleProcess); ExInitializeRundownProtection (&PsIdleProcess->RundownProtect); InitializeListHead (&PsIdleProcess->ThreadListHead);
PsIdleProcess->Pcb.KernelTime = 0; PsIdleProcess->Pcb.KernelTime = 0;
//
// Initialize the shutdown thread pointer
//
PspShutdownThread = NULL;
//
// Initialize the common fields of the Object Type Prototype record
//
RtlZeroMemory( &ObjectTypeInitializer, sizeof( ObjectTypeInitializer ) ); ObjectTypeInitializer.Length = sizeof( ObjectTypeInitializer ); ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK; ObjectTypeInitializer.SecurityRequired = TRUE; ObjectTypeInitializer.PoolType = NonPagedPool; ObjectTypeInitializer.InvalidAttributes = OBJ_PERMANENT | OBJ_EXCLUSIVE | OBJ_OPENIF;
//
// Create Object types for Thread and Process Objects.
//
RtlInitUnicodeString(&NameString, L"Process"); ObjectTypeInitializer.DefaultPagedPoolCharge = PSP_PROCESS_PAGED_CHARGE; ObjectTypeInitializer.DefaultNonPagedPoolCharge = PSP_PROCESS_NONPAGED_CHARGE; ObjectTypeInitializer.DeleteProcedure = PspProcessDelete; ObjectTypeInitializer.ValidAccessMask = PROCESS_ALL_ACCESS; ObjectTypeInitializer.GenericMapping = PspProcessMapping;
if ( !NT_SUCCESS(ObCreateObjectType(&NameString, &ObjectTypeInitializer, (PSECURITY_DESCRIPTOR) NULL, &PsProcessType )) ){ return FALSE; }
RtlInitUnicodeString(&NameString, L"Thread"); ObjectTypeInitializer.DefaultPagedPoolCharge = PSP_THREAD_PAGED_CHARGE; ObjectTypeInitializer.DefaultNonPagedPoolCharge = PSP_THREAD_NONPAGED_CHARGE; ObjectTypeInitializer.DeleteProcedure = PspThreadDelete; ObjectTypeInitializer.ValidAccessMask = THREAD_ALL_ACCESS; ObjectTypeInitializer.GenericMapping = PspThreadMapping;
if ( !NT_SUCCESS(ObCreateObjectType(&NameString, &ObjectTypeInitializer, (PSECURITY_DESCRIPTOR) NULL, &PsThreadType )) ){ return FALSE; }
RtlInitUnicodeString(&NameString, L"Job"); ObjectTypeInitializer.DefaultPagedPoolCharge = 0; ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(EJOB); ObjectTypeInitializer.DeleteProcedure = PspJobDelete; ObjectTypeInitializer.CloseProcedure = PspJobClose; ObjectTypeInitializer.ValidAccessMask = JOB_OBJECT_ALL_ACCESS; ObjectTypeInitializer.GenericMapping = PspJobMapping; ObjectTypeInitializer.InvalidAttributes = 0;
if ( !NT_SUCCESS(ObCreateObjectType(&NameString, &ObjectTypeInitializer, (PSECURITY_DESCRIPTOR) NULL, &PsJobType )) ){ return FALSE; }
//
// Initialize job list head and mutex
//
PspInitializeJobStructures(); InitializeListHead(&PspWorkingSetChangeHead.Links); ExInitializeFastMutex(&PspWorkingSetChangeHead.Lock);
//
// Initialize CID handle table.
//
// N.B. The CID handle table is removed from the handle table list so
// it will not be enumerated for object handle queries.
//
PspCidTable = ExCreateHandleTable(NULL); if (PspCidTable == NULL) { return FALSE; }
//
// Set PID and TID reuse to strict FIFO. This isn't absolutely needed but
// it makes tracking audits easier.
//
ExSetHandleTableStrictFIFO (PspCidTable);
ExRemoveHandleTable(PspCidTable);
#if defined(i386)
//
// Ldt Initialization
//
if ( !NT_SUCCESS(PspLdtInitialize()) ) { return FALSE; }
//
// Vdm support Initialization
//
if ( !NT_SUCCESS(PspVdmInitialize()) ) { return FALSE; }
#endif
//
// Initialize Reaper Data Structures
//
PsReaperList = NULL; PsReaperActive = FALSE;
ExInitializeWorkItem(&PsReaperWorkItem, PspReaper, NULL);
//
// Get a pointer to the system access token.
// This token is used by the boot process, so we can take the pointer
// from there.
//
PspBootAccessToken = ExFastRefGetObject (PsIdleProcess->Token);
InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
if (!NT_SUCCESS (PspCreateProcess (&PspInitialSystemProcessHandle, PROCESS_ALL_ACCESS, &ObjectAttributes, NULL, 0, NULL, NULL, NULL, 0))) { return FALSE; }
if ( !NT_SUCCESS(ObReferenceObjectByHandle( PspInitialSystemProcessHandle, 0L, PsProcessType, KernelMode, (PVOID *)&PsInitialSystemProcess, NULL )) ) {
return FALSE; }
strcpy((char *) &PsIdleProcess->ImageFileName[0],"Idle"); strcpy((char *) &PsInitialSystemProcess->ImageFileName[0],"System");
//
// The system process can allocate resources, and its name may be queried by
// NtQueryInfomationProcess and various audits. We must explicitly allocate memory
// for this field of the System EPROCESS, and initialize it appropriately. In this
// case, appropriate initialization means zeroing the memory.
//
PsInitialSystemProcess->SeAuditProcessCreationInfo.ImageFileName = ExAllocatePoolWithTag( PagedPool, sizeof(OBJECT_NAME_INFORMATION), 'aPeS' );
if (PsInitialSystemProcess->SeAuditProcessCreationInfo.ImageFileName != NULL) { RtlZeroMemory( PsInitialSystemProcess->SeAuditProcessCreationInfo.ImageFileName, sizeof(OBJECT_NAME_INFORMATION) ); } else { return FALSE; }
//
// Phase 1 System initialization
//
if ( !NT_SUCCESS(PsCreateSystemThread( &ThreadHandle, THREAD_ALL_ACCESS, &ObjectAttributes, 0L, NULL, Phase1Initialization, (PVOID)LoaderBlock )) ) { return FALSE; }
if ( !NT_SUCCESS(ObReferenceObjectByHandle( ThreadHandle, 0L, PsThreadType, KernelMode, (PVOID *)&Thread, NULL )) ) {
return FALSE; }
ZwClose( ThreadHandle );
//
// On checked systems install an image callout routine
//
#if DBG
Status = PsSetLoadImageNotifyRoutine (PspImageNotifyTest); if (!NT_SUCCESS (Status)) { return FALSE; }
#endif
return TRUE; }
BOOLEAN PspInitPhase1 ( IN PLOADER_PARAMETER_BLOCK LoaderBlock )
/*++
Routine Description:
This routine performs phase 1 process structure initialization. During this phase, the system DLL is located and relevant entry points are extracted.
Arguments:
None.
Return Value:
TRUE - Initialization was successful.
FALSE - Initialization Failed.
--*/
{
NTSTATUS st;
UNREFERENCED_PARAMETER (LoaderBlock);
PspInitializeJobStructuresPhase1();
st = PspInitializeSystemDll();
if ( !NT_SUCCESS(st) ) { return FALSE; }
return TRUE; }
NTSTATUS PsLocateSystemDll ( VOID )
/*++
Routine Description:
This function locates the system dll and creates a section for the DLL and maps it into the system process.
Arguments:
None.
Return Value:
TRUE - Initialization was successful.
FALSE - Initialization Failed.
--*/
{
HANDLE File; HANDLE Section; NTSTATUS st; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatus;
//
// First see if we need to load this DLL at all.
//
if (ExVerifySuite (EmbeddedNT) && (PsEmbeddedNTMask&PS_EMBEDDED_NO_USERMODE)) { return STATUS_SUCCESS; } //
// Initialize the system DLL
//
InitializeObjectAttributes( &ObjectAttributes, (PUNICODE_STRING)&PsNtDllPathName, OBJ_CASE_INSENSITIVE, NULL, NULL );
st = ZwOpenFile( &File, SYNCHRONIZE | FILE_EXECUTE, &ObjectAttributes, &IoStatus, FILE_SHARE_READ, 0 );
if (!NT_SUCCESS(st)) {
#if DBG
DbgPrint("PS: PsLocateSystemDll - NtOpenFile( NTDLL.DLL ) failed. Status == %lx\n", st ); #endif
KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED,st,2,0,0); // return st;
}
st = MmCheckSystemImage(File, TRUE); if ( st == STATUS_IMAGE_CHECKSUM_MISMATCH || st == STATUS_INVALID_IMAGE_PROTECT ) {
ULONG_PTR ErrorParameters; ULONG ErrorResponse;
//
// Hard error time. A driver is corrupt.
//
ErrorParameters = (ULONG_PTR)&PsNtDllPathName;
NtRaiseHardError( st, 1, 1, &ErrorParameters, OptionOk, &ErrorResponse ); return st; }
st = ZwCreateSection( &Section, SECTION_ALL_ACCESS, NULL, 0, PAGE_EXECUTE, SEC_IMAGE, File ); ZwClose( File );
if (!NT_SUCCESS(st)) { #if DBG
DbgPrint("PS: PsLocateSystemDll: NtCreateSection Status == %lx\n",st); #endif
KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED,st,3,0,0); // return st;
}
//
// Now that we have the section, reference it, store its address in the
// PspSystemDll and then close handle to the section.
//
st = ObReferenceObjectByHandle( Section, SECTION_ALL_ACCESS, MmSectionObjectType, KernelMode, &PspSystemDll.Section, NULL );
ZwClose(Section);
if ( !NT_SUCCESS(st) ) { KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED,st,4,0,0); // return st;
}
//
// Map the system dll into the user part of the address space
//
st = PspMapSystemDll(PsGetCurrentProcess(),&PspSystemDll.DllBase); PsSystemDllDllBase = PspSystemDll.DllBase;
if ( !NT_SUCCESS(st) ) { KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED,st,5,0,0); // return st;
} PsSystemDllBase = PspSystemDll.DllBase;
return STATUS_SUCCESS; }
NTSTATUS PspMapSystemDll ( IN PEPROCESS Process, OUT PVOID *DllBase OPTIONAL )
/*++
Routine Description:
This function maps the system DLL into the specified process.
Arguments:
Process - Supplies the address of the process to map the DLL into.
Return Value:
TBD
--*/
{ NTSTATUS st; PVOID ViewBase; LARGE_INTEGER SectionOffset; SIZE_T ViewSize;
PAGED_CODE();
ViewBase = NULL; SectionOffset.LowPart = 0; SectionOffset.HighPart = 0; ViewSize = 0;
//
// Map the system dll into the user part of the address space
//
st = MmMapViewOfSection( PspSystemDll.Section, Process, &ViewBase, 0L, 0L, &SectionOffset, &ViewSize, ViewShare, 0L, PAGE_READWRITE );
if ( st != STATUS_SUCCESS ) { #if DBG
DbgPrint("PS: Unable to map system dll at based address.\n"); #endif
st = STATUS_CONFLICTING_ADDRESSES; }
if ( ARGUMENT_PRESENT(DllBase) ) { *DllBase = ViewBase; }
return st; }
NTSTATUS PspInitializeSystemDll ( VOID )
/*++
Routine Description:
This function initializes the system DLL and locates various entrypoints within the DLL.
Arguments:
None.
Return Value:
TBD
--*/
{ NTSTATUS st; PSZ dll_entrypoint;
//
// If we skipped dll load becuase we are kernel only then exit now.
//
if (PsSystemDllDllBase == NULL) { return STATUS_SUCCESS; } //
// Locate the important system dll entrypoints
//
dll_entrypoint = "LdrInitializeThunk";
st = PspLookupSystemDllEntryPoint( dll_entrypoint, (PVOID *)&PspSystemDll.LoaderInitRoutine );
if ( !NT_SUCCESS(st) ) { #if DBG
DbgPrint("PS: Unable to locate LdrInitializeThunk in system dll\n"); #endif
KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED,st,6,0,0); // return st;
}
st = PspLookupKernelUserEntryPoints();
if ( !NT_SUCCESS(st) ) { KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED,st,8,0,0); }
KdUpdateDataBlock();
return st; }
NTSTATUS PspLookupSystemDllEntryPoint ( IN PSZ NameOfEntryPoint, OUT PVOID *AddressOfEntryPoint )
{ return LookupEntryPoint ( PspSystemDll.DllBase, NameOfEntryPoint, AddressOfEntryPoint ); }
const SCHAR PspFixedQuantums[6] = { 3*THREAD_QUANTUM, 3*THREAD_QUANTUM, 3*THREAD_QUANTUM, 6*THREAD_QUANTUM, 6*THREAD_QUANTUM, 6*THREAD_QUANTUM };
const SCHAR PspVariableQuantums[6] = { 1*THREAD_QUANTUM, 2*THREAD_QUANTUM, 3*THREAD_QUANTUM, 2*THREAD_QUANTUM, 4*THREAD_QUANTUM, 6*THREAD_QUANTUM };
//
// The table is ONLY used when fixed quantums are selected.
//
const SCHAR PspJobSchedulingClasses[PSP_NUMBER_OF_SCHEDULING_CLASSES] = { 1*THREAD_QUANTUM, // long fixed 0
2*THREAD_QUANTUM, // long fixed 1...
3*THREAD_QUANTUM, 4*THREAD_QUANTUM, 5*THREAD_QUANTUM, 6*THREAD_QUANTUM, // DEFAULT
7*THREAD_QUANTUM, 8*THREAD_QUANTUM, 9*THREAD_QUANTUM, 10*THREAD_QUANTUM // long fixed 9
};
VOID PsChangeQuantumTable( BOOLEAN ModifyActiveProcesses, ULONG PrioritySeparation ) {
PEPROCESS Process; PETHREAD CurrentThread; PLIST_ENTRY NextProcess; ULONG QuantumIndex; SCHAR const* QuantumTableBase; PEJOB Job;
//
// extract priority seperation value
//
switch ( PrioritySeparation & PROCESS_PRIORITY_SEPARATION_MASK ) { case 3: PsPrioritySeperation = PROCESS_PRIORITY_SEPARATION_MAX; break; default: PsPrioritySeperation = PrioritySeparation & PROCESS_PRIORITY_SEPARATION_MASK; break; }
//
// determine if we are using fixed or variable quantums
//
switch ( PrioritySeparation & PROCESS_QUANTUM_VARIABLE_MASK ) { case PROCESS_QUANTUM_VARIABLE_VALUE: QuantumTableBase = PspVariableQuantums; break;
case PROCESS_QUANTUM_FIXED_VALUE: QuantumTableBase = PspFixedQuantums; break;
case PROCESS_QUANTUM_VARIABLE_DEF: default: if ( MmIsThisAnNtAsSystem() ) { QuantumTableBase = PspFixedQuantums; } else { QuantumTableBase = PspVariableQuantums; } break; }
//
// determine if we are using long or short
//
switch ( PrioritySeparation & PROCESS_QUANTUM_LONG_MASK ) { case PROCESS_QUANTUM_LONG_VALUE: QuantumTableBase = QuantumTableBase + 3; break;
case PROCESS_QUANTUM_SHORT_VALUE: break;
case PROCESS_QUANTUM_LONG_DEF: default: if ( MmIsThisAnNtAsSystem() ) { QuantumTableBase = QuantumTableBase + 3; } break; }
//
// Job Scheduling classes are ONLY meaningful if long fixed quantums
// are selected. In practice, this means stock NTS configurations
//
if ( QuantumTableBase == &PspFixedQuantums[3] ) { PspUseJobSchedulingClasses = TRUE; } else { PspUseJobSchedulingClasses = FALSE; }
RtlCopyMemory(PspForegroundQuantum,QuantumTableBase,sizeof(PspForegroundQuantum));
if (ModifyActiveProcesses) {
CurrentThread = PsGetCurrentThread ();
PspLockProcessList (CurrentThread);
NextProcess = PsActiveProcessHead.Flink;
while (NextProcess != &PsActiveProcessHead) { Process = CONTAINING_RECORD(NextProcess, EPROCESS, ActiveProcessLinks);
if ( Process->Vm.Flags.MemoryPriority == MEMORY_PRIORITY_BACKGROUND ) { QuantumIndex = 0; } else { QuantumIndex = PsPrioritySeperation; }
if (Process->PriorityClass != PROCESS_PRIORITY_CLASS_IDLE) {
//
// If the process is contained within a JOB, AND we are
// running Fixed, Long Quantums, use the quantum associated
// with the Job's scheduling class
//
Job = Process->Job; if (Job != NULL && PspUseJobSchedulingClasses ) { Process->Pcb.ThreadQuantum = PspJobSchedulingClasses[Job->SchedulingClass]; } else { Process->Pcb.ThreadQuantum = PspForegroundQuantum[QuantumIndex]; } } else { Process->Pcb.ThreadQuantum = THREAD_QUANTUM; } NextProcess = NextProcess->Flink; } PspUnlockProcessList (CurrentThread); } }
|