2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ps/process.c
5 * PURPOSE: Process Manager: Process Management
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 * Thomas Weidenmueller (w3seek@reactos.org
10 /* INCLUDES ******************************************************************/
16 /* GLOBALS *******************************************************************/
18 extern ULONG PsMinimumWorkingSet
, PsMaximumWorkingSet
;
20 POBJECT_TYPE PsProcessType
= NULL
;
22 LIST_ENTRY PsActiveProcessHead
;
23 KGUARDED_MUTEX PspActiveProcessMutex
;
25 LARGE_INTEGER ShortPsLockDelay
;
27 ULONG PsRawPrioritySeparation
= 0;
28 ULONG PsPrioritySeparation
;
29 CHAR PspForegroundQuantum
[3];
31 /* Fixed quantum table */
32 CHAR PspFixedQuantums
[6] =
45 /* Variable quantum table */
46 CHAR PspVariableQuantums
[6] =
60 KPRIORITY PspPriorityTable
[PROCESS_PRIORITY_CLASS_ABOVE_NORMAL
+ 1] =
71 /* PRIVATE FUNCTIONS *********************************************************/
75 PspDeleteLdt(PEPROCESS Process
)
78 return STATUS_SUCCESS
;
83 PspDeleteVdmObjects(PEPROCESS Process
)
86 return STATUS_SUCCESS
;
91 PsGetNextProcessThread(IN PEPROCESS Process
,
92 IN PETHREAD Thread OPTIONAL
)
94 PETHREAD FoundThread
= NULL
;
95 PLIST_ENTRY ListHead
, Entry
;
97 PSTRACE(PS_PROCESS_DEBUG
,
98 "Process: %p Thread: %p\n", Process
, Thread
);
100 /* Lock the process */
101 KeEnterCriticalRegion();
102 ExAcquirePushLockShared(&Process
->ProcessLock
);
104 /* Check if we're already starting somewhere */
107 /* Start where we left off */
108 Entry
= Thread
->ThreadListEntry
.Flink
;
112 /* Start at the beginning */
113 Entry
= Process
->ThreadListHead
.Flink
;
116 /* Set the list head and start looping */
117 ListHead
= &Process
->ThreadListHead
;
118 while (ListHead
!= Entry
)
121 FoundThread
= CONTAINING_RECORD(Entry
, ETHREAD
, ThreadListEntry
);
123 /* Safe reference the thread */
124 if (ObReferenceObjectSafe(FoundThread
)) break;
126 /* Nothing found, keep looping */
128 Entry
= Entry
->Flink
;
131 /* Unlock the process */
132 ExReleasePushLockShared(&Process
->ProcessLock
);
133 KeLeaveCriticalRegion();
135 /* Check if we had a starting thread, and dereference it */
136 if (Thread
) ObDereferenceObject(Thread
);
138 /* Return what we found */
144 PsGetNextProcess(IN PEPROCESS OldProcess
)
146 PLIST_ENTRY Entry
, ListHead
;
147 PEPROCESS FoundProcess
= NULL
;
149 PSTRACE(PS_PROCESS_DEBUG
, "Process: %p\n", OldProcess
);
151 /* Acquire the Active Process Lock */
152 KeAcquireGuardedMutex(&PspActiveProcessMutex
);
154 /* Check if we're already starting somewhere */
157 /* Start where we left off */
158 Entry
= OldProcess
->ActiveProcessLinks
.Flink
;
162 /* Start at the beginning */
163 Entry
= PsActiveProcessHead
.Flink
;
166 /* Set the list head and start looping */
167 ListHead
= &PsActiveProcessHead
;
168 while (ListHead
!= Entry
)
171 FoundProcess
= CONTAINING_RECORD(Entry
, EPROCESS
, ActiveProcessLinks
);
173 /* Reference the process */
174 if (ObReferenceObjectSafe(FoundProcess
)) break;
176 /* Nothing found, keep trying */
178 Entry
= Entry
->Flink
;
181 /* Release the lock */
182 KeReleaseGuardedMutex(&PspActiveProcessMutex
);
184 /* Reference the Process we had referenced earlier */
185 if (OldProcess
) ObDereferenceObject(OldProcess
);
191 PspComputeQuantumAndPriority(IN PEPROCESS Process
,
192 IN PSPROCESSPRIORITYMODE Mode
,
196 UCHAR LocalQuantum
, MemoryPriority
;
198 PSTRACE(PS_PROCESS_DEBUG
, "Process: %p Mode: %lx\n", Process
, Mode
);
200 /* Check if this is a foreground process */
201 if (Mode
== PsProcessPriorityForeground
)
203 /* Set the memory priority and use priority separation */
204 MemoryPriority
= MEMORY_PRIORITY_FOREGROUND
;
205 i
= PsPrioritySeparation
;
209 /* Set the background memory priority and no separation */
210 MemoryPriority
= MEMORY_PRIORITY_BACKGROUND
;
214 /* Make sure that the process mode isn't spinning */
215 if (Mode
!= PsProcessPrioritySpinning
)
217 /* Set the priority */
218 MmSetMemoryPriorityProcess(Process
, MemoryPriority
);
221 /* Make sure that the process isn't idle */
222 if (Process
->PriorityClass
!= PROCESS_PRIORITY_CLASS_IDLE
)
224 /* Does the process have a job? */
225 if ((Process
->Job
) && (PspUseJobSchedulingClasses
))
227 /* Use job quantum */
228 LocalQuantum
= PspJobSchedulingClasses
[Process
->Job
->
233 /* Use calculated quantum */
234 LocalQuantum
= PspForegroundQuantum
[i
];
239 /* Process is idle, use default quantum */
243 /* Return quantum to caller */
244 *Quantum
= LocalQuantum
;
246 /* Return priority */
247 return PspPriorityTable
[Process
->PriorityClass
];
252 PsChangeQuantumTable(IN BOOLEAN Immediate
,
253 IN ULONG PrioritySeparation
)
255 PEPROCESS Process
= NULL
;
260 PSTRACE(PS_PROCESS_DEBUG
,
261 "%lx PrioritySeparation: %lx\n", Immediate
, PrioritySeparation
);
263 /* Write the current priority separation */
264 PsPrioritySeparation
= PspPrioritySeparationFromMask(PrioritySeparation
);
266 /* Normalize it if it was too high */
267 if (PsPrioritySeparation
== 3) PsPrioritySeparation
= 2;
269 /* Get the quantum table to use */
270 if (PspQuantumTypeFromMask(PrioritySeparation
) == PSP_VARIABLE_QUANTUMS
)
272 /* Use a variable table */
273 QuantumTable
= PspVariableQuantums
;
277 /* Use fixed table */
278 QuantumTable
= PspFixedQuantums
;
281 /* Now check if we should use long or short */
282 if (PspQuantumLengthFromMask(PrioritySeparation
) == PSP_LONG_QUANTUMS
)
284 /* Use long quantums */
288 /* Check if we're using long fixed quantums */
289 if (QuantumTable
== &PspFixedQuantums
[3])
291 /* Use Job scheduling classes */
292 PspUseJobSchedulingClasses
= TRUE
;
296 /* Otherwise, we don't */
297 PspUseJobSchedulingClasses
= FALSE
;
300 /* Copy the selected table into the Foreground Quantum table */
301 RtlCopyMemory(PspForegroundQuantum
,
303 sizeof(PspForegroundQuantum
));
305 /* Check if we should apply these changes real-time */
308 /* We are...loop every process */
309 Process
= PsGetNextProcess(Process
);
313 * Use the priority separation, unless the process has
314 * low memory priority
316 i
= (Process
->Vm
.Flags
.MemoryPriority
== 1) ?
317 0: PsPrioritySeparation
;
319 /* Make sure that the process isn't idle */
320 if (Process
->PriorityClass
!= PROCESS_PRIORITY_CLASS_IDLE
)
322 /* Does the process have a job? */
323 if ((Process
->Job
) && (PspUseJobSchedulingClasses
))
325 /* Use job quantum */
326 Quantum
= PspJobSchedulingClasses
[Process
->Job
->
331 /* Use calculated quantum */
332 Quantum
= PspForegroundQuantum
[i
];
337 /* Process is idle, use default quantum */
341 /* Now set the quantum */
342 KeSetQuantumProcess(&Process
->Pcb
, Quantum
);
344 /* Get the next process */
345 Process
= PsGetNextProcess(Process
);
352 PspCreateProcess(OUT PHANDLE ProcessHandle
,
353 IN ACCESS_MASK DesiredAccess
,
354 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
355 IN HANDLE ParentProcess OPTIONAL
,
357 IN HANDLE SectionHandle OPTIONAL
,
358 IN HANDLE DebugPort OPTIONAL
,
359 IN HANDLE ExceptionPort OPTIONAL
,
363 PEPROCESS Process
, Parent
;
364 PVOID ExceptionPortObject
;
365 PDEBUG_OBJECT DebugObject
;
366 PSECTION_OBJECT SectionObject
;
367 NTSTATUS Status
, AccessStatus
;
368 ULONG DirectoryTableBase
[2] = {0,0};
370 HANDLE_TABLE_ENTRY CidEntry
;
371 PETHREAD CurrentThread
= PsGetCurrentThread();
372 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
373 PEPROCESS CurrentProcess
= PsGetCurrentProcess();
375 ACCESS_STATE LocalAccessState
;
376 PACCESS_STATE AccessState
= &LocalAccessState
;
377 AUX_ACCESS_DATA AuxData
;
379 BOOLEAN Result
, SdAllocated
;
380 PSECURITY_DESCRIPTOR SecurityDescriptor
;
381 SECURITY_SUBJECT_CONTEXT SubjectContext
;
383 PSTRACE(PS_PROCESS_DEBUG
,
384 "ProcessHandle: %p Parent: %p\n", ProcessHandle
, ParentProcess
);
387 if (Flags
& ~PS_ALL_FLAGS
) return STATUS_INVALID_PARAMETER
;
389 /* Check for parent */
393 Status
= ObReferenceObjectByHandle(ParentProcess
,
394 PROCESS_CREATE_PROCESS
,
399 if (!NT_SUCCESS(Status
)) return Status
;
401 /* If this process should be in a job but the parent isn't */
402 if ((InJob
) && (!Parent
->Job
))
404 /* This is illegal. Dereference the parent and fail */
405 ObDereferenceObject(Parent
);
406 return STATUS_INVALID_PARAMETER
;
409 /* Inherit Parent process's Affinity. */
410 Affinity
= Parent
->Pcb
.Affinity
;
414 /* We have no parent */
416 Affinity
= KeActiveProcessors
;
419 /* Save working set data */
420 MinWs
= PsMinimumWorkingSet
;
421 MaxWs
= PsMaximumWorkingSet
;
423 /* Create the Object */
424 Status
= ObCreateObject(PreviousMode
,
433 if (!NT_SUCCESS(Status
)) goto Cleanup
;
435 /* Clean up the Object */
436 RtlZeroMemory(Process
, sizeof(EPROCESS
));
438 /* Initialize pushlock and rundown protection */
439 ExInitializeRundownProtection(&Process
->RundownProtect
);
440 Process
->ProcessLock
.Value
= 0;
442 /* Setup the Thread List Head */
443 InitializeListHead(&Process
->ThreadListHead
);
445 /* Set up the Quota Block from the Parent */
446 PspInheritQuota(Process
, Parent
);
448 /* Set up Dos Device Map from the Parent */
449 ObInheritDeviceMap(Parent
, Process
);
451 /* Check if we have a parent */
454 /* Inherit PID and Hard Error Processing */
455 Process
->InheritedFromUniqueProcessId
= Parent
->UniqueProcessId
;
456 Process
->DefaultHardErrorProcessing
= Parent
->
457 DefaultHardErrorProcessing
;
461 /* Use default hard error processing */
462 Process
->DefaultHardErrorProcessing
= TRUE
;
465 /* Check for a section handle */
468 /* Get a pointer to it */
469 Status
= ObReferenceObjectByHandle(SectionHandle
,
473 (PVOID
*)&SectionObject
,
475 if (!NT_SUCCESS(Status
)) goto CleanupWithRef
;
479 /* Assume no section object */
480 SectionObject
= NULL
;
482 /* Is the parent the initial process? */
483 if (Parent
!= PsInitialSystemProcess
)
485 /* It's not, so acquire the process rundown */
486 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
488 /* If the parent has a section, use it */
489 SectionObject
= Parent
->SectionObject
;
490 if (SectionObject
) ObReferenceObject(SectionObject
);
492 /* Release process rundown */
493 ExReleaseRundownProtection(&Process
->RundownProtect
);
496 /* If we don't have a section object */
499 /* Then the process is in termination, so fail */
500 Status
= STATUS_PROCESS_IS_TERMINATING
;
506 /* Save the pointer to the section object */
507 Process
->SectionObject
= SectionObject
;
509 /* Check for the debug port */
513 Status
= ObReferenceObjectByHandle(DebugPort
,
514 DEBUG_OBJECT_ADD_REMOVE_PROCESS
,
517 (PVOID
*)&DebugObject
,
519 if (!NT_SUCCESS(Status
)) goto CleanupWithRef
;
521 /* Save the debug object */
522 Process
->DebugPort
= DebugObject
;
524 /* Check if the caller doesn't want the debug stuff inherited */
525 if (Flags
& PS_NO_DEBUG_INHERIT
)
527 /* Set the process flag */
528 InterlockedOr((PLONG
)&Process
->Flags
, PSF_NO_DEBUG_INHERIT_BIT
);
533 /* Do we have a parent? Copy his debug port */
534 if (Parent
) DbgkCopyProcessDebugPort(Process
, Parent
);
537 /* Now check for an exception port */
541 Status
= ObReferenceObjectByHandle(ExceptionPort
,
545 (PVOID
*)&ExceptionPortObject
,
547 if (!NT_SUCCESS(Status
)) goto CleanupWithRef
;
549 /* Save the exception port */
550 Process
->ExceptionPort
= ExceptionPortObject
;
553 /* Save the pointer to the section object */
554 Process
->SectionObject
= SectionObject
;
556 /* Set default exit code */
557 Process
->ExitStatus
= STATUS_PENDING
;
559 /* Check if this is the initial process being built */
562 /* Create the address space for the child */
563 if (!MmCreateProcessAddressSpace(MinWs
,
568 Status
= STATUS_INSUFFICIENT_RESOURCES
;
574 /* Otherwise, we are the boot process, we're already semi-initialized */
575 Process
->ObjectTable
= CurrentProcess
->ObjectTable
;
576 Status
= MmInitializeHandBuiltProcess(Process
, DirectoryTableBase
);
577 if (!NT_SUCCESS(Status
)) goto CleanupWithRef
;
580 /* We now have an address space */
581 InterlockedOr((PLONG
)&Process
->Flags
, PSF_HAS_ADDRESS_SPACE_BIT
);
583 /* Set the maximum WS */
584 Process
->Vm
.MaximumWorkingSetSize
= MaxWs
;
586 /* Now initialize the Kernel Process */
587 KeInitializeProcess(&Process
->Pcb
,
588 PROCESS_PRIORITY_NORMAL
,
591 (BOOLEAN
)(Process
->DefaultHardErrorProcessing
& 4));
593 /* Duplicate Parent Token */
594 Status
= PspInitializeProcessSecurity(Process
, Parent
);
595 if (!NT_SUCCESS(Status
)) goto CleanupWithRef
;
597 /* Set default priority class */
598 Process
->PriorityClass
= PROCESS_PRIORITY_CLASS_NORMAL
;
600 /* Check if we have a parent */
603 /* Check our priority class */
604 if (Parent
->PriorityClass
== PROCESS_PRIORITY_CLASS_IDLE
||
605 Parent
->PriorityClass
== PROCESS_PRIORITY_CLASS_BELOW_NORMAL
)
608 Process
->PriorityClass
= Parent
->PriorityClass
;
611 /* Initialize object manager for the process */
612 Status
= ObInitProcess(Flags
& PS_INHERIT_HANDLES
? Parent
: NULL
,
614 if (!NT_SUCCESS(Status
)) goto CleanupWithRef
;
618 /* Do the second part of the boot process memory setup */
619 Status
= MmInitializeHandBuiltProcess2(Process
);
620 if (!NT_SUCCESS(Status
)) goto CleanupWithRef
;
623 /* Set success for now */
624 Status
= STATUS_SUCCESS
;
626 /* Check if this is a real user-mode process */
629 /* Initialize the address space */
630 Status
= MmInitializeProcessAddressSpace(Process
,
635 SeAuditProcessCreationInfo
.
637 if (!NT_SUCCESS(Status
)) goto CleanupWithRef
;
641 /* Check if this is a child of the system process */
642 if (Parent
!= PsInitialSystemProcess
)
644 /* This is a clone! */
645 ASSERTMSG("No support for cloning yet\n", FALSE
);
649 /* This is the initial system process */
650 Flags
&= ~PS_LARGE_PAGES
;
651 Status
= MmInitializeProcessAddressSpace(Process
,
656 if (!NT_SUCCESS(Status
)) goto CleanupWithRef
;
658 /* Create a dummy image file name */
659 Process
->SeAuditProcessCreationInfo
.ImageFileName
=
660 ExAllocatePoolWithTag(PagedPool
,
661 sizeof(OBJECT_NAME_INFORMATION
),
662 TAG('S', 'e', 'P', 'a'));
663 if (!Process
->SeAuditProcessCreationInfo
.ImageFileName
)
666 Status
= STATUS_INSUFFICIENT_RESOURCES
;
671 RtlZeroMemory(Process
->SeAuditProcessCreationInfo
.ImageFileName
,
672 sizeof(OBJECT_NAME_INFORMATION
));
676 /* Check if we have a section object and map the system DLL */
677 if (SectionObject
) PspMapSystemDll(Process
, NULL
, FALSE
);
679 /* Create a handle for the Process */
680 CidEntry
.Object
= Process
;
681 CidEntry
.GrantedAccess
= 0;
682 Process
->UniqueProcessId
= ExCreateHandle(PspCidTable
, &CidEntry
);
683 if (!Process
->UniqueProcessId
)
686 Status
= STATUS_INSUFFICIENT_RESOURCES
;
690 /* Set the handle table PID */
691 Process
->ObjectTable
->UniqueProcessId
= Process
->UniqueProcessId
;
693 /* Check if we need to audit */
694 if (SeDetailedAuditingWithToken(NULL
)) SeAuditProcessCreate(Process
);
696 /* Check if the parent had a job */
697 if ((Parent
) && (Parent
->Job
))
699 /* FIXME: We need to insert this process */
700 DPRINT1("Jobs not yet supported\n");
704 /* Create PEB only for User-Mode Processes */
708 Status
= MmCreatePeb(Process
);
709 if (!NT_SUCCESS(Status
)) goto CleanupWithRef
;
712 /* The process can now be activated */
713 KeAcquireGuardedMutex(&PspActiveProcessMutex
);
714 InsertTailList(&PsActiveProcessHead
, &Process
->ActiveProcessLinks
);
715 KeReleaseGuardedMutex(&PspActiveProcessMutex
);
717 /* Create an access state */
718 Status
= SeCreateAccessStateEx(CurrentThread
,
720 (Parent
== PsInitialSystemProcess
)) ?
721 Parent
: CurrentProcess
,
725 &PsProcessType
->TypeInfo
.GenericMapping
);
726 if (!NT_SUCCESS(Status
)) goto CleanupWithRef
;
728 /* Insert the Process into the Object Directory */
729 Status
= ObInsertObject(Process
,
736 /* Free the access state */
737 if (AccessState
) SeDeleteAccessState(AccessState
);
739 /* Cleanup on failure */
740 if (!NT_SUCCESS(Status
)) goto Cleanup
;
742 /* Compute Quantum and Priority */
743 ASSERT(IsListEmpty(&Process
->ThreadListHead
) == TRUE
);
744 Process
->Pcb
.BasePriority
=
745 (SCHAR
)PspComputeQuantumAndPriority(Process
,
746 PsProcessPriorityBackground
,
748 Process
->Pcb
.QuantumReset
= Quantum
;
750 /* Check if we have a parent other then the initial system process */
751 Process
->GrantedAccess
= PROCESS_TERMINATE
;
752 if ((Parent
) && (Parent
!= PsInitialSystemProcess
))
754 /* Get the process's SD */
755 Status
= ObGetObjectSecurity(Process
,
758 if (!NT_SUCCESS(Status
))
760 /* We failed, close the handle and clean up */
761 ObCloseHandle(hProcess
, PreviousMode
);
765 /* Create the subject context */
766 SubjectContext
.ProcessAuditId
= Process
;
767 SubjectContext
.PrimaryToken
= PsReferencePrimaryToken(Process
);
768 SubjectContext
.ClientToken
= NULL
;
770 /* Do the access check */
771 Result
= SeAccessCheck(SecurityDescriptor
,
777 &PsProcessType
->TypeInfo
.GenericMapping
,
779 &Process
->GrantedAccess
,
782 /* Dereference the token and let go the SD */
783 ObFastDereferenceObject(&Process
->Token
,
784 SubjectContext
.PrimaryToken
);
785 ObReleaseObjectSecurity(SecurityDescriptor
, SdAllocated
);
787 /* Remove access if it failed */
788 if (!Result
) Process
->GrantedAccess
= 0;
790 /* Give the process some basic access */
791 Process
->GrantedAccess
|= (PROCESS_VM_OPERATION
|
794 PROCESS_QUERY_INFORMATION
|
796 PROCESS_CREATE_THREAD
|
798 PROCESS_CREATE_PROCESS
|
799 PROCESS_SET_INFORMATION
|
800 STANDARD_RIGHTS_ALL
|
805 /* Set full granted access */
806 Process
->GrantedAccess
= PROCESS_ALL_ACCESS
;
809 /* Set the Creation Time */
810 KeQuerySystemTime(&Process
->CreateTime
);
812 /* Protect against bad user-mode pointer */
815 /* Save the process handle */
816 *ProcessHandle
= hProcess
;
818 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
820 /* Get the exception code */
821 Status
= _SEH2_GetExceptionCode();
825 /* Run the Notification Routines */
826 PspRunCreateProcessNotifyRoutines(Process
, TRUE
);
830 * Dereference the process. For failures, kills the process and does
831 * cleanup present in PspDeleteProcess. For success, kills the extra
832 * reference added by ObInsertObject.
834 ObDereferenceObject(Process
);
837 /* Dereference the parent */
838 if (Parent
) ObDereferenceObject(Parent
);
840 /* Return status to caller */
844 /* PUBLIC FUNCTIONS **********************************************************/
851 PsCreateSystemProcess(OUT PHANDLE ProcessHandle
,
852 IN ACCESS_MASK DesiredAccess
,
853 IN POBJECT_ATTRIBUTES ObjectAttributes
)
855 /* Call the internal API */
856 return PspCreateProcess(ProcessHandle
,
872 PsLookupProcessByProcessId(IN HANDLE ProcessId
,
873 OUT PEPROCESS
*Process
)
875 PHANDLE_TABLE_ENTRY CidEntry
;
876 PEPROCESS FoundProcess
;
877 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
879 PSTRACE(PS_PROCESS_DEBUG
, "ProcessId: %p\n", ProcessId
);
880 KeEnterCriticalRegion();
882 /* Get the CID Handle Entry */
883 CidEntry
= ExMapHandleToPointer(PspCidTable
, ProcessId
);
886 /* Get the Process */
887 FoundProcess
= CidEntry
->Object
;
889 /* Make sure it's really a process */
890 if (FoundProcess
->Pcb
.Header
.Type
== ProcessObject
)
892 /* Safe Reference and return it */
893 if (ObReferenceObjectSafe(FoundProcess
))
895 *Process
= FoundProcess
;
896 Status
= STATUS_SUCCESS
;
900 /* Unlock the Entry */
901 ExUnlockHandleTableEntry(PspCidTable
, CidEntry
);
904 /* Return to caller */
905 KeLeaveCriticalRegion();
914 PsLookupProcessThreadByCid(IN PCLIENT_ID Cid
,
915 OUT PEPROCESS
*Process OPTIONAL
,
916 OUT PETHREAD
*Thread
)
918 PHANDLE_TABLE_ENTRY CidEntry
;
919 PETHREAD FoundThread
;
920 NTSTATUS Status
= STATUS_INVALID_CID
;
922 PSTRACE(PS_PROCESS_DEBUG
, "Cid: %p\n", Cid
);
923 KeEnterCriticalRegion();
925 /* Get the CID Handle Entry */
926 CidEntry
= ExMapHandleToPointer(PspCidTable
, Cid
->UniqueThread
);
929 /* Get the Process */
930 FoundThread
= CidEntry
->Object
;
932 /* Make sure it's really a thread and this process' */
933 if ((FoundThread
->Tcb
.DispatcherHeader
.Type
== ThreadObject
) &&
934 (FoundThread
->Cid
.UniqueProcess
== Cid
->UniqueProcess
))
936 /* Safe Reference and return it */
937 if (ObReferenceObjectSafe(FoundThread
))
939 *Thread
= FoundThread
;
940 Status
= STATUS_SUCCESS
;
942 /* Check if we should return the Process too */
945 /* Return it and reference it */
946 *Process
= FoundThread
->ThreadsProcess
;
947 ObReferenceObject(*Process
);
952 /* Unlock the Entry */
953 ExUnlockHandleTableEntry(PspCidTable
, CidEntry
);
956 /* Return to caller */
957 KeLeaveCriticalRegion();
966 PsGetProcessExitTime(VOID
)
968 return PsGetCurrentProcess()->ExitTime
;
976 PsGetProcessCreateTimeQuadPart(PEPROCESS Process
)
978 return Process
->CreateTime
.QuadPart
;
986 PsGetProcessDebugPort(PEPROCESS Process
)
988 return Process
->DebugPort
;
996 PsGetProcessExitProcessCalled(PEPROCESS Process
)
998 return (BOOLEAN
)Process
->ProcessExiting
;
1006 PsGetProcessExitStatus(PEPROCESS Process
)
1008 return Process
->ExitStatus
;
1016 PsGetProcessId(PEPROCESS Process
)
1018 return (HANDLE
)Process
->UniqueProcessId
;
1026 PsGetProcessImageFileName(PEPROCESS Process
)
1028 return (LPSTR
)Process
->ImageFileName
;
1036 PsGetProcessInheritedFromUniqueProcessId(PEPROCESS Process
)
1038 return Process
->InheritedFromUniqueProcessId
;
1046 PsGetProcessJob(PEPROCESS Process
)
1048 return Process
->Job
;
1056 PsGetProcessPeb(PEPROCESS Process
)
1058 return Process
->Peb
;
1066 PsGetProcessPriorityClass(PEPROCESS Process
)
1068 return Process
->PriorityClass
;
1076 PsGetCurrentProcessId(VOID
)
1078 return (HANDLE
)PsGetCurrentProcess()->UniqueProcessId
;
1086 PsGetCurrentProcessSessionId(VOID
)
1088 return PsGetCurrentProcess()->Session
;
1096 PsGetProcessSectionBaseAddress(PEPROCESS Process
)
1098 return Process
->SectionBaseAddress
;
1106 PsGetProcessSecurityPort(PEPROCESS Process
)
1108 return Process
->SecurityPort
;
1116 PsGetProcessSessionId(PEPROCESS Process
)
1118 return (HANDLE
)Process
->Session
;
1126 PsGetCurrentProcessWin32Process(VOID
)
1128 return PsGetCurrentProcess()->Win32Process
;
1136 PsGetProcessWin32Process(PEPROCESS Process
)
1138 return Process
->Win32Process
;
1146 PsGetProcessWin32WindowStation(PEPROCESS Process
)
1148 return Process
->Win32WindowStation
;
1156 PsIsProcessBeingDebugged(PEPROCESS Process
)
1158 return Process
->DebugPort
!= NULL
;
1166 PsIsSystemProcess(IN PEPROCESS Process
)
1168 /* Return if this is the System Process */
1169 return Process
== PsInitialSystemProcess
;
1177 PsSetProcessPriorityClass(PEPROCESS Process
,
1178 ULONG PriorityClass
)
1180 Process
->PriorityClass
= (UCHAR
)PriorityClass
;
1188 PsSetProcessSecurityPort(PEPROCESS Process
,
1191 Process
->SecurityPort
= SecurityPort
;
1199 PsSetProcessWin32Process(PEPROCESS Process
,
1202 Process
->Win32Process
= Win32Process
;
1210 PsSetProcessWindowStation(PEPROCESS Process
,
1211 PVOID WindowStation
)
1213 Process
->Win32WindowStation
= WindowStation
;
1221 PsSetProcessPriorityByClass(IN PEPROCESS Process
,
1222 IN PSPROCESSPRIORITYMODE Type
)
1226 PSTRACE(PS_PROCESS_DEBUG
, "Process: %p Type: %lx\n", Process
, Type
);
1228 /* Compute quantum and priority */
1229 Priority
= PspComputeQuantumAndPriority(Process
, Type
, &Quantum
);
1232 KeSetPriorityAndQuantumProcess(&Process
->Pcb
, Priority
, Quantum
);
1240 NtCreateProcessEx(OUT PHANDLE ProcessHandle
,
1241 IN ACCESS_MASK DesiredAccess
,
1242 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
1243 IN HANDLE ParentProcess
,
1245 IN HANDLE SectionHandle OPTIONAL
,
1246 IN HANDLE DebugPort OPTIONAL
,
1247 IN HANDLE ExceptionPort OPTIONAL
,
1250 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1251 NTSTATUS Status
= STATUS_SUCCESS
;
1253 PSTRACE(PS_PROCESS_DEBUG
,
1254 "ParentProcess: %p Flags: %lx\n", ParentProcess
, Flags
);
1256 /* Check if we came from user mode */
1257 if(PreviousMode
!= KernelMode
)
1261 /* Probe process handle */
1262 ProbeForWriteHandle(ProcessHandle
);
1264 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1266 /* Get exception code */
1267 Status
= _SEH2_GetExceptionCode();
1270 if (!NT_SUCCESS(Status
)) return Status
;
1273 /* Make sure there's a parent process */
1276 /* Can't create System Processes like this */
1277 Status
= STATUS_INVALID_PARAMETER
;
1281 /* Create a user Process */
1282 Status
= PspCreateProcess(ProcessHandle
,
1302 NtCreateProcess(OUT PHANDLE ProcessHandle
,
1303 IN ACCESS_MASK DesiredAccess
,
1304 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
1305 IN HANDLE ParentProcess
,
1306 IN BOOLEAN InheritObjectTable
,
1307 IN HANDLE SectionHandle OPTIONAL
,
1308 IN HANDLE DebugPort OPTIONAL
,
1309 IN HANDLE ExceptionPort OPTIONAL
)
1312 PSTRACE(PS_PROCESS_DEBUG
,
1313 "Parent: %p Attributes: %p\n", ParentProcess
, ObjectAttributes
);
1315 /* Set new-style flags */
1316 if ((ULONG
)SectionHandle
& 1) Flags
= PS_REQUEST_BREAKAWAY
;
1317 if ((ULONG
)DebugPort
& 1) Flags
|= PS_NO_DEBUG_INHERIT
;
1318 if (InheritObjectTable
) Flags
|= PS_INHERIT_HANDLES
;
1320 /* Call the new API */
1321 return NtCreateProcessEx(ProcessHandle
,
1337 NtOpenProcess(OUT PHANDLE ProcessHandle
,
1338 IN ACCESS_MASK DesiredAccess
,
1339 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1340 IN PCLIENT_ID ClientId
)
1342 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1343 CLIENT_ID SafeClientId
;
1344 ULONG Attributes
= 0;
1346 BOOLEAN HasObjectName
= FALSE
;
1347 PETHREAD Thread
= NULL
;
1348 PEPROCESS Process
= NULL
;
1349 NTSTATUS Status
= STATUS_SUCCESS
;
1350 ACCESS_STATE AccessState
;
1351 AUX_ACCESS_DATA AuxData
;
1353 PSTRACE(PS_PROCESS_DEBUG
,
1354 "ClientId: %p Attributes: %p\n", ClientId
, ObjectAttributes
);
1356 /* Check if we were called from user mode */
1357 if (PreviousMode
!= KernelMode
)
1359 /* Enter SEH for probing */
1362 /* Probe the thread handle */
1363 ProbeForWriteHandle(ProcessHandle
);
1365 /* Check for a CID structure */
1368 /* Probe and capture it */
1369 ProbeForRead(ClientId
, sizeof(CLIENT_ID
), sizeof(ULONG
));
1370 SafeClientId
= *ClientId
;
1371 ClientId
= &SafeClientId
;
1375 * Just probe the object attributes structure, don't capture it
1376 * completely. This is done later if necessary
1378 ProbeForRead(ObjectAttributes
,
1379 sizeof(OBJECT_ATTRIBUTES
),
1381 HasObjectName
= (ObjectAttributes
->ObjectName
!= NULL
);
1382 Attributes
= ObjectAttributes
->Attributes
;
1384 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1386 /* Get the exception code */
1387 Status
= _SEH2_GetExceptionCode();
1390 if (!NT_SUCCESS(Status
)) return Status
;
1394 /* Otherwise just get the data directly */
1395 HasObjectName
= (ObjectAttributes
->ObjectName
!= NULL
);
1396 Attributes
= ObjectAttributes
->Attributes
;
1399 /* Can't pass both, fail */
1400 if ((HasObjectName
) && (ClientId
)) return STATUS_INVALID_PARAMETER_MIX
;
1402 /* Create an access state */
1403 Status
= SeCreateAccessState(&AccessState
,
1406 &PsProcessType
->TypeInfo
.GenericMapping
);
1407 if (!NT_SUCCESS(Status
)) return Status
;
1409 /* Check if this is a debugger */
1410 if (SeSinglePrivilegeCheck(SeDebugPrivilege
, PreviousMode
))
1412 /* Did he want full access? */
1413 if (AccessState
.RemainingDesiredAccess
& MAXIMUM_ALLOWED
)
1415 /* Give it to him */
1416 AccessState
.PreviouslyGrantedAccess
|= PROCESS_ALL_ACCESS
;
1420 /* Otherwise just give every other access he could want */
1421 AccessState
.PreviouslyGrantedAccess
|=
1422 AccessState
.RemainingDesiredAccess
;
1425 /* The caller desires nothing else now */
1426 AccessState
.RemainingDesiredAccess
= 0;
1429 /* Open by name if one was given */
1433 Status
= ObOpenObjectByName(ObjectAttributes
,
1441 /* Get rid of the access state */
1442 SeDeleteAccessState(&AccessState
);
1446 /* Open by Thread ID */
1447 if (ClientId
->UniqueThread
)
1449 /* Get the Process */
1450 Status
= PsLookupProcessThreadByCid(ClientId
, &Process
, &Thread
);
1454 /* Get the Process */
1455 Status
= PsLookupProcessByProcessId(ClientId
->UniqueProcess
,
1459 /* Check if we didn't find anything */
1460 if (!NT_SUCCESS(Status
))
1462 /* Get rid of the access state and return */
1463 SeDeleteAccessState(&AccessState
);
1467 /* Open the Process Object */
1468 Status
= ObOpenObjectByPointer(Process
,
1476 /* Delete the access state */
1477 SeDeleteAccessState(&AccessState
);
1479 /* Dereference the thread if we used it */
1480 if (Thread
) ObDereferenceObject(Thread
);
1482 /* Dereference the Process */
1483 ObDereferenceObject(Process
);
1487 /* neither an object name nor a client id was passed */
1488 return STATUS_INVALID_PARAMETER_MIX
;
1491 /* Check for success */
1492 if (NT_SUCCESS(Status
))
1494 /* Use SEH for write back */
1497 /* Write back the handle */
1498 *ProcessHandle
= hProcess
;
1500 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1502 /* Get the exception code */
1503 Status
= _SEH2_GetExceptionCode();