2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ps/process.c
5 * PURPOSE: Process managment
6 * PROGRAMMER: David Welch (welch@cwcom.net)
11 /* INCLUDES ******************************************************************/
13 #include <ddk/ntddk.h>
14 #include <internal/ob.h>
15 #include <internal/mm.h>
16 #include <internal/ke.h>
17 #include <internal/ps.h>
19 #include <internal/string.h>
20 #include <internal/id.h>
21 #include <internal/teb.h>
24 #include <internal/debug.h>
26 /* GLOBALS ******************************************************************/
28 PEPROCESS SystemProcess
= NULL
;
29 HANDLE SystemProcessHandle
= NULL
;
31 POBJECT_TYPE PsProcessType
= NULL
;
33 static LIST_ENTRY PsProcessListHead
;
34 static KSPIN_LOCK PsProcessListLock
;
35 static ULONG PiNextProcessUniqueId
= 0;
37 /* FUNCTIONS *****************************************************************/
39 VOID
PiKillMostProcesses(VOID
)
42 PLIST_ENTRY current_entry
;
45 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
47 current_entry
= PsProcessListHead
.Flink
;
48 while (current_entry
!= &PsProcessListHead
)
50 current
= CONTAINING_RECORD(current_entry
, EPROCESS
,
51 Pcb
.ProcessListEntry
);
52 current_entry
= current_entry
->Flink
;
54 if (current
->UniqueProcessId
!= SystemProcess
->UniqueProcessId
&&
55 current
->UniqueProcessId
!= (ULONG
)PsGetCurrentProcessId())
57 PiTerminateProcess(current
, STATUS_SUCCESS
);
61 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
64 VOID
PsInitProcessManagment(VOID
)
66 ANSI_STRING AnsiString
;
71 * Register the process object type
74 PsProcessType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
76 PsProcessType
->TotalObjects
= 0;
77 PsProcessType
->TotalHandles
= 0;
78 PsProcessType
->MaxObjects
= ULONG_MAX
;
79 PsProcessType
->MaxHandles
= ULONG_MAX
;
80 PsProcessType
->PagedPoolCharge
= 0;
81 PsProcessType
->NonpagedPoolCharge
= sizeof(EPROCESS
);
82 PsProcessType
->Dump
= NULL
;
83 PsProcessType
->Open
= NULL
;
84 PsProcessType
->Close
= NULL
;
85 PsProcessType
->Delete
= PiDeleteProcess
;
86 PsProcessType
->Parse
= NULL
;
87 PsProcessType
->Security
= NULL
;
88 PsProcessType
->QueryName
= NULL
;
89 PsProcessType
->OkayToClose
= NULL
;
90 PsProcessType
->Create
= NULL
;
92 RtlInitAnsiString(&AnsiString
,"Process");
93 RtlAnsiStringToUnicodeString(&PsProcessType
->TypeName
,&AnsiString
,TRUE
);
95 InitializeListHead(&PsProcessListHead
);
96 KeInitializeSpinLock(&PsProcessListLock
);
99 * Initialize the system process
101 SystemProcess
= ObCreateObject(NULL
,
105 SystemProcess
->Pcb
.BasePriority
= PROCESS_PRIO_NORMAL
;
106 KeInitializeDispatcherHeader(&SystemProcess
->Pcb
.DispatcherHeader
,
110 KProcess
= &SystemProcess
->Pcb
;
112 InitializeListHead(&(KProcess
->MemoryAreaList
));
113 ObCreateHandleTable(NULL
,FALSE
,SystemProcess
);
114 KProcess
->PageTableDirectory
= get_page_directory();
115 SystemProcess
->UniqueProcessId
=
116 InterlockedIncrement(&PiNextProcessUniqueId
);
118 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
119 InsertHeadList(&PsProcessListHead
, &KProcess
->ProcessListEntry
);
120 InitializeListHead( &KProcess
->ThreadListHead
);
121 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
123 ObCreateHandle(SystemProcess
,
127 &SystemProcessHandle
);
130 VOID
PiDeleteProcess(PVOID ObjectBody
)
134 DPRINT1("PiDeleteProcess(ObjectBody %x)\n",ObjectBody
);
136 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
137 RemoveEntryList(&((PEPROCESS
)ObjectBody
)->Pcb
.ProcessListEntry
);
138 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
139 (VOID
)MmReleaseMmInfo((PEPROCESS
)ObjectBody
);
140 ObDeleteHandleTable((PEPROCESS
)ObjectBody
);
144 static NTSTATUS
PsCreatePeb(HANDLE ProcessHandle
)
152 PebBase
= (PVOID
)PEB_BASE
;
154 Status
= NtAllocateVirtualMemory(ProcessHandle
,
160 if (!NT_SUCCESS(Status
))
165 memset(&Peb
, 0, sizeof(Peb
));
167 ZwWriteVirtualMemory(ProcessHandle
,
173 DPRINT("PsCreatePeb: Peb created at %x\n", PebBase
);
175 return(STATUS_SUCCESS
);
179 PKPROCESS
KeGetCurrentProcess(VOID
)
181 * FUNCTION: Returns a pointer to the current process
184 return(&(PsGetCurrentProcess()->Pcb
));
187 HANDLE
PsGetCurrentProcessId(VOID
)
189 return((HANDLE
)PsGetCurrentProcess()->UniqueProcessId
);
192 struct _EPROCESS
* PsGetCurrentProcess(VOID
)
194 * FUNCTION: Returns a pointer to the current process
197 if (PsGetCurrentThread() == NULL
||
198 PsGetCurrentThread()->ThreadsProcess
== NULL
)
200 return(SystemProcess
);
204 return(PsGetCurrentThread()->ThreadsProcess
);
211 OUT PHANDLE ProcessHandle
,
212 IN ACCESS_MASK DesiredAccess
,
213 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
214 IN HANDLE ParentProcessHandle
,
215 IN BOOLEAN InheritObjectTable
,
216 IN HANDLE SectionHandle OPTIONAL
,
217 IN HANDLE DebugPort OPTIONAL
,
218 IN HANDLE ExceptionPort OPTIONAL
221 * FUNCTION: Creates a process.
223 * ProcessHandle (OUT) = Caller supplied storage for the resulting
225 * DesiredAccess = Specifies the allowed or desired access to the
226 * process can be a combination of
227 * STANDARD_RIGHTS_REQUIRED| ..
228 * ObjectAttribute = Initialized attributes for the object, contains
229 * the rootdirectory and the filename
230 * ParentProcess = Handle to the parent process.
231 * InheritObjectTable = Specifies to inherit the objects of the parent
233 * SectionHandle = Handle to a section object to back the image file
234 * DebugPort = Handle to a DebugPort if NULL the system default debug
236 * ExceptionPort = Handle to a exception port.
238 * This function maps to the win32 CreateProcess.
243 PEPROCESS ParentProcess
;
248 DPRINT("NtCreateProcess(ObjectAttributes %x)\n",ObjectAttributes
);
250 Status
= ObReferenceObjectByHandle(ParentProcessHandle
,
251 PROCESS_CREATE_PROCESS
,
254 (PVOID
*)&ParentProcess
,
257 if (Status
!= STATUS_SUCCESS
)
259 DPRINT("NtCreateProcess() = %x\n",Status
);
263 Process
= ObCreateObject(ProcessHandle
,
267 KeInitializeDispatcherHeader(&Process
->Pcb
.DispatcherHeader
,
271 KProcess
= &(Process
->Pcb
);
273 KProcess
->BasePriority
= PROCESS_PRIO_NORMAL
;
274 InitializeListHead(&(KProcess
->MemoryAreaList
));
275 Process
->UniqueProcessId
= InterlockedIncrement(&PiNextProcessUniqueId
);
276 Process
->InheritedFromUniqueProcessId
= ParentProcess
->UniqueProcessId
;
277 ObCreateHandleTable(ParentProcess
,
280 MmCopyMmInfo(ParentProcess
, Process
);
282 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
283 InsertHeadList(&PsProcessListHead
, &KProcess
->ProcessListEntry
);
284 InitializeListHead( &KProcess
->ThreadListHead
);
285 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
287 Status
= PsCreatePeb (*ProcessHandle
);
288 if (!NT_SUCCESS(Status
))
290 // DPRINT("NtCreateProcess() Peb creation failed: Status %x\n",Status);
291 DbgPrint ("NtCreateProcess() Peb creation failed: Status %x\n",Status
);
296 * FIXME: I don't what I'm supposed to know with a section handle
298 if (SectionHandle
!= NULL
)
300 DbgPrint("NtCreateProcess() non-NULL SectionHandle\n");
301 return(STATUS_UNSUCCESSFUL
);
304 Process
->Pcb
.ProcessState
= PROCESS_STATE_ACTIVE
;
305 ObDereferenceObject(Process
);
306 ObDereferenceObject(ParentProcess
);
307 return(STATUS_SUCCESS
);
314 OUT PHANDLE ProcessHandle
,
315 IN ACCESS_MASK DesiredAccess
,
316 IN POBJECT_ATTRIBUTES ObjectAttributes
,
317 IN PCLIENT_ID ClientId
320 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
321 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
322 ProcessHandle
, DesiredAccess
, ObjectAttributes
, ClientId
,
323 ClientId
->UniqueProcess
, ClientId
->UniqueThread
);
327 * Not sure of the exact semantics
329 if (ObjectAttributes
!= NULL
&& ObjectAttributes
->ObjectName
!= NULL
&&
330 ObjectAttributes
->ObjectName
->Buffer
!= NULL
)
335 Status
= ObReferenceObjectByName(ObjectAttributes
->ObjectName
,
336 ObjectAttributes
->Attributes
,
343 if (Status
!= STATUS_SUCCESS
)
348 Status
= ObCreateHandle(PsGetCurrentProcess(),
353 ObDereferenceObject(Process
);
360 PLIST_ENTRY current_entry
;
364 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
365 current_entry
= PsProcessListHead
.Flink
;
366 while (current_entry
!= &PsProcessListHead
)
368 current
= CONTAINING_RECORD(current_entry
, EPROCESS
,
369 Pcb
.ProcessListEntry
);
370 if (current
->UniqueProcessId
== (ULONG
)ClientId
->UniqueProcess
)
372 ObReferenceObjectByPointer(current
,
376 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
377 Status
= ObCreateHandle(PsGetCurrentProcess(),
382 ObDereferenceObject(current
);
383 DPRINT("*ProcessHandle %x\n", ProcessHandle
);
384 DPRINT("NtOpenProcess() = %x\n", Status
);
387 current_entry
= current_entry
->Flink
;
389 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
390 DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
391 return(STATUS_UNSUCCESSFUL
);
393 return(STATUS_UNSUCCESSFUL
);
399 NtQueryInformationProcess (
400 IN HANDLE ProcessHandle
,
401 IN CINT ProcessInformationClass
,
402 OUT PVOID ProcessInformation
,
403 IN ULONG ProcessInformationLength
,
404 OUT PULONG ReturnLength
409 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP
;
411 Status
= ObReferenceObjectByHandle(ProcessHandle
,
412 PROCESS_SET_INFORMATION
,
417 if (Status
!= STATUS_SUCCESS
)
422 switch (ProcessInformationClass
)
424 case ProcessBasicInformation
:
425 ProcessBasicInformationP
= (PPROCESS_BASIC_INFORMATION
)
427 memset(ProcessBasicInformationP
, 0, sizeof(PROCESS_BASIC_INFORMATION
));
428 ProcessBasicInformationP
->AffinityMask
= Process
->Pcb
.Affinity
;
429 ProcessBasicInformationP
->UniqueProcessId
=
430 Process
->UniqueProcessId
;
431 ProcessBasicInformationP
->InheritedFromUniqueProcessId
=
432 Process
->InheritedFromUniqueProcessId
;
433 Status
= STATUS_SUCCESS
;
436 case ProcessQuotaLimits
:
437 case ProcessIoCounters
:
438 case ProcessVmCounters
:
440 case ProcessBasePriority
:
441 case ProcessRaisePriority
:
442 case ProcessDebugPort
:
443 case ProcessExceptionPort
:
444 case ProcessAccessToken
:
445 case ProcessLdtInformation
:
447 case ProcessDefaultHardErrorMode
:
448 case ProcessIoPortHandlers
:
449 case ProcessWorkingSetWatch
:
450 case ProcessUserModeIOPL
:
451 case ProcessEnableAlignmentFaultFixup
:
452 case ProcessPriorityClass
:
453 case ProcessWx86Information
:
454 case ProcessHandleCount
:
455 case ProcessAffinityMask
:
457 Status
= STATUS_NOT_IMPLEMENTED
;
459 ObDereferenceObject(Process
);
466 NtSetInformationProcess (
467 IN HANDLE ProcessHandle
,
468 IN CINT ProcessInformationClass
,
469 IN PVOID ProcessInformation
,
470 IN ULONG ProcessInformationLength
475 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP
;
477 Status
= ObReferenceObjectByHandle(ProcessHandle
,
478 PROCESS_SET_INFORMATION
,
483 if (Status
!= STATUS_SUCCESS
)
488 switch (ProcessInformationClass
)
490 case ProcessBasicInformation
:
491 ProcessBasicInformationP
= (PPROCESS_BASIC_INFORMATION
)
493 memset(ProcessBasicInformationP
, 0, sizeof(PROCESS_BASIC_INFORMATION
));
494 Process
->Pcb
.Affinity
= ProcessBasicInformationP
->AffinityMask
;
495 Status
= STATUS_SUCCESS
;
498 case ProcessQuotaLimits
:
499 case ProcessIoCounters
:
500 case ProcessVmCounters
:
502 case ProcessBasePriority
:
503 case ProcessRaisePriority
:
504 case ProcessDebugPort
:
505 case ProcessExceptionPort
:
506 case ProcessAccessToken
:
507 case ProcessLdtInformation
:
509 case ProcessDefaultHardErrorMode
:
510 case ProcessIoPortHandlers
:
511 case ProcessWorkingSetWatch
:
512 case ProcessUserModeIOPL
:
513 case ProcessEnableAlignmentFaultFixup
:
514 case ProcessPriorityClass
:
515 case ProcessWx86Information
:
516 case ProcessHandleCount
:
517 case ProcessAffinityMask
:
519 Status
= STATUS_NOT_IMPLEMENTED
;
521 ObDereferenceObject(Process
);