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>
22 #include <internal/ldr.h>
25 #include <internal/debug.h>
27 /* GLOBALS ******************************************************************/
29 PEPROCESS SystemProcess
= NULL
;
30 HANDLE SystemProcessHandle
= NULL
;
32 POBJECT_TYPE PsProcessType
= NULL
;
34 static LIST_ENTRY PsProcessListHead
;
35 static KSPIN_LOCK PsProcessListLock
;
36 static ULONG PiNextProcessUniqueId
= 0;
38 /* FUNCTIONS *****************************************************************/
40 NTSTATUS STDCALL
NtOpenProcessToken(IN HANDLE ProcessHandle
,
41 IN ACCESS_MASK DesiredAccess
,
42 OUT PHANDLE TokenHandle
)
47 Status
= PsOpenTokenOfProcess(ProcessHandle
,
49 if (!NT_SUCCESS(Status
))
53 Status
= ObCreateHandle(PsGetCurrentProcess(),
58 ObDereferenceObject(Token
);
62 PACCESS_TOKEN
PsReferencePrimaryToken(PEPROCESS Process
)
64 ObReferenceObjectByPointer(Process
->Token
,
68 return(Process
->Token
);
71 NTSTATUS
PsOpenTokenOfProcess(HANDLE ProcessHandle
,
77 Status
= ObReferenceObjectByHandle(ProcessHandle
,
78 PROCESS_QUERY_INFORMATION
,
83 if (!NT_SUCCESS(Status
))
87 *Token
= PsReferencePrimaryToken(Process
);
88 ObDereferenceObject(Process
);
89 return(STATUS_SUCCESS
);
92 VOID
PiKillMostProcesses(VOID
)
95 PLIST_ENTRY current_entry
;
98 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
100 current_entry
= PsProcessListHead
.Flink
;
101 while (current_entry
!= &PsProcessListHead
)
103 current
= CONTAINING_RECORD(current_entry
, EPROCESS
,
104 Pcb
.ProcessListEntry
);
105 current_entry
= current_entry
->Flink
;
107 if (current
->UniqueProcessId
!= SystemProcess
->UniqueProcessId
&&
108 current
->UniqueProcessId
!= (ULONG
)PsGetCurrentProcessId())
110 PiTerminateProcess(current
, STATUS_SUCCESS
);
114 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
117 VOID
PsInitProcessManagment(VOID
)
119 ANSI_STRING AnsiString
;
124 * Register the process object type
127 PsProcessType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
129 PsProcessType
->TotalObjects
= 0;
130 PsProcessType
->TotalHandles
= 0;
131 PsProcessType
->MaxObjects
= ULONG_MAX
;
132 PsProcessType
->MaxHandles
= ULONG_MAX
;
133 PsProcessType
->PagedPoolCharge
= 0;
134 PsProcessType
->NonpagedPoolCharge
= sizeof(EPROCESS
);
135 PsProcessType
->Dump
= NULL
;
136 PsProcessType
->Open
= NULL
;
137 PsProcessType
->Close
= NULL
;
138 PsProcessType
->Delete
= PiDeleteProcess
;
139 PsProcessType
->Parse
= NULL
;
140 PsProcessType
->Security
= NULL
;
141 PsProcessType
->QueryName
= NULL
;
142 PsProcessType
->OkayToClose
= NULL
;
143 PsProcessType
->Create
= NULL
;
145 RtlInitAnsiString(&AnsiString
,"Process");
146 RtlAnsiStringToUnicodeString(&PsProcessType
->TypeName
,&AnsiString
,TRUE
);
148 InitializeListHead(&PsProcessListHead
);
149 KeInitializeSpinLock(&PsProcessListLock
);
152 * Initialize the system process
154 SystemProcess
= ObCreateObject(NULL
,
158 SystemProcess
->Pcb
.BasePriority
= PROCESS_PRIO_NORMAL
;
159 KeInitializeDispatcherHeader(&SystemProcess
->Pcb
.DispatcherHeader
,
163 KProcess
= &SystemProcess
->Pcb
;
165 InitializeListHead(&(KProcess
->MemoryAreaList
));
166 ObCreateHandleTable(NULL
,FALSE
,SystemProcess
);
167 KProcess
->PageTableDirectory
= get_page_directory();
168 SystemProcess
->UniqueProcessId
=
169 InterlockedIncrement(&PiNextProcessUniqueId
);
171 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
172 InsertHeadList(&PsProcessListHead
, &KProcess
->ProcessListEntry
);
173 InitializeListHead( &KProcess
->ThreadListHead
);
174 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
176 strcpy(SystemProcess
->ImageFileName
, "SYSTEM");
178 ObCreateHandle(SystemProcess
,
182 &SystemProcessHandle
);
185 VOID
PiDeleteProcess(PVOID ObjectBody
)
189 DPRINT("PiDeleteProcess(ObjectBody %x)\n",ObjectBody
);
191 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
192 RemoveEntryList(&((PEPROCESS
)ObjectBody
)->Pcb
.ProcessListEntry
);
193 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
194 (VOID
)MmReleaseMmInfo((PEPROCESS
)ObjectBody
);
195 ObDeleteHandleTable((PEPROCESS
)ObjectBody
);
199 static NTSTATUS
PsCreatePeb(HANDLE ProcessHandle
,
209 memset(&Peb
, 0, sizeof(Peb
));
210 Peb
.ImageBaseAddress
= ImageBase
;
212 PebBase
= (PVOID
)PEB_BASE
;
214 Status
= NtAllocateVirtualMemory(ProcessHandle
,
220 if (!NT_SUCCESS(Status
))
225 ZwWriteVirtualMemory(ProcessHandle
,
231 DPRINT("PsCreatePeb: Peb created at %x\n", PebBase
);
235 return(STATUS_SUCCESS
);
239 PKPROCESS
KeGetCurrentProcess(VOID
)
241 * FUNCTION: Returns a pointer to the current process
244 return(&(PsGetCurrentProcess()->Pcb
));
247 HANDLE
PsGetCurrentProcessId(VOID
)
249 return((HANDLE
)PsGetCurrentProcess()->UniqueProcessId
);
252 struct _EPROCESS
* PsGetCurrentProcess(VOID
)
254 * FUNCTION: Returns a pointer to the current process
257 if (PsGetCurrentThread() == NULL
||
258 PsGetCurrentThread()->ThreadsProcess
== NULL
)
260 return(SystemProcess
);
264 return(PsGetCurrentThread()->ThreadsProcess
);
268 NTSTATUS STDCALL
NtCreateProcess (OUT PHANDLE ProcessHandle
,
269 IN ACCESS_MASK DesiredAccess
,
270 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
271 IN HANDLE ParentProcessHandle
,
272 IN BOOLEAN InheritObjectTable
,
273 IN HANDLE SectionHandle OPTIONAL
,
274 IN HANDLE DebugPort OPTIONAL
,
275 IN HANDLE ExceptionPort OPTIONAL
)
277 * FUNCTION: Creates a process.
279 * ProcessHandle (OUT) = Caller supplied storage for the resulting
281 * DesiredAccess = Specifies the allowed or desired access to the
282 * process can be a combination of
283 * STANDARD_RIGHTS_REQUIRED| ..
284 * ObjectAttribute = Initialized attributes for the object, contains
285 * the rootdirectory and the filename
286 * ParentProcess = Handle to the parent process.
287 * InheritObjectTable = Specifies to inherit the objects of the parent
289 * SectionHandle = Handle to a section object to back the image file
290 * DebugPort = Handle to a DebugPort if NULL the system default debug
292 * ExceptionPort = Handle to a exception port.
294 * This function maps to the win32 CreateProcess.
299 PEPROCESS ParentProcess
;
303 PVOID LdrStartupAddr
;
307 DPRINT("NtCreateProcess(ObjectAttributes %x)\n",ObjectAttributes
);
309 Status
= ObReferenceObjectByHandle(ParentProcessHandle
,
310 PROCESS_CREATE_PROCESS
,
313 (PVOID
*)&ParentProcess
,
316 if (Status
!= STATUS_SUCCESS
)
318 DPRINT("NtCreateProcess() = %x\n",Status
);
322 Process
= ObCreateObject(ProcessHandle
,
326 KeInitializeDispatcherHeader(&Process
->Pcb
.DispatcherHeader
,
330 KProcess
= &Process
->Pcb
;
332 KProcess
->BasePriority
= PROCESS_PRIO_NORMAL
;
333 InitializeListHead(&(KProcess
->MemoryAreaList
));
334 Process
->UniqueProcessId
= InterlockedIncrement(&PiNextProcessUniqueId
);
335 Process
->InheritedFromUniqueProcessId
= ParentProcess
->UniqueProcessId
;
336 ObCreateHandleTable(ParentProcess
,
339 MmCopyMmInfo(ParentProcess
, Process
);
341 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
342 InsertHeadList(&PsProcessListHead
, &KProcess
->ProcessListEntry
);
343 InitializeListHead( &KProcess
->ThreadListHead
);
344 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
346 Process
->Pcb
.ProcessState
= PROCESS_STATE_ACTIVE
;
349 * Now we have created the process proper
355 Status
= LdrpMapSystemDll(*ProcessHandle
,
357 if (!NT_SUCCESS(Status
))
359 DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status
);
360 ObDereferenceObject(Process
);
361 ObDereferenceObject(ParentProcess
);
366 * Map the process image
368 if (SectionHandle
!= NULL
)
370 DPRINT("Mapping process image\n");
371 Status
= LdrpMapImage(*ProcessHandle
,
374 if (!NT_SUCCESS(Status
))
376 DbgPrint("LdrpMapImage failed (Status %x)\n", Status
);
377 ObDereferenceObject(Process
);
378 ObDereferenceObject(ParentProcess
);
390 DPRINT("Creating PEB\n");
391 Status
= PsCreatePeb(*ProcessHandle
,
394 if (!NT_SUCCESS(Status
))
396 DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status
);
401 ObDereferenceObject(Process
);
402 ObDereferenceObject(ParentProcess
);
403 return(STATUS_SUCCESS
);
407 NTSTATUS STDCALL
NtOpenProcess (OUT PHANDLE ProcessHandle
,
408 IN ACCESS_MASK DesiredAccess
,
409 IN POBJECT_ATTRIBUTES ObjectAttributes
,
410 IN PCLIENT_ID ClientId
)
412 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
413 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
414 ProcessHandle
, DesiredAccess
, ObjectAttributes
, ClientId
,
415 ClientId
->UniqueProcess
, ClientId
->UniqueThread
);
419 * Not sure of the exact semantics
421 if (ObjectAttributes
!= NULL
&& ObjectAttributes
->ObjectName
!= NULL
&&
422 ObjectAttributes
->ObjectName
->Buffer
!= NULL
)
427 Status
= ObReferenceObjectByName(ObjectAttributes
->ObjectName
,
428 ObjectAttributes
->Attributes
,
435 if (Status
!= STATUS_SUCCESS
)
440 Status
= ObCreateHandle(PsGetCurrentProcess(),
445 ObDereferenceObject(Process
);
452 PLIST_ENTRY current_entry
;
456 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
457 current_entry
= PsProcessListHead
.Flink
;
458 while (current_entry
!= &PsProcessListHead
)
460 current
= CONTAINING_RECORD(current_entry
, EPROCESS
,
461 Pcb
.ProcessListEntry
);
462 if (current
->UniqueProcessId
== (ULONG
)ClientId
->UniqueProcess
)
464 ObReferenceObjectByPointer(current
,
468 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
469 Status
= ObCreateHandle(PsGetCurrentProcess(),
474 ObDereferenceObject(current
);
475 DPRINT("*ProcessHandle %x\n", ProcessHandle
);
476 DPRINT("NtOpenProcess() = %x\n", Status
);
479 current_entry
= current_entry
->Flink
;
481 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
482 DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
483 return(STATUS_UNSUCCESSFUL
);
485 return(STATUS_UNSUCCESSFUL
);
489 NTSTATUS STDCALL
NtQueryInformationProcess (IN HANDLE ProcessHandle
,
490 IN CINT ProcessInformationClass
,
491 OUT PVOID ProcessInformation
,
492 IN ULONG ProcessInformationLength
,
493 OUT PULONG ReturnLength
)
497 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP
;
499 Status
= ObReferenceObjectByHandle(ProcessHandle
,
500 PROCESS_SET_INFORMATION
,
505 if (Status
!= STATUS_SUCCESS
)
510 switch (ProcessInformationClass
)
512 case ProcessBasicInformation
:
513 ProcessBasicInformationP
= (PPROCESS_BASIC_INFORMATION
)
515 ProcessBasicInformationP
->ExitStatus
= Process
->ExitStatus
;
516 ProcessBasicInformationP
->PebBaseAddress
= Process
->Peb
;
517 ProcessBasicInformationP
->AffinityMask
= Process
->Pcb
.Affinity
;
518 ProcessBasicInformationP
->UniqueProcessId
=
519 Process
->UniqueProcessId
;
520 ProcessBasicInformationP
->InheritedFromUniqueProcessId
=
521 Process
->InheritedFromUniqueProcessId
;
522 Status
= STATUS_SUCCESS
;
525 case ProcessQuotaLimits
:
526 case ProcessIoCounters
:
527 case ProcessVmCounters
:
529 case ProcessBasePriority
:
530 case ProcessRaisePriority
:
531 case ProcessDebugPort
:
532 case ProcessExceptionPort
:
533 case ProcessAccessToken
:
534 case ProcessLdtInformation
:
536 Status
= STATUS_NOT_IMPLEMENTED
;
539 case ProcessDefaultHardErrorMode
:
540 *((PULONG
)ProcessInformation
) = Process
->DefaultHardErrorProcessing
;
543 case ProcessIoPortHandlers
:
544 case ProcessWorkingSetWatch
:
545 case ProcessUserModeIOPL
:
546 case ProcessEnableAlignmentFaultFixup
:
547 case ProcessPriorityClass
:
548 case ProcessWx86Information
:
549 case ProcessHandleCount
:
550 case ProcessAffinityMask
:
552 Status
= STATUS_NOT_IMPLEMENTED
;
554 ObDereferenceObject(Process
);
558 NTSTATUS
PspAssignPrimaryToken(PEPROCESS Process
,
562 PACCESS_TOKEN OldToken
;
565 Status
= ObReferenceObjectByHandle(TokenHandle
,
571 if (!NT_SUCCESS(Status
))
575 Status
= SeExchangePrimaryToken(Process
, Token
, &OldToken
);
576 if (!NT_SUCCESS(Status
))
578 ObDereferenceObject(OldToken
);
580 ObDereferenceObject(Token
);
584 NTSTATUS STDCALL
NtSetInformationProcess(IN HANDLE ProcessHandle
,
585 IN CINT ProcessInformationClass
,
586 IN PVOID ProcessInformation
,
587 IN ULONG ProcessInformationLength
)
591 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP
;
592 PHANDLE ProcessAccessTokenP
;
594 Status
= ObReferenceObjectByHandle(ProcessHandle
,
595 PROCESS_SET_INFORMATION
,
600 if (!NT_SUCCESS(Status
))
605 switch (ProcessInformationClass
)
607 case ProcessBasicInformation
:
608 ProcessBasicInformationP
= (PPROCESS_BASIC_INFORMATION
)
610 memset(ProcessBasicInformationP
, 0, sizeof(PROCESS_BASIC_INFORMATION
));
611 Process
->Pcb
.Affinity
= ProcessBasicInformationP
->AffinityMask
;
612 Status
= STATUS_SUCCESS
;
615 case ProcessQuotaLimits
:
616 case ProcessIoCounters
:
617 case ProcessVmCounters
:
619 case ProcessBasePriority
:
620 case ProcessRaisePriority
:
621 case ProcessDebugPort
:
622 case ProcessExceptionPort
:
623 case ProcessAccessToken
:
624 ProcessAccessTokenP
= (PHANDLE
)ProcessInformation
;
625 Status
= PspAssignPrimaryToken(Process
, *ProcessAccessTokenP
);
628 case ProcessImageFileName
:
629 memcpy(Process
->ImageFileName
, ProcessInformation
, 8);
630 // DPRINT1("Process->ImageFileName %.8s\n", Process->ImageFileName);
631 Status
= STATUS_SUCCESS
;
634 case ProcessLdtInformation
:
636 case ProcessDefaultHardErrorMode
:
637 case ProcessIoPortHandlers
:
638 case ProcessWorkingSetWatch
:
639 case ProcessUserModeIOPL
:
640 case ProcessEnableAlignmentFaultFixup
:
641 case ProcessPriorityClass
:
642 case ProcessWx86Information
:
643 case ProcessHandleCount
:
644 case ProcessAffinityMask
:
646 Status
= STATUS_NOT_IMPLEMENTED
;
648 ObDereferenceObject(Process
);