Leaked source code of windows server 2003
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.

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