3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ps/process.c
6 * PURPOSE: Process managment
8 * PROGRAMMERS: David Welch (welch@cwcom.net)
11 /* INCLUDES ******************************************************************/
15 #include <internal/debug.h>
17 /* GLOBALS ******************************************************************/
19 VOID INIT_FUNCTION
PsInitClientIDManagment(VOID
);
21 PEPROCESS EXPORTED PsInitialSystemProcess
= NULL
;
22 PEPROCESS PsIdleProcess
= NULL
;
24 POBJECT_TYPE EXPORTED PsProcessType
= NULL
;
26 LIST_ENTRY PsActiveProcessHead
;
27 FAST_MUTEX PspActiveProcessMutex
;
28 static LARGE_INTEGER ShortPsLockDelay
, PsLockTimeout
;
30 static GENERIC_MAPPING PiProcessMapping
= {STANDARD_RIGHTS_READ
| PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
31 STANDARD_RIGHTS_WRITE
| PROCESS_CREATE_PROCESS
| PROCESS_CREATE_THREAD
|
32 PROCESS_VM_OPERATION
| PROCESS_VM_WRITE
| PROCESS_DUP_HANDLE
|
33 PROCESS_TERMINATE
| PROCESS_SET_QUOTA
| PROCESS_SET_INFORMATION
| PROCESS_SET_PORT
,
34 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
,
37 #define MAX_PROCESS_NOTIFY_ROUTINE_COUNT 8
38 #define MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT 8
40 static PCREATE_PROCESS_NOTIFY_ROUTINE
41 PiProcessNotifyRoutine
[MAX_PROCESS_NOTIFY_ROUTINE_COUNT
];
42 static PLOAD_IMAGE_NOTIFY_ROUTINE
43 PiLoadImageNotifyRoutine
[MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT
];
46 /* FUNCTIONS *****************************************************************/
49 PsGetNextProcess(PEPROCESS OldProcess
)
51 PEPROCESS NextProcess
;
54 if (OldProcess
== NULL
)
56 Status
= ObReferenceObjectByPointer(PsIdleProcess
,
60 if (!NT_SUCCESS(Status
))
62 CPRINT("PsGetNextProcess(): ObReferenceObjectByPointer failed for PsIdleProcess\n");
68 ExAcquireFastMutex(&PspActiveProcessMutex
);
69 NextProcess
= OldProcess
;
72 PLIST_ENTRY Flink
= (NextProcess
== PsIdleProcess
? PsActiveProcessHead
.Flink
:
73 NextProcess
->ProcessListEntry
.Flink
);
74 if (Flink
!= &PsActiveProcessHead
)
76 NextProcess
= CONTAINING_RECORD(Flink
,
86 Status
= ObReferenceObjectByPointer(NextProcess
,
90 if (NT_SUCCESS(Status
))
94 else if (Status
== STATUS_PROCESS_IS_TERMINATING
)
98 else if (!NT_SUCCESS(Status
))
104 ExReleaseFastMutex(&PspActiveProcessMutex
);
105 ObDereferenceObject(OldProcess
);
111 PiKillMostProcesses(VOID
)
113 PLIST_ENTRY current_entry
;
116 ExAcquireFastMutex(&PspActiveProcessMutex
);
118 current_entry
= PsActiveProcessHead
.Flink
;
119 while (current_entry
!= &PsActiveProcessHead
)
121 current
= CONTAINING_RECORD(current_entry
, EPROCESS
,
123 current_entry
= current_entry
->Flink
;
125 if (current
->UniqueProcessId
!= PsInitialSystemProcess
->UniqueProcessId
&&
126 current
->UniqueProcessId
!= PsGetCurrentProcessId())
128 PspTerminateProcessThreads(current
, STATUS_SUCCESS
);
132 ExReleaseFastMutex(&PspActiveProcessMutex
);
136 PsInitProcessManagment(VOID
)
141 ShortPsLockDelay
.QuadPart
= -100LL;
142 PsLockTimeout
.QuadPart
= -10000000LL; /* one second */
144 * Register the process object type
147 PsProcessType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
149 PsProcessType
->Tag
= TAG('P', 'R', 'O', 'C');
150 PsProcessType
->TotalObjects
= 0;
151 PsProcessType
->TotalHandles
= 0;
152 PsProcessType
->PeakObjects
= 0;
153 PsProcessType
->PeakHandles
= 0;
154 PsProcessType
->PagedPoolCharge
= 0;
155 PsProcessType
->NonpagedPoolCharge
= sizeof(EPROCESS
);
156 PsProcessType
->Mapping
= &PiProcessMapping
;
157 PsProcessType
->Dump
= NULL
;
158 PsProcessType
->Open
= NULL
;
159 PsProcessType
->Close
= NULL
;
160 PsProcessType
->Delete
= PspDeleteProcess
;
161 PsProcessType
->Parse
= NULL
;
162 PsProcessType
->Security
= NULL
;
163 PsProcessType
->QueryName
= NULL
;
164 PsProcessType
->OkayToClose
= NULL
;
165 PsProcessType
->Create
= NULL
;
166 PsProcessType
->DuplicationNotify
= NULL
;
168 RtlInitUnicodeString(&PsProcessType
->TypeName
, L
"Process");
170 ObpCreateTypeObject(PsProcessType
);
172 InitializeListHead(&PsActiveProcessHead
);
173 ExInitializeFastMutex(&PspActiveProcessMutex
);
175 RtlZeroMemory(PiProcessNotifyRoutine
, sizeof(PiProcessNotifyRoutine
));
176 RtlZeroMemory(PiLoadImageNotifyRoutine
, sizeof(PiLoadImageNotifyRoutine
));
179 * Initialize the idle process
181 Status
= ObCreateObject(KernelMode
,
189 (PVOID
*)&PsIdleProcess
);
190 if (!NT_SUCCESS(Status
))
192 DPRINT1("Failed to create the idle process object, Status: 0x%x\n", Status
);
197 RtlZeroMemory(PsIdleProcess
, sizeof(EPROCESS
));
199 PsIdleProcess
->Pcb
.Affinity
= 0xFFFFFFFF;
200 PsIdleProcess
->Pcb
.IopmOffset
= 0xffff;
201 PsIdleProcess
->Pcb
.LdtDescriptor
[0] = 0;
202 PsIdleProcess
->Pcb
.LdtDescriptor
[1] = 0;
203 PsIdleProcess
->Pcb
.BasePriority
= PROCESS_PRIO_IDLE
;
204 PsIdleProcess
->Pcb
.ThreadQuantum
= 6;
205 InitializeListHead(&PsIdleProcess
->Pcb
.ThreadListHead
);
206 InitializeListHead(&PsIdleProcess
->ThreadListHead
);
207 InitializeListHead(&PsIdleProcess
->ProcessListEntry
);
208 KeInitializeDispatcherHeader(&PsIdleProcess
->Pcb
.DispatcherHeader
,
212 PsIdleProcess
->Pcb
.DirectoryTableBase
=
213 (LARGE_INTEGER
)(LONGLONG
)(ULONG
)MmGetPageDirectory();
214 strcpy(PsIdleProcess
->ImageFileName
, "Idle");
217 * Initialize the system process
219 Status
= ObCreateObject(KernelMode
,
227 (PVOID
*)&PsInitialSystemProcess
);
228 if (!NT_SUCCESS(Status
))
230 DPRINT1("Failed to create the system process object, Status: 0x%x\n", Status
);
235 /* System threads may run on any processor. */
236 PsInitialSystemProcess
->Pcb
.Affinity
= 0xFFFFFFFF;
237 PsInitialSystemProcess
->Pcb
.IopmOffset
= 0xffff;
238 PsInitialSystemProcess
->Pcb
.LdtDescriptor
[0] = 0;
239 PsInitialSystemProcess
->Pcb
.LdtDescriptor
[1] = 0;
240 PsInitialSystemProcess
->Pcb
.BasePriority
= PROCESS_PRIO_NORMAL
;
241 PsInitialSystemProcess
->Pcb
.ThreadQuantum
= 6;
242 InitializeListHead(&PsInitialSystemProcess
->Pcb
.ThreadListHead
);
243 KeInitializeDispatcherHeader(&PsInitialSystemProcess
->Pcb
.DispatcherHeader
,
247 KProcess
= &PsInitialSystemProcess
->Pcb
;
249 MmInitializeAddressSpace(PsInitialSystemProcess
,
250 &PsInitialSystemProcess
->AddressSpace
);
252 KeInitializeEvent(&PsInitialSystemProcess
->LockEvent
, SynchronizationEvent
, FALSE
);
253 PsInitialSystemProcess
->LockCount
= 0;
254 PsInitialSystemProcess
->LockOwner
= NULL
;
256 #if defined(__GNUC__)
257 KProcess
->DirectoryTableBase
=
258 (LARGE_INTEGER
)(LONGLONG
)(ULONG
)MmGetPageDirectory();
262 dummy
.QuadPart
= (LONGLONG
)(ULONG
)MmGetPageDirectory();
263 KProcess
->DirectoryTableBase
= dummy
;
267 strcpy(PsInitialSystemProcess
->ImageFileName
, "System");
269 PsInitialSystemProcess
->Win32WindowStation
= (HANDLE
)0;
271 InsertHeadList(&PsActiveProcessHead
,
272 &PsInitialSystemProcess
->ProcessListEntry
);
273 InitializeListHead(&PsInitialSystemProcess
->ThreadListHead
);
275 SepCreateSystemProcessToken(PsInitialSystemProcess
);
279 PspPostInitSystemProcess(VOID
)
283 /* this routine is called directly after the exectuive handle tables were
284 initialized. We'll set up the Client ID handle table and assign the system
286 PsInitClientIDManagment();
288 ObCreateHandleTable(NULL
, FALSE
, PsInitialSystemProcess
);
290 Status
= PsCreateCidHandle(PsInitialSystemProcess
,
292 &PsInitialSystemProcess
->UniqueProcessId
);
293 if(!NT_SUCCESS(Status
))
295 DPRINT1("Failed to create CID handle (unique process id) for the system process!\n");
301 PsCreatePeb(HANDLE ProcessHandle
,
308 LARGE_INTEGER SectionOffset
;
315 /* Allocate the Process Environment Block (PEB) */
316 Process
->TebBlock
= (PVOID
) MM_ROUND_DOWN(PEB_BASE
, MM_VIRTMEM_GRANULARITY
);
317 AllocSize
= MM_VIRTMEM_GRANULARITY
;
318 Status
= NtAllocateVirtualMemory(ProcessHandle
,
324 if (!NT_SUCCESS(Status
))
326 DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status
);
329 ASSERT((ULONG_PTR
) Process
->TebBlock
<= PEB_BASE
&&
330 PEB_BASE
+ PAGE_SIZE
<= (ULONG_PTR
) Process
->TebBlock
+ AllocSize
);
331 Peb
= (PPEB
)PEB_BASE
;
333 Status
= NtAllocateVirtualMemory(ProcessHandle
,
339 if (!NT_SUCCESS(Status
))
341 DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status
);
344 DPRINT("Peb %p PebSize %lu\n", Peb
, PebSize
);
345 ASSERT((PPEB
) PEB_BASE
== Peb
&& PAGE_SIZE
<= PebSize
);
346 Process
->TebLastAllocated
= (PVOID
) Peb
;
349 SectionOffset
.QuadPart
= (ULONGLONG
)0;
351 Status
= MmMapViewOfSection(NlsSectionObject
,
361 if (!NT_SUCCESS(Status
))
363 DPRINT1("MmMapViewOfSection() failed (Status %lx)\n", Status
);
366 DPRINT("TableBase %p ViewSize %lx\n", TableBase
, ViewSize
);
368 KeAttachProcess(&Process
->Pcb
);
370 /* Initialize the PEB */
371 RtlZeroMemory(Peb
, sizeof(PEB
));
372 Peb
->ImageBaseAddress
= ImageBase
;
374 Peb
->OSMajorVersion
= 4;
375 Peb
->OSMinorVersion
= 0;
376 Peb
->OSBuildNumber
= 1381;
377 Peb
->OSPlatformId
= 2; //VER_PLATFORM_WIN32_NT;
378 Peb
->OSCSDVersion
= 6 << 8;
380 Peb
->AnsiCodePageData
= (char*)TableBase
+ NlsAnsiTableOffset
;
381 Peb
->OemCodePageData
= (char*)TableBase
+ NlsOemTableOffset
;
382 Peb
->UnicodeCaseTableData
= (char*)TableBase
+ NlsUnicodeTableOffset
;
387 DPRINT("PsCreatePeb: Peb created at %p\n", Peb
);
389 return(STATUS_SUCCESS
);
394 KeGetCurrentProcess(VOID
)
396 * FUNCTION: Returns a pointer to the current process
399 return(&(PsGetCurrentProcess()->Pcb
));
403 * Warning: Even though it returns HANDLE, it's not a real HANDLE but really a
404 * ULONG ProcessId! (Skywing)
410 PsGetCurrentProcessId(VOID
)
412 return((HANDLE
)PsGetCurrentProcess()->UniqueProcessId
);
420 PsGetCurrentProcessSessionId (
424 return PsGetCurrentProcess()->SessionId
;
428 * FUNCTION: Returns a pointer to the current process
433 IoGetCurrentProcess(VOID
)
435 if (PsGetCurrentThread() == NULL
||
436 PsGetCurrentThread()->Tcb
.ApcState
.Process
== NULL
)
438 return(PsInitialSystemProcess
);
442 return(PEPROCESS
)(PsGetCurrentThread()->Tcb
.ApcState
.Process
);
447 PspCreateProcess(OUT PHANDLE ProcessHandle
,
448 IN ACCESS_MASK DesiredAccess
,
449 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
450 IN HANDLE ParentProcess OPTIONAL
,
451 IN BOOLEAN InheritObjectTable
,
452 IN HANDLE SectionHandle OPTIONAL
,
453 IN HANDLE DebugPort OPTIONAL
,
454 IN HANDLE ExceptionPort OPTIONAL
)
458 PEPROCESS pParentProcess
;
460 PVOID LdrStartupAddr
;
462 PMEMORY_AREA MemoryArea
;
463 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
464 KPROCESSOR_MODE PreviousMode
;
465 PVOID ImageBase
= NULL
;
466 PEPORT pDebugPort
= NULL
;
467 PEPORT pExceptionPort
= NULL
;
468 PSECTION_OBJECT SectionObject
= NULL
;
469 NTSTATUS Status
= STATUS_SUCCESS
;
471 DPRINT("PspCreateProcess(ObjectAttributes %x)\n", ObjectAttributes
);
473 PreviousMode
= ExGetPreviousMode();
475 BoundaryAddressMultiple
.QuadPart
= 0;
477 if(ParentProcess
!= NULL
)
479 Status
= ObReferenceObjectByHandle(ParentProcess
,
480 PROCESS_CREATE_PROCESS
,
483 (PVOID
*)&pParentProcess
,
485 if (!NT_SUCCESS(Status
))
487 DPRINT1("Failed to reference the parent process: Status: 0x%x\n", Status
);
493 pParentProcess
= NULL
;
499 if (DebugPort
!= NULL
)
501 Status
= ObReferenceObjectByHandle(DebugPort
,
507 if (!NT_SUCCESS(Status
))
509 DPRINT1("Failed to reference the debug port: Status: 0x%x\n", Status
);
510 goto exitdereferenceobjects
;
515 * Add the exception port
517 if (ExceptionPort
!= NULL
)
519 Status
= ObReferenceObjectByHandle(ExceptionPort
,
523 (PVOID
*)&pExceptionPort
,
525 if (!NT_SUCCESS(Status
))
527 DPRINT1("Failed to reference the exception port: Status: 0x%x\n", Status
);
528 goto exitdereferenceobjects
;
532 if (SectionHandle
!= NULL
)
534 Status
= ObReferenceObjectByHandle(SectionHandle
,
538 (PVOID
*)&SectionObject
,
540 if (!NT_SUCCESS(Status
))
542 DPRINT1("Failed to reference process image section: Status: 0x%x\n", Status
);
543 goto exitdereferenceobjects
;
547 Status
= ObCreateObject(PreviousMode
,
556 if (!NT_SUCCESS(Status
))
558 DPRINT1("Failed to create process object, Status: 0x%x\n", Status
);
560 exitdereferenceobjects
:
561 if(SectionObject
!= NULL
)
562 ObDereferenceObject(SectionObject
);
563 if(pExceptionPort
!= NULL
)
564 ObDereferenceObject(pExceptionPort
);
565 if(pDebugPort
!= NULL
)
566 ObDereferenceObject(pDebugPort
);
567 if(pParentProcess
!= NULL
)
568 ObDereferenceObject(pParentProcess
);
572 KProcess
= &Process
->Pcb
;
574 RtlZeroMemory(Process
, sizeof(EPROCESS
));
576 Status
= PsCreateCidHandle(Process
,
578 &Process
->UniqueProcessId
);
579 if(!NT_SUCCESS(Status
))
581 DPRINT1("Failed to create CID handle (unique process ID)! Status: 0x%x\n", Status
);
582 ObDereferenceObject(Process
);
583 goto exitdereferenceobjects
;
586 Process
->DebugPort
= pDebugPort
;
587 Process
->ExceptionPort
= pExceptionPort
;
589 if(SectionObject
!= NULL
)
591 UNICODE_STRING FileName
;
597 * Determine the image file name and save it to the EPROCESS structure
600 FileName
= SectionObject
->FileObject
->FileName
;
601 szSrc
= (PWCHAR
)(FileName
.Buffer
+ (FileName
.Length
/ sizeof(WCHAR
)) - 1);
602 while(szSrc
>= FileName
.Buffer
)
616 /* copy the image file name to the process and truncate it to 15 characters
618 szDest
= Process
->ImageFileName
;
619 lnFName
= min(lnFName
, sizeof(Process
->ImageFileName
) - 1);
622 *(szDest
++) = (UCHAR
)*(szSrc
++);
624 /* *szDest = '\0'; */
627 KeInitializeDispatcherHeader(&KProcess
->DispatcherHeader
,
632 /* Inherit parent process's affinity. */
633 if(pParentProcess
!= NULL
)
635 KProcess
->Affinity
= pParentProcess
->Pcb
.Affinity
;
636 Process
->InheritedFromUniqueProcessId
= pParentProcess
->UniqueProcessId
;
637 Process
->SessionId
= pParentProcess
->SessionId
;
641 KProcess
->Affinity
= KeActiveProcessors
;
644 KProcess
->BasePriority
= PROCESS_PRIO_NORMAL
;
645 KProcess
->IopmOffset
= 0xffff;
646 KProcess
->LdtDescriptor
[0] = 0;
647 KProcess
->LdtDescriptor
[1] = 0;
648 InitializeListHead(&KProcess
->ThreadListHead
);
649 KProcess
->ThreadQuantum
= 6;
650 KProcess
->AutoAlignment
= 0;
651 MmInitializeAddressSpace(Process
,
652 &Process
->AddressSpace
);
654 ObCreateHandleTable(pParentProcess
,
657 MmCopyMmInfo(pParentProcess
? pParentProcess
: PsInitialSystemProcess
, Process
);
659 KeInitializeEvent(&Process
->LockEvent
, SynchronizationEvent
, FALSE
);
660 Process
->LockCount
= 0;
661 Process
->LockOwner
= NULL
;
663 Process
->Win32WindowStation
= (HANDLE
)0;
665 ExAcquireFastMutex(&PspActiveProcessMutex
);
666 InsertTailList(&PsActiveProcessHead
, &Process
->ProcessListEntry
);
667 InitializeListHead(&Process
->ThreadListHead
);
668 ExReleaseFastMutex(&PspActiveProcessMutex
);
670 ExInitializeFastMutex(&Process
->TebLock
);
671 Process
->Pcb
.State
= PROCESS_STATE_ACTIVE
;
674 * Now we have created the process proper
677 MmLockAddressSpace(&Process
->AddressSpace
);
679 /* Protect the highest 64KB of the process address space */
680 BaseAddress
= (PVOID
)MmUserProbeAddress
;
681 Status
= MmCreateMemoryArea(Process
,
682 &Process
->AddressSpace
,
683 MEMORY_AREA_NO_ACCESS
,
690 BoundaryAddressMultiple
);
691 if (!NT_SUCCESS(Status
))
693 MmUnlockAddressSpace(&Process
->AddressSpace
);
694 DPRINT1("Failed to protect the highest 64KB of the process address space\n");
695 ObDereferenceObject(Process
);
696 goto exitdereferenceobjects
;
699 /* Protect the lowest 64KB of the process address space */
701 BaseAddress
= (PVOID
)0x00000000;
702 Status
= MmCreateMemoryArea(Process
,
703 &Process
->AddressSpace
,
704 MEMORY_AREA_NO_ACCESS
,
711 BoundaryAddressMultiple
);
712 if (!NT_SUCCESS(Status
))
714 MmUnlockAddressSpace(&Process
->AddressSpace
);
715 DPRINT1("Failed to protect the lowest 64KB of the process address space\n");
716 ObDereferenceObject(Process
);
717 goto exitdereferenceobjects
;
721 /* Protect the 60KB above the shared user page */
722 BaseAddress
= (char*)USER_SHARED_DATA
+ PAGE_SIZE
;
723 Status
= MmCreateMemoryArea(Process
,
724 &Process
->AddressSpace
,
725 MEMORY_AREA_NO_ACCESS
,
732 BoundaryAddressMultiple
);
733 if (!NT_SUCCESS(Status
))
735 MmUnlockAddressSpace(&Process
->AddressSpace
);
736 DPRINT1("Failed to protect the memory above the shared user page\n");
737 ObDereferenceObject(Process
);
738 goto exitdereferenceobjects
;
741 /* Create the shared data page */
742 BaseAddress
= (PVOID
)USER_SHARED_DATA
;
743 Status
= MmCreateMemoryArea(Process
,
744 &Process
->AddressSpace
,
745 MEMORY_AREA_SHARED_DATA
,
752 BoundaryAddressMultiple
);
753 MmUnlockAddressSpace(&Process
->AddressSpace
);
754 if (!NT_SUCCESS(Status
))
756 DPRINT1("Failed to create shared data page\n");
757 ObDereferenceObject(Process
);
758 goto exitdereferenceobjects
;
763 * FIXME - the handle should be created after all things are initialized, NOT HERE!
765 Status
= ObInsertObject ((PVOID
)Process
,
771 if (!NT_SUCCESS(Status
))
773 DPRINT1("Failed to create a handle for the process\n");
774 ObDereferenceObject(Process
);
775 goto exitdereferenceobjects
;
782 Status
= LdrpMapSystemDll(hProcess
, /* FIXME - hProcess shouldn't be available at this point! */
784 if (!NT_SUCCESS(Status
))
786 DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status
);
787 ObDereferenceObject(Process
);
788 goto exitdereferenceobjects
;
792 * Map the process image
794 if (SectionObject
!= NULL
)
797 DPRINT("Mapping process image\n");
798 Status
= MmMapViewOfSection(SectionObject
,
808 ObDereferenceObject(SectionObject
);
809 if (!NT_SUCCESS(Status
))
811 DbgPrint("Failed to map the process section (Status %x)\n", Status
);
812 ObDereferenceObject(Process
);
813 goto exitdereferenceobjects
;
817 if(pParentProcess
!= NULL
)
820 * Duplicate the token
822 Status
= SepInitializeNewProcess(Process
, pParentProcess
);
823 if (!NT_SUCCESS(Status
))
825 DbgPrint("SepInitializeNewProcess failed (Status %x)\n", Status
);
826 ObDereferenceObject(Process
);
827 goto exitdereferenceobjects
;
838 DPRINT("Creating PEB\n");
839 Status
= PsCreatePeb(hProcess
, /* FIXME - hProcess shouldn't be available at this point! */
842 if (!NT_SUCCESS(Status
))
844 DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status
);
845 ObDereferenceObject(Process
);
846 goto exitdereferenceobjects
;
850 * Maybe send a message to the creator process's debugger
853 if (pParentProcess
->DebugPort
!= NULL
)
855 LPC_DBG_MESSAGE Message
;
858 ObCreateHandle(NULL
, // Debugger Process
859 NULL
, // SectionHandle
864 Message
.Header
.MessageSize
= sizeof(LPC_DBG_MESSAGE
);
865 Message
.Header
.DataSize
= sizeof(LPC_DBG_MESSAGE
) -
867 Message
.Type
= DBG_EVENT_CREATE_PROCESS
;
868 Message
.Data
.CreateProcess
.FileHandle
= FileHandle
;
869 Message
.Data
.CreateProcess
.Base
= ImageBase
;
870 Message
.Data
.CreateProcess
.EntryPoint
= NULL
; //
872 Status
= LpcSendDebugMessagePort(pParentProcess
->DebugPort
,
877 PspRunCreateProcessNotifyRoutines(Process
, TRUE
);
880 * FIXME - the handle should be created not before this point!
883 Status
= ObInsertObject ((PVOID
)Process
,
890 if (NT_SUCCESS(Status
))
894 *ProcessHandle
= hProcess
;
898 Status
= _SEH_GetExceptionCode();
904 * don't dereference the debug port, exception port and section object even
905 * if ObInsertObject() failed, the process is alive! We just couldn't return
906 * the handle to the caller!
909 ObDereferenceObject(Process
);
910 if(pParentProcess
!= NULL
)
911 ObDereferenceObject(pParentProcess
);
921 PsCreateSystemProcess(PHANDLE ProcessHandle
,
922 ACCESS_MASK DesiredAccess
,
923 POBJECT_ATTRIBUTES ObjectAttributes
)
925 return PspCreateProcess(ProcessHandle
,
928 NULL
, /* no parent process */
940 NtCreateProcess(OUT PHANDLE ProcessHandle
,
941 IN ACCESS_MASK DesiredAccess
,
942 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
943 IN HANDLE ParentProcess
,
944 IN BOOLEAN InheritObjectTable
,
945 IN HANDLE SectionHandle OPTIONAL
,
946 IN HANDLE DebugPort OPTIONAL
,
947 IN HANDLE ExceptionPort OPTIONAL
)
949 * FUNCTION: Creates a process.
951 * ProcessHandle (OUT) = Caller supplied storage for the resulting
953 * DesiredAccess = Specifies the allowed or desired access to the
954 * process can be a combination of
955 * STANDARD_RIGHTS_REQUIRED| ..
956 * ObjectAttribute = Initialized attributes for the object, contains
957 * the rootdirectory and the filename
958 * ParentProcess = Handle to the parent process.
959 * InheritObjectTable = Specifies to inherit the objects of the parent
961 * SectionHandle = Handle to a section object to back the image file
962 * DebugPort = Handle to a DebugPort if NULL the system default debug
964 * ExceptionPort = Handle to a exception port.
966 * This function maps to the win32 CreateProcess.
970 KPROCESSOR_MODE PreviousMode
;
971 NTSTATUS Status
= STATUS_SUCCESS
;
975 PreviousMode
= ExGetPreviousMode();
977 if(PreviousMode
!= KernelMode
)
981 ProbeForWrite(ProcessHandle
,
987 Status
= _SEH_GetExceptionCode();
991 if(!NT_SUCCESS(Status
))
997 if(ParentProcess
== NULL
)
999 Status
= STATUS_INVALID_PARAMETER
;
1003 Status
= PspCreateProcess(ProcessHandle
,
1021 NtOpenProcess(OUT PHANDLE ProcessHandle
,
1022 IN ACCESS_MASK DesiredAccess
,
1023 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1024 IN PCLIENT_ID ClientId
)
1026 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
1027 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
1028 ProcessHandle
, DesiredAccess
, ObjectAttributes
, ClientId
,
1029 ClientId
->UniqueProcess
, ClientId
->UniqueThread
);
1034 * Not sure of the exact semantics
1036 if (ObjectAttributes
!= NULL
&& ObjectAttributes
->ObjectName
!= NULL
&&
1037 ObjectAttributes
->ObjectName
->Buffer
!= NULL
)
1042 Status
= ObReferenceObjectByName(ObjectAttributes
->ObjectName
,
1043 ObjectAttributes
->Attributes
,
1050 if (Status
!= STATUS_SUCCESS
)
1055 Status
= ObCreateHandle(PsGetCurrentProcess(),
1060 ObDereferenceObject(Process
);
1066 PLIST_ENTRY current_entry
;
1070 ExAcquireFastMutex(&PspActiveProcessMutex
);
1071 current_entry
= PsActiveProcessHead
.Flink
;
1072 while (current_entry
!= &PsActiveProcessHead
)
1074 current
= CONTAINING_RECORD(current_entry
, EPROCESS
,
1076 if (current
->UniqueProcessId
== ClientId
->UniqueProcess
)
1078 if (current
->Pcb
.State
== PROCESS_STATE_TERMINATED
)
1080 Status
= STATUS_PROCESS_IS_TERMINATING
;
1084 Status
= ObReferenceObjectByPointer(current
,
1089 ExReleaseFastMutex(&PspActiveProcessMutex
);
1090 if (NT_SUCCESS(Status
))
1092 Status
= ObCreateHandle(PsGetCurrentProcess(),
1097 ObDereferenceObject(current
);
1098 DPRINT("*ProcessHandle %x\n", ProcessHandle
);
1099 DPRINT("NtOpenProcess() = %x\n", Status
);
1103 current_entry
= current_entry
->Flink
;
1105 ExReleaseFastMutex(&PspActiveProcessMutex
);
1106 DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
1107 return(STATUS_UNSUCCESSFUL
);
1114 LARGE_INTEGER STDCALL
1115 PsGetProcessExitTime(VOID
)
1118 Li
.QuadPart
= PsGetCurrentProcess()->ExitTime
.QuadPart
;
1127 PsGetProcessCreateTimeQuadPart(
1131 return Process
->CreateTime
.QuadPart
;
1139 PsGetProcessDebugPort(
1143 return Process
->DebugPort
;
1151 PsGetProcessExitProcessCalled(
1155 return Process
->ExitProcessCalled
;
1163 PsGetProcessExitStatus(
1167 return Process
->ExitStatus
;
1179 return (HANDLE
)Process
->UniqueProcessId
;
1187 PsGetProcessImageFileName(
1191 return (LPSTR
)Process
->ImageFileName
;
1199 PsGetProcessInheritedFromUniqueProcessId(
1203 return Process
->InheritedFromUniqueProcessId
;
1215 return Process
->Job
;
1227 return Process
->Peb
;
1235 PsGetProcessPriorityClass(
1239 return Process
->PriorityClass
;
1247 PsGetProcessSectionBaseAddress(
1251 return Process
->SectionBaseAddress
;
1259 PsGetProcessSecurityPort(
1263 return Process
->SecurityPort
;
1271 PsGetProcessSessionId(
1275 return (HANDLE
)Process
->SessionId
;
1283 PsGetProcessWin32Process(
1287 return Process
->Win32Process
;
1295 PsGetProcessWin32WindowStation(
1299 return Process
->Win32WindowStation
;
1307 PsIsProcessBeingDebugged(
1311 return FALSE
/*Process->IsProcessBeingDebugged*/;
1319 PsLookupProcessByProcessId(IN HANDLE ProcessId
,
1320 OUT PEPROCESS
*Process
)
1322 PHANDLE_TABLE_ENTRY CidEntry
;
1323 PEPROCESS FoundProcess
;
1329 CidEntry
= PsLookupCidHandle(ProcessId
, PsProcessType
, (PVOID
*)&FoundProcess
);
1330 if(CidEntry
!= NULL
)
1332 ObReferenceObject(FoundProcess
);
1334 PsUnlockCidHandle(CidEntry
);
1336 *Process
= FoundProcess
;
1337 return STATUS_SUCCESS
;
1340 return STATUS_INVALID_PARAMETER
;
1345 PspRunCreateProcessNotifyRoutines
1347 PEPROCESS CurrentProcess
,
1352 HANDLE ProcessId
= (HANDLE
)CurrentProcess
->UniqueProcessId
;
1353 HANDLE ParentId
= CurrentProcess
->InheritedFromUniqueProcessId
;
1355 for(i
= 0; i
< MAX_PROCESS_NOTIFY_ROUTINE_COUNT
; ++ i
)
1356 if(PiProcessNotifyRoutine
[i
])
1357 PiProcessNotifyRoutine
[i
](ParentId
, ProcessId
, Create
);
1364 PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine
,
1371 for(i
=0;i
<MAX_PROCESS_NOTIFY_ROUTINE_COUNT
;i
++)
1373 if ((PVOID
)PiProcessNotifyRoutine
[i
] == (PVOID
)NotifyRoutine
)
1375 PiProcessNotifyRoutine
[i
] = NULL
;
1380 return(STATUS_SUCCESS
);
1384 for(i
=0;i
<MAX_PROCESS_NOTIFY_ROUTINE_COUNT
;i
++)
1386 if (PiProcessNotifyRoutine
[i
] == NULL
)
1388 PiProcessNotifyRoutine
[i
] = NotifyRoutine
;
1393 if (i
== MAX_PROCESS_NOTIFY_ROUTINE_COUNT
)
1395 return STATUS_INSUFFICIENT_RESOURCES
;
1398 return STATUS_SUCCESS
;
1402 PspRunLoadImageNotifyRoutines(
1403 PUNICODE_STRING FullImageName
,
1405 PIMAGE_INFO ImageInfo
)
1409 for (i
= 0; i
< MAX_PROCESS_NOTIFY_ROUTINE_COUNT
; ++ i
)
1410 if (PiLoadImageNotifyRoutine
[i
])
1411 PiLoadImageNotifyRoutine
[i
](FullImageName
, ProcessId
, ImageInfo
);
1419 PsRemoveLoadImageNotifyRoutine(
1420 IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine
1424 return STATUS_NOT_IMPLEMENTED
;
1431 PsSetLoadImageNotifyRoutine(IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine
)
1435 for (i
= 0; i
< MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT
; i
++)
1437 if (PiLoadImageNotifyRoutine
[i
] == NULL
)
1439 PiLoadImageNotifyRoutine
[i
] = NotifyRoutine
;
1444 if (i
== MAX_PROCESS_NOTIFY_ROUTINE_COUNT
)
1446 return STATUS_INSUFFICIENT_RESOURCES
;
1449 return STATUS_SUCCESS
;
1457 PsSetProcessPriorityClass(
1462 Process
->PriorityClass
= PriorityClass
;
1470 PsSetProcessSecurityPort(
1475 Process
->SecurityPort
= SecurityPort
;
1483 PsSetProcessWin32Process(
1488 Process
->Win32Process
= Win32Process
;
1496 PsSetProcessWin32WindowStation(
1501 Process
->Win32WindowStation
= WindowStation
;
1511 IN PEPROCESS Process
,
1512 IN POOL_TYPE PoolType
,
1518 /* Charge the usage */
1519 Status
= PsChargeProcessPoolQuota(Process
, PoolType
, Amount
);
1521 /* Raise Exception */
1522 if (!NT_SUCCESS(Status
)) {
1523 ExRaiseStatus(Status
);
1532 PsChargeProcessNonPagedPoolQuota (
1533 IN PEPROCESS Process
,
1537 /* Call the general function */
1538 return PsChargeProcessPoolQuota(Process
, NonPagedPool
, Amount
);
1546 PsChargeProcessPagedPoolQuota (
1547 IN PEPROCESS Process
,
1551 /* Call the general function */
1552 return PsChargeProcessPoolQuota(Process
, PagedPool
, Amount
);
1560 PsChargeProcessPoolQuota(
1561 IN PEPROCESS Process
,
1562 IN POOL_TYPE PoolType
,
1566 PEPROCESS_QUOTA_BLOCK QuotaBlock
;
1570 /* Get current Quota Block */
1571 QuotaBlock
= Process
->QuotaBlock
;
1573 /* Quota Operations are not to be done on the SYSTEM Process */
1574 if (Process
== PsInitialSystemProcess
) return STATUS_SUCCESS
;
1576 /* New Size in use */
1577 NewUsageSize
= QuotaBlock
->QuotaEntry
[PoolType
].Usage
+ Amount
;
1579 /* Does this size respect the quota? */
1580 if (NewUsageSize
> QuotaBlock
->QuotaEntry
[PoolType
].Limit
) {
1582 /* It doesn't, so keep raising the Quota */
1583 while (MiRaisePoolQuota(PoolType
, QuotaBlock
->QuotaEntry
[PoolType
].Limit
, &NewMaxQuota
)) {
1584 /* Save new Maximum Quota */
1585 QuotaBlock
->QuotaEntry
[PoolType
].Limit
= NewMaxQuota
;
1587 /* See if the new Maximum Quota fulfills our need */
1588 if (NewUsageSize
<= NewMaxQuota
) goto QuotaChanged
;
1591 return STATUS_QUOTA_EXCEEDED
;
1595 /* Save new Usage */
1596 QuotaBlock
->QuotaEntry
[PoolType
].Usage
= NewUsageSize
;
1598 /* Is this a new peak? */
1599 if (NewUsageSize
> QuotaBlock
->QuotaEntry
[PoolType
].Peak
) {
1600 QuotaBlock
->QuotaEntry
[PoolType
].Peak
= NewUsageSize
;
1604 return STATUS_SUCCESS
;
1613 IN PEPROCESS Process
,
1614 IN POOL_TYPE PoolType
,
1626 PsReturnProcessNonPagedPoolQuota(
1627 IN PEPROCESS Process
,
1639 PsReturnProcessPagedPoolQuota(
1640 IN PEPROCESS Process
,
1648 PsLockProcess(PEPROCESS Process
, BOOLEAN Timeout
)
1651 PKTHREAD PrevLockOwner
;
1652 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
1653 PLARGE_INTEGER Delay
= (Timeout
? &PsLockTimeout
: NULL
);
1654 PKTHREAD CallingThread
= KeGetCurrentThread();
1658 KeEnterCriticalRegion();
1662 PrevLockOwner
= (PKTHREAD
)InterlockedCompareExchangePointer(
1663 &Process
->LockOwner
, CallingThread
, NULL
);
1664 if(PrevLockOwner
== NULL
|| PrevLockOwner
== CallingThread
)
1666 /* we got the lock or already locked it */
1667 if(InterlockedIncrementUL(&Process
->LockCount
) == 1)
1669 KeClearEvent(&Process
->LockEvent
);
1672 return STATUS_SUCCESS
;
1678 Status
= KeWaitForSingleObject(&Process
->LockEvent
,
1683 if(!NT_SUCCESS(Status
) || Status
== STATUS_TIMEOUT
)
1686 if(Status
== STATUS_TIMEOUT
)
1688 DPRINT1("PsLockProcess(0x%x) timed out!\n", Process
);
1691 KeLeaveCriticalRegion();
1697 KeDelayExecutionThread(KernelMode
, FALSE
, &ShortPsLockDelay
);
1706 PsUnlockProcess(PEPROCESS Process
)
1710 ASSERT(Process
->LockOwner
== KeGetCurrentThread());
1712 if(InterlockedDecrementUL(&Process
->LockCount
) == 0)
1714 InterlockedExchangePointer(&Process
->LockOwner
, NULL
);
1715 KeSetEvent(&Process
->LockEvent
, IO_NO_INCREMENT
, FALSE
);
1718 KeLeaveCriticalRegion();