2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ps/psmgr.c
5 * PURPOSE: Process Manager: Initialization Code
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
15 extern ULONG ExpInitializationPhase
;
16 extern BOOLEAN SysThreadCreated
;
18 PVOID KeUserPopEntrySListEnd
;
19 PVOID KeUserPopEntrySListFault
;
20 PVOID KeUserPopEntrySListResume
;
22 GENERIC_MAPPING PspProcessMapping
=
24 STANDARD_RIGHTS_READ
| PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
25 STANDARD_RIGHTS_WRITE
| PROCESS_CREATE_PROCESS
| PROCESS_CREATE_THREAD
|
26 PROCESS_VM_OPERATION
| PROCESS_VM_WRITE
| PROCESS_DUP_HANDLE
|
27 PROCESS_TERMINATE
| PROCESS_SET_QUOTA
| PROCESS_SET_INFORMATION
|
28 PROCESS_SUSPEND_RESUME
,
29 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
,
33 GENERIC_MAPPING PspThreadMapping
=
35 STANDARD_RIGHTS_READ
| THREAD_GET_CONTEXT
| THREAD_QUERY_INFORMATION
,
36 STANDARD_RIGHTS_WRITE
| THREAD_TERMINATE
| THREAD_SUSPEND_RESUME
|
37 THREAD_ALERT
| THREAD_SET_INFORMATION
| THREAD_SET_CONTEXT
,
38 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
,
42 PVOID PspSystemDllBase
;
43 PVOID PspSystemDllSection
;
44 PVOID PspSystemDllEntryPoint
;
46 UNICODE_STRING PsNtDllPathName
=
47 RTL_CONSTANT_STRING(L
"\\SystemRoot\\system32\\ntdll.dll");
49 PHANDLE_TABLE PspCidTable
;
51 PEPROCESS PsInitialSystemProcess
= NULL
;
52 PEPROCESS PsIdleProcess
= NULL
;
53 HANDLE PspInitialSystemProcessHandle
;
55 ULONG PsMinimumWorkingSet
, PsMaximumWorkingSet
;
60 } PspWorkingSetChangeHead
;
61 ULONG PspDefaultPagedLimit
, PspDefaultNonPagedLimit
, PspDefaultPagefileLimit
;
62 BOOLEAN PspDoingGiveBacks
;
64 /* PRIVATE FUNCTIONS *********************************************************/
69 NameToOrdinal(IN PCHAR Name
,
71 IN ULONG NumberOfNames
,
73 IN PUSHORT OrdinalTable
)
78 /* Fail if no names */
79 if (!NumberOfNames
) return -1;
81 /* Do binary search */
82 Mid
= NumberOfNames
>> 1;
83 Ret
= strcmp(Name
, (PCHAR
)((ULONG_PTR
)DllBase
+ NameTable
[Mid
]));
85 /* Check if we found it */
86 if (!Ret
) return OrdinalTable
[Mid
];
88 /* We didn't. Check if we only had one name to check */
89 if (NumberOfNames
== 1) return -1;
91 /* Check if we should look up or down */
99 /* Look up, update tables */
100 NameTable
= &NameTable
[Mid
+ 1];
101 OrdinalTable
= &OrdinalTable
[Mid
+ 1];
102 NumberOfNames
-= (Mid
- 1);
105 /* Call us recursively */
106 return NameToOrdinal(Name
, DllBase
, NumberOfNames
, NameTable
, OrdinalTable
);
112 LookupEntryPoint(IN PVOID DllBase
,
114 OUT PVOID
*EntryPoint
)
117 PUSHORT OrdinalTable
;
118 PIMAGE_EXPORT_DIRECTORY ExportDirectory
;
124 /* Get the export directory */
125 ExportDirectory
= RtlImageDirectoryEntryToData(DllBase
,
127 IMAGE_DIRECTORY_ENTRY_EXPORT
,
130 /* Validate the name and copy it */
131 if (strlen(Name
) > sizeof(Buffer
) - 2) return STATUS_INVALID_PARAMETER
;
132 strcpy(Buffer
, Name
);
134 /* Setup name tables */
135 NameTable
= (PULONG
)((ULONG_PTR
)DllBase
+
136 ExportDirectory
->AddressOfNames
);
137 OrdinalTable
= (PUSHORT
)((ULONG_PTR
)DllBase
+
138 ExportDirectory
->AddressOfNameOrdinals
);
140 /* Get the ordinal */
141 Ordinal
= NameToOrdinal(Buffer
,
143 ExportDirectory
->NumberOfNames
,
147 /* Make sure the ordinal is valid */
148 if (Ordinal
>= ExportDirectory
->NumberOfFunctions
)
151 return STATUS_PROCEDURE_NOT_FOUND
;
154 /* Resolve the address and write it */
155 ExportTable
= (PULONG
)((ULONG_PTR
)DllBase
+
156 ExportDirectory
->AddressOfFunctions
);
157 *EntryPoint
= (PVOID
)((ULONG_PTR
)DllBase
+ ExportTable
[Ordinal
]);
158 return STATUS_SUCCESS
;
164 PspLookupSystemDllEntryPoint(IN PCHAR Name
,
165 IN PVOID
*EntryPoint
)
167 /* Call the LDR Routine */
168 return LookupEntryPoint(PspSystemDllBase
, Name
, EntryPoint
);
174 PspLookupKernelUserEntryPoints(VOID
)
178 /* Get user-mode APC trampoline */
179 Status
= PspLookupSystemDllEntryPoint("KiUserApcDispatcher",
180 &KeUserApcDispatcher
);
181 if (!NT_SUCCESS(Status
)) return Status
;
183 /* Get user-mode exception dispatcher */
184 Status
= PspLookupSystemDllEntryPoint("KiUserExceptionDispatcher",
185 &KeUserExceptionDispatcher
);
186 if (!NT_SUCCESS(Status
)) return Status
;
188 /* Get user-mode callback dispatcher */
189 Status
= PspLookupSystemDllEntryPoint("KiUserCallbackDispatcher",
190 &KeUserCallbackDispatcher
);
191 if (!NT_SUCCESS(Status
)) return Status
;
193 /* Get user-mode exception raise trampoline */
194 Status
= PspLookupSystemDllEntryPoint("KiRaiseUserExceptionDispatcher",
195 &KeRaiseUserExceptionDispatcher
);
196 if (!NT_SUCCESS(Status
)) return Status
;
198 /* Get user-mode SLIST exception functions for page fault rollback race hack */
199 Status
= PspLookupSystemDllEntryPoint("ExpInterlockedPopEntrySListEnd",
200 &KeUserPopEntrySListEnd
);
201 if (!NT_SUCCESS(Status
)) { DPRINT1("this not found\n"); return Status
; }
202 Status
= PspLookupSystemDllEntryPoint("ExpInterlockedPopEntrySListFault",
203 &KeUserPopEntrySListFault
);
204 if (!NT_SUCCESS(Status
)) { DPRINT1("this not found\n"); return Status
; }
205 Status
= PspLookupSystemDllEntryPoint("ExpInterlockedPopEntrySListResume",
206 &KeUserPopEntrySListResume
);
207 if (!NT_SUCCESS(Status
)) { DPRINT1("this not found\n"); return Status
; }
209 /* On x86, there are multiple ways to do a system call, find the right stubs */
211 /* Check if this is a machine that supports SYSENTER */
212 if (KeFeatureBits
& KF_FAST_SYSCALL
)
214 /* Get user-mode sysenter stub */
215 SharedUserData
->SystemCall
= (PsNtosImageBase
>> (PAGE_SHIFT
+ 1));
216 Status
= PspLookupSystemDllEntryPoint("KiFastSystemCall",
217 (PVOID
)&SharedUserData
->
219 if (!NT_SUCCESS(Status
)) return Status
;
221 /* Get user-mode sysenter return stub */
222 Status
= PspLookupSystemDllEntryPoint("KiFastSystemCallRet",
223 (PVOID
)&SharedUserData
->
225 if (!NT_SUCCESS(Status
)) return Status
;
229 /* Get the user-mode interrupt stub */
230 Status
= PspLookupSystemDllEntryPoint("KiIntSystemCall",
231 (PVOID
)&SharedUserData
->
233 if (!NT_SUCCESS(Status
)) return Status
;
236 /* Set the test instruction */
237 SharedUserData
->TestRetInstruction
= 0xC3;
240 /* Return the status */
247 PspMapSystemDll(IN PEPROCESS Process
,
249 IN BOOLEAN UseLargePages
)
252 LARGE_INTEGER Offset
= {{0, 0}};
256 /* Map the System DLL */
257 Status
= MmMapViewOfSection(PspSystemDllSection
,
267 if (Status
!= STATUS_SUCCESS
)
269 /* Normalize status code */
270 Status
= STATUS_CONFLICTING_ADDRESSES
;
273 /* Write the image base and return status */
274 if (DllBase
) *DllBase
= ImageBase
;
281 PsLocateSystemDll(VOID
)
283 OBJECT_ATTRIBUTES ObjectAttributes
;
284 IO_STATUS_BLOCK IoStatusBlock
;
285 HANDLE FileHandle
, SectionHandle
;
287 ULONG_PTR HardErrorParameters
;
288 ULONG HardErrorResponse
;
290 /* Locate and open NTDLL to determine ImageBase and LdrStartup */
291 InitializeObjectAttributes(&ObjectAttributes
,
296 Status
= ZwOpenFile(&FileHandle
,
302 if (!NT_SUCCESS(Status
))
304 /* Failed, bugcheck */
305 KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED
, Status
, 2, 0, 0);
308 /* Check if the image is valid */
309 Status
= MmCheckSystemImage(FileHandle
, TRUE
);
310 if (Status
== STATUS_IMAGE_CHECKSUM_MISMATCH
)
312 /* Raise a hard error */
313 HardErrorParameters
= (ULONG_PTR
)&PsNtDllPathName
;
314 NtRaiseHardError(Status
,
317 &HardErrorParameters
,
323 /* Create a section for NTDLL */
324 Status
= ZwCreateSection(&SectionHandle
,
332 if (!NT_SUCCESS(Status
))
334 /* Failed, bugcheck */
335 KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED
, Status
, 3, 0, 0);
338 /* Reference the Section */
339 Status
= ObReferenceObjectByHandle(SectionHandle
,
343 (PVOID
*)&PspSystemDllSection
,
345 ZwClose(SectionHandle
);
346 if (!NT_SUCCESS(Status
))
348 /* Failed, bugcheck */
349 KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED
, Status
, 4, 0, 0);
353 Status
= PspMapSystemDll(PsGetCurrentProcess(), &PspSystemDllBase
, FALSE
);
354 if (!NT_SUCCESS(Status
))
356 /* Failed, bugcheck */
357 KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED
, Status
, 5, 0, 0);
367 PspInitializeSystemDll(VOID
)
371 /* Get user-mode startup thunk */
372 Status
= PspLookupSystemDllEntryPoint("LdrInitializeThunk",
373 &PspSystemDllEntryPoint
);
374 if (!NT_SUCCESS(Status
))
376 /* Failed, bugcheck */
377 KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED
, Status
, 7, 0, 0);
380 /* Get all the other entrypoints */
381 Status
= PspLookupKernelUserEntryPoints();
382 if (!NT_SUCCESS(Status
))
384 /* Failed, bugcheck */
385 KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED
, Status
, 8, 0, 0);
389 /* Let KD know we are done */
402 /* Initialize the System DLL and return status of operation */
403 if (!NT_SUCCESS(PspInitializeSystemDll())) return FALSE
;
410 PspInitPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
413 OBJECT_ATTRIBUTES ObjectAttributes
;
414 HANDLE SysThreadHandle
;
416 MM_SYSTEMSIZE SystemSize
;
418 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
421 /* Get the system size */
422 SystemSize
= MmQuerySystemSize();
424 /* Setup some memory options */
425 PspDefaultPagefileLimit
= -1;
428 /* Medimum systems */
431 /* Increase the WS sizes a bit */
432 PsMinimumWorkingSet
+= 10;
433 PsMaximumWorkingSet
+= 100;
438 /* Increase the WS sizes a bit more */
439 PsMinimumWorkingSet
+= 30;
440 PsMaximumWorkingSet
+= 300;
442 /* Small and other systems */
447 /* Setup callbacks */
448 for (i
= 0; i
< PSP_MAX_CREATE_THREAD_NOTIFY
; i
++)
450 ExInitializeCallBack(&PspThreadNotifyRoutine
[i
]);
452 for (i
= 0; i
< PSP_MAX_CREATE_PROCESS_NOTIFY
; i
++)
454 ExInitializeCallBack(&PspProcessNotifyRoutine
[i
]);
456 for (i
= 0; i
< PSP_MAX_LOAD_IMAGE_NOTIFY
; i
++)
458 ExInitializeCallBack(&PspLoadImageNotifyRoutine
[i
]);
461 /* Setup the quantum table */
462 PsChangeQuantumTable(FALSE
, PsRawPrioritySeparation
);
464 /* Set quota settings */
465 if (!PspDefaultPagedLimit
) PspDefaultPagedLimit
= 0;
466 if (!PspDefaultNonPagedLimit
) PspDefaultNonPagedLimit
= 0;
467 if (!(PspDefaultNonPagedLimit
) && !(PspDefaultPagedLimit
))
469 /* Enable give-backs */
470 PspDoingGiveBacks
= TRUE
;
475 PspDoingGiveBacks
= FALSE
;
478 /* Now multiply limits by 1MB */
479 PspDefaultPagedLimit
<<= 20;
480 PspDefaultNonPagedLimit
<<= 20;
481 if (PspDefaultPagefileLimit
!= MAXULONG
) PspDefaultPagefileLimit
<<= 20;
483 /* Initialize the Active Process List */
484 InitializeListHead(&PsActiveProcessHead
);
485 KeInitializeGuardedMutex(&PspActiveProcessMutex
);
487 /* Get the idle process */
488 PsIdleProcess
= PsGetCurrentProcess();
490 /* Setup the locks */
491 PsIdleProcess
->ProcessLock
.Value
= 0;
492 ExInitializeRundownProtection(&PsIdleProcess
->RundownProtect
);
494 /* Initialize the thread list */
495 InitializeListHead(&PsIdleProcess
->ThreadListHead
);
497 /* Clear kernel time */
498 PsIdleProcess
->Pcb
.KernelTime
= 0;
500 /* Initialize Object Initializer */
501 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
502 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
503 ObjectTypeInitializer
.InvalidAttributes
= OBJ_OPENLINK
|
507 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
508 ObjectTypeInitializer
.SecurityRequired
= TRUE
;
510 /* Initialize the Process type */
511 RtlInitUnicodeString(&Name
, L
"Process");
512 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(EPROCESS
);
513 ObjectTypeInitializer
.GenericMapping
= PspProcessMapping
;
514 ObjectTypeInitializer
.ValidAccessMask
= PROCESS_ALL_ACCESS
;
515 ObjectTypeInitializer
.DeleteProcedure
= PspDeleteProcess
;
516 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &PsProcessType
);
518 /* Initialize the Thread type */
519 RtlInitUnicodeString(&Name
, L
"Thread");
520 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
521 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(ETHREAD
);
522 ObjectTypeInitializer
.GenericMapping
= PspThreadMapping
;
523 ObjectTypeInitializer
.ValidAccessMask
= THREAD_ALL_ACCESS
;
524 ObjectTypeInitializer
.DeleteProcedure
= PspDeleteThread
;
525 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &PsThreadType
);
527 /* Initialize the Job type */
528 RtlInitUnicodeString(&Name
, L
"Job");
529 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
530 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(EJOB
);
531 ObjectTypeInitializer
.GenericMapping
= PspJobMapping
;
532 ObjectTypeInitializer
.ValidAccessMask
= JOB_OBJECT_ALL_ACCESS
;
533 ObjectTypeInitializer
.DeleteProcedure
= PspDeleteJob
;
534 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &PsJobType
);
536 /* Initialize job structures external to this file */
537 PspInitializeJobStructures();
539 /* Initialize the Working Set data */
540 InitializeListHead(&PspWorkingSetChangeHead
.List
);
541 KeInitializeGuardedMutex(&PspWorkingSetChangeHead
.Lock
);
543 /* Create the CID Handle table */
544 PspCidTable
= ExCreateHandleTable(NULL
);
545 if (!PspCidTable
) return FALSE
;
547 /* FIXME: Initialize LDT/VDM support */
549 /* Setup the reaper */
550 ExInitializeWorkItem(&PspReaperWorkItem
, PspReapRoutine
, NULL
);
552 /* Set the boot access token */
553 PspBootAccessToken
= (PTOKEN
)(PsIdleProcess
->Token
.Value
& ~MAX_FAST_REFS
);
555 /* Setup default object attributes */
556 InitializeObjectAttributes(&ObjectAttributes
,
562 /* Create the Initial System Process */
563 Status
= PspCreateProcess(&PspInitialSystemProcessHandle
,
572 if (!NT_SUCCESS(Status
)) return FALSE
;
574 /* Get a reference to it */
575 ObReferenceObjectByHandle(PspInitialSystemProcessHandle
,
579 (PVOID
*)&PsInitialSystemProcess
,
582 /* Copy the process names */
583 strcpy(PsIdleProcess
->ImageFileName
, "Idle");
584 strcpy(PsInitialSystemProcess
->ImageFileName
, "System");
586 /* Allocate a structure for the audit name */
587 PsInitialSystemProcess
->SeAuditProcessCreationInfo
.ImageFileName
=
588 ExAllocatePoolWithTag(PagedPool
,
589 sizeof(OBJECT_NAME_INFORMATION
),
591 if (!PsInitialSystemProcess
->SeAuditProcessCreationInfo
.ImageFileName
)
593 /* Allocation failed */
598 RtlZeroMemory(PsInitialSystemProcess
->
599 SeAuditProcessCreationInfo
.ImageFileName
,
600 sizeof(OBJECT_NAME_INFORMATION
));
602 /* Setup the system initialization thread */
603 Status
= PsCreateSystemThread(&SysThreadHandle
,
608 Phase1Initialization
,
610 if (!NT_SUCCESS(Status
)) return FALSE
;
612 /* Create a handle to it */
613 ObReferenceObjectByHandle(SysThreadHandle
,
619 ObCloseHandle(SysThreadHandle
, KernelMode
);
620 SysThreadCreated
= TRUE
;
629 PsInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
631 /* Check the initialization phase */
632 switch (ExpInitializationPhase
)
637 return PspInitPhase0(LoaderBlock
);
642 return PspInitPhase1();
646 /* Don't know any other phase! Bugcheck! */
647 KeBugCheckEx(UNEXPECTED_INITIALIZATION_CALL
,
649 ExpInitializationPhase
,
656 /* PUBLIC FUNCTIONS **********************************************************/
663 PsGetVersion(IN PULONG MajorVersion OPTIONAL
,
664 IN PULONG MinorVersion OPTIONAL
,
665 IN PULONG BuildNumber OPTIONAL
,
666 IN PUNICODE_STRING CSDVersion OPTIONAL
)
668 if (MajorVersion
) *MajorVersion
= NtMajorVersion
;
669 if (MinorVersion
) *MinorVersion
= NtMinorVersion
;
670 if (BuildNumber
) *BuildNumber
= NtBuildNumber
;
674 CSDVersion
->Length
= 0;
675 CSDVersion
->MaximumLength
= 0;
676 CSDVersion
->Buffer
= NULL
;
678 CSDVersion
->Length
= CmCSDVersionString
.Length
;
679 CSDVersion
->MaximumLength
= CmCSDVersionString
.Maximum
;
680 CSDVersion
->Buffer
= CmCSDVersionString
.Buffer
;
684 /* Check the High word */
685 return (NtBuildNumber
>> 28) == 0xC;
690 NtApphelpCacheControl(IN APPHELPCACHESERVICECLASS Service
,
691 IN PVOID ServiceData
)
694 return STATUS_NOT_IMPLEMENTED
;