3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ps/psmgr.c
6 * PURPOSE: Process management
8 * PROGRAMMERS: David Welch (welch@mcmail.com)
11 /* INCLUDES **************************************************************/
15 #include <internal/debug.h>
17 extern LARGE_INTEGER ShortPsLockDelay
, PsLockTimeout
;
18 extern LIST_ENTRY PriorityListHead
[MAXIMUM_PRIORITY
];
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
,
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
,
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
;
44 PVOID PspSystemDllBase
= NULL
;
45 PVOID PspSystemDllSection
= NULL
;
46 PVOID PspSystemDllEntryPoint
= NULL
;
47 PHANDLE_TABLE PspCidTable
= NULL
;
48 VOID STDCALL
PspKillMostProcesses();
50 /* FUNCTIONS ***************************************************************/
54 PiShutdownProcessManager(VOID
)
56 DPRINT("PiShutdownProcessManager()\n");
58 PspKillMostProcesses();
64 PiInitProcessManager(VOID
)
67 PsInitProcessManagment();
68 PsInitThreadManagment();
70 PsInitialiseW32Call();
76 PsInitClientIDManagment(VOID
)
78 PspCidTable
= ExCreateHandleTable(NULL
);
85 PsInitThreadManagment(VOID
)
87 * FUNCTION: Initialize thread managment
91 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
95 for (i
=0; i
< MAXIMUM_PRIORITY
; i
++)
97 InitializeListHead(&PriorityListHead
[i
]);
100 DPRINT("Creating Thread Object Type\n");
102 /* Initialize the Thread type */
103 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
104 RtlInitUnicodeString(&Name
, L
"Thread");
105 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
106 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(ETHREAD
);
107 ObjectTypeInitializer
.GenericMapping
= PiThreadMapping
;
108 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
109 ObjectTypeInitializer
.ValidAccessMask
= THREAD_ALL_ACCESS
;
110 ObjectTypeInitializer
.DeleteProcedure
= PspDeleteThread
;
111 ObpCreateTypeObject(&ObjectTypeInitializer
, &Name
, &PsThreadType
);
113 PsInitializeIdleOrFirstThread(PsInitialSystemProcess
, &FirstThread
, NULL
, KernelMode
, TRUE
);
114 FirstThread
->Tcb
.State
= Running
;
115 FirstThread
->Tcb
.FreezeCount
= 0;
116 FirstThread
->Tcb
.UserAffinity
= (1 << 0); /* Set the affinity of the first thread to the boot processor */
117 FirstThread
->Tcb
.Affinity
= (1 << 0);
118 KeGetCurrentPrcb()->CurrentThread
= (PVOID
)FirstThread
;
120 DPRINT("FirstThread %x\n",FirstThread
);
122 ExInitializeWorkItem(&PspReaperWorkItem
, PspReapRoutine
, NULL
);
128 PsInitProcessManagment(VOID
)
133 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
135 ShortPsLockDelay
.QuadPart
= -100LL;
136 PsLockTimeout
.QuadPart
= -10000000LL; /* one second */
138 * Register the process object type
141 DPRINT("Creating Process Object Type\n");
143 /* Initialize the Process type */
144 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
145 RtlInitUnicodeString(&Name
, L
"Process");
146 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
147 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(EPROCESS
);
148 ObjectTypeInitializer
.GenericMapping
= PiProcessMapping
;
149 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
150 ObjectTypeInitializer
.ValidAccessMask
= PROCESS_ALL_ACCESS
;
151 ObjectTypeInitializer
.DeleteProcedure
= PspDeleteProcess
;
152 ObpCreateTypeObject(&ObjectTypeInitializer
, &Name
, &PsProcessType
);
154 InitializeListHead(&PsActiveProcessHead
);
155 ExInitializeFastMutex(&PspActiveProcessMutex
);
158 * Initialize the default quota block.
161 RtlZeroMemory(&PspDefaultQuotaBlock
, sizeof(PspDefaultQuotaBlock
));
162 PspDefaultQuotaBlock
.QuotaEntry
[PagedPool
].Limit
= (SIZE_T
)-1;
163 PspDefaultQuotaBlock
.QuotaEntry
[NonPagedPool
].Limit
= (SIZE_T
)-1;
164 PspDefaultQuotaBlock
.QuotaEntry
[2].Limit
= (SIZE_T
)-1; /* Page file */
167 * Initialize the idle process
169 Status
= ObCreateObject(KernelMode
,
177 (PVOID
*)&PsIdleProcess
);
178 if (!NT_SUCCESS(Status
))
180 DPRINT1("Failed to create the idle process object, Status: 0x%x\n", Status
);
185 RtlZeroMemory(PsIdleProcess
, sizeof(EPROCESS
));
187 PsIdleProcess
->Pcb
.Affinity
= 0xFFFFFFFF;
188 PsIdleProcess
->Pcb
.IopmOffset
= 0xffff;
189 PsIdleProcess
->Pcb
.BasePriority
= PROCESS_PRIORITY_IDLE
;
190 PsIdleProcess
->Pcb
.QuantumReset
= 6;
191 InitializeListHead(&PsIdleProcess
->Pcb
.ThreadListHead
);
192 InitializeListHead(&PsIdleProcess
->ThreadListHead
);
193 InitializeListHead(&PsIdleProcess
->ActiveProcessLinks
);
194 KeInitializeDispatcherHeader(&PsIdleProcess
->Pcb
.Header
,
198 PsIdleProcess
->Pcb
.DirectoryTableBase
.QuadPart
= (ULONG_PTR
)MmGetPageDirectory();
199 strcpy(PsIdleProcess
->ImageFileName
, "Idle");
200 PspInheritQuota(PsIdleProcess
, NULL
);
203 * Initialize the system process
205 Status
= ObCreateObject(KernelMode
,
213 (PVOID
*)&PsInitialSystemProcess
);
214 if (!NT_SUCCESS(Status
))
216 DPRINT1("Failed to create the system process object, Status: 0x%x\n", Status
);
221 /* System threads may run on any processor. */
222 RtlZeroMemory(PsInitialSystemProcess
, sizeof(EPROCESS
));
225 * Only the boot cpu is initialized. Threads of the
226 * system process should be able to run on all cpus.
228 PsInitialSystemProcess
->Pcb
.Affinity
= 0xffffffff;
230 PsInitialSystemProcess
->Pcb
.Affinity
= KeActiveProcessors
;
232 PsInitialSystemProcess
->Pcb
.IopmOffset
= 0xffff;
233 PsInitialSystemProcess
->Pcb
.BasePriority
= PROCESS_PRIORITY_NORMAL
;
234 PsInitialSystemProcess
->Pcb
.QuantumReset
= 6;
235 InitializeListHead(&PsInitialSystemProcess
->Pcb
.ThreadListHead
);
236 KeInitializeDispatcherHeader(&PsInitialSystemProcess
->Pcb
.Header
,
240 KProcess
= &PsInitialSystemProcess
->Pcb
;
241 PspInheritQuota(PsInitialSystemProcess
, NULL
);
243 MmInitializeAddressSpace(PsInitialSystemProcess
,
244 &PsInitialSystemProcess
->AddressSpace
);
246 KeInitializeEvent(&PsInitialSystemProcess
->LockEvent
, SynchronizationEvent
, FALSE
);
248 #if defined(__GNUC__)
249 KProcess
->DirectoryTableBase
=
250 (LARGE_INTEGER
)(LONGLONG
)(ULONG
)MmGetPageDirectory();
254 dummy
.QuadPart
= (LONGLONG
)(ULONG
)MmGetPageDirectory();
255 KProcess
->DirectoryTableBase
= dummy
;
259 strcpy(PsInitialSystemProcess
->ImageFileName
, "System");
261 PsInitialSystemProcess
->Win32WindowStation
= (HANDLE
)0;
263 InsertHeadList(&PsActiveProcessHead
,
264 &PsInitialSystemProcess
->ActiveProcessLinks
);
265 InitializeListHead(&PsInitialSystemProcess
->ThreadListHead
);
267 #ifndef SCHED_REWRITE
271 /* No parent, this is the Initial System Process. Assign Boot Token */
272 BootToken
= SepCreateSystemProcessToken();
273 BootToken
->TokenInUse
= TRUE
;
274 PsInitialSystemProcess
->Token
.Object
= BootToken
; /* FIXME */
275 ObReferenceObject(BootToken
);
281 PspPostInitSystemProcess(VOID
)
283 HANDLE_TABLE_ENTRY CidEntry
;
285 /* this routine is called directly after the exectuive handle tables were
286 initialized. We'll set up the Client ID handle table and assign the system
288 PsInitClientIDManagment();
290 ObCreateHandleTable(NULL
, FALSE
, PsInitialSystemProcess
);
291 ObpKernelHandleTable
= PsInitialSystemProcess
->ObjectTable
;
293 CidEntry
.u1
.Object
= PsInitialSystemProcess
;
294 CidEntry
.u2
.GrantedAccess
= 0;
295 PsInitialSystemProcess
->UniqueProcessId
= ExCreateHandle(PspCidTable
, &CidEntry
);
297 if(!PsInitialSystemProcess
->UniqueProcessId
)
299 DPRINT1("Failed to create CID handle (unique process id) for the system process!\n");
307 PspLookupKernelUserEntryPoints(VOID
)
309 ANSI_STRING ProcedureName
;
312 /* Retrieve ntdll's startup address */
313 DPRINT("Getting Entrypoint: %p\n", PspSystemDllBase
);
314 RtlInitAnsiString(&ProcedureName
, "LdrInitializeThunk");
315 Status
= LdrGetProcedureAddress((PVOID
)PspSystemDllBase
,
318 &PspSystemDllEntryPoint
);
320 if (!NT_SUCCESS(Status
)) {
322 DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status
);
326 /* Get User APC Dispatcher */
327 DPRINT("Getting Entrypoint\n");
328 RtlInitAnsiString(&ProcedureName
, "KiUserApcDispatcher");
329 Status
= LdrGetProcedureAddress((PVOID
)PspSystemDllBase
,
332 &KeUserApcDispatcher
);
334 if (!NT_SUCCESS(Status
)) {
336 DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status
);
340 /* Get Exception Dispatcher */
341 DPRINT("Getting Entrypoint\n");
342 RtlInitAnsiString(&ProcedureName
, "KiUserExceptionDispatcher");
343 Status
= LdrGetProcedureAddress((PVOID
)PspSystemDllBase
,
346 &KeUserExceptionDispatcher
);
348 if (!NT_SUCCESS(Status
)) {
350 DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status
);
354 /* Get Callback Dispatcher */
355 DPRINT("Getting Entrypoint\n");
356 RtlInitAnsiString(&ProcedureName
, "KiUserCallbackDispatcher");
357 Status
= LdrGetProcedureAddress((PVOID
)PspSystemDllBase
,
360 &KeUserCallbackDispatcher
);
362 if (!NT_SUCCESS(Status
)) {
364 DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status
);
368 /* Get Raise Exception Dispatcher */
369 DPRINT("Getting Entrypoint\n");
370 RtlInitAnsiString(&ProcedureName
, "KiRaiseUserExceptionDispatcher");
371 Status
= LdrGetProcedureAddress((PVOID
)PspSystemDllBase
,
374 &KeRaiseUserExceptionDispatcher
);
376 if (!NT_SUCCESS(Status
)) {
378 DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status
);
383 return(STATUS_SUCCESS
);
388 PspMapSystemDll(PEPROCESS Process
,
395 /* Map the System DLL */
396 DPRINT("Mapping System DLL\n");
397 Status
= MmMapViewOfSection(PspSystemDllSection
,
408 if (!NT_SUCCESS(Status
)) {
410 DPRINT1("Failed to map System DLL Into Process\n");
413 if (DllBase
) *DllBase
= ImageBase
;
421 PsLocateSystemDll(VOID
)
423 UNICODE_STRING DllPathname
= RTL_CONSTANT_STRING(L
"\\SystemRoot\\system32\\ntdll.dll");
424 OBJECT_ATTRIBUTES FileObjectAttributes
;
425 IO_STATUS_BLOCK Iosb
;
427 HANDLE NTDllSectionHandle
;
429 CHAR BlockBuffer
[1024];
430 PIMAGE_DOS_HEADER DosHeader
;
431 PIMAGE_NT_HEADERS NTHeaders
;
433 /* Locate and open NTDLL to determine ImageBase and LdrStartup */
434 InitializeObjectAttributes(&FileObjectAttributes
,
440 DPRINT("Opening NTDLL\n");
441 Status
= ZwOpenFile(&FileHandle
,
443 &FileObjectAttributes
,
446 FILE_SYNCHRONOUS_IO_NONALERT
);
448 if (!NT_SUCCESS(Status
)) {
449 DPRINT1("NTDLL open failed (Status %x)\n", Status
);
453 /* Load NTDLL is valid */
454 DPRINT("Reading NTDLL\n");
455 Status
= ZwReadFile(FileHandle
,
464 if (!NT_SUCCESS(Status
) || Iosb
.Information
!= sizeof(BlockBuffer
)) {
466 DPRINT1("NTDLL header read failed (Status %x)\n", Status
);
471 /* Check if it's valid */
472 DosHeader
= (PIMAGE_DOS_HEADER
)BlockBuffer
;
473 NTHeaders
= (PIMAGE_NT_HEADERS
)(BlockBuffer
+ DosHeader
->e_lfanew
);
475 if ((DosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
) ||
476 (DosHeader
->e_lfanew
== 0L) ||
477 (*(PULONG
) NTHeaders
!= IMAGE_NT_SIGNATURE
)) {
479 DPRINT1("NTDLL format invalid\n");
481 return(STATUS_UNSUCCESSFUL
);
484 /* Create a section for NTDLL */
485 DPRINT("Creating section\n");
486 Status
= ZwCreateSection(&NTDllSectionHandle
,
491 SEC_IMAGE
| SEC_COMMIT
,
493 if (!NT_SUCCESS(Status
)) {
495 DPRINT1("NTDLL create section failed (Status %x)\n", Status
);
501 /* Reference the Section */
502 DPRINT("ObReferenceObjectByHandle section: %d\n", NTDllSectionHandle
);
503 Status
= ObReferenceObjectByHandle(NTDllSectionHandle
,
507 (PVOID
*)&PspSystemDllSection
,
509 if (!NT_SUCCESS(Status
)) {
511 DPRINT1("NTDLL section reference failed (Status %x)\n", Status
);
516 PspMapSystemDll(PsGetCurrentProcess(), &PspSystemDllBase
);
517 DPRINT("LdrpSystemDllBase: %x\n", PspSystemDllBase
);
519 /* Now get the Entrypoints */
520 PspLookupKernelUserEntryPoints();
522 return STATUS_SUCCESS
;
526 /**********************************************************************
531 * Retrieves the current OS version.
534 * MajorVersion Pointer to a variable that will be set to the
535 * major version of the OS. Can be NULL.
537 * MinorVersion Pointer to a variable that will be set to the
538 * minor version of the OS. Can be NULL.
540 * BuildNumber Pointer to a variable that will be set to the
541 * build number of the OS. Can be NULL.
543 * CSDVersion Pointer to a variable that will be set to the
544 * CSD string of the OS. Can be NULL.
547 * TRUE OS is a checked build.
548 * FALSE OS is a free build.
556 PsGetVersion(PULONG MajorVersion OPTIONAL
,
557 PULONG MinorVersion OPTIONAL
,
558 PULONG BuildNumber OPTIONAL
,
559 PUNICODE_STRING CSDVersion OPTIONAL
)
562 *MajorVersion
= NtMajorVersion
;
565 *MinorVersion
= NtMinorVersion
;
568 *BuildNumber
= NtBuildNumber
;
572 CSDVersion
->Length
= 0;
573 CSDVersion
->MaximumLength
= 0;
574 CSDVersion
->Buffer
= NULL
;
576 CSDVersion
->Length
= CmCSDVersionString
.Length
;
577 CSDVersion
->MaximumLength
= CmCSDVersionString
.Maximum
;
578 CSDVersion
->Buffer
= CmCSDVersionString
.Buffer
;
582 /* Check the High word */
583 return (NtBuildNumber
>> 28) == 0xC;