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 GENERIC_MAPPING PspProcessMapping
=
20 STANDARD_RIGHTS_READ
| PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
21 STANDARD_RIGHTS_WRITE
| PROCESS_CREATE_PROCESS
| PROCESS_CREATE_THREAD
|
22 PROCESS_VM_OPERATION
| PROCESS_VM_WRITE
| PROCESS_DUP_HANDLE
|
23 PROCESS_TERMINATE
| PROCESS_SET_QUOTA
| PROCESS_SET_INFORMATION
|
24 PROCESS_SUSPEND_RESUME
,
25 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
,
29 GENERIC_MAPPING PspThreadMapping
=
31 STANDARD_RIGHTS_READ
| THREAD_GET_CONTEXT
| THREAD_QUERY_INFORMATION
,
32 STANDARD_RIGHTS_WRITE
| THREAD_TERMINATE
| THREAD_SUSPEND_RESUME
|
33 THREAD_ALERT
| THREAD_SET_INFORMATION
| THREAD_SET_CONTEXT
,
34 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
,
38 PVOID PspSystemDllBase
;
39 PVOID PspSystemDllSection
;
40 PVOID PspSystemDllEntryPoint
;
42 UNICODE_STRING PsNtDllPathName
=
43 RTL_CONSTANT_STRING(L
"\\SystemRoot\\system32\\ntdll.dll");
45 PHANDLE_TABLE PspCidTable
;
47 PEPROCESS PsInitialSystemProcess
= NULL
;
48 PEPROCESS PsIdleProcess
= NULL
;
49 HANDLE PspInitialSystemProcessHandle
;
51 ULONG PsMinimumWorkingSet
, PsMaximumWorkingSet
;
56 } PspWorkingSetChangeHead
;
57 ULONG PspDefaultPagedLimit
, PspDefaultNonPagedLimit
, PspDefaultPagefileLimit
;
58 BOOLEAN PspDoingGiveBacks
;
60 /* PRIVATE FUNCTIONS *********************************************************/
64 NameToOrdinal(IN PCHAR Name
,
66 IN ULONG NumberOfNames
,
68 IN PUSHORT OrdinalTable
)
73 /* Fail if no names */
74 if (!NumberOfNames
) return -1;
76 /* Do binary search */
77 Mid
= NumberOfNames
>> 1;
78 Ret
= strcmp(Name
, (PCHAR
)((ULONG_PTR
)DllBase
+ NameTable
[Mid
]));
80 /* Check if we found it */
81 if (!Ret
) return OrdinalTable
[Mid
];
83 /* We didn't. Check if we only had one name to check */
84 if (NumberOfNames
== 1) return -1;
86 /* Check if we should look up or down */
94 /* Look up, update tables */
95 NameTable
= &NameTable
[Mid
+ 1];
96 OrdinalTable
= &OrdinalTable
[Mid
+ 1];
97 NumberOfNames
-= (Mid
- 1);
100 /* Call us recursively */
101 return NameToOrdinal(Name
, DllBase
, NumberOfNames
, NameTable
, OrdinalTable
);
106 LookupEntryPoint(IN PVOID DllBase
,
108 OUT PVOID
*EntryPoint
)
111 PUSHORT OrdinalTable
;
112 PIMAGE_EXPORT_DIRECTORY ExportDirectory
;
118 /* Get the export directory */
119 ExportDirectory
= RtlImageDirectoryEntryToData(DllBase
,
121 IMAGE_DIRECTORY_ENTRY_EXPORT
,
124 /* Validate the name and copy it */
125 if (strlen(Name
) > sizeof(Buffer
) - 2) return STATUS_INVALID_PARAMETER
;
126 strcpy(Buffer
, Name
);
128 /* Setup name tables */
129 NameTable
= (PULONG
)((ULONG_PTR
)DllBase
+
130 ExportDirectory
->AddressOfNames
);
131 OrdinalTable
= (PUSHORT
)((ULONG_PTR
)DllBase
+
132 ExportDirectory
->AddressOfNameOrdinals
);
134 /* Get the ordinal */
135 Ordinal
= NameToOrdinal(Buffer
,
137 ExportDirectory
->NumberOfNames
,
141 /* Make sure the ordinal is valid */
142 if (Ordinal
>= ExportDirectory
->NumberOfFunctions
)
145 return STATUS_PROCEDURE_NOT_FOUND
;
148 /* Resolve the address and write it */
149 ExportTable
= (PULONG
)((ULONG_PTR
)DllBase
+
150 ExportDirectory
->AddressOfFunctions
);
151 *EntryPoint
= (PVOID
)((ULONG_PTR
)DllBase
+ ExportTable
[Ordinal
]);
152 return STATUS_SUCCESS
;
157 PspLookupSystemDllEntryPoint(IN PCHAR Name
,
158 IN PVOID
*EntryPoint
)
160 /* Call the LDR Routine */
161 return LookupEntryPoint(PspSystemDllBase
, Name
, EntryPoint
);
166 PspLookupKernelUserEntryPoints(VOID
)
170 /* Get user-mode APC trampoline */
171 Status
= PspLookupSystemDllEntryPoint("KiUserApcDispatcher",
172 &KeUserApcDispatcher
);
173 if (!NT_SUCCESS(Status
)) return Status
;
175 /* Get user-mode exception dispatcher */
176 Status
= PspLookupSystemDllEntryPoint("KiUserExceptionDispatcher",
177 &KeUserExceptionDispatcher
);
178 if (!NT_SUCCESS(Status
)) return Status
;
180 /* Get user-mode callback dispatcher */
181 Status
= PspLookupSystemDllEntryPoint("KiUserCallbackDispatcher",
182 &KeUserCallbackDispatcher
);
183 if (!NT_SUCCESS(Status
)) return Status
;
185 /* Get user-mode exception raise trampoline */
186 Status
= PspLookupSystemDllEntryPoint("KiRaiseUserExceptionDispatcher",
187 &KeRaiseUserExceptionDispatcher
);
188 if (!NT_SUCCESS(Status
)) return Status
;
190 /* Check if this is a machine that supports SYSENTER */
191 if (KeFeatureBits
& KF_FAST_SYSCALL
)
193 /* Get user-mode sysenter stub */
194 Status
= PspLookupSystemDllEntryPoint("KiFastSystemCall",
195 (PVOID
)&SharedUserData
->
197 if (!NT_SUCCESS(Status
)) return Status
;
199 /* Get user-mode sysenter return stub */
200 Status
= PspLookupSystemDllEntryPoint("KiFastSystemCallRet",
201 (PVOID
)&SharedUserData
->
206 /* Get the user-mode interrupt stub */
207 Status
= PspLookupSystemDllEntryPoint("KiIntSystemCall",
208 (PVOID
)&SharedUserData
->
212 /* Set the test instruction */
213 if (!NT_SUCCESS(Status
)) SharedUserData
->TestRetInstruction
= 0xC3;
215 /* Return the status */
221 PspMapSystemDll(IN PEPROCESS Process
,
223 IN BOOLEAN UseLargePages
)
226 LARGE_INTEGER Offset
= {{0, 0}};
230 /* Map the System DLL */
231 Status
= MmMapViewOfSection(PspSystemDllSection
,
241 if (Status
!= STATUS_SUCCESS
)
243 /* Normalize status code */
244 Status
= STATUS_CONFLICTING_ADDRESSES
;
247 /* Write the image base and return status */
248 if (DllBase
) *DllBase
= ImageBase
;
254 PsLocateSystemDll(VOID
)
256 OBJECT_ATTRIBUTES ObjectAttributes
;
257 IO_STATUS_BLOCK IoStatusBlock
;
258 HANDLE FileHandle
, SectionHandle
;
260 ULONG_PTR HardErrorParameters
;
261 ULONG HardErrorResponse
;
263 /* Locate and open NTDLL to determine ImageBase and LdrStartup */
264 InitializeObjectAttributes(&ObjectAttributes
,
269 Status
= ZwOpenFile(&FileHandle
,
275 if (!NT_SUCCESS(Status
))
277 /* Failed, bugcheck */
278 KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED
, Status
, 2, 0, 0);
281 /* Check if the image is valid */
282 Status
= MmCheckSystemImage(FileHandle
, TRUE
);
283 if (Status
== STATUS_IMAGE_CHECKSUM_MISMATCH
)
285 /* Raise a hard error */
286 HardErrorParameters
= (ULONG_PTR
)&PsNtDllPathName
;
287 NtRaiseHardError(Status
,
290 &HardErrorParameters
,
296 /* Create a section for NTDLL */
297 Status
= ZwCreateSection(&SectionHandle
,
305 if (!NT_SUCCESS(Status
))
307 /* Failed, bugcheck */
308 KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED
, Status
, 3, 0, 0);
311 /* Reference the Section */
312 Status
= ObReferenceObjectByHandle(SectionHandle
,
316 (PVOID
*)&PspSystemDllSection
,
318 ZwClose(SectionHandle
);
319 if (!NT_SUCCESS(Status
))
321 /* Failed, bugcheck */
322 KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED
, Status
, 4, 0, 0);
326 Status
= PspMapSystemDll(PsGetCurrentProcess(), &PspSystemDllBase
, FALSE
);
327 if (!NT_SUCCESS(Status
))
329 /* Failed, bugcheck */
330 KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED
, Status
, 5, 0, 0);
339 PspInitializeSystemDll(VOID
)
343 /* Get user-mode startup thunk */
344 Status
= PspLookupSystemDllEntryPoint("LdrInitializeThunk",
345 &PspSystemDllEntryPoint
);
346 if (!NT_SUCCESS(Status
))
348 /* Failed, bugcheck */
349 KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED
, Status
, 7, 0, 0);
352 /* Get all the other entrypoints */
353 Status
= PspLookupKernelUserEntryPoints();
354 if (!NT_SUCCESS(Status
))
356 /* Failed, bugcheck */
357 KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED
, Status
, 8, 0, 0);
368 /* Initialize the System DLL and return status of operation */
369 if (!NT_SUCCESS(PspInitializeSystemDll())) return FALSE
;
375 PspInitPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
378 OBJECT_ATTRIBUTES ObjectAttributes
;
379 HANDLE SysThreadHandle
;
381 MM_SYSTEMSIZE SystemSize
;
383 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
386 /* Get the system size */
387 SystemSize
= MmQuerySystemSize();
389 /* Setup some memory options */
390 PspDefaultPagefileLimit
= -1;
393 /* Medimum systems */
396 /* Increase the WS sizes a bit */
397 PsMinimumWorkingSet
+= 10;
398 PsMaximumWorkingSet
+= 100;
403 /* Increase the WS sizes a bit more */
404 PsMinimumWorkingSet
+= 30;
405 PsMaximumWorkingSet
+= 300;
407 /* Small and other systems */
412 /* Setup callbacks */
413 for (i
= 0; i
< PSP_MAX_CREATE_THREAD_NOTIFY
; i
++)
415 ExInitializeCallBack(&PspThreadNotifyRoutine
[i
]);
417 for (i
= 0; i
< PSP_MAX_CREATE_PROCESS_NOTIFY
; i
++)
419 ExInitializeCallBack(&PspProcessNotifyRoutine
[i
]);
421 for (i
= 0; i
< PSP_MAX_LOAD_IMAGE_NOTIFY
; i
++)
423 ExInitializeCallBack(&PspLoadImageNotifyRoutine
[i
]);
426 /* Setup the quantum table */
427 PsChangeQuantumTable(FALSE
, PsRawPrioritySeparation
);
429 /* Set quota settings */
430 if (!PspDefaultPagedLimit
) PspDefaultPagedLimit
= 0;
431 if (!PspDefaultNonPagedLimit
) PspDefaultNonPagedLimit
= 0;
432 if (!(PspDefaultNonPagedLimit
) && !(PspDefaultPagedLimit
))
434 /* Enable give-backs */
435 PspDoingGiveBacks
= TRUE
;
440 PspDoingGiveBacks
= FALSE
;
443 /* Now multiply limits by 1MB */
444 PspDefaultPagedLimit
<<= 20;
445 PspDefaultNonPagedLimit
<<= 20;
446 if (PspDefaultPagefileLimit
!= -1U) PspDefaultPagefileLimit
<<= 20;
448 /* Initialize the Active Process List */
449 InitializeListHead(&PsActiveProcessHead
);
450 KeInitializeGuardedMutex(&PspActiveProcessMutex
);
452 /* Get the idle process */
453 PsIdleProcess
= PsGetCurrentProcess();
455 /* Setup the locks */
456 PsIdleProcess
->ProcessLock
.Value
= 0;
457 ExInitializeRundownProtection(&PsIdleProcess
->RundownProtect
);
459 /* Initialize the thread list */
460 InitializeListHead(&PsIdleProcess
->ThreadListHead
);
462 /* Clear kernel time */
463 PsIdleProcess
->Pcb
.KernelTime
= 0;
465 /* Initialize Object Initializer */
466 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
467 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
468 ObjectTypeInitializer
.InvalidAttributes
= OBJ_OPENLINK
|
472 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
473 ObjectTypeInitializer
.SecurityRequired
= TRUE
;
475 /* Initialize the Process type */
476 RtlInitUnicodeString(&Name
, L
"Process");
477 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(EPROCESS
);
478 ObjectTypeInitializer
.GenericMapping
= PspProcessMapping
;
479 ObjectTypeInitializer
.ValidAccessMask
= PROCESS_ALL_ACCESS
;
480 ObjectTypeInitializer
.DeleteProcedure
= PspDeleteProcess
;
481 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &PsProcessType
);
483 /* Initialize the Thread type */
484 RtlInitUnicodeString(&Name
, L
"Thread");
485 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
486 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(ETHREAD
);
487 ObjectTypeInitializer
.GenericMapping
= PspThreadMapping
;
488 ObjectTypeInitializer
.ValidAccessMask
= THREAD_ALL_ACCESS
;
489 ObjectTypeInitializer
.DeleteProcedure
= PspDeleteThread
;
490 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &PsThreadType
);
492 /* Initialize the Job type */
493 RtlInitUnicodeString(&Name
, L
"Job");
494 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
495 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(EJOB
);
496 ObjectTypeInitializer
.GenericMapping
= PspJobMapping
;
497 ObjectTypeInitializer
.ValidAccessMask
= JOB_OBJECT_ALL_ACCESS
;
498 ObjectTypeInitializer
.DeleteProcedure
= PspDeleteJob
;
499 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &PsJobType
);
501 /* Initialize job structures external to this file */
502 PspInitializeJobStructures();
504 /* Initialize the Working Set data */
505 InitializeListHead(&PspWorkingSetChangeHead
.List
);
506 KeInitializeGuardedMutex(&PspWorkingSetChangeHead
.Lock
);
508 /* Create the CID Handle table */
509 PspCidTable
= ExCreateHandleTable(NULL
);
510 if (!PspCidTable
) return FALSE
;
512 /* FIXME: Initialize LDT/VDM support */
514 /* Setup the reaper */
515 ExInitializeWorkItem(&PspReaperWorkItem
, PspReapRoutine
, NULL
);
517 /* Set the boot access token */
518 PspBootAccessToken
= (PTOKEN
)(PsIdleProcess
->Token
.Value
& ~MAX_FAST_REFS
);
520 /* Setup default object attributes */
521 InitializeObjectAttributes(&ObjectAttributes
,
527 /* Create the Initial System Process */
528 Status
= PspCreateProcess(&PspInitialSystemProcessHandle
,
537 if (!NT_SUCCESS(Status
)) return FALSE
;
539 /* Get a reference to it */
540 ObReferenceObjectByHandle(PspInitialSystemProcessHandle
,
544 (PVOID
*)&PsInitialSystemProcess
,
547 /* Copy the process names */
548 strcpy(PsIdleProcess
->ImageFileName
, "Idle");
549 strcpy(PsInitialSystemProcess
->ImageFileName
, "System");
551 /* Allocate a structure for the audit name */
552 PsInitialSystemProcess
->SeAuditProcessCreationInfo
.ImageFileName
=
553 ExAllocatePoolWithTag(PagedPool
,
554 sizeof(OBJECT_NAME_INFORMATION
),
556 if (!PsInitialSystemProcess
->SeAuditProcessCreationInfo
.ImageFileName
)
558 /* Allocation failed */
563 RtlZeroMemory(PsInitialSystemProcess
->
564 SeAuditProcessCreationInfo
.ImageFileName
,
565 sizeof(OBJECT_NAME_INFORMATION
));
567 /* Setup the system initialization thread */
568 Status
= PsCreateSystemThread(&SysThreadHandle
,
573 Phase1Initialization
,
575 if (!NT_SUCCESS(Status
)) return FALSE
;
577 /* Create a handle to it */
578 ObReferenceObjectByHandle(SysThreadHandle
,
584 ZwClose(SysThreadHandle
);
585 SysThreadCreated
= TRUE
;
593 PsInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
595 /* Check the initialization phase */
596 switch (ExpInitializationPhase
)
601 return PspInitPhase0(LoaderBlock
);
606 return PspInitPhase1();
610 /* Don't know any other phase! Bugcheck! */
611 KeBugCheckEx(UNEXPECTED_INITIALIZATION_CALL
,
613 ExpInitializationPhase
,
620 /* PUBLIC FUNCTIONS **********************************************************/
627 PsGetVersion(IN PULONG MajorVersion OPTIONAL
,
628 IN PULONG MinorVersion OPTIONAL
,
629 IN PULONG BuildNumber OPTIONAL
,
630 IN PUNICODE_STRING CSDVersion OPTIONAL
)
632 if (MajorVersion
) *MajorVersion
= NtMajorVersion
;
633 if (MinorVersion
) *MinorVersion
= NtMinorVersion
;
634 if (BuildNumber
) *BuildNumber
= NtBuildNumber
;
638 CSDVersion
->Length
= 0;
639 CSDVersion
->MaximumLength
= 0;
640 CSDVersion
->Buffer
= NULL
;
642 CSDVersion
->Length
= CmCSDVersionString
.Length
;
643 CSDVersion
->MaximumLength
= CmCSDVersionString
.Maximum
;
644 CSDVersion
->Buffer
= CmCSDVersionString
.Buffer
;
648 /* Check the High word */
649 return (NtBuildNumber
>> 28) == 0xC;
654 NtApphelpCacheControl(IN APPHELPCACHESERVICECLASS Service
,
655 IN PVOID ServiceData
)
658 return STATUS_NOT_IMPLEMENTED
;