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();
49 VOID INIT_FUNCTION NTAPI
PsInitClientIDManagment(VOID
);
50 NTSTATUS STDCALL INIT_FUNCTION
PspLookupKernelUserEntryPoints(VOID
);
52 #if defined (ALLOC_PRAGMA)
53 #pragma alloc_text(INIT, PiInitProcessManager)
54 #pragma alloc_text(INIT, PsInitClientIDManagment)
55 #pragma alloc_text(INIT, PsInitThreadManagment)
56 #pragma alloc_text(INIT, PsInitProcessManagment)
57 #pragma alloc_text(INIT, PspLookupKernelUserEntryPoints)
58 #pragma alloc_text(INIT, PsLocateSystemDll)
61 /* FUNCTIONS ***************************************************************/
65 PiShutdownProcessManager(VOID
)
67 DPRINT("PiShutdownProcessManager()\n");
69 PspKillMostProcesses();
75 PiInitProcessManager(VOID
)
78 PsInitProcessManagment();
79 PsInitThreadManagment();
81 PsInitialiseW32Call();
87 PsInitClientIDManagment(VOID
)
89 PspCidTable
= ExCreateHandleTable(NULL
);
96 PsInitThreadManagment(VOID
)
98 * FUNCTION: Initialize thread managment
102 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
103 PETHREAD FirstThread
;
106 for (i
=0; i
< MAXIMUM_PRIORITY
; i
++)
108 InitializeListHead(&PriorityListHead
[i
]);
111 DPRINT("Creating Thread Object Type\n");
113 /* Initialize the Thread type */
114 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
115 RtlInitUnicodeString(&Name
, L
"Thread");
116 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
117 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(ETHREAD
);
118 ObjectTypeInitializer
.GenericMapping
= PiThreadMapping
;
119 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
120 ObjectTypeInitializer
.ValidAccessMask
= THREAD_ALL_ACCESS
;
121 ObjectTypeInitializer
.DeleteProcedure
= PspDeleteThread
;
122 ObpCreateTypeObject(&ObjectTypeInitializer
, &Name
, &PsThreadType
);
124 PsInitializeIdleOrFirstThread(PsInitialSystemProcess
, &FirstThread
, NULL
, KernelMode
, TRUE
);
125 FirstThread
->Tcb
.State
= Running
;
126 FirstThread
->Tcb
.FreezeCount
= 0;
127 FirstThread
->Tcb
.UserAffinity
= (1 << 0); /* Set the affinity of the first thread to the boot processor */
128 FirstThread
->Tcb
.Affinity
= (1 << 0);
129 KeGetCurrentPrcb()->CurrentThread
= (PVOID
)FirstThread
;
131 DPRINT("FirstThread %x\n",FirstThread
);
133 ExInitializeWorkItem(&PspReaperWorkItem
, PspReapRoutine
, NULL
);
139 PsInitProcessManagment(VOID
)
144 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
146 ShortPsLockDelay
.QuadPart
= -100LL;
147 PsLockTimeout
.QuadPart
= -10000000LL; /* one second */
149 * Register the process object type
152 DPRINT("Creating Process Object Type\n");
154 /* Initialize the Process type */
155 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
156 RtlInitUnicodeString(&Name
, L
"Process");
157 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
158 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(EPROCESS
);
159 ObjectTypeInitializer
.GenericMapping
= PiProcessMapping
;
160 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
161 ObjectTypeInitializer
.ValidAccessMask
= PROCESS_ALL_ACCESS
;
162 ObjectTypeInitializer
.DeleteProcedure
= PspDeleteProcess
;
163 ObpCreateTypeObject(&ObjectTypeInitializer
, &Name
, &PsProcessType
);
165 InitializeListHead(&PsActiveProcessHead
);
166 ExInitializeFastMutex(&PspActiveProcessMutex
);
169 * Initialize the default quota block.
172 RtlZeroMemory(&PspDefaultQuotaBlock
, sizeof(PspDefaultQuotaBlock
));
173 PspDefaultQuotaBlock
.QuotaEntry
[PagedPool
].Limit
= (SIZE_T
)-1;
174 PspDefaultQuotaBlock
.QuotaEntry
[NonPagedPool
].Limit
= (SIZE_T
)-1;
175 PspDefaultQuotaBlock
.QuotaEntry
[2].Limit
= (SIZE_T
)-1; /* Page file */
178 * Initialize the idle process
180 Status
= ObCreateObject(KernelMode
,
188 (PVOID
*)&PsIdleProcess
);
189 if (!NT_SUCCESS(Status
))
191 DPRINT1("Failed to create the idle process object, Status: 0x%x\n", Status
);
196 RtlZeroMemory(PsIdleProcess
, sizeof(EPROCESS
));
198 PsIdleProcess
->Pcb
.Affinity
= 0xFFFFFFFF;
199 PsIdleProcess
->Pcb
.IopmOffset
= 0xffff;
200 PsIdleProcess
->Pcb
.BasePriority
= PROCESS_PRIORITY_IDLE
;
201 PsIdleProcess
->Pcb
.QuantumReset
= 6;
202 InitializeListHead(&PsIdleProcess
->Pcb
.ThreadListHead
);
203 InitializeListHead(&PsIdleProcess
->ThreadListHead
);
204 InitializeListHead(&PsIdleProcess
->ActiveProcessLinks
);
205 KeInitializeDispatcherHeader(&PsIdleProcess
->Pcb
.Header
,
209 PsIdleProcess
->Pcb
.DirectoryTableBase
.QuadPart
= (ULONG_PTR
)MmGetPageDirectory();
210 strcpy(PsIdleProcess
->ImageFileName
, "Idle");
211 PspInheritQuota(PsIdleProcess
, NULL
);
214 * Initialize the system process
216 Status
= ObCreateObject(KernelMode
,
224 (PVOID
*)&PsInitialSystemProcess
);
225 if (!NT_SUCCESS(Status
))
227 DPRINT1("Failed to create the system process object, Status: 0x%x\n", Status
);
232 /* System threads may run on any processor. */
233 RtlZeroMemory(PsInitialSystemProcess
, sizeof(EPROCESS
));
236 * Only the boot cpu is initialized. Threads of the
237 * system process should be able to run on all cpus.
239 PsInitialSystemProcess
->Pcb
.Affinity
= 0xffffffff;
241 PsInitialSystemProcess
->Pcb
.Affinity
= KeActiveProcessors
;
243 PsInitialSystemProcess
->Pcb
.IopmOffset
= 0xffff;
244 PsInitialSystemProcess
->Pcb
.BasePriority
= PROCESS_PRIORITY_NORMAL
;
245 PsInitialSystemProcess
->Pcb
.QuantumReset
= 6;
246 InitializeListHead(&PsInitialSystemProcess
->Pcb
.ThreadListHead
);
247 KeInitializeDispatcherHeader(&PsInitialSystemProcess
->Pcb
.Header
,
251 KProcess
= &PsInitialSystemProcess
->Pcb
;
252 PspInheritQuota(PsInitialSystemProcess
, NULL
);
254 MmInitializeAddressSpace(PsInitialSystemProcess
,
255 &PsInitialSystemProcess
->AddressSpace
);
257 KeInitializeEvent(&PsInitialSystemProcess
->LockEvent
, SynchronizationEvent
, FALSE
);
259 #if defined(__GNUC__)
260 KProcess
->DirectoryTableBase
=
261 (LARGE_INTEGER
)(LONGLONG
)(ULONG
)MmGetPageDirectory();
265 dummy
.QuadPart
= (LONGLONG
)(ULONG
)MmGetPageDirectory();
266 KProcess
->DirectoryTableBase
= dummy
;
270 strcpy(PsInitialSystemProcess
->ImageFileName
, "System");
272 PsInitialSystemProcess
->Win32WindowStation
= (HANDLE
)0;
274 InsertHeadList(&PsActiveProcessHead
,
275 &PsInitialSystemProcess
->ActiveProcessLinks
);
276 InitializeListHead(&PsInitialSystemProcess
->ThreadListHead
);
278 #ifndef SCHED_REWRITE
282 /* No parent, this is the Initial System Process. Assign Boot Token */
283 BootToken
= SepCreateSystemProcessToken();
284 BootToken
->TokenInUse
= TRUE
;
285 PsInitialSystemProcess
->Token
.Object
= BootToken
; /* FIXME */
286 ObReferenceObject(BootToken
);
292 PspPostInitSystemProcess(VOID
)
294 HANDLE_TABLE_ENTRY CidEntry
;
296 /* this routine is called directly after the exectuive handle tables were
297 initialized. We'll set up the Client ID handle table and assign the system
299 PsInitClientIDManagment();
301 ObCreateHandleTable(NULL
, FALSE
, PsInitialSystemProcess
);
302 ObpKernelHandleTable
= PsInitialSystemProcess
->ObjectTable
;
304 CidEntry
.u1
.Object
= PsInitialSystemProcess
;
305 CidEntry
.u2
.GrantedAccess
= 0;
306 PsInitialSystemProcess
->UniqueProcessId
= ExCreateHandle(PspCidTable
, &CidEntry
);
308 if(!PsInitialSystemProcess
->UniqueProcessId
)
310 DPRINT1("Failed to create CID handle (unique process id) for the system process!\n");
318 PspLookupKernelUserEntryPoints(VOID
)
320 ANSI_STRING ProcedureName
;
323 /* Retrieve ntdll's startup address */
324 DPRINT("Getting Entrypoint: %p\n", PspSystemDllBase
);
325 RtlInitAnsiString(&ProcedureName
, "LdrInitializeThunk");
326 Status
= LdrGetProcedureAddress((PVOID
)PspSystemDllBase
,
329 &PspSystemDllEntryPoint
);
331 if (!NT_SUCCESS(Status
)) {
333 DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status
);
337 /* Get User APC Dispatcher */
338 DPRINT("Getting Entrypoint\n");
339 RtlInitAnsiString(&ProcedureName
, "KiUserApcDispatcher");
340 Status
= LdrGetProcedureAddress((PVOID
)PspSystemDllBase
,
343 &KeUserApcDispatcher
);
345 if (!NT_SUCCESS(Status
)) {
347 DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status
);
351 /* Get Exception Dispatcher */
352 DPRINT("Getting Entrypoint\n");
353 RtlInitAnsiString(&ProcedureName
, "KiUserExceptionDispatcher");
354 Status
= LdrGetProcedureAddress((PVOID
)PspSystemDllBase
,
357 &KeUserExceptionDispatcher
);
359 if (!NT_SUCCESS(Status
)) {
361 DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status
);
365 /* Get Callback Dispatcher */
366 DPRINT("Getting Entrypoint\n");
367 RtlInitAnsiString(&ProcedureName
, "KiUserCallbackDispatcher");
368 Status
= LdrGetProcedureAddress((PVOID
)PspSystemDllBase
,
371 &KeUserCallbackDispatcher
);
373 if (!NT_SUCCESS(Status
)) {
375 DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status
);
379 /* Get Raise Exception Dispatcher */
380 DPRINT("Getting Entrypoint\n");
381 RtlInitAnsiString(&ProcedureName
, "KiRaiseUserExceptionDispatcher");
382 Status
= LdrGetProcedureAddress((PVOID
)PspSystemDllBase
,
385 &KeRaiseUserExceptionDispatcher
);
387 if (!NT_SUCCESS(Status
)) {
389 DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status
);
394 return(STATUS_SUCCESS
);
399 PspMapSystemDll(PEPROCESS Process
,
406 /* Map the System DLL */
407 DPRINT("Mapping System DLL\n");
408 Status
= MmMapViewOfSection(PspSystemDllSection
,
419 if (!NT_SUCCESS(Status
)) {
421 DPRINT1("Failed to map System DLL Into Process\n");
424 if (DllBase
) *DllBase
= ImageBase
;
432 PsLocateSystemDll(VOID
)
434 UNICODE_STRING DllPathname
= RTL_CONSTANT_STRING(L
"\\SystemRoot\\system32\\ntdll.dll");
435 OBJECT_ATTRIBUTES FileObjectAttributes
;
436 IO_STATUS_BLOCK Iosb
;
438 HANDLE NTDllSectionHandle
;
440 CHAR BlockBuffer
[1024];
441 PIMAGE_DOS_HEADER DosHeader
;
442 PIMAGE_NT_HEADERS NTHeaders
;
444 /* Locate and open NTDLL to determine ImageBase and LdrStartup */
445 InitializeObjectAttributes(&FileObjectAttributes
,
451 DPRINT("Opening NTDLL\n");
452 Status
= ZwOpenFile(&FileHandle
,
454 &FileObjectAttributes
,
457 FILE_SYNCHRONOUS_IO_NONALERT
);
459 if (!NT_SUCCESS(Status
)) {
460 DPRINT1("NTDLL open failed (Status %x)\n", Status
);
464 /* Load NTDLL is valid */
465 DPRINT("Reading NTDLL\n");
466 Status
= ZwReadFile(FileHandle
,
475 if (!NT_SUCCESS(Status
) || Iosb
.Information
!= sizeof(BlockBuffer
)) {
477 DPRINT1("NTDLL header read failed (Status %x)\n", Status
);
482 /* Check if it's valid */
483 DosHeader
= (PIMAGE_DOS_HEADER
)BlockBuffer
;
484 NTHeaders
= (PIMAGE_NT_HEADERS
)(BlockBuffer
+ DosHeader
->e_lfanew
);
486 if ((DosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
) ||
487 (DosHeader
->e_lfanew
== 0L) ||
488 (*(PULONG
) NTHeaders
!= IMAGE_NT_SIGNATURE
)) {
490 DPRINT1("NTDLL format invalid\n");
492 return(STATUS_UNSUCCESSFUL
);
495 /* Create a section for NTDLL */
496 DPRINT("Creating section\n");
497 Status
= ZwCreateSection(&NTDllSectionHandle
,
502 SEC_IMAGE
| SEC_COMMIT
,
504 if (!NT_SUCCESS(Status
)) {
506 DPRINT1("NTDLL create section failed (Status %x)\n", Status
);
512 /* Reference the Section */
513 DPRINT("ObReferenceObjectByHandle section: %d\n", NTDllSectionHandle
);
514 Status
= ObReferenceObjectByHandle(NTDllSectionHandle
,
518 (PVOID
*)&PspSystemDllSection
,
520 if (!NT_SUCCESS(Status
)) {
522 DPRINT1("NTDLL section reference failed (Status %x)\n", Status
);
527 PspMapSystemDll(PsGetCurrentProcess(), &PspSystemDllBase
);
528 DPRINT("LdrpSystemDllBase: %x\n", PspSystemDllBase
);
530 /* Now get the Entrypoints */
531 PspLookupKernelUserEntryPoints();
533 return STATUS_SUCCESS
;
537 /**********************************************************************
542 * Retrieves the current OS version.
545 * MajorVersion Pointer to a variable that will be set to the
546 * major version of the OS. Can be NULL.
548 * MinorVersion Pointer to a variable that will be set to the
549 * minor version of the OS. Can be NULL.
551 * BuildNumber Pointer to a variable that will be set to the
552 * build number of the OS. Can be NULL.
554 * CSDVersion Pointer to a variable that will be set to the
555 * CSD string of the OS. Can be NULL.
558 * TRUE OS is a checked build.
559 * FALSE OS is a free build.
567 PsGetVersion(PULONG MajorVersion OPTIONAL
,
568 PULONG MinorVersion OPTIONAL
,
569 PULONG BuildNumber OPTIONAL
,
570 PUNICODE_STRING CSDVersion OPTIONAL
)
573 *MajorVersion
= NtMajorVersion
;
576 *MinorVersion
= NtMinorVersion
;
579 *BuildNumber
= NtBuildNumber
;
583 CSDVersion
->Length
= 0;
584 CSDVersion
->MaximumLength
= 0;
585 CSDVersion
->Buffer
= NULL
;
587 CSDVersion
->Length
= CmCSDVersionString
.Length
;
588 CSDVersion
->MaximumLength
= CmCSDVersionString
.Maximum
;
589 CSDVersion
->Buffer
= CmCSDVersionString
.Buffer
;
593 /* Check the High word */
594 return (NtBuildNumber
>> 28) == 0xC;