/*++ 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" 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,PspInitializeSystemDll) #pragma alloc_text(INIT,PspLookupSystemDllEntryPoint) #pragma alloc_text(INIT,PspNameToOrdinal) #pragma alloc_text(PAGE,PsLocateSystemDll) #pragma alloc_text(PAGE,PsMapSystemDll) #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; KGUARDED_MUTEX PspJobListLock; KSPIN_LOCK PspQuotaLock; LIST_ENTRY PspJobList; SINGLE_LIST_ENTRY PsReaperListHead; WORK_QUEUE_ITEM PsReaperWorkItem; PVOID PsSystemDllBase; #define PSP_1MB (1024*1024) // // List head and mutex that links all processes that have been initialized // KGUARDED_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 (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); PspInitializeProcessListLock (); // // 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.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); PspInitializeWorkingSetChangeLock (); // // 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 // PsReaperListHead.Next = NULL; 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, &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, &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 ( BOOLEAN ReplaceExisting ) /*++ 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; PVOID NtDllSection; // // First see if we need to load this DLL at all. // if (ExVerifySuite (EmbeddedNT) && (PsEmbeddedNTMask&PS_EMBEDDED_NO_USERMODE)) { return STATUS_SUCCESS; } if (!ReplaceExisting) { ExInitializePushLock(&PspSystemDll.DllLock); } // // Initialize the system DLL // InitializeObjectAttributes (&ObjectAttributes, (PUNICODE_STRING) &PsNtDllPathName, OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, 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 if (ReplaceExisting) { return st; } KeBugCheckEx (PROCESS1_INITIALIZATION_FAILED, st, 2, 0, 0); } 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 if (ReplaceExisting) { return st; } 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, &NtDllSection, NULL); ZwClose (Section); if (!NT_SUCCESS (st)) { if (ReplaceExisting) { return st; } KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED,st,4,0,0); // return st; } if (ReplaceExisting) { PVOID ExistingSection; KeEnterCriticalRegion(); ExAcquirePushLockExclusive(&PspSystemDll.DllLock); ExistingSection = PspSystemDll.Section; PspSystemDll.Section = NtDllSection; ExReleasePushLockExclusive(&PspSystemDll.DllLock); KeLeaveCriticalRegion(); if (ExistingSection) { ObDereferenceObject(ExistingSection); } } else { PspSystemDll.Section = NtDllSection; // // Map the system dll into the user part of the address space // st = PsMapSystemDll (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 PsMapSystemDll ( 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; PVOID CapturedSection; PAGED_CODE(); ViewBase = NULL; SectionOffset.LowPart = 0; SectionOffset.HighPart = 0; ViewSize = 0; KeEnterCriticalRegion(); ExAcquirePushLockShared(&PspSystemDll.DllLock); CapturedSection = PspSystemDll.Section; ObReferenceObject(CapturedSection); ExReleasePushLockShared(&PspSystemDll.DllLock); KeLeaveCriticalRegion(); // // Map the system dll into the user part of the address space // st = MmMapViewOfSection( CapturedSection, Process, &ViewBase, 0L, 0L, &SectionOffset, &ViewSize, ViewShare, 0L, PAGE_READWRITE ); ObDereferenceObject(CapturedSection); 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); } 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); } } #ifdef ALLOC_DATA_PRAGMA #pragma const_seg() #endif