f234c20ef4e4f10b28b623a0cbee3ff74fe07ed6
[reactos.git] / reactos / ntoskrnl / ps / psmgr.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ps/psmgr.c
6 * PURPOSE: Process management
7 *
8 * PROGRAMMERS: David Welch (welch@mcmail.com)
9 */
10
11 /* INCLUDES **************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 extern LARGE_INTEGER ShortPsLockDelay, PsLockTimeout;
18 extern LIST_ENTRY PriorityListHead[MAXIMUM_PRIORITY];
19
20 static GENERIC_MAPPING PiProcessMapping = {
21 STANDARD_RIGHTS_READ | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
22 STANDARD_RIGHTS_WRITE | PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD |
23 PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_DUP_HANDLE |
24 PROCESS_TERMINATE | PROCESS_SET_QUOTA | PROCESS_SET_INFORMATION |
25 PROCESS_SUSPEND_RESUME,
26 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
27 PROCESS_ALL_ACCESS};
28
29 static GENERIC_MAPPING PiThreadMapping = {
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 extern ULONG NtBuildNumber;
37 extern ULONG NtMajorVersion;
38 extern ULONG NtMinorVersion;
39 extern PVOID KeUserApcDispatcher;
40 extern PVOID KeUserCallbackDispatcher;
41 extern PVOID KeUserExceptionDispatcher;
42 extern PVOID KeRaiseUserExceptionDispatcher;
43
44 PVOID PspSystemDllBase = NULL;
45 PVOID PspSystemDllSection = NULL;
46 PVOID PspSystemDllEntryPoint = NULL;
47
48 VOID
49 INIT_FUNCTION
50 PsInitClientIDManagment(VOID);
51
52 VOID STDCALL PspKillMostProcesses();
53
54 /* FUNCTIONS ***************************************************************/
55
56 VOID PiShutdownProcessManager(VOID)
57 {
58 DPRINT("PiShutdownProcessManager()\n");
59
60 PspKillMostProcesses();
61 }
62
63 VOID INIT_FUNCTION
64 PiInitProcessManager(VOID)
65 {
66 PsInitJobManagment();
67 PsInitProcessManagment();
68 PsInitThreadManagment();
69 PsInitIdleThread();
70 PsInitialiseW32Call();
71 }
72
73 VOID
74 INIT_FUNCTION
75 PsInitThreadManagment(VOID)
76 /*
77 * FUNCTION: Initialize thread managment
78 */
79 {
80 UNICODE_STRING Name;
81 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
82 PETHREAD FirstThread;
83 ULONG i;
84
85 for (i=0; i < MAXIMUM_PRIORITY; i++)
86 {
87 InitializeListHead(&PriorityListHead[i]);
88 }
89
90 DPRINT("Creating Thread Object Type\n");
91
92 /* Initialize the Thread type */
93 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
94 RtlInitUnicodeString(&Name, L"Thread");
95 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
96 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(ETHREAD);
97 ObjectTypeInitializer.GenericMapping = PiThreadMapping;
98 ObjectTypeInitializer.PoolType = NonPagedPool;
99 ObjectTypeInitializer.ValidAccessMask = THREAD_ALL_ACCESS;
100 ObjectTypeInitializer.DeleteProcedure = PspDeleteThread;
101 ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &PsThreadType);
102
103 PsInitializeIdleOrFirstThread(PsInitialSystemProcess, &FirstThread, NULL, KernelMode, TRUE);
104 FirstThread->Tcb.State = Running;
105 FirstThread->Tcb.FreezeCount = 0;
106 FirstThread->Tcb.UserAffinity = (1 << 0); /* Set the affinity of the first thread to the boot processor */
107 FirstThread->Tcb.Affinity = (1 << 0);
108 KeGetCurrentPrcb()->CurrentThread = (PVOID)FirstThread;
109
110 DPRINT("FirstThread %x\n",FirstThread);
111
112 ExInitializeWorkItem(&PspReaperWorkItem, PspReapRoutine, NULL);
113 }
114
115 VOID
116 INIT_FUNCTION
117 PsInitProcessManagment(VOID)
118 {
119 PKPROCESS KProcess;
120 NTSTATUS Status;
121 UNICODE_STRING Name;
122 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
123
124 ShortPsLockDelay.QuadPart = -100LL;
125 PsLockTimeout.QuadPart = -10000000LL; /* one second */
126 /*
127 * Register the process object type
128 */
129
130 DPRINT("Creating Process Object Type\n");
131
132 /* Initialize the Process type */
133 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
134 RtlInitUnicodeString(&Name, L"Process");
135 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
136 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(EPROCESS);
137 ObjectTypeInitializer.GenericMapping = PiProcessMapping;
138 ObjectTypeInitializer.PoolType = NonPagedPool;
139 ObjectTypeInitializer.ValidAccessMask = PROCESS_ALL_ACCESS;
140 ObjectTypeInitializer.DeleteProcedure = PspDeleteProcess;
141 ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &PsProcessType);
142
143 InitializeListHead(&PsActiveProcessHead);
144 ExInitializeFastMutex(&PspActiveProcessMutex);
145
146 /*
147 * Initialize the default quota block.
148 */
149
150 RtlZeroMemory(&PspDefaultQuotaBlock, sizeof(PspDefaultQuotaBlock));
151 PspDefaultQuotaBlock.QuotaEntry[PagedPool].Limit = (SIZE_T)-1;
152 PspDefaultQuotaBlock.QuotaEntry[NonPagedPool].Limit = (SIZE_T)-1;
153 PspDefaultQuotaBlock.QuotaEntry[2].Limit = (SIZE_T)-1; /* Page file */
154
155 /*
156 * Initialize the idle process
157 */
158 Status = ObCreateObject(KernelMode,
159 PsProcessType,
160 NULL,
161 KernelMode,
162 NULL,
163 sizeof(EPROCESS),
164 0,
165 0,
166 (PVOID*)&PsIdleProcess);
167 if (!NT_SUCCESS(Status))
168 {
169 DPRINT1("Failed to create the idle process object, Status: 0x%x\n", Status);
170 KEBUGCHECK(0);
171 return;
172 }
173
174 RtlZeroMemory(PsIdleProcess, sizeof(EPROCESS));
175
176 PsIdleProcess->Pcb.Affinity = 0xFFFFFFFF;
177 PsIdleProcess->Pcb.IopmOffset = 0xffff;
178 PsIdleProcess->Pcb.BasePriority = PROCESS_PRIO_IDLE;
179 PsIdleProcess->Pcb.QuantumReset = 6;
180 InitializeListHead(&PsIdleProcess->Pcb.ThreadListHead);
181 InitializeListHead(&PsIdleProcess->ThreadListHead);
182 InitializeListHead(&PsIdleProcess->ActiveProcessLinks);
183 KeInitializeDispatcherHeader(&PsIdleProcess->Pcb.Header,
184 ProcessObject,
185 sizeof(EPROCESS),
186 FALSE);
187 PsIdleProcess->Pcb.DirectoryTableBase.QuadPart = (ULONG_PTR)MmGetPageDirectory();
188 strcpy(PsIdleProcess->ImageFileName, "Idle");
189 PspInheritQuota(PsIdleProcess, NULL);
190
191 /*
192 * Initialize the system process
193 */
194 Status = ObCreateObject(KernelMode,
195 PsProcessType,
196 NULL,
197 KernelMode,
198 NULL,
199 sizeof(EPROCESS),
200 0,
201 0,
202 (PVOID*)&PsInitialSystemProcess);
203 if (!NT_SUCCESS(Status))
204 {
205 DPRINT1("Failed to create the system process object, Status: 0x%x\n", Status);
206 KEBUGCHECK(0);
207 return;
208 }
209
210 /* System threads may run on any processor. */
211 RtlZeroMemory(PsInitialSystemProcess, sizeof(EPROCESS));
212 PsInitialSystemProcess->Pcb.Affinity = 0xFFFFFFFF;
213 PsInitialSystemProcess->Pcb.IopmOffset = 0xffff;
214 PsInitialSystemProcess->Pcb.BasePriority = PROCESS_PRIO_NORMAL;
215 PsInitialSystemProcess->Pcb.QuantumReset = 6;
216 InitializeListHead(&PsInitialSystemProcess->Pcb.ThreadListHead);
217 KeInitializeDispatcherHeader(&PsInitialSystemProcess->Pcb.Header,
218 ProcessObject,
219 sizeof(EPROCESS),
220 FALSE);
221 KProcess = &PsInitialSystemProcess->Pcb;
222 PspInheritQuota(PsInitialSystemProcess, NULL);
223
224 MmInitializeAddressSpace(PsInitialSystemProcess,
225 &PsInitialSystemProcess->AddressSpace);
226
227 KeInitializeEvent(&PsInitialSystemProcess->LockEvent, SynchronizationEvent, FALSE);
228
229 #if defined(__GNUC__)
230 KProcess->DirectoryTableBase =
231 (LARGE_INTEGER)(LONGLONG)(ULONG)MmGetPageDirectory();
232 #else
233 {
234 LARGE_INTEGER dummy;
235 dummy.QuadPart = (LONGLONG)(ULONG)MmGetPageDirectory();
236 KProcess->DirectoryTableBase = dummy;
237 }
238 #endif
239
240 strcpy(PsInitialSystemProcess->ImageFileName, "System");
241
242 PsInitialSystemProcess->Win32WindowStation = (HANDLE)0;
243
244 InsertHeadList(&PsActiveProcessHead,
245 &PsInitialSystemProcess->ActiveProcessLinks);
246 InitializeListHead(&PsInitialSystemProcess->ThreadListHead);
247
248 #ifndef SCHED_REWRITE
249 {
250 PTOKEN BootToken;
251
252 /* No parent, this is the Initial System Process. Assign Boot Token */
253 BootToken = SepCreateSystemProcessToken();
254 BootToken->TokenInUse = TRUE;
255 PsInitialSystemProcess->Token.Object = BootToken; /* FIXME */
256 ObReferenceObject(BootToken);
257 }
258 #endif
259 }
260
261 VOID
262 PspPostInitSystemProcess(VOID)
263 {
264 NTSTATUS Status;
265
266 /* this routine is called directly after the exectuive handle tables were
267 initialized. We'll set up the Client ID handle table and assign the system
268 process a PID */
269 PsInitClientIDManagment();
270
271 ObCreateHandleTable(NULL, FALSE, PsInitialSystemProcess);
272 ObpKernelHandleTable = PsInitialSystemProcess->ObjectTable;
273
274 Status = PsCreateCidHandle(PsInitialSystemProcess,
275 PsProcessType,
276 &PsInitialSystemProcess->UniqueProcessId);
277 if(!NT_SUCCESS(Status))
278 {
279 DPRINT1("Failed to create CID handle (unique process id) for the system process!\n");
280 KEBUGCHECK(0);
281 }
282 }
283
284 NTSTATUS
285 STDCALL
286 INIT_FUNCTION
287 PspLookupKernelUserEntryPoints(VOID)
288 {
289 ANSI_STRING ProcedureName;
290 NTSTATUS Status;
291
292 /* Retrieve ntdll's startup address */
293 DPRINT("Getting Entrypoint: %p\n", PspSystemDllBase);
294 RtlInitAnsiString(&ProcedureName, "LdrInitializeThunk");
295 Status = LdrGetProcedureAddress((PVOID)PspSystemDllBase,
296 &ProcedureName,
297 0,
298 &PspSystemDllEntryPoint);
299
300 if (!NT_SUCCESS(Status)) {
301
302 DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status);
303 return (Status);
304 }
305
306 /* Get User APC Dispatcher */
307 DPRINT("Getting Entrypoint\n");
308 RtlInitAnsiString(&ProcedureName, "KiUserApcDispatcher");
309 Status = LdrGetProcedureAddress((PVOID)PspSystemDllBase,
310 &ProcedureName,
311 0,
312 &KeUserApcDispatcher);
313
314 if (!NT_SUCCESS(Status)) {
315
316 DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status);
317 return (Status);
318 }
319
320 /* Get Exception Dispatcher */
321 DPRINT("Getting Entrypoint\n");
322 RtlInitAnsiString(&ProcedureName, "KiUserExceptionDispatcher");
323 Status = LdrGetProcedureAddress((PVOID)PspSystemDllBase,
324 &ProcedureName,
325 0,
326 &KeUserExceptionDispatcher);
327
328 if (!NT_SUCCESS(Status)) {
329
330 DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status);
331 return (Status);
332 }
333
334 /* Get Callback Dispatcher */
335 DPRINT("Getting Entrypoint\n");
336 RtlInitAnsiString(&ProcedureName, "KiUserCallbackDispatcher");
337 Status = LdrGetProcedureAddress((PVOID)PspSystemDllBase,
338 &ProcedureName,
339 0,
340 &KeUserCallbackDispatcher);
341
342 if (!NT_SUCCESS(Status)) {
343
344 DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status);
345 return (Status);
346 }
347
348 /* Get Raise Exception Dispatcher */
349 DPRINT("Getting Entrypoint\n");
350 RtlInitAnsiString(&ProcedureName, "KiRaiseUserExceptionDispatcher");
351 Status = LdrGetProcedureAddress((PVOID)PspSystemDllBase,
352 &ProcedureName,
353 0,
354 &KeRaiseUserExceptionDispatcher);
355
356 if (!NT_SUCCESS(Status)) {
357
358 DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status);
359 return (Status);
360 }
361
362 /* Return success */
363 return(STATUS_SUCCESS);
364 }
365
366 NTSTATUS
367 STDCALL
368 PspMapSystemDll(PEPROCESS Process,
369 PVOID *DllBase)
370 {
371 NTSTATUS Status;
372 ULONG ViewSize = 0;
373 PVOID ImageBase = 0;
374
375 /* Map the System DLL */
376 DPRINT("Mapping System DLL\n");
377 Status = MmMapViewOfSection(PspSystemDllSection,
378 Process,
379 (PVOID*)&ImageBase,
380 0,
381 0,
382 NULL,
383 &ViewSize,
384 0,
385 MEM_COMMIT,
386 PAGE_READWRITE);
387
388 if (!NT_SUCCESS(Status)) {
389
390 DPRINT1("Failed to map System DLL Into Process\n");
391 }
392
393 if (DllBase) *DllBase = ImageBase;
394
395 return Status;
396 }
397
398 NTSTATUS
399 STDCALL
400 INIT_FUNCTION
401 PsLocateSystemDll(VOID)
402 {
403 UNICODE_STRING DllPathname = RTL_CONSTANT_STRING(L"\\SystemRoot\\system32\\ntdll.dll");
404 OBJECT_ATTRIBUTES FileObjectAttributes;
405 IO_STATUS_BLOCK Iosb;
406 HANDLE FileHandle;
407 HANDLE NTDllSectionHandle;
408 NTSTATUS Status;
409 CHAR BlockBuffer[1024];
410 PIMAGE_DOS_HEADER DosHeader;
411 PIMAGE_NT_HEADERS NTHeaders;
412
413 /* Locate and open NTDLL to determine ImageBase and LdrStartup */
414 InitializeObjectAttributes(&FileObjectAttributes,
415 &DllPathname,
416 0,
417 NULL,
418 NULL);
419
420 DPRINT("Opening NTDLL\n");
421 Status = ZwOpenFile(&FileHandle,
422 FILE_READ_ACCESS,
423 &FileObjectAttributes,
424 &Iosb,
425 FILE_SHARE_READ,
426 FILE_SYNCHRONOUS_IO_NONALERT);
427
428 if (!NT_SUCCESS(Status)) {
429 DPRINT1("NTDLL open failed (Status %x)\n", Status);
430 return Status;
431 }
432
433 /* Load NTDLL is valid */
434 DPRINT("Reading NTDLL\n");
435 Status = ZwReadFile(FileHandle,
436 0,
437 0,
438 0,
439 &Iosb,
440 BlockBuffer,
441 sizeof(BlockBuffer),
442 0,
443 0);
444 if (!NT_SUCCESS(Status) || Iosb.Information != sizeof(BlockBuffer)) {
445
446 DPRINT1("NTDLL header read failed (Status %x)\n", Status);
447 ZwClose(FileHandle);
448 return Status;
449 }
450
451 /* Check if it's valid */
452 DosHeader = (PIMAGE_DOS_HEADER)BlockBuffer;
453 NTHeaders = (PIMAGE_NT_HEADERS)(BlockBuffer + DosHeader->e_lfanew);
454
455 if ((DosHeader->e_magic != IMAGE_DOS_SIGNATURE) ||
456 (DosHeader->e_lfanew == 0L) ||
457 (*(PULONG) NTHeaders != IMAGE_NT_SIGNATURE)) {
458
459 DPRINT1("NTDLL format invalid\n");
460 ZwClose(FileHandle);
461 return(STATUS_UNSUCCESSFUL);
462 }
463
464 /* Create a section for NTDLL */
465 DPRINT("Creating section\n");
466 Status = ZwCreateSection(&NTDllSectionHandle,
467 SECTION_ALL_ACCESS,
468 NULL,
469 NULL,
470 PAGE_READONLY,
471 SEC_IMAGE | SEC_COMMIT,
472 FileHandle);
473 if (!NT_SUCCESS(Status)) {
474
475 DPRINT1("NTDLL create section failed (Status %x)\n", Status);
476 ZwClose(FileHandle);
477 return(Status);
478 }
479 ZwClose(FileHandle);
480
481 /* Reference the Section */
482 DPRINT("ObReferenceObjectByHandle section: %d\n", NTDllSectionHandle);
483 Status = ObReferenceObjectByHandle(NTDllSectionHandle,
484 SECTION_ALL_ACCESS,
485 MmSectionObjectType,
486 KernelMode,
487 (PVOID*)&PspSystemDllSection,
488 NULL);
489 if (!NT_SUCCESS(Status)) {
490
491 DPRINT1("NTDLL section reference failed (Status %x)\n", Status);
492 return(Status);
493 }
494
495 /* Map it */
496 PspMapSystemDll(PsGetCurrentProcess(), &PspSystemDllBase);
497 DPRINT("LdrpSystemDllBase: %x\n", PspSystemDllBase);
498
499 /* Now get the Entrypoints */
500 PspLookupKernelUserEntryPoints();
501
502 return STATUS_SUCCESS;
503 }
504
505
506 /**********************************************************************
507 * NAME EXPORTED
508 * PsGetVersion
509 *
510 * DESCRIPTION
511 * Retrieves the current OS version.
512 *
513 * ARGUMENTS
514 * MajorVersion Pointer to a variable that will be set to the
515 * major version of the OS. Can be NULL.
516 *
517 * MinorVersion Pointer to a variable that will be set to the
518 * minor version of the OS. Can be NULL.
519 *
520 * BuildNumber Pointer to a variable that will be set to the
521 * build number of the OS. Can be NULL.
522 *
523 * CSDVersion Pointer to a variable that will be set to the
524 * CSD string of the OS. Can be NULL.
525 *
526 * RETURN VALUE
527 * TRUE OS is a checked build.
528 * FALSE OS is a free build.
529 *
530 * NOTES
531 *
532 * @implemented
533 */
534 BOOLEAN
535 STDCALL
536 PsGetVersion(PULONG MajorVersion OPTIONAL,
537 PULONG MinorVersion OPTIONAL,
538 PULONG BuildNumber OPTIONAL,
539 PUNICODE_STRING CSDVersion OPTIONAL)
540 {
541 if (MajorVersion)
542 *MajorVersion = NtMajorVersion;
543
544 if (MinorVersion)
545 *MinorVersion = NtMinorVersion;
546
547 if (BuildNumber)
548 *BuildNumber = NtBuildNumber;
549
550 if (CSDVersion)
551 {
552 CSDVersion->Length = 0;
553 CSDVersion->MaximumLength = 0;
554 CSDVersion->Buffer = NULL;
555 #if 0
556 CSDVersion->Length = CmCSDVersionString.Length;
557 CSDVersion->MaximumLength = CmCSDVersionString.Maximum;
558 CSDVersion->Buffer = CmCSDVersionString.Buffer;
559 #endif
560 }
561
562 /* Check the High word */
563 return (NtBuildNumber >> 28) == 0xC;
564 }
565
566 /* EOF */