- Rename KiSetSystemTime to KeSetSystemTime and enhance prototype for later use.
[reactos.git] / reactos / ntoskrnl / ps / psmgr.c
1 /*
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)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <internal/debug.h>
14
15 extern ULONG ExpInitializationPhase;
16
17 GENERIC_MAPPING PspProcessMapping =
18 {
19 STANDARD_RIGHTS_READ | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
20 STANDARD_RIGHTS_WRITE | PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD |
21 PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_DUP_HANDLE |
22 PROCESS_TERMINATE | PROCESS_SET_QUOTA | PROCESS_SET_INFORMATION |
23 PROCESS_SUSPEND_RESUME,
24 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
25 PROCESS_ALL_ACCESS
26 };
27
28 GENERIC_MAPPING PspThreadMapping =
29 {
30 STANDARD_RIGHTS_READ | THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION,
31 STANDARD_RIGHTS_WRITE | THREAD_TERMINATE | THREAD_SUSPEND_RESUME |
32 THREAD_ALERT | THREAD_SET_INFORMATION | THREAD_SET_CONTEXT,
33 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
34 THREAD_ALL_ACCESS
35 };
36
37 PVOID PspSystemDllBase;
38 PVOID PspSystemDllSection;
39 PVOID PspSystemDllEntryPoint;
40
41 ANSI_STRING ThunkName = RTL_CONSTANT_STRING("LdrInitializeThunk");
42 ANSI_STRING ApcName = RTL_CONSTANT_STRING("KiUserApcDispatcher");
43 ANSI_STRING ExceptName = RTL_CONSTANT_STRING("KiUserExceptionDispatcher");
44 ANSI_STRING CallbackName = RTL_CONSTANT_STRING("KiUserCallbackDispatcher");
45 ANSI_STRING RaiseName = RTL_CONSTANT_STRING("KiRaiseUserExceptionDispatcher");
46 ANSI_STRING FastName = RTL_CONSTANT_STRING("KiFastSystemCall");
47 ANSI_STRING FastReturnName = RTL_CONSTANT_STRING("KiFastSystemCallRet");
48 ANSI_STRING InterruptName = RTL_CONSTANT_STRING("KiIntSystemCall");
49
50 UNICODE_STRING PsNtDllPathName =
51 RTL_CONSTANT_STRING(L"\\SystemRoot\\system32\\ntdll.dll");
52
53 PHANDLE_TABLE PspCidTable;
54
55 PEPROCESS PsInitialSystemProcess = NULL;
56 PEPROCESS PsIdleProcess = NULL;
57 HANDLE PspInitialSystemProcessHandle;
58
59 ULONG PsMinimumWorkingSet, PsMaximumWorkingSet;
60 struct
61 {
62 LIST_ENTRY List;
63 KGUARDED_MUTEX Lock;
64 } PspWorkingSetChangeHead;
65 ULONG PspDefaultPagedLimit, PspDefaultNonPagedLimit, PspDefaultPagefileLimit;
66 BOOLEAN PspDoingGiveBacks;
67
68 /* PRIVATE FUNCTIONS *********************************************************/
69
70 NTSTATUS
71 NTAPI
72 PspLookupSystemDllEntryPoint(IN PANSI_STRING Name,
73 IN PVOID *EntryPoint)
74 {
75 /* Call the LDR Routine */
76 return LdrGetProcedureAddress(PspSystemDllBase, Name, 0, EntryPoint);
77 }
78
79 NTSTATUS
80 NTAPI
81 PspLookupKernelUserEntryPoints(VOID)
82 {
83 NTSTATUS Status;
84
85 /* Get user-mode APC trampoline */
86 Status = PspLookupSystemDllEntryPoint(&ApcName,
87 &KeUserApcDispatcher);
88 if (!NT_SUCCESS(Status)) return Status;
89
90 /* Get user-mode exception dispatcher */
91 Status = PspLookupSystemDllEntryPoint(&ExceptName,
92 &KeUserExceptionDispatcher);
93 if (!NT_SUCCESS(Status)) return Status;
94
95 /* Get user-mode callback dispatcher */
96 Status = PspLookupSystemDllEntryPoint(&CallbackName,
97 &KeUserCallbackDispatcher);
98 if (!NT_SUCCESS(Status)) return Status;
99
100 /* Get user-mode exception raise trampoline */
101 Status = PspLookupSystemDllEntryPoint(&RaiseName,
102 &KeRaiseUserExceptionDispatcher);
103 if (!NT_SUCCESS(Status)) return Status;
104
105 /* Check if this is a machine that supports SYSENTER */
106 if (KeFeatureBits & KF_FAST_SYSCALL)
107 {
108 /* Get user-mode sysenter stub */
109 Status = PspLookupSystemDllEntryPoint(&FastName,
110 (PVOID)&SharedUserData->
111 SystemCall);
112 if (!NT_SUCCESS(Status)) return Status;
113
114 /* Get user-mode sysenter return stub */
115 Status = PspLookupSystemDllEntryPoint(&FastReturnName,
116 (PVOID)&SharedUserData->
117 SystemCallReturn);
118 }
119 else
120 {
121 /* Get the user-mode interrupt stub */
122 Status = PspLookupSystemDllEntryPoint(&InterruptName,
123 (PVOID)&SharedUserData->
124 SystemCall);
125 }
126
127 /* Set the test instruction */
128 if (!NT_SUCCESS(Status)) SharedUserData->TestRetInstruction = 0xC3;
129
130 /* Return the status */
131 return Status;
132 }
133
134 NTSTATUS
135 NTAPI
136 PspMapSystemDll(IN PEPROCESS Process,
137 IN PVOID *DllBase)
138 {
139 NTSTATUS Status;
140 LARGE_INTEGER Offset = {{0}};
141 SIZE_T ViewSize = 0;
142 PVOID ImageBase = 0;
143
144 /* Map the System DLL */
145 Status = MmMapViewOfSection(PspSystemDllSection,
146 Process,
147 (PVOID*)&ImageBase,
148 0,
149 0,
150 &Offset,
151 &ViewSize,
152 ViewShare,
153 0,
154 PAGE_READWRITE);
155
156 /* Write the image base and return status */
157 if (DllBase) *DllBase = ImageBase;
158 return Status;
159 }
160
161 NTSTATUS
162 NTAPI
163 PsLocateSystemDll(VOID)
164 {
165 OBJECT_ATTRIBUTES ObjectAttributes;
166 IO_STATUS_BLOCK IoStatusBlock;
167 HANDLE FileHandle, SectionHandle;
168 NTSTATUS Status;
169 ULONG_PTR HardErrorParameters;
170 ULONG HardErrorResponse;
171
172 /* Locate and open NTDLL to determine ImageBase and LdrStartup */
173 InitializeObjectAttributes(&ObjectAttributes,
174 &PsNtDllPathName,
175 0,
176 NULL,
177 NULL);
178 Status = ZwOpenFile(&FileHandle,
179 FILE_READ_ACCESS,
180 &ObjectAttributes,
181 &IoStatusBlock,
182 FILE_SHARE_READ,
183 0);
184 if (!NT_SUCCESS(Status))
185 {
186 /* Failed, bugcheck */
187 KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED, Status, 2, 0, 0);
188 }
189
190 /* FIXME: Check if the image is valid */
191 Status = MmCheckSystemImage(FileHandle, TRUE);
192 if (Status == STATUS_IMAGE_CHECKSUM_MISMATCH)
193 {
194 /* Raise a hard error */
195 HardErrorParameters = (ULONG_PTR)&PsNtDllPathName;
196 NtRaiseHardError(Status,
197 1,
198 1,
199 &HardErrorParameters,
200 OptionOk,
201 &HardErrorResponse);
202 return Status;
203 }
204
205 /* Create a section for NTDLL */
206 Status = ZwCreateSection(&SectionHandle,
207 SECTION_ALL_ACCESS,
208 NULL,
209 NULL,
210 PAGE_EXECUTE,
211 SEC_IMAGE,
212 FileHandle);
213 ZwClose(FileHandle);
214 if (!NT_SUCCESS(Status))
215 {
216 /* Failed, bugcheck */
217 KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED, Status, 3, 0, 0);
218 }
219
220 /* Reference the Section */
221 Status = ObReferenceObjectByHandle(SectionHandle,
222 SECTION_ALL_ACCESS,
223 MmSectionObjectType,
224 KernelMode,
225 (PVOID*)&PspSystemDllSection,
226 NULL);
227 ZwClose(SectionHandle);
228 if (!NT_SUCCESS(Status))
229 {
230 /* Failed, bugcheck */
231 KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED, Status, 4, 0, 0);
232 }
233
234 /* Map it */
235 Status = PspMapSystemDll(PsGetCurrentProcess(), &PspSystemDllBase);
236 if (!NT_SUCCESS(Status))
237 {
238 /* Failed, bugcheck */
239 KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED, Status, 5, 0, 0);
240 }
241
242 /* Return status */
243 return Status;
244 }
245
246 NTSTATUS
247 NTAPI
248 PspInitializeSystemDll(VOID)
249 {
250 NTSTATUS Status;
251
252 /* Get user-mode startup thunk */
253 Status = PspLookupSystemDllEntryPoint(&ThunkName, &PspSystemDllEntryPoint);
254 if (!NT_SUCCESS(Status))
255 {
256 /* Failed, bugcheck */
257 KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED, Status, 7, 0, 0);
258 }
259
260 /* Get all the other entrypoints */
261 Status = PspLookupKernelUserEntryPoints();
262 if (!NT_SUCCESS(Status))
263 {
264 /* Failed, bugcheck */
265 KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED, Status, 8, 0, 0);
266 }
267
268 /* Return status */
269 return Status;
270 }
271
272 BOOLEAN
273 NTAPI
274 PspInitPhase1()
275 {
276 /* Initialize the System DLL and return status of operation */
277 if (!NT_SUCCESS(PspInitializeSystemDll())) return FALSE;
278 return TRUE;
279 }
280
281 BOOLEAN
282 NTAPI
283 PspInitPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
284 {
285 NTSTATUS Status;
286 OBJECT_ATTRIBUTES ObjectAttributes;
287 HANDLE SysThreadHandle;
288 PETHREAD SysThread;
289 MM_SYSTEMSIZE SystemSize;
290 UNICODE_STRING Name;
291 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
292 ULONG i;
293
294 /* Get the system size */
295 SystemSize = MmQuerySystemSize();
296
297 /* Setup some memory options */
298 PspDefaultPagefileLimit = -1;
299 switch (SystemSize)
300 {
301 /* Medimum systems */
302 case MmMediumSystem:
303
304 /* Increase the WS sizes a bit */
305 PsMinimumWorkingSet += 10;
306 PsMaximumWorkingSet += 100;
307
308 /* Large systems */
309 case MmLargeSystem:
310
311 /* Increase the WS sizes a bit more */
312 PsMinimumWorkingSet += 30;
313 PsMaximumWorkingSet += 300;
314
315 /* Small and other systems */
316 default:
317 break;
318 }
319
320 /* Setup callbacks */
321 for (i = 0; i < PSP_MAX_CREATE_THREAD_NOTIFY; i++)
322 {
323 ExInitializeCallBack(&PspThreadNotifyRoutine[i]);
324 }
325 for (i = 0; i < PSP_MAX_CREATE_PROCESS_NOTIFY; i++)
326 {
327 ExInitializeCallBack(&PspProcessNotifyRoutine[i]);
328 }
329 for (i = 0; i < PSP_MAX_LOAD_IMAGE_NOTIFY; i++)
330 {
331 ExInitializeCallBack(&PspLoadImageNotifyRoutine[i]);
332 }
333
334 /* Setup the quantum table */
335 PsChangeQuantumTable(FALSE, PsRawPrioritySeparation);
336
337 /* Set quota settings */
338 if (!PspDefaultPagedLimit) PspDefaultPagedLimit = 0;
339 if (!PspDefaultNonPagedLimit) PspDefaultNonPagedLimit = 0;
340 if (!(PspDefaultNonPagedLimit) && !(PspDefaultPagedLimit))
341 {
342 /* Enable give-backs */
343 PspDoingGiveBacks = TRUE;
344 }
345 else
346 {
347 /* Disable them */
348 PspDoingGiveBacks = FALSE;
349 }
350
351 /* Now multiply limits by 1MB */
352 PspDefaultPagedLimit <<= 20;
353 PspDefaultNonPagedLimit <<= 20;
354 if (PspDefaultPagefileLimit != -1) PspDefaultPagefileLimit <<= 20;
355
356 /* Initialize the Active Process List */
357 InitializeListHead(&PsActiveProcessHead);
358 KeInitializeGuardedMutex(&PspActiveProcessMutex);
359
360 /* Get the idle process */
361 PsIdleProcess = PsGetCurrentProcess();
362
363 /* Setup the locks */
364 PsIdleProcess->ProcessLock.Value = 0;
365 ExInitializeRundownProtection(&PsIdleProcess->RundownProtect);
366
367 /* Initialize the thread list */
368 InitializeListHead(&PsIdleProcess->ThreadListHead);
369
370 /* Clear kernel time */
371 PsIdleProcess->Pcb.KernelTime = 0;
372
373 /* Initialize Object Initializer */
374 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
375 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
376 ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK |
377 OBJ_PERMANENT |
378 OBJ_EXCLUSIVE |
379 OBJ_OPENIF;
380 ObjectTypeInitializer.PoolType = NonPagedPool;
381 ObjectTypeInitializer.SecurityRequired = TRUE;
382
383 /* Initialize the Process type */
384 RtlInitUnicodeString(&Name, L"Process");
385 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(EPROCESS);
386 ObjectTypeInitializer.GenericMapping = PspProcessMapping;
387 ObjectTypeInitializer.ValidAccessMask = PROCESS_ALL_ACCESS;
388 ObjectTypeInitializer.DeleteProcedure = PspDeleteProcess;
389 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &PsProcessType);
390
391 /* Initialize the Thread type */
392 RtlInitUnicodeString(&Name, L"Thread");
393 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
394 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(ETHREAD);
395 ObjectTypeInitializer.GenericMapping = PspThreadMapping;
396 ObjectTypeInitializer.ValidAccessMask = THREAD_ALL_ACCESS;
397 ObjectTypeInitializer.DeleteProcedure = PspDeleteThread;
398 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &PsThreadType);
399
400 /* Initialize the Job type */
401 RtlInitUnicodeString(&Name, L"Job");
402 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
403 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(EJOB);
404 ObjectTypeInitializer.GenericMapping = PspJobMapping;
405 ObjectTypeInitializer.ValidAccessMask = JOB_OBJECT_ALL_ACCESS;
406 ObjectTypeInitializer.DeleteProcedure = PspDeleteJob;
407 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &PsJobType);
408
409 /* Initialize job structures external to this file */
410 PspInitializeJobStructures();
411
412 /* Initialize the Working Set data */
413 InitializeListHead(&PspWorkingSetChangeHead.List);
414 KeInitializeGuardedMutex(&PspWorkingSetChangeHead.Lock);
415
416 /* Create the CID Handle table */
417 PspCidTable = ExCreateHandleTable(NULL);
418 if (!PspCidTable) return FALSE;
419
420 /* FIXME: Initialize LDT/VDM support */
421
422 /* Setup the reaper */
423 ExInitializeWorkItem(&PspReaperWorkItem, PspReapRoutine, NULL);
424
425 /* Set the boot access token */
426 PspBootAccessToken = (PTOKEN)(PsIdleProcess->Token.Value & ~MAX_FAST_REFS);
427
428 /* Setup default object attributes */
429 InitializeObjectAttributes(&ObjectAttributes,
430 NULL,
431 0,
432 NULL,
433 NULL);
434
435 /* Create the Initial System Process */
436 Status = PspCreateProcess(&PspInitialSystemProcessHandle,
437 PROCESS_ALL_ACCESS,
438 &ObjectAttributes,
439 0,
440 FALSE,
441 0,
442 0,
443 0,
444 FALSE);
445 if (!NT_SUCCESS(Status)) return FALSE;
446
447 /* Get a reference to it */
448 ObReferenceObjectByHandle(PspInitialSystemProcessHandle,
449 0,
450 PsProcessType,
451 KernelMode,
452 (PVOID*)&PsInitialSystemProcess,
453 NULL);
454
455 /* Copy the process names */
456 strcpy(PsIdleProcess->ImageFileName, "Idle");
457 strcpy(PsInitialSystemProcess->ImageFileName, "System");
458
459 /* Allocate a structure for the audit name */
460 PsInitialSystemProcess->SeAuditProcessCreationInfo.ImageFileName =
461 ExAllocatePoolWithTag(PagedPool,
462 sizeof(OBJECT_NAME_INFORMATION),
463 TAG_SEPA);
464 if (!PsInitialSystemProcess->SeAuditProcessCreationInfo.ImageFileName)
465 {
466 /* Allocation failed */
467 return FALSE;
468 }
469
470 /* Zero it */
471 RtlZeroMemory(PsInitialSystemProcess->
472 SeAuditProcessCreationInfo.ImageFileName,
473 sizeof(OBJECT_NAME_INFORMATION));
474
475 /* Setup the system initialization thread */
476 Status = PsCreateSystemThread(&SysThreadHandle,
477 THREAD_ALL_ACCESS,
478 &ObjectAttributes,
479 0,
480 NULL,
481 Phase1Initialization,
482 LoaderBlock);
483 if (!NT_SUCCESS(Status)) return FALSE;
484
485 /* Create a handle to it */
486 ObReferenceObjectByHandle(SysThreadHandle,
487 0,
488 PsThreadType,
489 KernelMode,
490 (PVOID*)&SysThread,
491 NULL);
492 ZwClose(SysThreadHandle);
493
494 /* Return success */
495 return TRUE;
496 }
497
498 BOOLEAN
499 NTAPI
500 PsInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
501 {
502 /* Check the initialization phase */
503 switch (ExpInitializationPhase)
504 {
505 case 0:
506
507 /* Do Phase 0 */
508 return PspInitPhase0(LoaderBlock);
509
510 case 1:
511
512 /* Do Phase 1 */
513 return PspInitPhase1();
514
515 default:
516
517 /* Don't know any other phase! Bugcheck! */
518 KeBugCheckEx(UNEXPECTED_INITIALIZATION_CALL,
519 1,
520 ExpInitializationPhase,
521 0,
522 0);
523 return FALSE;
524 }
525 }
526
527 /* PUBLIC FUNCTIONS **********************************************************/
528
529 /*
530 * @implemented
531 */
532 BOOLEAN
533 NTAPI
534 PsGetVersion(IN PULONG MajorVersion OPTIONAL,
535 IN PULONG MinorVersion OPTIONAL,
536 IN PULONG BuildNumber OPTIONAL,
537 IN PUNICODE_STRING CSDVersion OPTIONAL)
538 {
539 if (MajorVersion) *MajorVersion = NtMajorVersion;
540 if (MinorVersion) *MinorVersion = NtMinorVersion;
541 if (BuildNumber) *BuildNumber = NtBuildNumber;
542
543 if (CSDVersion)
544 {
545 CSDVersion->Length = 0;
546 CSDVersion->MaximumLength = 0;
547 CSDVersion->Buffer = NULL;
548 #if 0
549 CSDVersion->Length = CmCSDVersionString.Length;
550 CSDVersion->MaximumLength = CmCSDVersionString.Maximum;
551 CSDVersion->Buffer = CmCSDVersionString.Buffer;
552 #endif
553 }
554
555 /* Check the High word */
556 return (NtBuildNumber >> 28) == 0xC;
557 }
558
559 NTSTATUS
560 NTAPI
561 NtApphelpCacheControl(IN APPHELPCACHESERVICECLASS Service,
562 IN PVOID ServiceData)
563 {
564 UNIMPLEMENTED;
565 return STATUS_NOT_IMPLEMENTED;
566 }
567
568 /* EOF */