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 ***************************************************************/
52 VOID
PiShutdownProcessManager(VOID
)
54 DPRINT("PiShutdownProcessManager()\n");
56 PspKillMostProcesses();
60 PiInitProcessManager(VOID
)
63 PsInitProcessManagment();
64 PsInitThreadManagment();
66 PsInitialiseW32Call();
71 PsInitClientIDManagment(VOID
)
73 PspCidTable
= ExCreateHandleTable(NULL
);
79 PsInitThreadManagment(VOID
)
81 * FUNCTION: Initialize thread managment
85 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
89 for (i
=0; i
< MAXIMUM_PRIORITY
; i
++)
91 InitializeListHead(&PriorityListHead
[i
]);
94 DPRINT("Creating Thread Object Type\n");
96 /* Initialize the Thread type */
97 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
98 RtlInitUnicodeString(&Name
, L
"Thread");
99 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
100 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(ETHREAD
);
101 ObjectTypeInitializer
.GenericMapping
= PiThreadMapping
;
102 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
103 ObjectTypeInitializer
.ValidAccessMask
= THREAD_ALL_ACCESS
;
104 ObjectTypeInitializer
.DeleteProcedure
= PspDeleteThread
;
105 ObpCreateTypeObject(&ObjectTypeInitializer
, &Name
, &PsThreadType
);
107 PsInitializeIdleOrFirstThread(PsInitialSystemProcess
, &FirstThread
, NULL
, KernelMode
, TRUE
);
108 FirstThread
->Tcb
.State
= Running
;
109 FirstThread
->Tcb
.FreezeCount
= 0;
110 FirstThread
->Tcb
.UserAffinity
= (1 << 0); /* Set the affinity of the first thread to the boot processor */
111 FirstThread
->Tcb
.Affinity
= (1 << 0);
112 KeGetCurrentPrcb()->CurrentThread
= (PVOID
)FirstThread
;
114 DPRINT("FirstThread %x\n",FirstThread
);
116 ExInitializeWorkItem(&PspReaperWorkItem
, PspReapRoutine
, NULL
);
121 PsInitProcessManagment(VOID
)
126 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
128 ShortPsLockDelay
.QuadPart
= -100LL;
129 PsLockTimeout
.QuadPart
= -10000000LL; /* one second */
131 * Register the process object type
134 DPRINT("Creating Process Object Type\n");
136 /* Initialize the Process type */
137 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
138 RtlInitUnicodeString(&Name
, L
"Process");
139 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
140 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(EPROCESS
);
141 ObjectTypeInitializer
.GenericMapping
= PiProcessMapping
;
142 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
143 ObjectTypeInitializer
.ValidAccessMask
= PROCESS_ALL_ACCESS
;
144 ObjectTypeInitializer
.DeleteProcedure
= PspDeleteProcess
;
145 ObpCreateTypeObject(&ObjectTypeInitializer
, &Name
, &PsProcessType
);
147 InitializeListHead(&PsActiveProcessHead
);
148 ExInitializeFastMutex(&PspActiveProcessMutex
);
151 * Initialize the default quota block.
154 RtlZeroMemory(&PspDefaultQuotaBlock
, sizeof(PspDefaultQuotaBlock
));
155 PspDefaultQuotaBlock
.QuotaEntry
[PagedPool
].Limit
= (SIZE_T
)-1;
156 PspDefaultQuotaBlock
.QuotaEntry
[NonPagedPool
].Limit
= (SIZE_T
)-1;
157 PspDefaultQuotaBlock
.QuotaEntry
[2].Limit
= (SIZE_T
)-1; /* Page file */
160 * Initialize the idle process
162 Status
= ObCreateObject(KernelMode
,
170 (PVOID
*)&PsIdleProcess
);
171 if (!NT_SUCCESS(Status
))
173 DPRINT1("Failed to create the idle process object, Status: 0x%x\n", Status
);
178 RtlZeroMemory(PsIdleProcess
, sizeof(EPROCESS
));
180 PsIdleProcess
->Pcb
.Affinity
= 0xFFFFFFFF;
181 PsIdleProcess
->Pcb
.IopmOffset
= 0xffff;
182 PsIdleProcess
->Pcb
.BasePriority
= PROCESS_PRIO_IDLE
;
183 PsIdleProcess
->Pcb
.QuantumReset
= 6;
184 InitializeListHead(&PsIdleProcess
->Pcb
.ThreadListHead
);
185 InitializeListHead(&PsIdleProcess
->ThreadListHead
);
186 InitializeListHead(&PsIdleProcess
->ActiveProcessLinks
);
187 KeInitializeDispatcherHeader(&PsIdleProcess
->Pcb
.Header
,
191 PsIdleProcess
->Pcb
.DirectoryTableBase
.QuadPart
= (ULONG_PTR
)MmGetPageDirectory();
192 strcpy(PsIdleProcess
->ImageFileName
, "Idle");
193 PspInheritQuota(PsIdleProcess
, NULL
);
196 * Initialize the system process
198 Status
= ObCreateObject(KernelMode
,
206 (PVOID
*)&PsInitialSystemProcess
);
207 if (!NT_SUCCESS(Status
))
209 DPRINT1("Failed to create the system process object, Status: 0x%x\n", Status
);
214 /* System threads may run on any processor. */
215 RtlZeroMemory(PsInitialSystemProcess
, sizeof(EPROCESS
));
216 PsInitialSystemProcess
->Pcb
.Affinity
= KeActiveProcessors
;
217 PsInitialSystemProcess
->Pcb
.IopmOffset
= 0xffff;
218 PsInitialSystemProcess
->Pcb
.BasePriority
= PROCESS_PRIO_NORMAL
;
219 PsInitialSystemProcess
->Pcb
.QuantumReset
= 6;
220 InitializeListHead(&PsInitialSystemProcess
->Pcb
.ThreadListHead
);
221 KeInitializeDispatcherHeader(&PsInitialSystemProcess
->Pcb
.Header
,
225 KProcess
= &PsInitialSystemProcess
->Pcb
;
226 PspInheritQuota(PsInitialSystemProcess
, NULL
);
228 MmInitializeAddressSpace(PsInitialSystemProcess
,
229 &PsInitialSystemProcess
->AddressSpace
);
231 KeInitializeEvent(&PsInitialSystemProcess
->LockEvent
, SynchronizationEvent
, FALSE
);
233 #if defined(__GNUC__)
234 KProcess
->DirectoryTableBase
=
235 (LARGE_INTEGER
)(LONGLONG
)(ULONG
)MmGetPageDirectory();
239 dummy
.QuadPart
= (LONGLONG
)(ULONG
)MmGetPageDirectory();
240 KProcess
->DirectoryTableBase
= dummy
;
244 strcpy(PsInitialSystemProcess
->ImageFileName
, "System");
246 PsInitialSystemProcess
->Win32WindowStation
= (HANDLE
)0;
248 InsertHeadList(&PsActiveProcessHead
,
249 &PsInitialSystemProcess
->ActiveProcessLinks
);
250 InitializeListHead(&PsInitialSystemProcess
->ThreadListHead
);
252 #ifndef SCHED_REWRITE
256 /* No parent, this is the Initial System Process. Assign Boot Token */
257 BootToken
= SepCreateSystemProcessToken();
258 BootToken
->TokenInUse
= TRUE
;
259 PsInitialSystemProcess
->Token
.Object
= BootToken
; /* FIXME */
260 ObReferenceObject(BootToken
);
266 PspPostInitSystemProcess(VOID
)
268 HANDLE_TABLE_ENTRY CidEntry
;
270 /* this routine is called directly after the exectuive handle tables were
271 initialized. We'll set up the Client ID handle table and assign the system
273 PsInitClientIDManagment();
275 ObCreateHandleTable(NULL
, FALSE
, PsInitialSystemProcess
);
276 ObpKernelHandleTable
= PsInitialSystemProcess
->ObjectTable
;
278 CidEntry
.u1
.Object
= PsInitialSystemProcess
;
279 CidEntry
.u2
.GrantedAccess
= 0;
280 PsInitialSystemProcess
->UniqueProcessId
= ExCreateHandle(PspCidTable
, &CidEntry
);
282 if(!PsInitialSystemProcess
->UniqueProcessId
)
284 DPRINT1("Failed to create CID handle (unique process id) for the system process!\n");
292 PspLookupKernelUserEntryPoints(VOID
)
294 ANSI_STRING ProcedureName
;
297 /* Retrieve ntdll's startup address */
298 DPRINT("Getting Entrypoint: %p\n", PspSystemDllBase
);
299 RtlInitAnsiString(&ProcedureName
, "LdrInitializeThunk");
300 Status
= LdrGetProcedureAddress((PVOID
)PspSystemDllBase
,
303 &PspSystemDllEntryPoint
);
305 if (!NT_SUCCESS(Status
)) {
307 DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status
);
311 /* Get User APC Dispatcher */
312 DPRINT("Getting Entrypoint\n");
313 RtlInitAnsiString(&ProcedureName
, "KiUserApcDispatcher");
314 Status
= LdrGetProcedureAddress((PVOID
)PspSystemDllBase
,
317 &KeUserApcDispatcher
);
319 if (!NT_SUCCESS(Status
)) {
321 DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status
);
325 /* Get Exception Dispatcher */
326 DPRINT("Getting Entrypoint\n");
327 RtlInitAnsiString(&ProcedureName
, "KiUserExceptionDispatcher");
328 Status
= LdrGetProcedureAddress((PVOID
)PspSystemDllBase
,
331 &KeUserExceptionDispatcher
);
333 if (!NT_SUCCESS(Status
)) {
335 DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status
);
339 /* Get Callback Dispatcher */
340 DPRINT("Getting Entrypoint\n");
341 RtlInitAnsiString(&ProcedureName
, "KiUserCallbackDispatcher");
342 Status
= LdrGetProcedureAddress((PVOID
)PspSystemDllBase
,
345 &KeUserCallbackDispatcher
);
347 if (!NT_SUCCESS(Status
)) {
349 DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status
);
353 /* Get Raise Exception Dispatcher */
354 DPRINT("Getting Entrypoint\n");
355 RtlInitAnsiString(&ProcedureName
, "KiRaiseUserExceptionDispatcher");
356 Status
= LdrGetProcedureAddress((PVOID
)PspSystemDllBase
,
359 &KeRaiseUserExceptionDispatcher
);
361 if (!NT_SUCCESS(Status
)) {
363 DPRINT1 ("LdrGetProcedureAddress failed (Status %x)\n", Status
);
368 return(STATUS_SUCCESS
);
373 PspMapSystemDll(PEPROCESS Process
,
380 /* Map the System DLL */
381 DPRINT("Mapping System DLL\n");
382 Status
= MmMapViewOfSection(PspSystemDllSection
,
393 if (!NT_SUCCESS(Status
)) {
395 DPRINT1("Failed to map System DLL Into Process\n");
398 if (DllBase
) *DllBase
= ImageBase
;
406 PsLocateSystemDll(VOID
)
408 UNICODE_STRING DllPathname
= RTL_CONSTANT_STRING(L
"\\SystemRoot\\system32\\ntdll.dll");
409 OBJECT_ATTRIBUTES FileObjectAttributes
;
410 IO_STATUS_BLOCK Iosb
;
412 HANDLE NTDllSectionHandle
;
414 CHAR BlockBuffer
[1024];
415 PIMAGE_DOS_HEADER DosHeader
;
416 PIMAGE_NT_HEADERS NTHeaders
;
418 /* Locate and open NTDLL to determine ImageBase and LdrStartup */
419 InitializeObjectAttributes(&FileObjectAttributes
,
425 DPRINT("Opening NTDLL\n");
426 Status
= ZwOpenFile(&FileHandle
,
428 &FileObjectAttributes
,
431 FILE_SYNCHRONOUS_IO_NONALERT
);
433 if (!NT_SUCCESS(Status
)) {
434 DPRINT1("NTDLL open failed (Status %x)\n", Status
);
438 /* Load NTDLL is valid */
439 DPRINT("Reading NTDLL\n");
440 Status
= ZwReadFile(FileHandle
,
449 if (!NT_SUCCESS(Status
) || Iosb
.Information
!= sizeof(BlockBuffer
)) {
451 DPRINT1("NTDLL header read failed (Status %x)\n", Status
);
456 /* Check if it's valid */
457 DosHeader
= (PIMAGE_DOS_HEADER
)BlockBuffer
;
458 NTHeaders
= (PIMAGE_NT_HEADERS
)(BlockBuffer
+ DosHeader
->e_lfanew
);
460 if ((DosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
) ||
461 (DosHeader
->e_lfanew
== 0L) ||
462 (*(PULONG
) NTHeaders
!= IMAGE_NT_SIGNATURE
)) {
464 DPRINT1("NTDLL format invalid\n");
466 return(STATUS_UNSUCCESSFUL
);
469 /* Create a section for NTDLL */
470 DPRINT("Creating section\n");
471 Status
= ZwCreateSection(&NTDllSectionHandle
,
476 SEC_IMAGE
| SEC_COMMIT
,
478 if (!NT_SUCCESS(Status
)) {
480 DPRINT1("NTDLL create section failed (Status %x)\n", Status
);
486 /* Reference the Section */
487 DPRINT("ObReferenceObjectByHandle section: %d\n", NTDllSectionHandle
);
488 Status
= ObReferenceObjectByHandle(NTDllSectionHandle
,
492 (PVOID
*)&PspSystemDllSection
,
494 if (!NT_SUCCESS(Status
)) {
496 DPRINT1("NTDLL section reference failed (Status %x)\n", Status
);
501 PspMapSystemDll(PsGetCurrentProcess(), &PspSystemDllBase
);
502 DPRINT("LdrpSystemDllBase: %x\n", PspSystemDllBase
);
504 /* Now get the Entrypoints */
505 PspLookupKernelUserEntryPoints();
507 return STATUS_SUCCESS
;
511 /**********************************************************************
516 * Retrieves the current OS version.
519 * MajorVersion Pointer to a variable that will be set to the
520 * major version of the OS. Can be NULL.
522 * MinorVersion Pointer to a variable that will be set to the
523 * minor version of the OS. Can be NULL.
525 * BuildNumber Pointer to a variable that will be set to the
526 * build number of the OS. Can be NULL.
528 * CSDVersion Pointer to a variable that will be set to the
529 * CSD string of the OS. Can be NULL.
532 * TRUE OS is a checked build.
533 * FALSE OS is a free build.
541 PsGetVersion(PULONG MajorVersion OPTIONAL
,
542 PULONG MinorVersion OPTIONAL
,
543 PULONG BuildNumber OPTIONAL
,
544 PUNICODE_STRING CSDVersion OPTIONAL
)
547 *MajorVersion
= NtMajorVersion
;
550 *MinorVersion
= NtMinorVersion
;
553 *BuildNumber
= NtBuildNumber
;
557 CSDVersion
->Length
= 0;
558 CSDVersion
->MaximumLength
= 0;
559 CSDVersion
->Buffer
= NULL
;
561 CSDVersion
->Length
= CmCSDVersionString
.Length
;
562 CSDVersion
->MaximumLength
= CmCSDVersionString
.Maximum
;
563 CSDVersion
->Buffer
= CmCSDVersionString
.Buffer
;
567 /* Check the High word */
568 return (NtBuildNumber
>> 28) == 0xC;