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 Process
->Pcb
.State
= PROCESS_STATE_ACTIVE
;
673 * Now we have created the process proper
676 MmLockAddressSpace(&Process
->AddressSpace
);
678 /* Protect the highest 64KB of the process address space */
679 BaseAddress
= (PVOID
)MmUserProbeAddress
;
680 Status
= MmCreateMemoryArea(Process
,
681 &Process
->AddressSpace
,
682 MEMORY_AREA_NO_ACCESS
,
689 BoundaryAddressMultiple
);
690 if (!NT_SUCCESS(Status
))
692 MmUnlockAddressSpace(&Process
->AddressSpace
);
693 DPRINT1("Failed to protect the highest 64KB of the process address space\n");
694 ObDereferenceObject(Process
);
695 goto exitdereferenceobjects
;
698 /* Protect the lowest 64KB of the process address space */
700 BaseAddress
= (PVOID
)0x00000000;
701 Status
= MmCreateMemoryArea(Process
,
702 &Process
->AddressSpace
,
703 MEMORY_AREA_NO_ACCESS
,
710 BoundaryAddressMultiple
);
711 if (!NT_SUCCESS(Status
))
713 MmUnlockAddressSpace(&Process
->AddressSpace
);
714 DPRINT1("Failed to protect the lowest 64KB of the process address space\n");
715 ObDereferenceObject(Process
);
716 goto exitdereferenceobjects
;
720 /* Protect the 60KB above the shared user page */
721 BaseAddress
= (char*)USER_SHARED_DATA
+ PAGE_SIZE
;
722 Status
= MmCreateMemoryArea(Process
,
723 &Process
->AddressSpace
,
724 MEMORY_AREA_NO_ACCESS
,
731 BoundaryAddressMultiple
);
732 if (!NT_SUCCESS(Status
))
734 MmUnlockAddressSpace(&Process
->AddressSpace
);
735 DPRINT1("Failed to protect the memory above the shared user page\n");
736 ObDereferenceObject(Process
);
737 goto exitdereferenceobjects
;
740 /* Create the shared data page */
741 BaseAddress
= (PVOID
)USER_SHARED_DATA
;
742 Status
= MmCreateMemoryArea(Process
,
743 &Process
->AddressSpace
,
744 MEMORY_AREA_SHARED_DATA
,
751 BoundaryAddressMultiple
);
752 MmUnlockAddressSpace(&Process
->AddressSpace
);
753 if (!NT_SUCCESS(Status
))
755 DPRINT1("Failed to create shared data page\n");
756 ObDereferenceObject(Process
);
757 goto exitdereferenceobjects
;
762 * FIXME - the handle should be created after all things are initialized, NOT HERE!
764 Status
= ObInsertObject ((PVOID
)Process
,
770 if (!NT_SUCCESS(Status
))
772 DPRINT1("Failed to create a handle for the process\n");
773 ObDereferenceObject(Process
);
774 goto exitdereferenceobjects
;
781 Status
= LdrpMapSystemDll(hProcess
, /* FIXME - hProcess shouldn't be available at this point! */
783 if (!NT_SUCCESS(Status
))
785 DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status
);
786 ObDereferenceObject(Process
);
787 goto exitdereferenceobjects
;
791 * Map the process image
793 if (SectionObject
!= NULL
)
796 DPRINT("Mapping process image\n");
797 Status
= MmMapViewOfSection(SectionObject
,
807 ObDereferenceObject(SectionObject
);
808 if (!NT_SUCCESS(Status
))
810 DbgPrint("Failed to map the process section (Status %x)\n", Status
);
811 ObDereferenceObject(Process
);
812 goto exitdereferenceobjects
;
816 if(pParentProcess
!= NULL
)
819 * Duplicate the token
821 Status
= SepInitializeNewProcess(Process
, pParentProcess
);
822 if (!NT_SUCCESS(Status
))
824 DbgPrint("SepInitializeNewProcess failed (Status %x)\n", Status
);
825 ObDereferenceObject(Process
);
826 goto exitdereferenceobjects
;
837 DPRINT("Creating PEB\n");
838 Status
= PsCreatePeb(hProcess
, /* FIXME - hProcess shouldn't be available at this point! */
841 if (!NT_SUCCESS(Status
))
843 DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status
);
844 ObDereferenceObject(Process
);
845 goto exitdereferenceobjects
;
849 * Maybe send a message to the creator process's debugger
852 if (pParentProcess
->DebugPort
!= NULL
)
854 LPC_DBG_MESSAGE Message
;
857 ObCreateHandle(NULL
, // Debugger Process
858 NULL
, // SectionHandle
863 Message
.Header
.MessageSize
= sizeof(LPC_DBG_MESSAGE
);
864 Message
.Header
.DataSize
= sizeof(LPC_DBG_MESSAGE
) -
866 Message
.Type
= DBG_EVENT_CREATE_PROCESS
;
867 Message
.Data
.CreateProcess
.FileHandle
= FileHandle
;
868 Message
.Data
.CreateProcess
.Base
= ImageBase
;
869 Message
.Data
.CreateProcess
.EntryPoint
= NULL
; //
871 Status
= LpcSendDebugMessagePort(pParentProcess
->DebugPort
,
876 PspRunCreateProcessNotifyRoutines(Process
, TRUE
);
879 * FIXME - the handle should be created not before this point!
882 Status
= ObInsertObject ((PVOID
)Process
,
889 if (NT_SUCCESS(Status
))
893 *ProcessHandle
= hProcess
;
897 Status
= _SEH_GetExceptionCode();
903 * don't dereference the debug port, exception port and section object even
904 * if ObInsertObject() failed, the process is alive! We just couldn't return
905 * the handle to the caller!
908 ObDereferenceObject(Process
);
909 if(pParentProcess
!= NULL
)
910 ObDereferenceObject(pParentProcess
);
920 PsCreateSystemProcess(PHANDLE ProcessHandle
,
921 ACCESS_MASK DesiredAccess
,
922 POBJECT_ATTRIBUTES ObjectAttributes
)
924 return PspCreateProcess(ProcessHandle
,
927 NULL
, /* no parent process */
939 NtCreateProcess(OUT PHANDLE ProcessHandle
,
940 IN ACCESS_MASK DesiredAccess
,
941 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
942 IN HANDLE ParentProcess
,
943 IN BOOLEAN InheritObjectTable
,
944 IN HANDLE SectionHandle OPTIONAL
,
945 IN HANDLE DebugPort OPTIONAL
,
946 IN HANDLE ExceptionPort OPTIONAL
)
948 * FUNCTION: Creates a process.
950 * ProcessHandle (OUT) = Caller supplied storage for the resulting
952 * DesiredAccess = Specifies the allowed or desired access to the
953 * process can be a combination of
954 * STANDARD_RIGHTS_REQUIRED| ..
955 * ObjectAttribute = Initialized attributes for the object, contains
956 * the rootdirectory and the filename
957 * ParentProcess = Handle to the parent process.
958 * InheritObjectTable = Specifies to inherit the objects of the parent
960 * SectionHandle = Handle to a section object to back the image file
961 * DebugPort = Handle to a DebugPort if NULL the system default debug
963 * ExceptionPort = Handle to a exception port.
965 * This function maps to the win32 CreateProcess.
969 KPROCESSOR_MODE PreviousMode
;
970 NTSTATUS Status
= STATUS_SUCCESS
;
974 PreviousMode
= ExGetPreviousMode();
976 if(PreviousMode
!= KernelMode
)
980 ProbeForWrite(ProcessHandle
,
986 Status
= _SEH_GetExceptionCode();
990 if(!NT_SUCCESS(Status
))
996 if(ParentProcess
== NULL
)
998 Status
= STATUS_INVALID_PARAMETER
;
1002 Status
= PspCreateProcess(ProcessHandle
,
1020 NtOpenProcess(OUT PHANDLE ProcessHandle
,
1021 IN ACCESS_MASK DesiredAccess
,
1022 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1023 IN PCLIENT_ID ClientId
)
1025 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
1026 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
1027 ProcessHandle
, DesiredAccess
, ObjectAttributes
, ClientId
,
1028 ClientId
->UniqueProcess
, ClientId
->UniqueThread
);
1033 * Not sure of the exact semantics
1035 if (ObjectAttributes
!= NULL
&& ObjectAttributes
->ObjectName
!= NULL
&&
1036 ObjectAttributes
->ObjectName
->Buffer
!= NULL
)
1041 Status
= ObReferenceObjectByName(ObjectAttributes
->ObjectName
,
1042 ObjectAttributes
->Attributes
,
1049 if (Status
!= STATUS_SUCCESS
)
1054 Status
= ObCreateHandle(PsGetCurrentProcess(),
1059 ObDereferenceObject(Process
);
1065 PLIST_ENTRY current_entry
;
1069 ExAcquireFastMutex(&PspActiveProcessMutex
);
1070 current_entry
= PsActiveProcessHead
.Flink
;
1071 while (current_entry
!= &PsActiveProcessHead
)
1073 current
= CONTAINING_RECORD(current_entry
, EPROCESS
,
1075 if (current
->UniqueProcessId
== ClientId
->UniqueProcess
)
1077 if (current
->Pcb
.State
== PROCESS_STATE_TERMINATED
)
1079 Status
= STATUS_PROCESS_IS_TERMINATING
;
1083 Status
= ObReferenceObjectByPointer(current
,
1088 ExReleaseFastMutex(&PspActiveProcessMutex
);
1089 if (NT_SUCCESS(Status
))
1091 Status
= ObCreateHandle(PsGetCurrentProcess(),
1096 ObDereferenceObject(current
);
1097 DPRINT("*ProcessHandle %x\n", ProcessHandle
);
1098 DPRINT("NtOpenProcess() = %x\n", Status
);
1102 current_entry
= current_entry
->Flink
;
1104 ExReleaseFastMutex(&PspActiveProcessMutex
);
1105 DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
1106 return(STATUS_UNSUCCESSFUL
);
1113 LARGE_INTEGER STDCALL
1114 PsGetProcessExitTime(VOID
)
1117 Li
.QuadPart
= PsGetCurrentProcess()->ExitTime
.QuadPart
;
1126 PsGetProcessCreateTimeQuadPart(
1130 return Process
->CreateTime
.QuadPart
;
1138 PsGetProcessDebugPort(
1142 return Process
->DebugPort
;
1150 PsGetProcessExitProcessCalled(
1154 return Process
->ExitProcessCalled
;
1162 PsGetProcessExitStatus(
1166 return Process
->ExitStatus
;
1178 return (HANDLE
)Process
->UniqueProcessId
;
1186 PsGetProcessImageFileName(
1190 return (LPSTR
)Process
->ImageFileName
;
1198 PsGetProcessInheritedFromUniqueProcessId(
1202 return Process
->InheritedFromUniqueProcessId
;
1214 return Process
->Job
;
1226 return Process
->Peb
;
1234 PsGetProcessPriorityClass(
1238 return Process
->PriorityClass
;
1246 PsGetProcessSectionBaseAddress(
1250 return Process
->SectionBaseAddress
;
1258 PsGetProcessSecurityPort(
1262 return Process
->SecurityPort
;
1270 PsGetProcessSessionId(
1274 return (HANDLE
)Process
->SessionId
;
1282 PsGetProcessWin32Process(
1286 return Process
->Win32Process
;
1294 PsGetProcessWin32WindowStation(
1298 return Process
->Win32WindowStation
;
1306 PsIsProcessBeingDebugged(
1310 return FALSE
/*Process->IsProcessBeingDebugged*/;
1318 PsLookupProcessByProcessId(IN HANDLE ProcessId
,
1319 OUT PEPROCESS
*Process
)
1321 PHANDLE_TABLE_ENTRY CidEntry
;
1322 PEPROCESS FoundProcess
;
1328 CidEntry
= PsLookupCidHandle(ProcessId
, PsProcessType
, (PVOID
*)&FoundProcess
);
1329 if(CidEntry
!= NULL
)
1331 ObReferenceObject(FoundProcess
);
1333 PsUnlockCidHandle(CidEntry
);
1335 *Process
= FoundProcess
;
1336 return STATUS_SUCCESS
;
1339 return STATUS_INVALID_PARAMETER
;
1344 PspRunCreateProcessNotifyRoutines
1346 PEPROCESS CurrentProcess
,
1351 HANDLE ProcessId
= (HANDLE
)CurrentProcess
->UniqueProcessId
;
1352 HANDLE ParentId
= CurrentProcess
->InheritedFromUniqueProcessId
;
1354 for(i
= 0; i
< MAX_PROCESS_NOTIFY_ROUTINE_COUNT
; ++ i
)
1355 if(PiProcessNotifyRoutine
[i
])
1356 PiProcessNotifyRoutine
[i
](ParentId
, ProcessId
, Create
);
1363 PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine
,
1370 for(i
=0;i
<MAX_PROCESS_NOTIFY_ROUTINE_COUNT
;i
++)
1372 if ((PVOID
)PiProcessNotifyRoutine
[i
] == (PVOID
)NotifyRoutine
)
1374 PiProcessNotifyRoutine
[i
] = NULL
;
1379 return(STATUS_SUCCESS
);
1383 for(i
=0;i
<MAX_PROCESS_NOTIFY_ROUTINE_COUNT
;i
++)
1385 if (PiProcessNotifyRoutine
[i
] == NULL
)
1387 PiProcessNotifyRoutine
[i
] = NotifyRoutine
;
1392 if (i
== MAX_PROCESS_NOTIFY_ROUTINE_COUNT
)
1394 return STATUS_INSUFFICIENT_RESOURCES
;
1397 return STATUS_SUCCESS
;
1401 PspRunLoadImageNotifyRoutines(
1402 PUNICODE_STRING FullImageName
,
1404 PIMAGE_INFO ImageInfo
)
1408 for (i
= 0; i
< MAX_PROCESS_NOTIFY_ROUTINE_COUNT
; ++ i
)
1409 if (PiLoadImageNotifyRoutine
[i
])
1410 PiLoadImageNotifyRoutine
[i
](FullImageName
, ProcessId
, ImageInfo
);
1418 PsRemoveLoadImageNotifyRoutine(
1419 IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine
1423 return STATUS_NOT_IMPLEMENTED
;
1430 PsSetLoadImageNotifyRoutine(IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine
)
1434 for (i
= 0; i
< MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT
; i
++)
1436 if (PiLoadImageNotifyRoutine
[i
] == NULL
)
1438 PiLoadImageNotifyRoutine
[i
] = NotifyRoutine
;
1443 if (i
== MAX_PROCESS_NOTIFY_ROUTINE_COUNT
)
1445 return STATUS_INSUFFICIENT_RESOURCES
;
1448 return STATUS_SUCCESS
;
1456 PsSetProcessPriorityClass(
1461 Process
->PriorityClass
= PriorityClass
;
1469 PsSetProcessSecurityPort(
1474 Process
->SecurityPort
= SecurityPort
;
1482 PsSetProcessWin32Process(
1487 Process
->Win32Process
= Win32Process
;
1495 PsSetProcessWin32WindowStation(
1500 Process
->Win32WindowStation
= WindowStation
;
1510 IN PEPROCESS Process
,
1511 IN POOL_TYPE PoolType
,
1517 /* Charge the usage */
1518 Status
= PsChargeProcessPoolQuota(Process
, PoolType
, Amount
);
1520 /* Raise Exception */
1521 if (!NT_SUCCESS(Status
)) {
1522 ExRaiseStatus(Status
);
1531 PsChargeProcessNonPagedPoolQuota (
1532 IN PEPROCESS Process
,
1536 /* Call the general function */
1537 return PsChargeProcessPoolQuota(Process
, NonPagedPool
, Amount
);
1545 PsChargeProcessPagedPoolQuota (
1546 IN PEPROCESS Process
,
1550 /* Call the general function */
1551 return PsChargeProcessPoolQuota(Process
, PagedPool
, Amount
);
1559 PsChargeProcessPoolQuota(
1560 IN PEPROCESS Process
,
1561 IN POOL_TYPE PoolType
,
1565 PEPROCESS_QUOTA_BLOCK QuotaBlock
;
1569 /* Get current Quota Block */
1570 QuotaBlock
= Process
->QuotaBlock
;
1572 /* Quota Operations are not to be done on the SYSTEM Process */
1573 if (Process
== PsInitialSystemProcess
) return STATUS_SUCCESS
;
1575 /* New Size in use */
1576 NewUsageSize
= QuotaBlock
->QuotaEntry
[PoolType
].Usage
+ Amount
;
1578 /* Does this size respect the quota? */
1579 if (NewUsageSize
> QuotaBlock
->QuotaEntry
[PoolType
].Limit
) {
1581 /* It doesn't, so keep raising the Quota */
1582 while (MiRaisePoolQuota(PoolType
, QuotaBlock
->QuotaEntry
[PoolType
].Limit
, &NewMaxQuota
)) {
1583 /* Save new Maximum Quota */
1584 QuotaBlock
->QuotaEntry
[PoolType
].Limit
= NewMaxQuota
;
1586 /* See if the new Maximum Quota fulfills our need */
1587 if (NewUsageSize
<= NewMaxQuota
) goto QuotaChanged
;
1590 return STATUS_QUOTA_EXCEEDED
;
1594 /* Save new Usage */
1595 QuotaBlock
->QuotaEntry
[PoolType
].Usage
= NewUsageSize
;
1597 /* Is this a new peak? */
1598 if (NewUsageSize
> QuotaBlock
->QuotaEntry
[PoolType
].Peak
) {
1599 QuotaBlock
->QuotaEntry
[PoolType
].Peak
= NewUsageSize
;
1603 return STATUS_SUCCESS
;
1612 IN PEPROCESS Process
,
1613 IN POOL_TYPE PoolType
,
1625 PsReturnProcessNonPagedPoolQuota(
1626 IN PEPROCESS Process
,
1638 PsReturnProcessPagedPoolQuota(
1639 IN PEPROCESS Process
,
1647 PsLockProcess(PEPROCESS Process
, BOOLEAN Timeout
)
1650 PKTHREAD PrevLockOwner
;
1651 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
1652 PLARGE_INTEGER Delay
= (Timeout
? &PsLockTimeout
: NULL
);
1653 PKTHREAD CallingThread
= KeGetCurrentThread();
1657 KeEnterCriticalRegion();
1661 PrevLockOwner
= (PKTHREAD
)InterlockedCompareExchangePointer(
1662 &Process
->LockOwner
, CallingThread
, NULL
);
1663 if(PrevLockOwner
== NULL
|| PrevLockOwner
== CallingThread
)
1665 /* we got the lock or already locked it */
1666 if(InterlockedIncrementUL(&Process
->LockCount
) == 1)
1668 KeClearEvent(&Process
->LockEvent
);
1671 return STATUS_SUCCESS
;
1677 Status
= KeWaitForSingleObject(&Process
->LockEvent
,
1682 if(!NT_SUCCESS(Status
) || Status
== STATUS_TIMEOUT
)
1685 if(Status
== STATUS_TIMEOUT
)
1687 DPRINT1("PsLockProcess(0x%x) timed out!\n", Process
);
1690 KeLeaveCriticalRegion();
1696 KeDelayExecutionThread(KernelMode
, FALSE
, &ShortPsLockDelay
);
1705 PsUnlockProcess(PEPROCESS Process
)
1709 ASSERT(Process
->LockOwner
== KeGetCurrentThread());
1711 if(InterlockedDecrementUL(&Process
->LockCount
) == 0)
1713 InterlockedExchangePointer(&Process
->LockOwner
, NULL
);
1714 KeSetEvent(&Process
->LockEvent
, IO_NO_INCREMENT
, FALSE
);
1717 KeLeaveCriticalRegion();