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
;
50 PsInitClientIDManagment(VOID
);
52 VOID STDCALL
PspKillMostProcesses();
54 /* FUNCTIONS ***************************************************************/
56 VOID
PiShutdownProcessManager(VOID
)
58 DPRINT("PiShutdownProcessManager()\n");
60 PspKillMostProcesses();
64 PiInitProcessManager(VOID
)
67 PsInitProcessManagment();
68 PsInitThreadManagment();
70 PsInitialiseW32Call();
75 PsInitThreadManagment(VOID
)
77 * FUNCTION: Initialize thread managment
81 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
85 for (i
=0; i
< MAXIMUM_PRIORITY
; i
++)
87 InitializeListHead(&PriorityListHead
[i
]);
90 DPRINT("Creating Thread Object Type\n");
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
);
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
;
110 DPRINT("FirstThread %x\n",FirstThread
);
112 ExInitializeWorkItem(&PspReaperWorkItem
, PspReapRoutine
, NULL
);
117 PsInitProcessManagment(VOID
)
122 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
124 ShortPsLockDelay
.QuadPart
= -100LL;
125 PsLockTimeout
.QuadPart
= -10000000LL; /* one second */
127 * Register the process object type
130 DPRINT("Creating Process Object Type\n");
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
);
143 InitializeListHead(&PsActiveProcessHead
);
144 ExInitializeFastMutex(&PspActiveProcessMutex
);
147 * Initialize the default quota block.
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 */
156 * Initialize the idle process
158 Status
= ObCreateObject(KernelMode
,
166 (PVOID
*)&PsIdleProcess
);
167 if (!NT_SUCCESS(Status
))
169 DPRINT1("Failed to create the idle process object, Status: 0x%x\n", Status
);
174 RtlZeroMemory(PsIdleProcess
, sizeof(EPROCESS
));
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
,
187 PsIdleProcess
->Pcb
.DirectoryTableBase
.QuadPart
= (ULONG_PTR
)MmGetPageDirectory();
188 strcpy(PsIdleProcess
->ImageFileName
, "Idle");
189 PspInheritQuota(PsIdleProcess
, NULL
);
192 * Initialize the system process
194 Status
= ObCreateObject(KernelMode
,
202 (PVOID
*)&PsInitialSystemProcess
);
203 if (!NT_SUCCESS(Status
))
205 DPRINT1("Failed to create the system process object, Status: 0x%x\n", Status
);
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
,
221 KProcess
= &PsInitialSystemProcess
->Pcb
;
222 PspInheritQuota(PsInitialSystemProcess
, NULL
);
224 MmInitializeAddressSpace(PsInitialSystemProcess
,
225 &PsInitialSystemProcess
->AddressSpace
);
227 KeInitializeEvent(&PsInitialSystemProcess
->LockEvent
, SynchronizationEvent
, FALSE
);
229 #if defined(__GNUC__)
230 KProcess
->DirectoryTableBase
=
231 (LARGE_INTEGER
)(LONGLONG
)(ULONG
)MmGetPageDirectory();
235 dummy
.QuadPart
= (LONGLONG
)(ULONG
)MmGetPageDirectory();
236 KProcess
->DirectoryTableBase
= dummy
;
240 strcpy(PsInitialSystemProcess
->ImageFileName
, "System");
242 PsInitialSystemProcess
->Win32WindowStation
= (HANDLE
)0;
244 InsertHeadList(&PsActiveProcessHead
,
245 &PsInitialSystemProcess
->ActiveProcessLinks
);
246 InitializeListHead(&PsInitialSystemProcess
->ThreadListHead
);
248 #ifndef SCHED_REWRITE
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
);
262 PspPostInitSystemProcess(VOID
)
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
269 PsInitClientIDManagment();
271 ObCreateHandleTable(NULL
, FALSE
, PsInitialSystemProcess
);
272 ObpKernelHandleTable
= PsInitialSystemProcess
->ObjectTable
;
274 Status
= PsCreateCidHandle(PsInitialSystemProcess
,
276 &PsInitialSystemProcess
->UniqueProcessId
);
277 if(!NT_SUCCESS(Status
))
279 DPRINT1("Failed to create CID handle (unique process id) for the system process!\n");
287 PspLookupKernelUserEntryPoints(VOID
)
289 ANSI_STRING ProcedureName
;
292 /* Retrieve ntdll's startup address */
293 DPRINT("Getting Entrypoint: %p\n", PspSystemDllBase
);
294 RtlInitAnsiString(&ProcedureName
, "LdrInitializeThunk");
295 Status
= LdrGetProcedureAddress((PVOID
)PspSystemDllBase
,
298 &PspSystemDllEntryPoint
);
300 if (!NT_SUCCESS(Status
)) {
302 DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status
);
306 /* Get User APC Dispatcher */
307 DPRINT("Getting Entrypoint\n");
308 RtlInitAnsiString(&ProcedureName
, "KiUserApcDispatcher");
309 Status
= LdrGetProcedureAddress((PVOID
)PspSystemDllBase
,
312 &KeUserApcDispatcher
);
314 if (!NT_SUCCESS(Status
)) {
316 DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status
);
320 /* Get Exception Dispatcher */
321 DPRINT("Getting Entrypoint\n");
322 RtlInitAnsiString(&ProcedureName
, "KiUserExceptionDispatcher");
323 Status
= LdrGetProcedureAddress((PVOID
)PspSystemDllBase
,
326 &KeUserExceptionDispatcher
);
328 if (!NT_SUCCESS(Status
)) {
330 DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status
);
334 /* Get Callback Dispatcher */
335 DPRINT("Getting Entrypoint\n");
336 RtlInitAnsiString(&ProcedureName
, "KiUserCallbackDispatcher");
337 Status
= LdrGetProcedureAddress((PVOID
)PspSystemDllBase
,
340 &KeUserCallbackDispatcher
);
342 if (!NT_SUCCESS(Status
)) {
344 DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status
);
348 /* Get Raise Exception Dispatcher */
349 DPRINT("Getting Entrypoint\n");
350 RtlInitAnsiString(&ProcedureName
, "KiRaiseUserExceptionDispatcher");
351 Status
= LdrGetProcedureAddress((PVOID
)PspSystemDllBase
,
354 &KeRaiseUserExceptionDispatcher
);
356 if (!NT_SUCCESS(Status
)) {
358 DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status
);
363 return(STATUS_SUCCESS
);
368 PspMapSystemDll(PEPROCESS Process
,
375 /* Map the System DLL */
376 DPRINT("Mapping System DLL\n");
377 Status
= MmMapViewOfSection(PspSystemDllSection
,
388 if (!NT_SUCCESS(Status
)) {
390 DPRINT1("Failed to map System DLL Into Process\n");
393 if (DllBase
) *DllBase
= ImageBase
;
401 PsLocateSystemDll(VOID
)
403 UNICODE_STRING DllPathname
= RTL_CONSTANT_STRING(L
"\\SystemRoot\\system32\\ntdll.dll");
404 OBJECT_ATTRIBUTES FileObjectAttributes
;
405 IO_STATUS_BLOCK Iosb
;
407 HANDLE NTDllSectionHandle
;
409 CHAR BlockBuffer
[1024];
410 PIMAGE_DOS_HEADER DosHeader
;
411 PIMAGE_NT_HEADERS NTHeaders
;
413 /* Locate and open NTDLL to determine ImageBase and LdrStartup */
414 InitializeObjectAttributes(&FileObjectAttributes
,
420 DPRINT("Opening NTDLL\n");
421 Status
= ZwOpenFile(&FileHandle
,
423 &FileObjectAttributes
,
426 FILE_SYNCHRONOUS_IO_NONALERT
);
428 if (!NT_SUCCESS(Status
)) {
429 DPRINT1("NTDLL open failed (Status %x)\n", Status
);
433 /* Load NTDLL is valid */
434 DPRINT("Reading NTDLL\n");
435 Status
= ZwReadFile(FileHandle
,
444 if (!NT_SUCCESS(Status
) || Iosb
.Information
!= sizeof(BlockBuffer
)) {
446 DPRINT1("NTDLL header read failed (Status %x)\n", Status
);
451 /* Check if it's valid */
452 DosHeader
= (PIMAGE_DOS_HEADER
)BlockBuffer
;
453 NTHeaders
= (PIMAGE_NT_HEADERS
)(BlockBuffer
+ DosHeader
->e_lfanew
);
455 if ((DosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
) ||
456 (DosHeader
->e_lfanew
== 0L) ||
457 (*(PULONG
) NTHeaders
!= IMAGE_NT_SIGNATURE
)) {
459 DPRINT1("NTDLL format invalid\n");
461 return(STATUS_UNSUCCESSFUL
);
464 /* Create a section for NTDLL */
465 DPRINT("Creating section\n");
466 Status
= ZwCreateSection(&NTDllSectionHandle
,
471 SEC_IMAGE
| SEC_COMMIT
,
473 if (!NT_SUCCESS(Status
)) {
475 DPRINT1("NTDLL create section failed (Status %x)\n", Status
);
481 /* Reference the Section */
482 DPRINT("ObReferenceObjectByHandle section: %d\n", NTDllSectionHandle
);
483 Status
= ObReferenceObjectByHandle(NTDllSectionHandle
,
487 (PVOID
*)&PspSystemDllSection
,
489 if (!NT_SUCCESS(Status
)) {
491 DPRINT1("NTDLL section reference failed (Status %x)\n", Status
);
496 PspMapSystemDll(PsGetCurrentProcess(), &PspSystemDllBase
);
497 DPRINT("LdrpSystemDllBase: %x\n", PspSystemDllBase
);
499 /* Now get the Entrypoints */
500 PspLookupKernelUserEntryPoints();
502 return STATUS_SUCCESS
;
506 /**********************************************************************
511 * Retrieves the current OS version.
514 * MajorVersion Pointer to a variable that will be set to the
515 * major version of the OS. Can be NULL.
517 * MinorVersion Pointer to a variable that will be set to the
518 * minor version of the OS. Can be NULL.
520 * BuildNumber Pointer to a variable that will be set to the
521 * build number of the OS. Can be NULL.
523 * CSDVersion Pointer to a variable that will be set to the
524 * CSD string of the OS. Can be NULL.
527 * TRUE OS is a checked build.
528 * FALSE OS is a free build.
536 PsGetVersion(PULONG MajorVersion OPTIONAL
,
537 PULONG MinorVersion OPTIONAL
,
538 PULONG BuildNumber OPTIONAL
,
539 PUNICODE_STRING CSDVersion OPTIONAL
)
542 *MajorVersion
= NtMajorVersion
;
545 *MinorVersion
= NtMinorVersion
;
548 *BuildNumber
= NtBuildNumber
;
552 CSDVersion
->Length
= 0;
553 CSDVersion
->MaximumLength
= 0;
554 CSDVersion
->Buffer
= NULL
;
556 CSDVersion
->Length
= CmCSDVersionString
.Length
;
557 CSDVersion
->MaximumLength
= CmCSDVersionString
.Maximum
;
558 CSDVersion
->Buffer
= CmCSDVersionString
.Buffer
;
562 /* Check the High word */
563 return (NtBuildNumber
>> 28) == 0xC;