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 */
205 i
= PsPrioritySeparation
;
209 /* Set the background memory priority and no separation */
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 /* Ineherit 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_TIMEOUT
;
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
;
820 /* Get the exception code */
821 Status
= _SEH_GetExceptionCode();
827 * Dereference the process. For failures, kills the process and does
828 * cleanup present in PspDeleteProcess. For success, kills the extra
829 * reference added by ObInsertObject.
831 ObDereferenceObject(Process
);
834 /* Dereference the parent */
835 if (Parent
) ObDereferenceObject(Parent
);
837 /* Return status to caller */
841 /* PUBLIC FUNCTIONS **********************************************************/
848 PsCreateSystemProcess(OUT PHANDLE ProcessHandle
,
849 IN ACCESS_MASK DesiredAccess
,
850 IN POBJECT_ATTRIBUTES ObjectAttributes
)
852 /* Call the internal API */
853 return PspCreateProcess(ProcessHandle
,
869 PsLookupProcessByProcessId(IN HANDLE ProcessId
,
870 OUT PEPROCESS
*Process
)
872 PHANDLE_TABLE_ENTRY CidEntry
;
873 PEPROCESS FoundProcess
;
874 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
876 PSTRACE(PS_PROCESS_DEBUG
, "ProcessId: %p\n", ProcessId
);
877 KeEnterCriticalRegion();
879 /* Get the CID Handle Entry */
880 CidEntry
= ExMapHandleToPointer(PspCidTable
, ProcessId
);
883 /* Get the Process */
884 FoundProcess
= CidEntry
->Object
;
886 /* Make sure it's really a process */
887 if (FoundProcess
->Pcb
.Header
.Type
== ProcessObject
)
889 /* Safe Reference and return it */
890 if (ObReferenceObjectSafe(FoundProcess
))
892 *Process
= FoundProcess
;
893 Status
= STATUS_SUCCESS
;
897 /* Unlock the Entry */
898 ExUnlockHandleTableEntry(PspCidTable
, CidEntry
);
901 /* Return to caller */
902 KeLeaveCriticalRegion();
911 PsLookupProcessThreadByCid(IN PCLIENT_ID Cid
,
912 OUT PEPROCESS
*Process OPTIONAL
,
913 OUT PETHREAD
*Thread
)
915 PHANDLE_TABLE_ENTRY CidEntry
;
916 PETHREAD FoundThread
;
917 NTSTATUS Status
= STATUS_INVALID_CID
;
919 PSTRACE(PS_PROCESS_DEBUG
, "Cid: %p\n", Cid
);
920 KeEnterCriticalRegion();
922 /* Get the CID Handle Entry */
923 CidEntry
= ExMapHandleToPointer(PspCidTable
, Cid
->UniqueThread
);
926 /* Get the Process */
927 FoundThread
= CidEntry
->Object
;
929 /* Make sure it's really a thread and this process' */
930 if ((FoundThread
->Tcb
.DispatcherHeader
.Type
== ThreadObject
) &&
931 (FoundThread
->Cid
.UniqueProcess
== Cid
->UniqueProcess
))
933 /* Safe Reference and return it */
934 if (ObReferenceObjectSafe(FoundThread
))
936 *Thread
= FoundThread
;
937 Status
= STATUS_SUCCESS
;
939 /* Check if we should return the Process too */
942 /* Return it and reference it */
943 *Process
= FoundThread
->ThreadsProcess
;
944 ObReferenceObject(*Process
);
949 /* Unlock the Entry */
950 ExUnlockHandleTableEntry(PspCidTable
, CidEntry
);
953 /* Return to caller */
954 KeLeaveCriticalRegion();
963 PsGetProcessExitTime(VOID
)
965 return PsGetCurrentProcess()->ExitTime
;
973 PsGetProcessCreateTimeQuadPart(PEPROCESS Process
)
975 return Process
->CreateTime
.QuadPart
;
983 PsGetProcessDebugPort(PEPROCESS Process
)
985 return Process
->DebugPort
;
993 PsGetProcessExitProcessCalled(PEPROCESS Process
)
995 return (BOOLEAN
)Process
->ProcessExiting
;
1003 PsGetProcessExitStatus(PEPROCESS Process
)
1005 return Process
->ExitStatus
;
1013 PsGetProcessId(PEPROCESS Process
)
1015 return (HANDLE
)Process
->UniqueProcessId
;
1023 PsGetProcessImageFileName(PEPROCESS Process
)
1025 return (LPSTR
)Process
->ImageFileName
;
1033 PsGetProcessInheritedFromUniqueProcessId(PEPROCESS Process
)
1035 return Process
->InheritedFromUniqueProcessId
;
1043 PsGetProcessJob(PEPROCESS Process
)
1045 return Process
->Job
;
1053 PsGetProcessPeb(PEPROCESS Process
)
1055 return Process
->Peb
;
1063 PsGetProcessPriorityClass(PEPROCESS Process
)
1065 return Process
->PriorityClass
;
1073 PsGetCurrentProcessId(VOID
)
1075 return (HANDLE
)PsGetCurrentProcess()->UniqueProcessId
;
1083 PsGetCurrentProcessSessionId(VOID
)
1085 return PsGetCurrentProcess()->Session
;
1093 PsGetProcessSectionBaseAddress(PEPROCESS Process
)
1095 return Process
->SectionBaseAddress
;
1103 PsGetProcessSecurityPort(PEPROCESS Process
)
1105 return Process
->SecurityPort
;
1113 PsGetProcessSessionId(PEPROCESS Process
)
1115 return (HANDLE
)Process
->Session
;
1123 PsGetCurrentProcessWin32Process(VOID
)
1125 return PsGetCurrentProcess()->Win32Process
;
1133 PsGetProcessWin32Process(PEPROCESS Process
)
1135 return Process
->Win32Process
;
1143 PsGetProcessWin32WindowStation(PEPROCESS Process
)
1145 return Process
->Win32WindowStation
;
1153 PsIsProcessBeingDebugged(PEPROCESS Process
)
1155 return Process
->DebugPort
!= NULL
;
1163 PsIsSystemProcess(IN PEPROCESS Process
)
1165 /* Return if this is the System Process */
1166 return Process
== PsInitialSystemProcess
;
1174 PsSetProcessPriorityClass(PEPROCESS Process
,
1175 ULONG PriorityClass
)
1177 Process
->PriorityClass
= (UCHAR
)PriorityClass
;
1185 PsSetProcessSecurityPort(PEPROCESS Process
,
1188 Process
->SecurityPort
= SecurityPort
;
1196 PsSetProcessWin32Process(PEPROCESS Process
,
1199 Process
->Win32Process
= Win32Process
;
1207 PsSetProcessWindowStation(PEPROCESS Process
,
1208 PVOID WindowStation
)
1210 Process
->Win32WindowStation
= WindowStation
;
1218 PsSetProcessPriorityByClass(IN PEPROCESS Process
,
1219 IN PSPROCESSPRIORITYMODE Type
)
1223 PSTRACE(PS_PROCESS_DEBUG
, "Process: %p Type: %lx\n", Process
, Type
);
1225 /* Compute quantum and priority */
1226 Priority
= PspComputeQuantumAndPriority(Process
, Type
, &Quantum
);
1229 KeSetPriorityAndQuantumProcess(&Process
->Pcb
, Priority
, Quantum
);
1237 NtCreateProcessEx(OUT PHANDLE ProcessHandle
,
1238 IN ACCESS_MASK DesiredAccess
,
1239 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
1240 IN HANDLE ParentProcess
,
1242 IN HANDLE SectionHandle OPTIONAL
,
1243 IN HANDLE DebugPort OPTIONAL
,
1244 IN HANDLE ExceptionPort OPTIONAL
,
1247 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1248 NTSTATUS Status
= STATUS_SUCCESS
;
1250 PSTRACE(PS_PROCESS_DEBUG
,
1251 "ParentProcess: %p Flags: %lx\n", ParentProcess
, Flags
);
1253 /* Check if we came from user mode */
1254 if(PreviousMode
!= KernelMode
)
1258 /* Probe process handle */
1259 ProbeForWriteHandle(ProcessHandle
);
1263 /* Get exception code */
1264 Status
= _SEH_GetExceptionCode();
1267 if (!NT_SUCCESS(Status
)) return Status
;
1270 /* Make sure there's a parent process */
1273 /* Can't create System Processes like this */
1274 Status
= STATUS_INVALID_PARAMETER
;
1278 /* Create a user Process */
1279 Status
= PspCreateProcess(ProcessHandle
,
1299 NtCreateProcess(OUT PHANDLE ProcessHandle
,
1300 IN ACCESS_MASK DesiredAccess
,
1301 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
1302 IN HANDLE ParentProcess
,
1303 IN BOOLEAN InheritObjectTable
,
1304 IN HANDLE SectionHandle OPTIONAL
,
1305 IN HANDLE DebugPort OPTIONAL
,
1306 IN HANDLE ExceptionPort OPTIONAL
)
1309 PSTRACE(PS_PROCESS_DEBUG
,
1310 "Parent: %p Attributes: %p\n", ParentProcess
, ObjectAttributes
);
1312 /* Set new-style flags */
1313 if ((ULONG
)SectionHandle
& 1) Flags
= PS_REQUEST_BREAKAWAY
;
1314 if ((ULONG
)DebugPort
& 1) Flags
|= PS_NO_DEBUG_INHERIT
;
1315 if (InheritObjectTable
) Flags
|= PS_INHERIT_HANDLES
;
1317 /* Call the new API */
1318 return NtCreateProcessEx(ProcessHandle
,
1334 NtOpenProcess(OUT PHANDLE ProcessHandle
,
1335 IN ACCESS_MASK DesiredAccess
,
1336 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1337 IN PCLIENT_ID ClientId
)
1339 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
1340 CLIENT_ID SafeClientId
;
1341 ULONG Attributes
= 0;
1343 BOOLEAN HasObjectName
= FALSE
;
1344 PETHREAD Thread
= NULL
;
1345 PEPROCESS Process
= NULL
;
1346 NTSTATUS Status
= STATUS_SUCCESS
;
1347 ACCESS_STATE AccessState
;
1348 AUX_ACCESS_DATA AuxData
;
1350 PSTRACE(PS_PROCESS_DEBUG
,
1351 "ClientId: %p Attributes: %p\n", ClientId
, ObjectAttributes
);
1353 /* Check if we were called from user mode */
1354 if (PreviousMode
!= KernelMode
)
1356 /* Enter SEH for probing */
1359 /* Probe the thread handle */
1360 ProbeForWriteHandle(ProcessHandle
);
1362 /* Check for a CID structure */
1365 /* Probe and capture it */
1366 ProbeForRead(ClientId
, sizeof(CLIENT_ID
), sizeof(ULONG
));
1367 SafeClientId
= *ClientId
;
1368 ClientId
= &SafeClientId
;
1372 * Just probe the object attributes structure, don't capture it
1373 * completely. This is done later if necessary
1375 ProbeForRead(ObjectAttributes
,
1376 sizeof(OBJECT_ATTRIBUTES
),
1378 HasObjectName
= (ObjectAttributes
->ObjectName
!= NULL
);
1379 Attributes
= ObjectAttributes
->Attributes
;
1383 /* Get the exception code */
1384 Status
= _SEH_GetExceptionCode();
1387 if (!NT_SUCCESS(Status
)) return Status
;
1391 /* Otherwise just get the data directly */
1392 HasObjectName
= (ObjectAttributes
->ObjectName
!= NULL
);
1393 Attributes
= ObjectAttributes
->Attributes
;
1396 /* Can't pass both, fail */
1397 if ((HasObjectName
) && (ClientId
)) return STATUS_INVALID_PARAMETER_MIX
;
1399 /* Create an access state */
1400 Status
= SeCreateAccessState(&AccessState
,
1403 &PsProcessType
->TypeInfo
.GenericMapping
);
1404 if (!NT_SUCCESS(Status
)) return Status
;
1406 /* Check if this is a debugger */
1407 if (SeSinglePrivilegeCheck(SeDebugPrivilege
, PreviousMode
))
1409 /* Did he want full access? */
1410 if (AccessState
.RemainingDesiredAccess
& MAXIMUM_ALLOWED
)
1412 /* Give it to him */
1413 AccessState
.PreviouslyGrantedAccess
|= PROCESS_ALL_ACCESS
;
1417 /* Otherwise just give every other access he could want */
1418 AccessState
.PreviouslyGrantedAccess
|=
1419 AccessState
.RemainingDesiredAccess
;
1422 /* The caller desires nothing else now */
1423 AccessState
.RemainingDesiredAccess
= 0;
1426 /* Open by name if one was given */
1430 Status
= ObOpenObjectByName(ObjectAttributes
,
1438 /* Get rid of the access state */
1439 SeDeleteAccessState(&AccessState
);
1443 /* Open by Thread ID */
1444 if (ClientId
->UniqueThread
)
1446 /* Get the Process */
1447 Status
= PsLookupProcessThreadByCid(ClientId
, &Process
, &Thread
);
1451 /* Get the Process */
1452 Status
= PsLookupProcessByProcessId(ClientId
->UniqueProcess
,
1456 /* Check if we didn't find anything */
1457 if (!NT_SUCCESS(Status
))
1459 /* Get rid of the access state and return */
1460 SeDeleteAccessState(&AccessState
);
1464 /* Open the Process Object */
1465 Status
= ObOpenObjectByPointer(Process
,
1473 /* Delete the access state */
1474 SeDeleteAccessState(&AccessState
);
1476 /* Dereference the thread if we used it */
1477 if (Thread
) ObDereferenceObject(Thread
);
1479 /* Dereference the Process */
1480 ObDereferenceObject(Process
);
1484 /* neither an object name nor a client id was passed */
1485 return STATUS_INVALID_PARAMETER_MIX
;
1488 /* Check for success */
1489 if (NT_SUCCESS(Status
))
1491 /* Use SEH for write back */
1494 /* Write back the handle */
1495 *ProcessHandle
= hProcess
;
1499 /* Get the exception code */
1500 Status
= _SEH_GetExceptionCode();