Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1060 lines
26 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. psinit.c
  5. Abstract:
  6. Process Structure Initialization.
  7. Author:
  8. Mark Lucovsky (markl) 20-Apr-1989
  9. Revision History:
  10. --*/
  11. #include "psp.h"
  12. #define ROUND_UP(VALUE,ROUND) ((ULONG)(((ULONG)VALUE + \
  13. ((ULONG)ROUND - 1L)) & (~((ULONG)ROUND - 1L))))
  14. extern ULONG PsMinimumWorkingSet;
  15. extern ULONG PsMaximumWorkingSet;
  16. #ifdef ALLOC_DATA_PRAGMA
  17. #pragma const_seg("PAGECONST")
  18. #pragma data_seg("PAGEDATA")
  19. #endif
  20. #define NTDLL_PATH_NAME L"\\SystemRoot\\System32\\ntdll.dll"
  21. const UNICODE_STRING PsNtDllPathName = {
  22. sizeof(NTDLL_PATH_NAME) - sizeof(UNICODE_NULL),
  23. sizeof(NTDLL_PATH_NAME),
  24. NTDLL_PATH_NAME
  25. };
  26. ULONG PsPrioritySeperation; // nonpaged
  27. BOOLEAN PspUseJobSchedulingClasses = FALSE;
  28. PACCESS_TOKEN PspBootAccessToken = NULL;
  29. HANDLE PspInitialSystemProcessHandle = NULL;
  30. PHANDLE_TABLE PspCidTable; // nonpaged
  31. SYSTEM_DLL PspSystemDll = {NULL};
  32. #ifdef ALLOC_DATA_PRAGMA
  33. #pragma const_seg("INITCONST")
  34. #pragma data_seg("INITDATA")
  35. #endif
  36. ULONG PsRawPrioritySeparation = 0;
  37. ULONG PsEmbeddedNTMask = 0;
  38. NTSTATUS
  39. MmCheckSystemImage(
  40. IN HANDLE ImageFileHandle,
  41. IN LOGICAL PurgeSection
  42. );
  43. NTSTATUS
  44. LookupEntryPoint (
  45. IN PVOID DllBase,
  46. IN PSZ NameOfEntryPoint,
  47. OUT PVOID *AddressOfEntryPoint
  48. );
  49. const GENERIC_MAPPING PspProcessMapping = {
  50. STANDARD_RIGHTS_READ |
  51. PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
  52. STANDARD_RIGHTS_WRITE |
  53. PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD |
  54. PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_DUP_HANDLE |
  55. PROCESS_TERMINATE | PROCESS_SET_QUOTA |
  56. PROCESS_SET_INFORMATION | PROCESS_SET_PORT,
  57. STANDARD_RIGHTS_EXECUTE |
  58. SYNCHRONIZE,
  59. PROCESS_ALL_ACCESS
  60. };
  61. const GENERIC_MAPPING PspThreadMapping = {
  62. STANDARD_RIGHTS_READ |
  63. THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION,
  64. STANDARD_RIGHTS_WRITE |
  65. THREAD_TERMINATE | THREAD_SUSPEND_RESUME | THREAD_ALERT |
  66. THREAD_SET_INFORMATION | THREAD_SET_CONTEXT,
  67. STANDARD_RIGHTS_EXECUTE |
  68. SYNCHRONIZE,
  69. THREAD_ALL_ACCESS
  70. };
  71. const GENERIC_MAPPING PspJobMapping = {
  72. STANDARD_RIGHTS_READ |
  73. JOB_OBJECT_QUERY,
  74. STANDARD_RIGHTS_WRITE |
  75. JOB_OBJECT_ASSIGN_PROCESS | JOB_OBJECT_SET_ATTRIBUTES | JOB_OBJECT_TERMINATE,
  76. STANDARD_RIGHTS_EXECUTE |
  77. SYNCHRONIZE,
  78. THREAD_ALL_ACCESS
  79. };
  80. #ifdef ALLOC_DATA_PRAGMA
  81. #pragma data_seg()
  82. #pragma const_seg("PAGECONST")
  83. #endif
  84. #ifdef ALLOC_PRAGMA
  85. #pragma alloc_text(INIT,PsInitSystem)
  86. #pragma alloc_text(INIT,PspInitPhase0)
  87. #pragma alloc_text(INIT,PspInitPhase1)
  88. #pragma alloc_text(INIT,PsLocateSystemDll)
  89. #pragma alloc_text(INIT,PspInitializeSystemDll)
  90. #pragma alloc_text(INIT,PspLookupSystemDllEntryPoint)
  91. #pragma alloc_text(INIT,PspNameToOrdinal)
  92. #pragma alloc_text(PAGE,PspMapSystemDll)
  93. #pragma alloc_text(PAGE,PsChangeQuantumTable)
  94. #endif
  95. //
  96. // Process Structure Global Data
  97. //
  98. POBJECT_TYPE PsThreadType;
  99. POBJECT_TYPE PsProcessType;
  100. PEPROCESS PsInitialSystemProcess;
  101. PVOID PsSystemDllDllBase;
  102. ULONG PspDefaultPagedLimit;
  103. ULONG PspDefaultNonPagedLimit;
  104. ULONG PspDefaultPagefileLimit;
  105. SCHAR PspForegroundQuantum[3];
  106. EPROCESS_QUOTA_BLOCK PspDefaultQuotaBlock;
  107. BOOLEAN PspDoingGiveBacks;
  108. POBJECT_TYPE PsJobType;
  109. FAST_MUTEX PspJobListLock;
  110. KSPIN_LOCK PspQuotaLock;
  111. LIST_ENTRY PspJobList;
  112. BOOLEAN PsReaperActive;
  113. PETHREAD PsReaperList;
  114. WORK_QUEUE_ITEM PsReaperWorkItem;
  115. PVOID PsSystemDllBase;
  116. #define PSP_1MB (1024*1024)
  117. //
  118. // List head and mutex that links all processes that have been initialized
  119. //
  120. FAST_MUTEX PspActiveProcessMutex;
  121. LIST_ENTRY PsActiveProcessHead;
  122. //extern PIMAGE_FILE_HEADER _header;
  123. PEPROCESS PsIdleProcess;
  124. PETHREAD PspShutdownThread;
  125. BOOLEAN
  126. PsInitSystem (
  127. IN ULONG Phase,
  128. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  129. )
  130. /*++
  131. Routine Description:
  132. This function performs process structure initialization.
  133. It is called during phase 0 and phase 1 initialization. Its
  134. function is to dispatch to the appropriate phase initialization
  135. routine.
  136. Arguments:
  137. Phase - Supplies the initialization phase number.
  138. LoaderBlock - Supplies a pointer to a loader parameter block.
  139. Return Value:
  140. TRUE - Initialization succeeded.
  141. FALSE - Initialization failed.
  142. --*/
  143. {
  144. UNREFERENCED_PARAMETER (Phase);
  145. switch ( InitializationPhase ) {
  146. case 0 :
  147. return PspInitPhase0(LoaderBlock);
  148. case 1 :
  149. return PspInitPhase1(LoaderBlock);
  150. default:
  151. KeBugCheckEx(UNEXPECTED_INITIALIZATION_CALL, 1, InitializationPhase, 0, 0);
  152. }
  153. // return 0; // Not reachable, quiet compiler
  154. }
  155. BOOLEAN
  156. PspInitPhase0 (
  157. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  158. )
  159. /*++
  160. Routine Description:
  161. This routine performs phase 0 process structure initialization.
  162. During this phase, the initial system process, phase 1 initialization
  163. thread, and reaper threads are created. All object types and other
  164. process structures are created and initialized.
  165. Arguments:
  166. None.
  167. Return Value:
  168. TRUE - Initialization was successful.
  169. FALSE - Initialization Failed.
  170. --*/
  171. {
  172. UNICODE_STRING NameString;
  173. OBJECT_ATTRIBUTES ObjectAttributes;
  174. OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
  175. HANDLE ThreadHandle;
  176. PETHREAD Thread;
  177. MM_SYSTEMSIZE SystemSize;
  178. ULONG i;
  179. #if DBG
  180. NTSTATUS Status;
  181. #endif
  182. SystemSize = MmQuerySystemSize();
  183. PspDefaultPagefileLimit = (ULONG)-1;
  184. #ifdef _WIN64
  185. if ( sizeof(TEB) > 8192 || sizeof(PEB) > 4096 ) {
  186. #else
  187. if ( sizeof(TEB) > 4096 || sizeof(PEB) > 4096 ) {
  188. #endif
  189. KeBugCheckEx(PROCESS_INITIALIZATION_FAILED,99,sizeof(TEB),sizeof(PEB),99);
  190. }
  191. switch ( SystemSize ) {
  192. case MmMediumSystem :
  193. PsMinimumWorkingSet += 10;
  194. PsMaximumWorkingSet += 100;
  195. break;
  196. case MmLargeSystem :
  197. PsMinimumWorkingSet += 30;
  198. PsMaximumWorkingSet += 300;
  199. break;
  200. case MmSmallSystem :
  201. default:
  202. break;
  203. }
  204. //
  205. // Initialize all the callback structures
  206. //
  207. for (i = 0; i < PSP_MAX_CREATE_THREAD_NOTIFY; i++) {
  208. ExInitializeCallBack (&PspCreateThreadNotifyRoutine[i]);
  209. }
  210. for (i = 0; i < PSP_MAX_CREATE_PROCESS_NOTIFY; i++) {
  211. ExInitializeCallBack (&PspCreateProcessNotifyRoutine[i]);
  212. }
  213. for (i = 0; i < PSP_MAX_LOAD_IMAGE_NOTIFY; i++) {
  214. ExInitializeCallBack (&PspLoadImageNotifyRoutine[i]);
  215. }
  216. PsChangeQuantumTable(FALSE,PsRawPrioritySeparation);
  217. //
  218. // Quotas grow as needed automatically
  219. //
  220. // if ( !PspDefaultPagedLimit ) {
  221. // PspDefaultPagedLimit = 0;
  222. // }
  223. // if ( !PspDefaultNonPagedLimit ) {
  224. // PspDefaultNonPagedLimit = 0;
  225. // }
  226. if (PspDefaultNonPagedLimit == 0 && PspDefaultPagedLimit == 0) {
  227. PspDoingGiveBacks = TRUE;
  228. } else {
  229. PspDoingGiveBacks = FALSE;
  230. }
  231. PspDefaultPagedLimit *= PSP_1MB;
  232. PspDefaultNonPagedLimit *= PSP_1MB;
  233. if (PspDefaultPagefileLimit != -1) {
  234. PspDefaultPagefileLimit *= PSP_1MB;
  235. }
  236. //
  237. // Initialize active process list head and mutex
  238. //
  239. InitializeListHead(&PsActiveProcessHead);
  240. ExInitializeFastMutex(&PspActiveProcessMutex);
  241. //
  242. // Initialize the process security fields lock
  243. //
  244. PsIdleProcess = PsGetCurrentProcess();
  245. PspInitializeProcessLock (PsIdleProcess);
  246. ExInitializeRundownProtection (&PsIdleProcess->RundownProtect);
  247. InitializeListHead (&PsIdleProcess->ThreadListHead);
  248. PsIdleProcess->Pcb.KernelTime = 0;
  249. PsIdleProcess->Pcb.KernelTime = 0;
  250. //
  251. // Initialize the shutdown thread pointer
  252. //
  253. PspShutdownThread = NULL;
  254. //
  255. // Initialize the common fields of the Object Type Prototype record
  256. //
  257. RtlZeroMemory( &ObjectTypeInitializer, sizeof( ObjectTypeInitializer ) );
  258. ObjectTypeInitializer.Length = sizeof( ObjectTypeInitializer );
  259. ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
  260. ObjectTypeInitializer.SecurityRequired = TRUE;
  261. ObjectTypeInitializer.PoolType = NonPagedPool;
  262. ObjectTypeInitializer.InvalidAttributes = OBJ_PERMANENT |
  263. OBJ_EXCLUSIVE |
  264. OBJ_OPENIF;
  265. //
  266. // Create Object types for Thread and Process Objects.
  267. //
  268. RtlInitUnicodeString(&NameString, L"Process");
  269. ObjectTypeInitializer.DefaultPagedPoolCharge = PSP_PROCESS_PAGED_CHARGE;
  270. ObjectTypeInitializer.DefaultNonPagedPoolCharge = PSP_PROCESS_NONPAGED_CHARGE;
  271. ObjectTypeInitializer.DeleteProcedure = PspProcessDelete;
  272. ObjectTypeInitializer.ValidAccessMask = PROCESS_ALL_ACCESS;
  273. ObjectTypeInitializer.GenericMapping = PspProcessMapping;
  274. if ( !NT_SUCCESS(ObCreateObjectType(&NameString,
  275. &ObjectTypeInitializer,
  276. (PSECURITY_DESCRIPTOR) NULL,
  277. &PsProcessType
  278. )) ){
  279. return FALSE;
  280. }
  281. RtlInitUnicodeString(&NameString, L"Thread");
  282. ObjectTypeInitializer.DefaultPagedPoolCharge = PSP_THREAD_PAGED_CHARGE;
  283. ObjectTypeInitializer.DefaultNonPagedPoolCharge = PSP_THREAD_NONPAGED_CHARGE;
  284. ObjectTypeInitializer.DeleteProcedure = PspThreadDelete;
  285. ObjectTypeInitializer.ValidAccessMask = THREAD_ALL_ACCESS;
  286. ObjectTypeInitializer.GenericMapping = PspThreadMapping;
  287. if ( !NT_SUCCESS(ObCreateObjectType(&NameString,
  288. &ObjectTypeInitializer,
  289. (PSECURITY_DESCRIPTOR) NULL,
  290. &PsThreadType
  291. )) ){
  292. return FALSE;
  293. }
  294. RtlInitUnicodeString(&NameString, L"Job");
  295. ObjectTypeInitializer.DefaultPagedPoolCharge = 0;
  296. ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(EJOB);
  297. ObjectTypeInitializer.DeleteProcedure = PspJobDelete;
  298. ObjectTypeInitializer.CloseProcedure = PspJobClose;
  299. ObjectTypeInitializer.ValidAccessMask = JOB_OBJECT_ALL_ACCESS;
  300. ObjectTypeInitializer.GenericMapping = PspJobMapping;
  301. ObjectTypeInitializer.InvalidAttributes = 0;
  302. if ( !NT_SUCCESS(ObCreateObjectType(&NameString,
  303. &ObjectTypeInitializer,
  304. (PSECURITY_DESCRIPTOR) NULL,
  305. &PsJobType
  306. )) ){
  307. return FALSE;
  308. }
  309. //
  310. // Initialize job list head and mutex
  311. //
  312. PspInitializeJobStructures();
  313. InitializeListHead(&PspWorkingSetChangeHead.Links);
  314. ExInitializeFastMutex(&PspWorkingSetChangeHead.Lock);
  315. //
  316. // Initialize CID handle table.
  317. //
  318. // N.B. The CID handle table is removed from the handle table list so
  319. // it will not be enumerated for object handle queries.
  320. //
  321. PspCidTable = ExCreateHandleTable(NULL);
  322. if (PspCidTable == NULL) {
  323. return FALSE;
  324. }
  325. //
  326. // Set PID and TID reuse to strict FIFO. This isn't absolutely needed but
  327. // it makes tracking audits easier.
  328. //
  329. ExSetHandleTableStrictFIFO (PspCidTable);
  330. ExRemoveHandleTable(PspCidTable);
  331. #if defined(i386)
  332. //
  333. // Ldt Initialization
  334. //
  335. if ( !NT_SUCCESS(PspLdtInitialize()) ) {
  336. return FALSE;
  337. }
  338. //
  339. // Vdm support Initialization
  340. //
  341. if ( !NT_SUCCESS(PspVdmInitialize()) ) {
  342. return FALSE;
  343. }
  344. #endif
  345. //
  346. // Initialize Reaper Data Structures
  347. //
  348. PsReaperList = NULL;
  349. PsReaperActive = FALSE;
  350. ExInitializeWorkItem(&PsReaperWorkItem, PspReaper, NULL);
  351. //
  352. // Get a pointer to the system access token.
  353. // This token is used by the boot process, so we can take the pointer
  354. // from there.
  355. //
  356. PspBootAccessToken = ExFastRefGetObject (PsIdleProcess->Token);
  357. InitializeObjectAttributes( &ObjectAttributes,
  358. NULL,
  359. 0,
  360. NULL,
  361. NULL
  362. );
  363. if (!NT_SUCCESS (PspCreateProcess (&PspInitialSystemProcessHandle,
  364. PROCESS_ALL_ACCESS,
  365. &ObjectAttributes,
  366. NULL,
  367. 0,
  368. NULL,
  369. NULL,
  370. NULL,
  371. 0))) {
  372. return FALSE;
  373. }
  374. if ( !NT_SUCCESS(ObReferenceObjectByHandle(
  375. PspInitialSystemProcessHandle,
  376. 0L,
  377. PsProcessType,
  378. KernelMode,
  379. (PVOID *)&PsInitialSystemProcess,
  380. NULL
  381. )) ) {
  382. return FALSE;
  383. }
  384. strcpy((char *) &PsIdleProcess->ImageFileName[0],"Idle");
  385. strcpy((char *) &PsInitialSystemProcess->ImageFileName[0],"System");
  386. //
  387. // The system process can allocate resources, and its name may be queried by
  388. // NtQueryInfomationProcess and various audits. We must explicitly allocate memory
  389. // for this field of the System EPROCESS, and initialize it appropriately. In this
  390. // case, appropriate initialization means zeroing the memory.
  391. //
  392. PsInitialSystemProcess->SeAuditProcessCreationInfo.ImageFileName = ExAllocatePoolWithTag(
  393. PagedPool,
  394. sizeof(OBJECT_NAME_INFORMATION),
  395. 'aPeS'
  396. );
  397. if (PsInitialSystemProcess->SeAuditProcessCreationInfo.ImageFileName != NULL) {
  398. RtlZeroMemory(
  399. PsInitialSystemProcess->SeAuditProcessCreationInfo.ImageFileName,
  400. sizeof(OBJECT_NAME_INFORMATION)
  401. );
  402. } else {
  403. return FALSE;
  404. }
  405. //
  406. // Phase 1 System initialization
  407. //
  408. if ( !NT_SUCCESS(PsCreateSystemThread(
  409. &ThreadHandle,
  410. THREAD_ALL_ACCESS,
  411. &ObjectAttributes,
  412. 0L,
  413. NULL,
  414. Phase1Initialization,
  415. (PVOID)LoaderBlock
  416. )) ) {
  417. return FALSE;
  418. }
  419. if ( !NT_SUCCESS(ObReferenceObjectByHandle(
  420. ThreadHandle,
  421. 0L,
  422. PsThreadType,
  423. KernelMode,
  424. (PVOID *)&Thread,
  425. NULL
  426. )) ) {
  427. return FALSE;
  428. }
  429. ZwClose( ThreadHandle );
  430. //
  431. // On checked systems install an image callout routine
  432. //
  433. #if DBG
  434. Status = PsSetLoadImageNotifyRoutine (PspImageNotifyTest);
  435. if (!NT_SUCCESS (Status)) {
  436. return FALSE;
  437. }
  438. #endif
  439. return TRUE;
  440. }
  441. BOOLEAN
  442. PspInitPhase1 (
  443. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  444. )
  445. /*++
  446. Routine Description:
  447. This routine performs phase 1 process structure initialization.
  448. During this phase, the system DLL is located and relevant entry
  449. points are extracted.
  450. Arguments:
  451. None.
  452. Return Value:
  453. TRUE - Initialization was successful.
  454. FALSE - Initialization Failed.
  455. --*/
  456. {
  457. NTSTATUS st;
  458. UNREFERENCED_PARAMETER (LoaderBlock);
  459. PspInitializeJobStructuresPhase1();
  460. st = PspInitializeSystemDll();
  461. if ( !NT_SUCCESS(st) ) {
  462. return FALSE;
  463. }
  464. return TRUE;
  465. }
  466. NTSTATUS
  467. PsLocateSystemDll (
  468. VOID
  469. )
  470. /*++
  471. Routine Description:
  472. This function locates the system dll and creates a section for the
  473. DLL and maps it into the system process.
  474. Arguments:
  475. None.
  476. Return Value:
  477. TRUE - Initialization was successful.
  478. FALSE - Initialization Failed.
  479. --*/
  480. {
  481. HANDLE File;
  482. HANDLE Section;
  483. NTSTATUS st;
  484. OBJECT_ATTRIBUTES ObjectAttributes;
  485. IO_STATUS_BLOCK IoStatus;
  486. //
  487. // First see if we need to load this DLL at all.
  488. //
  489. if (ExVerifySuite (EmbeddedNT) && (PsEmbeddedNTMask&PS_EMBEDDED_NO_USERMODE)) {
  490. return STATUS_SUCCESS;
  491. }
  492. //
  493. // Initialize the system DLL
  494. //
  495. InitializeObjectAttributes(
  496. &ObjectAttributes,
  497. (PUNICODE_STRING)&PsNtDllPathName,
  498. OBJ_CASE_INSENSITIVE,
  499. NULL,
  500. NULL
  501. );
  502. st = ZwOpenFile(
  503. &File,
  504. SYNCHRONIZE | FILE_EXECUTE,
  505. &ObjectAttributes,
  506. &IoStatus,
  507. FILE_SHARE_READ,
  508. 0
  509. );
  510. if (!NT_SUCCESS(st)) {
  511. #if DBG
  512. DbgPrint("PS: PsLocateSystemDll - NtOpenFile( NTDLL.DLL ) failed. Status == %lx\n",
  513. st
  514. );
  515. #endif
  516. KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED,st,2,0,0);
  517. // return st;
  518. }
  519. st = MmCheckSystemImage(File, TRUE);
  520. if ( st == STATUS_IMAGE_CHECKSUM_MISMATCH ||
  521. st == STATUS_INVALID_IMAGE_PROTECT ) {
  522. ULONG_PTR ErrorParameters;
  523. ULONG ErrorResponse;
  524. //
  525. // Hard error time. A driver is corrupt.
  526. //
  527. ErrorParameters = (ULONG_PTR)&PsNtDllPathName;
  528. NtRaiseHardError(
  529. st,
  530. 1,
  531. 1,
  532. &ErrorParameters,
  533. OptionOk,
  534. &ErrorResponse
  535. );
  536. return st;
  537. }
  538. st = ZwCreateSection(
  539. &Section,
  540. SECTION_ALL_ACCESS,
  541. NULL,
  542. 0,
  543. PAGE_EXECUTE,
  544. SEC_IMAGE,
  545. File
  546. );
  547. ZwClose( File );
  548. if (!NT_SUCCESS(st)) {
  549. #if DBG
  550. DbgPrint("PS: PsLocateSystemDll: NtCreateSection Status == %lx\n",st);
  551. #endif
  552. KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED,st,3,0,0);
  553. // return st;
  554. }
  555. //
  556. // Now that we have the section, reference it, store its address in the
  557. // PspSystemDll and then close handle to the section.
  558. //
  559. st = ObReferenceObjectByHandle(
  560. Section,
  561. SECTION_ALL_ACCESS,
  562. MmSectionObjectType,
  563. KernelMode,
  564. &PspSystemDll.Section,
  565. NULL
  566. );
  567. ZwClose(Section);
  568. if ( !NT_SUCCESS(st) ) {
  569. KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED,st,4,0,0);
  570. // return st;
  571. }
  572. //
  573. // Map the system dll into the user part of the address space
  574. //
  575. st = PspMapSystemDll(PsGetCurrentProcess(),&PspSystemDll.DllBase);
  576. PsSystemDllDllBase = PspSystemDll.DllBase;
  577. if ( !NT_SUCCESS(st) ) {
  578. KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED,st,5,0,0);
  579. // return st;
  580. }
  581. PsSystemDllBase = PspSystemDll.DllBase;
  582. return STATUS_SUCCESS;
  583. }
  584. NTSTATUS
  585. PspMapSystemDll (
  586. IN PEPROCESS Process,
  587. OUT PVOID *DllBase OPTIONAL
  588. )
  589. /*++
  590. Routine Description:
  591. This function maps the system DLL into the specified process.
  592. Arguments:
  593. Process - Supplies the address of the process to map the DLL into.
  594. Return Value:
  595. TBD
  596. --*/
  597. {
  598. NTSTATUS st;
  599. PVOID ViewBase;
  600. LARGE_INTEGER SectionOffset;
  601. SIZE_T ViewSize;
  602. PAGED_CODE();
  603. ViewBase = NULL;
  604. SectionOffset.LowPart = 0;
  605. SectionOffset.HighPart = 0;
  606. ViewSize = 0;
  607. //
  608. // Map the system dll into the user part of the address space
  609. //
  610. st = MmMapViewOfSection(
  611. PspSystemDll.Section,
  612. Process,
  613. &ViewBase,
  614. 0L,
  615. 0L,
  616. &SectionOffset,
  617. &ViewSize,
  618. ViewShare,
  619. 0L,
  620. PAGE_READWRITE
  621. );
  622. if ( st != STATUS_SUCCESS ) {
  623. #if DBG
  624. DbgPrint("PS: Unable to map system dll at based address.\n");
  625. #endif
  626. st = STATUS_CONFLICTING_ADDRESSES;
  627. }
  628. if ( ARGUMENT_PRESENT(DllBase) ) {
  629. *DllBase = ViewBase;
  630. }
  631. return st;
  632. }
  633. NTSTATUS
  634. PspInitializeSystemDll (
  635. VOID
  636. )
  637. /*++
  638. Routine Description:
  639. This function initializes the system DLL and locates
  640. various entrypoints within the DLL.
  641. Arguments:
  642. None.
  643. Return Value:
  644. TBD
  645. --*/
  646. {
  647. NTSTATUS st;
  648. PSZ dll_entrypoint;
  649. //
  650. // If we skipped dll load becuase we are kernel only then exit now.
  651. //
  652. if (PsSystemDllDllBase == NULL) {
  653. return STATUS_SUCCESS;
  654. }
  655. //
  656. // Locate the important system dll entrypoints
  657. //
  658. dll_entrypoint = "LdrInitializeThunk";
  659. st = PspLookupSystemDllEntryPoint(
  660. dll_entrypoint,
  661. (PVOID *)&PspSystemDll.LoaderInitRoutine
  662. );
  663. if ( !NT_SUCCESS(st) ) {
  664. #if DBG
  665. DbgPrint("PS: Unable to locate LdrInitializeThunk in system dll\n");
  666. #endif
  667. KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED,st,6,0,0);
  668. // return st;
  669. }
  670. st = PspLookupKernelUserEntryPoints();
  671. if ( !NT_SUCCESS(st) ) {
  672. KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED,st,8,0,0);
  673. }
  674. KdUpdateDataBlock();
  675. return st;
  676. }
  677. NTSTATUS
  678. PspLookupSystemDllEntryPoint (
  679. IN PSZ NameOfEntryPoint,
  680. OUT PVOID *AddressOfEntryPoint
  681. )
  682. {
  683. return LookupEntryPoint (
  684. PspSystemDll.DllBase,
  685. NameOfEntryPoint,
  686. AddressOfEntryPoint
  687. );
  688. }
  689. const SCHAR PspFixedQuantums[6] = {
  690. 3*THREAD_QUANTUM,
  691. 3*THREAD_QUANTUM,
  692. 3*THREAD_QUANTUM,
  693. 6*THREAD_QUANTUM,
  694. 6*THREAD_QUANTUM,
  695. 6*THREAD_QUANTUM
  696. };
  697. const SCHAR PspVariableQuantums[6] = {
  698. 1*THREAD_QUANTUM,
  699. 2*THREAD_QUANTUM,
  700. 3*THREAD_QUANTUM,
  701. 2*THREAD_QUANTUM,
  702. 4*THREAD_QUANTUM,
  703. 6*THREAD_QUANTUM
  704. };
  705. //
  706. // The table is ONLY used when fixed quantums are selected.
  707. //
  708. const SCHAR PspJobSchedulingClasses[PSP_NUMBER_OF_SCHEDULING_CLASSES] = {
  709. 1*THREAD_QUANTUM, // long fixed 0
  710. 2*THREAD_QUANTUM, // long fixed 1...
  711. 3*THREAD_QUANTUM,
  712. 4*THREAD_QUANTUM,
  713. 5*THREAD_QUANTUM,
  714. 6*THREAD_QUANTUM, // DEFAULT
  715. 7*THREAD_QUANTUM,
  716. 8*THREAD_QUANTUM,
  717. 9*THREAD_QUANTUM,
  718. 10*THREAD_QUANTUM // long fixed 9
  719. };
  720. VOID
  721. PsChangeQuantumTable(
  722. BOOLEAN ModifyActiveProcesses,
  723. ULONG PrioritySeparation
  724. )
  725. {
  726. PEPROCESS Process;
  727. PETHREAD CurrentThread;
  728. PLIST_ENTRY NextProcess;
  729. ULONG QuantumIndex;
  730. SCHAR const* QuantumTableBase;
  731. PEJOB Job;
  732. //
  733. // extract priority seperation value
  734. //
  735. switch ( PrioritySeparation & PROCESS_PRIORITY_SEPARATION_MASK ) {
  736. case 3:
  737. PsPrioritySeperation = PROCESS_PRIORITY_SEPARATION_MAX;
  738. break;
  739. default:
  740. PsPrioritySeperation = PrioritySeparation & PROCESS_PRIORITY_SEPARATION_MASK;
  741. break;
  742. }
  743. //
  744. // determine if we are using fixed or variable quantums
  745. //
  746. switch ( PrioritySeparation & PROCESS_QUANTUM_VARIABLE_MASK ) {
  747. case PROCESS_QUANTUM_VARIABLE_VALUE:
  748. QuantumTableBase = PspVariableQuantums;
  749. break;
  750. case PROCESS_QUANTUM_FIXED_VALUE:
  751. QuantumTableBase = PspFixedQuantums;
  752. break;
  753. case PROCESS_QUANTUM_VARIABLE_DEF:
  754. default:
  755. if ( MmIsThisAnNtAsSystem() ) {
  756. QuantumTableBase = PspFixedQuantums;
  757. } else {
  758. QuantumTableBase = PspVariableQuantums;
  759. }
  760. break;
  761. }
  762. //
  763. // determine if we are using long or short
  764. //
  765. switch ( PrioritySeparation & PROCESS_QUANTUM_LONG_MASK ) {
  766. case PROCESS_QUANTUM_LONG_VALUE:
  767. QuantumTableBase = QuantumTableBase + 3;
  768. break;
  769. case PROCESS_QUANTUM_SHORT_VALUE:
  770. break;
  771. case PROCESS_QUANTUM_LONG_DEF:
  772. default:
  773. if ( MmIsThisAnNtAsSystem() ) {
  774. QuantumTableBase = QuantumTableBase + 3;
  775. }
  776. break;
  777. }
  778. //
  779. // Job Scheduling classes are ONLY meaningful if long fixed quantums
  780. // are selected. In practice, this means stock NTS configurations
  781. //
  782. if ( QuantumTableBase == &PspFixedQuantums[3] ) {
  783. PspUseJobSchedulingClasses = TRUE;
  784. } else {
  785. PspUseJobSchedulingClasses = FALSE;
  786. }
  787. RtlCopyMemory(PspForegroundQuantum,QuantumTableBase,sizeof(PspForegroundQuantum));
  788. if (ModifyActiveProcesses) {
  789. CurrentThread = PsGetCurrentThread ();
  790. PspLockProcessList (CurrentThread);
  791. NextProcess = PsActiveProcessHead.Flink;
  792. while (NextProcess != &PsActiveProcessHead) {
  793. Process = CONTAINING_RECORD(NextProcess,
  794. EPROCESS,
  795. ActiveProcessLinks);
  796. if ( Process->Vm.Flags.MemoryPriority == MEMORY_PRIORITY_BACKGROUND ) {
  797. QuantumIndex = 0;
  798. } else {
  799. QuantumIndex = PsPrioritySeperation;
  800. }
  801. if (Process->PriorityClass != PROCESS_PRIORITY_CLASS_IDLE) {
  802. //
  803. // If the process is contained within a JOB, AND we are
  804. // running Fixed, Long Quantums, use the quantum associated
  805. // with the Job's scheduling class
  806. //
  807. Job = Process->Job;
  808. if (Job != NULL && PspUseJobSchedulingClasses ) {
  809. Process->Pcb.ThreadQuantum = PspJobSchedulingClasses[Job->SchedulingClass];
  810. } else {
  811. Process->Pcb.ThreadQuantum = PspForegroundQuantum[QuantumIndex];
  812. }
  813. } else {
  814. Process->Pcb.ThreadQuantum = THREAD_QUANTUM;
  815. }
  816. NextProcess = NextProcess->Flink;
  817. }
  818. PspUnlockProcessList (CurrentThread);
  819. }
  820. }