ReactOS 0.4.17-dev-806-gffa4164
job.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for job.c:

Go to the source code of this file.

Classes

struct  PSP_TERMINATE_PROCESS_CONTEXT
 
struct  PSP_QUERY_JOB_PROCESS_ID_CONTEXT
 

Macros

#define NDEBUG
 

Typedefs

typedef struct PSP_TERMINATE_PROCESS_CONTEXT PSP_TERMINATE_PROCESS_CONTEXT
 
typedef struct PSP_TERMINATE_PROCESS_CONTEXTPPSP_TERMINATE_PROCESS_CONTEXT
 
typedef struct PSP_QUERY_JOB_PROCESS_ID_CONTEXT PSP_QUERY_JOB_PROCESS_ID_CONTEXT
 
typedef struct PSP_QUERY_JOB_PROCESS_ID_CONTEXTPPSP_QUERY_JOB_PROCESS_ID_CONTEXT
 

Functions

VOID NTAPI PspInitializeJobStructures (VOID)
 
static PEPROCESS PspGetNextProcessInJobLocked (_In_ PEJOB Job, _In_opt_ PEPROCESS PreviousProcess)
 
static PEPROCESS PspGetNextProcessInJob (_In_ PEJOB Job, _In_opt_ PEPROCESS PreviousProcess)
 
NTSTATUS NTAPI PspEnumerateProcessesInJob (_In_ PEJOB Job, _In_ PJOB_ENUMERATOR_CALLBACK Callback, _In_opt_ PVOID Context)
 
static NTSTATUS PspEnumerateProcessesInJobLocked (_In_ PEJOB Job, _In_ PJOB_ENUMERATOR_CALLBACK Callback, _In_opt_ PVOID Context)
 
NTSTATUS NTAPI PspSendJobMessageLocked (_In_ PEJOB Job, _In_ ULONG Message, _In_opt_ PVOID CompletionValue, _In_ BOOLEAN Quota)
 
NTSTATUS NTAPI PspAssignProcessToJob (_In_ PEPROCESS Process, _In_ PEJOB Job)
 
static BOOLEAN PspDeactivateProcessFromJobLocked (_In_ PEJOB Job, _In_ PEPROCESS Process)
 
VOID NTAPI PspRemoveProcessFromJob (_In_ PEPROCESS Process)
 
VOID NTAPI PspExitProcessFromJob (_In_ PEPROCESS Process)
 
static NTSTATUS NTAPI PspTerminateProcessCallback (_In_ PEPROCESS Process, _In_ PVOID Context)
 
NTSTATUS NTAPI PspTerminateJobObject (_In_ PEJOB Job, _In_ NTSTATUS ExitStatus)
 
VOID NTAPI PspCloseJob (_In_ PEPROCESS Process, _In_ PVOID ObjectBody, _In_ ACCESS_MASK GrantedAccess, _In_ ULONG_PTR ProcessHandleCount, _In_ ULONG_PTR SystemHandleCount)
 
VOID NTAPI PspDeleteJob (_In_ PVOID ObjectBody)
 
static NTSTATUS PspSetJobLimitsBasicOrExtended (_In_ PEJOB Job, _In_ PJOBOBJECT_EXTENDED_LIMIT_INFORMATION ExtendedLimit, _In_ BOOLEAN IsExtendedLimit)
 
static NTSTATUS NTAPI PspAssociateCompletionPortCallback (_In_ PEPROCESS Process, _In_ PVOID Context)
 
static NTSTATUS PspAssociateCompletionPortWithJob (_In_ PEJOB Job, _In_ PJOBOBJECT_ASSOCIATE_COMPLETION_PORT AssociateCpInfo)
 
static NTSTATUS PspQueryJobBasicAccountingInfo (_In_ PEJOB Job, _Out_ PJOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION BasicAndIo)
 
static NTSTATUS PspQueryJobLimitInformation (_In_ PEJOB Job, _In_ BOOLEAN Extended, _Out_ PJOBOBJECT_EXTENDED_LIMIT_INFORMATION ExtendedLimit)
 
static NTSTATUS NTAPI PspQueryJobProcessIdListCallback (_In_ PEPROCESS Process, _Inout_ PVOID Context)
 
static NTSTATUS PspQueryJobProcessIdList (_In_ PEJOB Job, _Out_writes_bytes_(JobInformationLength) PJOBOBJECT_BASIC_PROCESS_ID_LIST ProcIdList, _In_ ULONG JobInformationLength, _Out_ PULONG ReturnRequiredLength)
 
PVOID NTAPI PsGetJobLock (PEJOB Job)
 
ULONG NTAPI PsGetJobSessionId (PEJOB Job)
 
ULONG NTAPI PsGetJobUIRestrictionsClass (PEJOB Job)
 
VOID NTAPI PsSetJobUIRestrictionsClass (PEJOB Job, ULONG UIRestrictionsClass)
 
NTSTATUS NTAPI PspInvokeW32JobCallout (_In_ PEJOB Job, _In_ PSW32JOBCALLOUTTYPE CalloutType, _In_opt_ PVOID Data)
 
static NTSTATUS PspSetJobUIRestrictions (_In_ PEJOB Job, _In_ ULONG UIRestrictionsClass)
 
NTSTATUS NTAPI NtCreateJobObject (_Out_ PHANDLE JobHandle, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes)
 
NTSTATUS NTAPI NtCreateJobSet (IN ULONG NumJob, IN PJOB_SET_ARRAY UserJobSet, IN ULONG Flags)
 
NTSTATUS NTAPI NtOpenJobObject (_Out_ PHANDLE JobHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes)
 
NTSTATUS NTAPI NtAssignProcessToJobObject (_In_ HANDLE JobHandle, _In_ HANDLE ProcessHandle)
 
NTSTATUS NTAPI NtIsProcessInJob (_In_ HANDLE ProcessHandle, _In_opt_ HANDLE JobHandle)
 
NTSTATUS NTAPI NtTerminateJobObject (_In_ HANDLE JobHandle, _In_ NTSTATUS ExitStatus)
 
NTSTATUS NTAPI NtQueryInformationJobObject (_In_opt_ HANDLE JobHandle, _In_ JOBOBJECTINFOCLASS JobInformationClass, _Out_writes_bytes_(JobInformationLength) PVOID JobInformation, _In_ ULONG JobInformationLength, _Out_opt_ PULONG ReturnLength)
 
NTSTATUS NTAPI NtSetInformationJobObject (_In_ HANDLE JobHandle, _In_ JOBOBJECTINFOCLASS JobInformationClass, _In_reads_bytes_(JobInformationLength) PVOID JobInformation, _In_ ULONG JobInformationLength)
 

Variables

POBJECT_TYPE PsJobType = NULL
 
LIST_ENTRY PsJobListHead
 
static FAST_MUTEX PsJobListLock
 
BOOLEAN PspUseJobSchedulingClasses
 
CHAR PspJobSchedulingClasses [PSP_JOB_SCHEDULING_CLASSES]
 
GENERIC_MAPPING PspJobMapping
 
ULONG PspJobInfoLengths []
 
ULONG PspJobInfoAlign []
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 18 of file job.c.

Typedef Documentation

◆ PPSP_QUERY_JOB_PROCESS_ID_CONTEXT

◆ PPSP_TERMINATE_PROCESS_CONTEXT

◆ PSP_QUERY_JOB_PROCESS_ID_CONTEXT

Context structure used to collect process IDs for a job object.

Parameters
[in,out]ProcessIdListA pointer to the output process identifier list.
[in,out]NextProcessIdA pointer to the next output array entry.
[in,out]RemainingLengthThe number of bytes remaining in the output array.

◆ PSP_TERMINATE_PROCESS_CONTEXT

Context structure used to pass the job object and exit status to the process termination callback.

Parameters
[in]JobA pointer to the job object.
[in]ExitStatusThe exit status to be used for all terminated processes.

Function Documentation

◆ NtAssignProcessToJobObject()

NTSTATUS NTAPI NtAssignProcessToJobObject ( _In_ HANDLE  JobHandle,
_In_ HANDLE  ProcessHandle 
)

Assigns a process to a job object.

Parameters
[in]JobHandleHandle to the job object.
[in]ProcessHandleHandle to the process to be assigned.
Returns
STATUS_SUCCESS if the process is successfully assigned to the job. An appropriate NTSTATUS error code otherwise.

Definition at line 1928 of file job.c.

1932{
1934 PEJOB Job;
1938
1939 PAGED_CODE();
1940
1942
1943 /* Reference the job. JOB_OBJECT_ASSIGN_PROCESS rights are required
1944 for assignment */
1947 PsJobType,
1949 (PVOID *)&Job,
1950 NULL);
1951 if (!NT_SUCCESS(Status))
1952 {
1953 return Status;
1954 }
1955
1956 /* Reference the process. The handle must have the PROCESS_SET_QUOTA and
1957 PROCESS_TERMINATE access rights. */
1962 (PVOID *)&Process,
1963 NULL);
1964 if (!NT_SUCCESS(Status))
1965 {
1967 return Status;
1968 }
1969
1970 /* Get the session ID - it must match the process and the job creator */
1972
1973 if (Process->Job != NULL || SessionId != Job->SessionId)
1974 {
1975 /* Return STATUS_ACCESS_DENIED if the process is already assigned
1976 to a job or the session ID is different */
1979 return STATUS_ACCESS_DENIED;
1980 }
1981
1983
1985 {
1986 /* Preserve the assignment failure */
1988 }
1989
1992
1993 return Status;
1994}
#define PAGED_CODE()
_In_ PVOID _In_ ULONG _Out_ PVOID _In_ ULONG _Inout_ PULONG _In_ KPROCESSOR_MODE PreviousMode
#define VOID
Definition: acefi.h:82
LONG NTSTATUS
Definition: precomp.h:26
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
ULONG SessionId
Definition: dllmain.c:28
#define ExGetPreviousMode
Definition: ex.h:143
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
Status
Definition: gdiplustypes.h:24
#define PROCESS_TERMINATE
Definition: pstypes.h:153
#define JOB_OBJECT_ASSIGN_PROCESS
Definition: pstypes.h:196
#define PROCESS_SET_QUOTA
Definition: pstypes.h:160
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:407
NTSTATUS NTAPI PspAssignProcessToJob(_In_ PEPROCESS Process, _In_ PEJOB Job)
Definition: job.c:432
POBJECT_TYPE PsProcessType
Definition: process.c:20
ULONG NTAPI PsGetProcessSessionId(IN PEPROCESS Process)
Definition: process.c:1193
#define STATUS_QUOTA_EXCEEDED
Definition: ntstatus.h:398
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:493
NTSTATUS NTAPI PsTerminateProcess(IN PEPROCESS Process, IN NTSTATUS ExitStatus)
Definition: kill.c:126
POBJECT_TYPE PsJobType
Definition: job.c:23
ULONG SessionId
Definition: pstypes.h:1646
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
#define ObDereferenceObject
Definition: obfuncs.h:203

Referenced by AssignProcessToJobObject(), and CreateProcessInternalW().

◆ NtCreateJobObject()

NTSTATUS NTAPI NtCreateJobObject ( _Out_ PHANDLE  JobHandle,
_In_ ACCESS_MASK  DesiredAccess,
_In_opt_ POBJECT_ATTRIBUTES  ObjectAttributes 
)

Creates a job object.

Parameters
[out]JobHandleA pointer to a handle that will receive the handle of the created job object.
[in]DesiredAccessSpecifies the desired access rights for the job object.
[in,optional]ObjectAttributes An optional pointer to an object attributes block
Returns
STATUS_SUCCESS if the job object is successfully created. An appropriate NTSTATUS error code otherwise.

Definition at line 1728 of file job.c.

1733{
1734 HANDLE Handle;
1735 PEJOB Job;
1737 PEPROCESS CurrentProcess;
1739
1740 PAGED_CODE();
1741
1743 CurrentProcess = PsGetCurrentProcess();
1744
1745 /* Check for valid buffers */
1746 if (PreviousMode != KernelMode)
1747 {
1748 _SEH2_TRY
1749 {
1750 ProbeForWriteHandle(JobHandle);
1751 }
1753 {
1754 return _SEH2_GetExceptionCode();
1755 }
1756 _SEH2_END;
1757 }
1758
1759 /* Create the job object */
1761 PsJobType,
1764 NULL,
1765 sizeof(EJOB),
1766 0,
1767 0,
1768 (PVOID *)&Job);
1769
1770 if (!NT_SUCCESS(Status))
1771 {
1772 DPRINT1("Failed to create job object, Status 0x%08lx\n", Status);
1773 return Status;
1774 }
1775
1776 /* Initialize the job object */
1777
1778 RtlZeroMemory(Job, sizeof(*Job));
1779
1782
1783 /* Make sure that early destruction doesn't attempt to remove
1784 the object from the list before it even gets added */
1786
1787 /* Inherit the session ID from the caller */
1788 Job->SessionId = PsGetProcessSessionId(CurrentProcess);
1789
1790 /* Initialize the job limits lock */
1792
1793 /* Initialize the job lock */
1795
1796 /* Initialize the event object within the job */
1798
1799 /* Set the scheduling class */
1801
1802 /* Link the object into the global job list */
1806
1807 /* Insert the job object into the object table */
1808 Status = ObInsertObject(Job,
1809 NULL,
1811 0,
1812 NULL,
1813 &Handle);
1814
1815 if (NT_SUCCESS(Status))
1816 {
1817 /* Pass the handle back to the caller */
1818 _SEH2_TRY
1819 {
1820 *JobHandle = Handle;
1821 }
1823 {
1825 }
1826 _SEH2_END;
1827 }
1828
1829 return Status;
1830}
#define DPRINT1
Definition: precomp.h:8
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define FALSE
Definition: types.h:117
#define InsertTailList(ListHead, Entry)
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
ULONG Handle
Definition: gdb_input.c:15
VOID FASTCALL KeInitializeGuardedMutex(OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:31
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define KernelMode
Definition: asm.h:38
@ NotificationEvent
static FAST_MUTEX PsJobListLock
Definition: job.c:26
LIST_ENTRY PsJobListHead
Definition: job.c:25
NTSTATUS NTAPI ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias, OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle)
Definition: obhandle.c:2957
NTSTATUS NTAPI ObCreateObject(IN KPROCESSOR_MODE ProbeMode OPTIONAL, IN POBJECT_TYPE Type, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext OPTIONAL, IN ULONG ObjectSize, IN ULONG PagedPoolCharge OPTIONAL, IN ULONG NonPagedPoolCharge OPTIONAL, OUT PVOID *Object)
Definition: oblife.c:1040
#define PSP_JOB_SCHEDULING_CLASS_DEFAULT
Definition: ps.h:72
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:204
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:104
#define _SEH2_END
Definition: pseh2_64.h:194
#define _SEH2_TRY
Definition: pseh2_64.h:93
#define ProbeForWriteHandle(Ptr)
Definition: probe.h:43
LIST_ENTRY ProcessListHead
Definition: pstypes.h:1621
KEVENT Event
Definition: pstypes.h:1619
ULONG SchedulingClass
Definition: pstypes.h:1647
LIST_ENTRY JobLinks
Definition: pstypes.h:1620
EX_PUSH_LOCK MemoryLimitsLock
Definition: pstypes.h:1665
ERESOURCE JobLock
Definition: pstypes.h:1622
LIST_ENTRY JobSetLinks
Definition: pstypes.h:1667
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2664
#define ExInitializeResource
Definition: exfuncs.h:346
#define PsGetCurrentProcess
Definition: psfuncs.h:17

◆ NtCreateJobSet()

NTSTATUS NTAPI NtCreateJobSet ( IN ULONG  NumJob,
IN PJOB_SET_ARRAY  UserJobSet,
IN ULONG  Flags 
)

Definition at line 1834 of file job.c.

1837{
1840}
#define UNIMPLEMENTED
Definition: ntoskrnl.c:15
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42

Referenced by CreateJobSet().

◆ NtIsProcessInJob()

NTSTATUS NTAPI NtIsProcessInJob ( _In_ HANDLE  ProcessHandle,
_In_opt_ HANDLE  JobHandle 
)

Determines if a specified process is associated with a specified or any job.

Parameters
[in]ProcessHandleA handle to the process being queried.
[in,optional]JobHandle An optional handle to the job object being compared. If NULL, the function checks if the process is associated with any job.
Returns
STATUS_PROCESS_IN_JOB if the process is in the job or any job (when JobHandle is NULL). STATUS_PROCESS_NOT_IN_JOB if the process is not in the job or any job. Otherwise, an appropriate NTSTATUS error code.

Definition at line 2014 of file job.c.

2018{
2021 PEJOB ProcessJob;
2022 PEJOB JobObjectFromHandle;
2024
2026
2027 PAGED_CODE();
2028
2029 /* Check if the process handle is the current process */
2031 {
2032 /* If so, directly use the current process object */
2034 }
2035 else
2036 {
2037 /* Reference the process object by handle */
2042 (PVOID *)&Process,
2043 NULL);
2044 if (!NT_SUCCESS(Status))
2045 {
2046 return Status;
2047 }
2048 }
2049
2050 /* Get the job object associated with the process */
2051 ProcessJob = Process->Job;
2052
2053 if (ProcessJob != NULL)
2054 {
2055 /* If no specific job handle is provided,
2056 the process is assigned to a job */
2057 if (JobHandle == NULL)
2058 {
2060 }
2061 else
2062 {
2063 /* Get the job object from the provided job handle
2064 and compare it with the process job */
2067 PsJobType,
2069 (PVOID *)&JobObjectFromHandle,
2070 NULL);
2071 if (NT_SUCCESS(Status))
2072 {
2073 /* Compare the job objects */
2074 if ((ProcessJob == JobObjectFromHandle))
2075 {
2077 }
2078 else
2079 {
2081 }
2082
2083 /* Dereference the job object handle */
2084 ObDereferenceObject(JobObjectFromHandle);
2085 }
2086 }
2087 }
2088 else
2089 {
2090 /* The process is not assigned to any job */
2092 }
2093
2094 /* Dereference the process object if it was referenced */
2096 {
2098 }
2099
2100 return Status;
2101}
#define PROCESS_QUERY_INFORMATION
Definition: pstypes.h:162
#define JOB_OBJECT_QUERY
Definition: pstypes.h:198
#define NtCurrentProcess()
Definition: nt_native.h:1660
#define STATUS_PROCESS_IN_JOB
Definition: ntstatus.h:161
#define STATUS_PROCESS_NOT_IN_JOB
Definition: ntstatus.h:160

Referenced by CreateProcessInternalW(), and IsProcessInJob().

◆ NtOpenJobObject()

NTSTATUS NTAPI NtOpenJobObject ( _Out_ PHANDLE  JobHandle,
_In_ ACCESS_MASK  DesiredAccess,
_In_ POBJECT_ATTRIBUTES  ObjectAttributes 
)

Opens a handle to an existing job object.

Parameters
JobHandleA pointer to a handle that will receive the handle of the created job object.
DesiredAccessSpecifies the desired access rights for the job object.
ObjectAttributesPointer to the OBJECT_ATTRIBUTES structure specifying the object name and attributes.
Returns
STATUS_SUCCESS if the job object is successfully created. An appropriate NTSTATUS error code otherwise.

Definition at line 1862 of file job.c.

1867{
1869 HANDLE Handle;
1871
1872 PAGED_CODE();
1873
1875
1876 /* Check for valid buffers */
1877 if (PreviousMode != KernelMode)
1878 {
1879 _SEH2_TRY
1880 {
1881 ProbeForWriteHandle(JobHandle);
1882 }
1884 {
1886 }
1887 _SEH2_END;
1888 }
1889
1891 PsJobType,
1893 NULL,
1895 NULL,
1896 &Handle);
1897 if (NT_SUCCESS(Status))
1898 {
1899 _SEH2_TRY
1900 {
1901 *JobHandle = Handle;
1902 }
1904 {
1906 }
1907 _SEH2_END;
1908 }
1909
1910 return Status;
1911}
NTSTATUS NTAPI ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, IN PACCESS_STATE PassedAccessState, IN ACCESS_MASK DesiredAccess, IN OUT PVOID ParseContext, OUT PHANDLE Handle)
Definition: obhandle.c:2554
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:207

◆ NtQueryInformationJobObject()

NTSTATUS NTAPI NtQueryInformationJobObject ( _In_opt_ HANDLE  JobHandle,
_In_ JOBOBJECTINFOCLASS  JobInformationClass,
_Out_writes_bytes_(JobInformationLength) PVOID  JobInformation,
_In_ ULONG  JobInformationLength,
_Out_opt_ PULONG  ReturnLength 
)

Retrieves information about a job object based on the requested information class.

Parameters
[in,optional]JobHandle Handle to the job object for which information is being queried. The handle must have the JOB_OBJECT_QUERY access right. If NULL, the current process' job is used.
[in]JobInformationClassSpecifies the type of information to query.
[out]JobInformationPointer to a buffer that receives the requested job object information.
[in]JobInformationLengthSpecifies the size, in bytes, of the JobInformation buffer.
[out,optional]ReturnLength Pointer to a variable that receives the size, in bytes, of the information written to the JobInformation buffer. Specify NULL to not receive this information.
Returns
STATUS_SUCCESS on success. Otherwise, an appropriate NTSTATUS error code.
Remarks
Not fully implemented. The function currently does not support all information classes.

Definition at line 2179 of file job.c.

2186{
2187 PEJOB Job;
2189 BOOLEAN NoOutput;
2190 PVOID JobInfoBuffer;
2191 PKTHREAD CurrentThread;
2195 JOBOBJECT_BASIC_UI_RESTRICTIONS UiRestrictions;
2196 ULONG RequiredLength, RequiredAlign, ReturnRequiredLength;
2197
2198 PAGED_CODE();
2199
2200 CurrentThread = KeGetCurrentThread();
2201
2202 /* Validate that JobInformationClass is in the expected range */
2203 if (JobInformationClass > JobObjectJobSetInformation ||
2204 JobInformationClass < JobObjectBasicAccountingInformation)
2205 {
2207 }
2208
2209 /* Determine the required length and alignment for the class */
2210 RequiredLength = PspJobInfoLengths[JobInformationClass];
2211 RequiredAlign = PspJobInfoAlign[JobInformationClass];
2212 ReturnRequiredLength = RequiredLength;
2213
2214 /* If length mismatch (needed versus provided) */
2215 if (JobInformationLength != RequiredLength)
2216 {
2217 /* This can only be accepted if the class is variable length
2218 (JobObjectBasicProcessIdList or JobObjectSecurityLimitInformation) or
2219 if size is bigger than needed */
2220 if ((JobInformationClass != JobObjectBasicProcessIdList &&
2221 JobInformationClass != JobObjectSecurityLimitInformation) ||
2222 JobInformationLength < RequiredLength)
2223 {
2225 }
2226
2227 /* Set what we need to copy out */
2228 RequiredLength = JobInformationLength;
2229 }
2230
2232
2233 /* If the request is coming from user mode, probe the user buffer */
2234 if (PreviousMode != KernelMode)
2235 {
2236 ASSERT(RequiredAlign == 1 ||
2237 RequiredAlign == 2 ||
2238 RequiredAlign == 4 ||
2239 RequiredAlign == 8 ||
2240 RequiredAlign == 16);
2241
2242 _SEH2_TRY
2243 {
2244 /* Probe the buffer */
2245 if (JobInformation != NULL)
2246 {
2247 ProbeForWrite(JobInformation, JobInformationLength, RequiredAlign);
2248 }
2249
2250 /* Probe the return length if required */
2251 if (ReturnLength != NULL)
2252 {
2254 }
2255 }
2257 {
2259 }
2260 _SEH2_END;
2261 }
2262
2263 /* If a job handle was provided, use it */
2264 if (JobHandle != NULL)
2265 {
2268 PsJobType,
2270 (PVOID *)&Job,
2271 NULL);
2272 if (!NT_SUCCESS(Status))
2273 {
2274 return Status;
2275 }
2276 }
2277 /* Otherwise, get our current process' job, if any */
2278 else
2279 {
2280 PEPROCESS CurrentProcess;
2281
2282 CurrentProcess = (PEPROCESS)CurrentThread->ApcState.Process;
2283 Job = CurrentProcess->Job;
2284 if (Job == NULL)
2285 {
2286 return STATUS_ACCESS_DENIED;
2287 }
2288
2289 ObReferenceObject(Job);
2290 }
2291
2292 /* By default, assume we'll have to copy data */
2293 NoOutput = FALSE;
2294
2295 switch (JobInformationClass)
2296 {
2299 {
2300 Status = PspQueryJobBasicAccountingInfo(Job, &BasicAndIo);
2301 JobInfoBuffer = &BasicAndIo;
2302 break;
2303 }
2306 {
2308 JobInformationClass == JobObjectExtendedLimitInformation,
2309 &ExtendedLimit);
2310 JobInfoBuffer = &ExtendedLimit;
2311 break;
2312 }
2314 {
2316 (PJOBOBJECT_BASIC_PROCESS_ID_LIST)JobInformation,
2317 JobInformationLength,
2318 &ReturnRequiredLength);
2319
2320 /* No need to copy data as it's directly filled in the helper */
2321 NoOutput = TRUE;
2322 break;
2323 }
2325 {
2326 UiRestrictions.UIRestrictionsClass = Job->UIRestrictionsClass;
2327 JobInfoBuffer = &UiRestrictions;
2328 break;
2329 }
2334 DPRINT1("Class %d not implemented\n", JobInformationClass);
2336 break;
2338 default:
2339 DPRINT1("Invalid class %d\n", JobInformationClass);
2341 break;
2342 }
2343
2344 /* Job is no longer required */
2346
2347 /* If we succeeded, copy back data */
2348 if (NT_SUCCESS(Status))
2349 {
2350 _SEH2_TRY
2351 {
2352 /* If we have anything to copy, do it */
2353 if (!NoOutput)
2354 {
2355 RtlCopyMemory(JobInformation, JobInfoBuffer, RequiredLength);
2356 }
2357
2358 /* And return length if asked */
2359 if (ReturnLength != NULL)
2360 {
2361 *ReturnLength = ReturnRequiredLength;
2362 }
2363 }
2365 {
2367 }
2368 _SEH2_END;
2369 }
2370
2371 return Status;
2372}
_In_ PVOID _In_ ULONG _Out_ PVOID _In_ ULONG _Inout_ PULONG ReturnLength
unsigned char BOOLEAN
Definition: actypes.h:127
#define TRUE
Definition: types.h:120
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define KeGetCurrentThread
Definition: hal.h:55
@ JobObjectAssociateCompletionPortInformation
Definition: pstypes.h:498
@ JobObjectBasicLimitInformation
Definition: pstypes.h:493
@ JobObjectBasicAndIoAccountingInformation
Definition: pstypes.h:499
@ JobObjectBasicAccountingInformation
Definition: pstypes.h:492
@ JobObjectSecurityLimitInformation
Definition: pstypes.h:496
@ JobObjectExtendedLimitInformation
Definition: pstypes.h:500
@ JobObjectEndOfJobTimeInformation
Definition: pstypes.h:497
@ JobObjectBasicUIRestrictions
Definition: pstypes.h:495
@ JobObjectBasicProcessIdList
Definition: pstypes.h:494
@ MaxJobObjectInfoClass
Definition: pstypes.h:502
@ JobObjectJobSetInformation
Definition: pstypes.h:501
if(dx< 0)
Definition: linetemp.h:194
#define ASSERT(a)
Definition: mode.c:44
struct _EPROCESS * PEPROCESS
Definition: nt_native.h:30
static NTSTATUS PspQueryJobProcessIdList(_In_ PEJOB Job, _Out_writes_bytes_(JobInformationLength) PJOBOBJECT_BASIC_PROCESS_ID_LIST ProcIdList, _In_ ULONG JobInformationLength, _Out_ PULONG ReturnRequiredLength)
Definition: job.c:1510
ULONG PspJobInfoAlign[]
Definition: job.c:71
static NTSTATUS PspQueryJobBasicAccountingInfo(_In_ PEJOB Job, _Out_ PJOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION BasicAndIo)
Definition: job.c:1297
static NTSTATUS PspQueryJobLimitInformation(_In_ PEJOB Job, _In_ BOOLEAN Extended, _Out_ PJOBOBJECT_EXTENDED_LIMIT_INFORMATION ExtendedLimit)
Definition: job.c:1379
ULONG PspJobInfoLengths[]
Definition: job.c:56
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:333
#define ProbeForWriteUlong(Ptr)
Definition: probe.h:36
ULONG UIRestrictionsClass
Definition: pstypes.h:1639
struct _EJOB * Job
Definition: pstypes.h:1440
KAPC_STATE ApcState
Definition: ketypes.h:1925
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
_In_ ULONG _Out_opt_ PULONG RequiredLength
Definition: wmifuncs.h:30
#define ObReferenceObject
Definition: obfuncs.h:204

Referenced by QueryInformationJobObject().

◆ NtSetInformationJobObject()

NTSTATUS NTAPI NtSetInformationJobObject ( _In_ HANDLE  JobHandle,
_In_ JOBOBJECTINFOCLASS  JobInformationClass,
_In_reads_bytes_(JobInformationLength) PVOID  JobInformation,
_In_ ULONG  JobInformationLength 
)

Sets the information for a job object, updating the specified job object limits.

This function is called to modify various job object limits, including basic limits, extended limits, security limits, and other job-specific settings.

Parameters
[in]JobHandleA handle to the job object that is being modified. The handle must have the JOB_OBJECT_SET_ATTRIBUTES access right.
[in]JobInformationClassThe class of information to set. This determines the structure and content of the JobInformation parameter.
[in]JobInformationA pointer to a buffer that contains the information to be set. The type and content of the buffer depend on the value of JobInformationClass.
[in]JobInformationLengthThe size of the buffer pointed to by JobInformation, in bytes.
Returns
STATUS_SUCCESS on success. Otherwise, an appropriate NTSTATUS error code.
Remarks
Not fully implemented. The function currently does not support all information classes.

Definition at line 2406 of file job.c.

2412{
2413 PEJOB Job;
2415 PKTHREAD CurrentThread;
2418 ULONG RequiredLength, RequiredAlign;
2419
2420 PAGED_CODE();
2421
2422 CurrentThread = KeGetCurrentThread();
2423
2424 /* Validate that JobInformationClass is in the expected range */
2425 if (JobInformationClass > JobObjectJobSetInformation ||
2426 JobInformationClass < JobObjectBasicAccountingInformation)
2427 {
2429 }
2430
2431 /* Determine the required length and alignment for the class */
2432 RequiredLength = PspJobInfoLengths[JobInformationClass];
2433 RequiredAlign = PspJobInfoAlign[JobInformationClass];
2434
2436
2437 /* If the request is coming from user mode, probe the user buffer */
2438 if (PreviousMode != KernelMode)
2439 {
2440 ASSERT(RequiredAlign == 1 ||
2441 RequiredAlign == 2 ||
2442 RequiredAlign == 4 ||
2443 RequiredAlign == 8 ||
2444 RequiredAlign == 16);
2445
2446 _SEH2_TRY
2447 {
2448 /* Probe out buffer for read */
2449 if (JobInformationLength != 0)
2450 {
2451 ProbeForRead(JobInformation, JobInformationLength, RequiredAlign);
2452 }
2453 }
2455 {
2457 }
2458 _SEH2_END;
2459 }
2460
2461 /* Validate that the provided buffer length matches the expected size
2462 for the class */
2463 if (JobInformationLength != RequiredLength)
2464 {
2466 }
2467
2469
2470 /* If setting security limits, additional security access rights
2471 are required */
2472 if (JobInformationClass == JobObjectSecurityLimitInformation)
2473 {
2475 }
2476
2479 PsJobType,
2481 (PVOID *)&Job,
2482 NULL);
2483 if (!NT_SUCCESS(Status))
2484 {
2485 return Status;
2486 }
2487
2488 /* And set the information.
2489 *
2490 * N.B. Disable APC delivery for the set operation. The handlers below may
2491 * acquire locks using unsafe variants which expect the caller to have
2492 * already established this state.
2493 */
2494
2495 KeEnterGuardedRegionThread(CurrentThread);
2496
2497 switch (JobInformationClass)
2498 {
2501 {
2503 BOOLEAN IsExtendedLimit = JobInformationClass == JobObjectExtendedLimitInformation;
2504
2505 _SEH2_TRY
2506 {
2507 /* If asking for extending limits */
2508 if (IsExtendedLimit)
2509 {
2510 ExtendedLimit = *(PJOBOBJECT_EXTENDED_LIMIT_INFORMATION)JobInformation;
2511 }
2512 else
2513 {
2514 RtlZeroMemory(&ExtendedLimit, sizeof(ExtendedLimit));
2515 ExtendedLimit.BasicLimitInformation =
2516 *(PJOBOBJECT_BASIC_LIMIT_INFORMATION)JobInformation;
2517 }
2518 }
2520 {
2522 goto Exit;
2523 }
2524 _SEH2_END;
2525
2527 &ExtendedLimit,
2528 IsExtendedLimit);
2529 goto Exit;
2530 }
2532 {
2534
2535 _SEH2_TRY
2536 {
2537 RtlCopyMemory(&AssociateCpInfo,
2538 JobInformation,
2539 sizeof(AssociateCpInfo));
2540 }
2542 {
2544 break;
2545 }
2546 _SEH2_END;
2547
2548 Status = PspAssociateCompletionPortWithJob(Job, &AssociateCpInfo);
2549 break;
2550 }
2552 {
2553 JOBOBJECT_BASIC_UI_RESTRICTIONS UiRestrictions;
2554
2555 _SEH2_TRY
2556 {
2557 UiRestrictions = *(PJOBOBJECT_BASIC_UI_RESTRICTIONS)JobInformation;
2558 }
2560 {
2562 goto Exit;
2563 }
2564 _SEH2_END;
2565
2566 Status = PspSetJobUIRestrictions(Job, UiRestrictions.UIRestrictionsClass);
2567 break;
2568 }
2575 DPRINT1("Class %d not implemented\n", JobInformationClass);
2577 break;
2579 default:
2580 DPRINT1("Invalid class %d\n", JobInformationClass);
2582 break;
2583 }
2584
2585Exit:
2586 KeLeaveGuardedRegionThread(CurrentThread);
2587
2589
2590 return Status;
2591}
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
#define JOB_OBJECT_SET_SECURITY_ATTRIBUTES
Definition: pstypes.h:200
struct _JOBOBJECT_BASIC_LIMIT_INFORMATION * PJOBOBJECT_BASIC_LIMIT_INFORMATION
struct _JOBOBJECT_EXTENDED_LIMIT_INFORMATION * PJOBOBJECT_EXTENDED_LIMIT_INFORMATION
#define JOB_OBJECT_SET_ATTRIBUTES
Definition: pstypes.h:197
struct _JOBOBJECT_BASIC_UI_RESTRICTIONS * PJOBOBJECT_BASIC_UI_RESTRICTIONS
#define KeEnterGuardedRegionThread(_Thread)
Definition: ke_x.h:27
#define KeLeaveGuardedRegionThread(_Thread)
Definition: ke_x.h:48
ULONG ACCESS_MASK
Definition: nt_native.h:40
static NTSTATUS PspAssociateCompletionPortWithJob(_In_ PEJOB Job, _In_ PJOBOBJECT_ASSOCIATE_COMPLETION_PORT AssociateCpInfo)
Definition: job.c:1223
static NTSTATUS PspSetJobLimitsBasicOrExtended(_In_ PEJOB Job, _In_ PJOBOBJECT_EXTENDED_LIMIT_INFORMATION ExtendedLimit, _In_ BOOLEAN IsExtendedLimit)
Definition: job.c:966
static NTSTATUS PspSetJobUIRestrictions(_In_ PEJOB Job, _In_ ULONG UIRestrictionsClass)
Definition: job.c:1678
static void Exit(void)
Definition: sock.c:1330
JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation
Definition: pstypes.h:1741
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135

Referenced by SetInformationJobObject().

◆ NtTerminateJobObject()

NTSTATUS NTAPI NtTerminateJobObject ( _In_ HANDLE  JobHandle,
_In_ NTSTATUS  ExitStatus 
)

Terminates all processes currently associated with the specified job object.

Parameters
[in]JobHandleA handle to the job object to be terminated.
[in]ExitStatusThe exit status to be used for all terminated processes.
Returns
STATUS_SUCCESS if the job object was successfully terminated. Otherwise, an appropriate NTSTATUS error code.

Definition at line 2118 of file job.c.

2122{
2124 PEJOB Job;
2126
2127 PAGED_CODE();
2128
2130
2133 PsJobType,
2135 (PVOID *)&Job,
2136 NULL);
2137 if (NT_SUCCESS(Status))
2138 {
2141 }
2142
2143 return Status;
2144}
#define JOB_OBJECT_TERMINATE
Definition: pstypes.h:199
_In_ NTSTATUS ExitStatus
Definition: psfuncs.h:890
NTSTATUS NTAPI PspTerminateJobObject(_In_ PEJOB Job, _In_ NTSTATUS ExitStatus)
Definition: job.c:788

Referenced by TerminateJobObject().

◆ PsGetJobLock()

PVOID NTAPI PsGetJobLock ( PEJOB  Job)

Definition at line 1571 of file job.c.

1572{
1573 ASSERT(Job);
1574 return (PVOID)&Job->JobLock;
1575}

◆ PsGetJobSessionId()

ULONG NTAPI PsGetJobSessionId ( PEJOB  Job)

Definition at line 1582 of file job.c.

1583{
1584 ASSERT(Job);
1585 return Job->SessionId;
1586}

◆ PsGetJobUIRestrictionsClass()

ULONG NTAPI PsGetJobUIRestrictionsClass ( PEJOB  Job)

Definition at line 1593 of file job.c.

1594{
1595 ASSERT(Job);
1596 return Job->UIRestrictionsClass;
1597}

◆ PspAssignProcessToJob()

NTSTATUS NTAPI PspAssignProcessToJob ( _In_ PEPROCESS  Process,
_In_ PEJOB  Job 
)

Assigns a process to a job object.

Parameters
[in]ProcessPointer to the process to be assigned to the job.
[in]JobPointer to the job object to which the process is to be assigned.
Returns
STATUS_SUCCESS if the process is successfully assigned to the job. An appropriate NTSTATUS error code otherwise.

Definition at line 432 of file job.c.

436{
438 NTSTATUS CalloutStatus = STATUS_SUCCESS;
439 PVOID PreviousJob;
440
441 if (!ExAcquireRundownProtection(&Process->RundownProtect))
442 {
444 }
445
447
448 /* https://learn.microsoft.com/en-us/windows/win32/api/jobapi2/nf-jobapi2-assignprocesstojobobject:
449 "If the job or any of its parent jobs in the job chain is terminating
450 when AssignProcessToJob is called, the function fails" */
451 if (FlagOn(Job->JobFlags, PSP_JOB_TERMINATING))
452 {
454 goto Exit;
455 }
456
457 /* Prevent processes from being added to the job if it is flagged
458 for closing and has a limit on process termination on closing */
459 if (FlagOn(Job->LimitFlags, JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE) &&
460 FlagOn(Job->JobFlags, PSP_JOB_CLOSE_DONE))
461 {
463 goto Exit;
464 }
465
466 /* Check if the job has a limit on the number of active processes */
467 if (FlagOn(Job->LimitFlags, JOB_OBJECT_LIMIT_ACTIVE_PROCESS) &&
468 Job->ActiveProcesses >= Job->ActiveProcessLimit)
469 {
470 /* Check if job limit on active processes has been reached */
471 if (Job->CompletionPort)
472 {
473 /* If the job has a completion port, notify the job that the
474 limit on the number of active processes has been exceeded */
477 NULL,
478 TRUE);
479 }
480
482 goto Exit;
483 }
484
485 /* Acquire the reference owned by Process->Job before publishing the pointer.
486 This ensures that every observable non-NULL Process->Job is already
487 backed by its lifetime reference. If another assignment wins the race,
488 release the unused reference. */
490
491 /* JobLock protects the target job, but another caller may simultaneously
492 hold a different job's lock while trying to assign the same process */
494 Job,
495 NULL);
496 if (PreviousJob)
497 {
500 goto Exit;
501 }
502
503 /* Assignment is committed at this point. No subsequent structural
504 operation may fail.
505
506 Readers of Job->ProcessListHead are blocked by JobLock until the list
507 and counters are complete. */
508
509 ASSERT(IsListEmpty(&Process->JobLinks));
510
511 InsertTailList(&Job->ProcessListHead, &Process->JobLinks);
512
513 Job->TotalProcesses++;
514 Job->ActiveProcesses++;
515
516 if (Job->CompletionPort && Process->UniqueProcessId)
517 {
518 /* If the job has a completion port and the process has a unique ID,
519 notify the job of the new process */
522 Process->UniqueProcessId,
523 FALSE);
524 }
525
526 /* Hand the process to win32k, which enforces the UI restrictions. One
527 that has not connected to win32k yet is picked up when it does. */
528 if (Job->UIRestrictionsClass != 0 && Process->Win32Process != NULL)
529 {
530 CalloutStatus = PspInvokeW32JobCallout(Job,
532 Process->Win32Process);
533 }
534
535Exit:
537 ExReleaseRundownProtection(&Process->RundownProtect);
538
539 /* The assignment is committed, but win32k will not be enforcing the UI
540 restrictions, so the process must not run at all. The caller is told
541 the assignment failed, since that is what it asked for. */
542 if (!NT_SUCCESS(CalloutStatus))
543 {
544 DPRINT1("Failed to apply the UI restrictions of job %p to process %p: 0x%lx\n",
545 Job, Process, CalloutStatus);
546
547 (VOID)PsTerminateProcess(Process, CalloutStatus);
548 Status = CalloutStatus;
549 }
550
551 /* TODO: Ensure that job limits are respected */
552
553 return Status;
554}
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define ExReleaseRundownProtection
Definition: ex.h:139
#define ExAcquireRundownProtection
Definition: ex.h:138
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
#define JOB_OBJECT_MSG_ACTIVE_PROCESS_LIMIT
Definition: pstypes.h:251
@ PsW32JobCalloutAddProcess
Definition: pstypes.h:554
#define JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
Definition: pstypes.h:221
#define JOB_OBJECT_LIMIT_ACTIVE_PROCESS
Definition: pstypes.h:211
#define JOB_OBJECT_MSG_NEW_PROCESS
Definition: pstypes.h:253
#define InterlockedCompareExchangePointer
Definition: interlocked.h:144
PVOID NTAPI ExEnterCriticalRegionAndAcquireResourceExclusive(IN PERESOURCE Resource)
Definition: resource.c:2194
VOID FASTCALL ExReleaseResourceAndLeaveCriticalRegion(IN PERESOURCE Resource)
Definition: resource.c:2283
NTSTATUS NTAPI PspInvokeW32JobCallout(_In_ PEJOB Job, _In_ PSW32JOBCALLOUTTYPE CalloutType, _In_opt_ PVOID Data)
Definition: job.c:1637
NTSTATUS NTAPI PspSendJobMessageLocked(_In_ PEJOB Job, _In_ ULONG Message, _In_opt_ PVOID CompletionValue, _In_ BOOLEAN Quota)
Definition: job.c:397
#define STATUS_PROCESS_IS_TERMINATING
Definition: ntstatus.h:596
#define PSP_JOB_CLOSE_DONE
Definition: ps.h:120
#define PSP_JOB_TERMINATING
Definition: ps.h:121
#define STATUS_SUCCESS
Definition: shellext.h:65

Referenced by NtAssignProcessToJobObject(), and PspCreateProcess().

◆ PspAssociateCompletionPortCallback()

static NTSTATUS NTAPI PspAssociateCompletionPortCallback ( _In_ PEPROCESS  Process,
_In_ PVOID  Context 
)
static

Queues an initial new-process notification for a process already assigned to a job.

Parameters
[in]ProcessA borrowed pointer to the process being notified.
[in]ContextA pointer to the job associated with the completion port.
Returns
STATUS_SUCCESS.
Remarks
The callback is invoked while the job lock is held exclusively. Notification failures are recorded for diagnostic purposes and do not undo the completion port association.

Definition at line 1174 of file job.c.

1177{
1178 PEJOB Job;
1179
1180 Job = (PEJOB)Context;
1181
1182 ASSERT(Process->Job == Job);
1183 ASSERT(Job->CompletionPort != NULL);
1184
1186
1187 /* Ensure the process is active and has a valid unique process ID */
1188 if (!FlagOn(Process->JobStatus, PSP_JOB_NOT_REALLY_ACTIVE) &&
1189 Process->UniqueProcessId)
1190 {
1193 Process->UniqueProcessId,
1194 FALSE);
1195 }
1196
1197 return STATUS_SUCCESS;
1198}
struct _EJOB * PEJOB
BOOLEAN NTAPI ExIsResourceAcquiredExclusiveLite(IN PERESOURCE Resource)
Definition: resource.c:1624
#define PSP_JOB_NOT_REALLY_ACTIVE
Definition: ps.h:111
_In_ PVOID Context
Definition: storport.h:2269
PVOID CompletionPort
Definition: pstypes.h:1644

Referenced by PspAssociateCompletionPortWithJob().

◆ PspAssociateCompletionPortWithJob()

static NTSTATUS PspAssociateCompletionPortWithJob ( _In_ PEJOB  Job,
_In_ PJOBOBJECT_ASSOCIATE_COMPLETION_PORT  AssociateCpInfo 
)
static

Associates an I/O completion port with a job object and enumerates its processes to propagate the association.

Parameters
[in]JobA pointer to the job object to which the I/O completion port will be associated.
[in]AssociateCpInfoA structure containing information used to associate a completion port with a job (the handle of the I/O completion port and the key).
Returns
STATUS_SUCCESS if the completion port was associated with the job. Otherwise, an appropriate NTSTATUS error code.
Remarks
Once the completion port is installed, failure to queue an initial process notification is recorded diagnostically and does not undo the association.

Definition at line 1223 of file job.c.

1227{
1231
1233
1234 if (!AssociateCpInfo->CompletionPort)
1235 {
1237 }
1238
1239 Status = ObReferenceObjectByHandle(AssociateCpInfo->CompletionPort,
1243 &IoCompletion,
1244 NULL);
1245 if (!NT_SUCCESS(Status))
1246 {
1247 return Status;
1248 }
1249
1250 ExAcquireResourceExclusiveLite(&Job->JobLock, TRUE);
1251
1252 /* Check if the job already has a completion port or is in a final state */
1253 if (Job->CompletionPort || FlagOn(Job->JobFlags, PSP_JOB_CLOSE_DONE))
1254 {
1255 ExReleaseResourceLite(&Job->JobLock);
1258 }
1259
1260 Job->CompletionKey = AssociateCpInfo->CompletionKey;
1261 Job->CompletionPort = IoCompletion;
1262
1263 /* Inform all processes in the job about the association
1264 N.B. Assignment is serialized by JobLock; a process is therefore covered
1265 either by this enumeration or by the normal assignment path */
1268 Job);
1269
1271
1272 ExReleaseResourceLite(&Job->JobLock);
1273
1274 /* The completion port association is committed at this point. Initial process
1275 notifications are best-effort and a failure to queue one must not turn
1276 a successful association into a failure. */
1277 return STATUS_SUCCESS;
1278}
NTSTATUS NTAPI IoCompletion(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Ctx)
Definition: control.c:393
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
#define IO_COMPLETION_MODIFY_STATE
Definition: iotypes.h:37
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
POBJECT_TYPE IoCompletionType
Definition: iocomp.c:16
BOOLEAN NTAPI KeAreAllApcsDisabled(VOID)
Definition: apc.c:985
static NTSTATUS NTAPI PspAssociateCompletionPortCallback(_In_ PEPROCESS Process, _In_ PVOID Context)
Definition: job.c:1174
static NTSTATUS PspEnumerateProcessesInJobLocked(_In_ PEJOB Job, _In_ PJOB_ENUMERATOR_CALLBACK Callback, _In_opt_ PVOID Context)
Definition: job.c:347

Referenced by NtSetInformationJobObject().

◆ PspCloseJob()

VOID NTAPI PspCloseJob ( _In_ PEPROCESS  Process,
_In_ PVOID  ObjectBody,
_In_ ACCESS_MASK  GrantedAccess,
_In_ ULONG_PTR  ProcessHandleCount,
_In_ ULONG_PTR  SystemHandleCount 
)

Handles the closing of a job object.

Parameters
[in]ProcessUnused.
[in]ObjectBodyA pointer to the job object being closed.
[in]GrantedAccessUnused.
[in]ProcessHandleCountUnused.
[in]SystemHandleCountThe number of system handles currently open for the job object.
Remarks
This function terminates the job if the JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE flag is set.

Definition at line 845 of file job.c.

852{
854 PEJOB Job = (PEJOB)ObjectBody;
855 PVOID CompletionPort = NULL;
856
857 PAGED_CODE();
858
862
863 /* Proceed only when the last handle is left */
864 if (SystemHandleCount > 1)
865 {
866 DPRINT1("PspJobClose called with unexpected SystemHandleCount: %lu\n",
867 SystemHandleCount);
868 return;
869 }
870
871 /* Flag the job as closed */
873
875
876 /* If the job is set to kill on close, terminate all associated processes */
878 {
879 /* Keep the completion port associated during termination so that
880 final job messages can still be delivered */
882
885
887 }
888
889 CompletionPort = Job->CompletionPort;
890 Job->CompletionPort = NULL;
891 Job->CompletionKey = NULL;
892
894
895 if (CompletionPort)
896 {
897 ObDereferenceObject(CompletionPort);
898 }
899}
#define InterlockedOr
Definition: interlocked.h:239
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
ULONG LimitFlags
Definition: pstypes.h:1633
PVOID CompletionKey
Definition: pstypes.h:1645
ULONG JobFlags
Definition: pstypes.h:1669
int32_t * PLONG
Definition: typedefs.h:58
@ ProcessHandleCount
Definition: winternl.h:1902
_In_ PSECURITY_SUBJECT_CONTEXT _In_ BOOLEAN _In_ ACCESS_MASK _In_ ACCESS_MASK _Outptr_opt_ PPRIVILEGE_SET _In_ PGENERIC_MAPPING _In_ KPROCESSOR_MODE _Out_ PACCESS_MASK GrantedAccess
Definition: sefuncs.h:20

Referenced by PspInitPhase0().

◆ PspDeactivateProcessFromJobLocked()

static BOOLEAN PspDeactivateProcessFromJobLocked ( _In_ PEJOB  Job,
_In_ PEPROCESS  Process 
)
static

Marks a process inactive in its assigned job.

Parameters
[in]JobA pointer to the process's assigned job.
[in]ProcessA pointer to the process being marked inactive.
Returns
TRUE if this call performed the active-to-inactive transition and reduced the job's active process count to zero; otherwise, FALSE.
Remarks
The caller must hold the job lock exclusively.

Definition at line 574 of file job.c.

578{
579 ASSERT(Process->Job == Job);
580
581 ASSERT(ExIsResourceAcquiredExclusiveLite(&Job->JobLock) != 0);
582
584 {
585 return FALSE;
586 }
587
588 ASSERT(Job->ActiveProcesses != 0);
589
590 Job->ActiveProcesses--;
591
593
594 return Job->ActiveProcesses == 0;
595}

Referenced by PspExitProcessFromJob(), PspRemoveProcessFromJob(), and PspTerminateProcessCallback().

◆ PspDeleteJob()

VOID NTAPI PspDeleteJob ( _In_ PVOID  ObjectBody)

Deletes the specified job object and cleans up associated resources.

Parameters
[in]ObjectBodyA pointer to the job object to be deleted.

Definition at line 909 of file job.c.

910{
911 PEJOB Job = (PEJOB)ObjectBody;
912
913 PAGED_CODE();
914
915 /* Let win32k tear down any per-job state it keeps for UI restrictions */
916 if (Job->UIRestrictionsClass != 0)
917 {
919 Job->UIRestrictionsClass = 0;
920 }
921
922 Job->LimitFlags = 0;
923
924 /* Remove the reference to the completion port if associated */
925 if (Job->CompletionPort)
926 {
928 Job->CompletionPort = NULL;
929 }
930
931 /* TODO: Ensure that job sets are respected */
932
933 /* Unlink the job object under lock */
935
936 ASSERT(!IsListEmpty(&Job->JobLinks));
938
940
941 /* TODO: Clean up security information */
942
943 /* Delete the resource associated with the job object */
945}
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
@ PsW32JobCalloutTerminate
Definition: pstypes.h:555
#define ExDeleteResource
Definition: exfuncs.h:345

Referenced by PspInitPhase0().

◆ PspEnumerateProcessesInJob()

NTSTATUS NTAPI PspEnumerateProcessesInJob ( _In_ PEJOB  Job,
_In_ PJOB_ENUMERATOR_CALLBACK  Callback,
_In_opt_ PVOID  Context 
)

Enumerates all processes currently associated with the specified job object and invokes a callback for each process.

Parameters
[in]JobA pointer to the job object whose processes are to be enumerated.
[in]CallbackA pointer to the callback invoked for each referenced process.
[in,optional]Context An optional context pointer passed to the callback.
Returns
STATUS_SUCCESS if every callback succeeds. Otherwise, the first unsuccessful callback status is returned.
Remarks
Enumeration stops when a callback returns an unsuccessful status.

The callback is invoked without the job lock held.

Definition at line 290 of file job.c.

295{
298
299 /* Iterate through all processes in the job */
301 Process != NULL;
303 {
305 if (!NT_SUCCESS(Status))
306 {
307 /*
308 * On successful iteration, PspGetNextProcessInJob consumes
309 * this reference. On failure, it must be released explicitly.
310 */
312 break;
313 }
314 }
315
316 return Status;
317}
_In_ ULONG _In_ ULONG _In_opt_ DXGKCB_MIRACAST_SEND_MESSAGE_CALLBACK Callback
Definition: dispmprt.h:620
static PEPROCESS PspGetNextProcessInJob(_In_ PEJOB Job, _In_opt_ PEPROCESS PreviousProcess)
Definition: job.c:227

Referenced by PspTerminateJobObject().

◆ PspEnumerateProcessesInJobLocked()

static NTSTATUS PspEnumerateProcessesInJobLocked ( _In_ PEJOB  Job,
_In_ PJOB_ENUMERATOR_CALLBACK  Callback,
_In_opt_ PVOID  Context 
)
static

Enumerates all assigned processes while the caller holds the job lock and invokes a callback for each process.

Parameters
[in]JobA pointer to the job object whose processes are to be enumerated.
[in]CallbackA pointer to the callback invoked for each process.
[in,optional]Context An optional context pointer passed to the callback.
Returns
STATUS_SUCCESS if every callback succeeds. Otherwise, the first unsuccessful callback status is returned.
Remarks
Enumeration stops when a callback returns an unsuccessful status.

The caller must hold the job lock shared or exclusive.

The callback must not release or recursively acquire the job lock, modify job membership, dereference the process object, or retain the process pointer after returning.

Definition at line 347 of file job.c.

352{
355
356 ASSERT(ExIsResourceAcquiredSharedLite(&Job->JobLock) != 0 ||
357 ExIsResourceAcquiredExclusiveLite(&Job->JobLock) != 0);
358
359 /* Iterate through all processes in the job */
361 Process != NULL;
363 {
365 if (!NT_SUCCESS(Status))
366 break;
367 }
368
369 return Status;
370}
ULONG NTAPI ExIsResourceAcquiredSharedLite(IN PERESOURCE Resource)
Definition: resource.c:1663
static PEPROCESS PspGetNextProcessInJobLocked(_In_ PEJOB Job, _In_opt_ PEPROCESS PreviousProcess)
Definition: job.c:158

Referenced by PspAssociateCompletionPortWithJob(), and PspQueryJobProcessIdList().

◆ PspExitProcessFromJob()

VOID NTAPI PspExitProcessFromJob ( _In_ PEPROCESS  Process)

Handles the exit of a process from the specified job object.

Parameters
[in]ProcessA pointer to the process that is exiting the job.
Remarks
This function is called from PspExitThread() when the last thread exits. The process must be assigned to a job.

Definition at line 659 of file job.c.

662{
663 PEJOB Job;
664 BOOLEAN ActiveProcessZero;
665
666 Job = Process->Job;
667 ASSERT(Job != NULL);
668
670
671 /* Job membership is immutable in the current implementation */
672 ASSERT(Process->Job == Job);
673
674 /* Decrement the job's active process count if the process is still active */
675 ActiveProcessZero = PspDeactivateProcessFromJobLocked(Job, Process);
676
677 /* If no active processes remain, notify the job completion port */
678 if (ActiveProcessZero && Job->CompletionPort)
679 {
682 NULL,
683 FALSE);
684 }
685
686 /* TODO: Ensure that job limits are respected */
687
689}
#define JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO
Definition: pstypes.h:252
static BOOLEAN PspDeactivateProcessFromJobLocked(_In_ PEJOB Job, _In_ PEPROCESS Process)
Definition: job.c:574

Referenced by PspExitThread().

◆ PspGetNextProcessInJob()

static PEPROCESS PspGetNextProcessInJob ( _In_ PEJOB  Job,
_In_opt_ PEPROCESS  PreviousProcess 
)
static

Returns the next referenced process directly assigned to a job.

Parameters
[in]JobA pointer to the job object being enumerated.
[in,optional]PreviousProcess A referenced process returned by the previous call, or NULL to start enumeration. When non-NULL, its reference is consumed by this function, regardless of whether another process is returned.
Returns
A referenced pointer to the next process, or NULL if enumeration has completed.
Remarks
The returned reference must either be passed to the next call or released with ObDereferenceObject().

The job lock is not held when this function returns.

This relies on job membership remaining fixed until process object deletion. The reference to PreviousProcess therefore keeps its JobLinks valid until the next process has been selected.

Definition at line 227 of file job.c.

231{
232 PEPROCESS Candidate;
233 PEPROCESS NextProcess = NULL;
234
236
237 Candidate = PreviousProcess;
238
239 while ((Candidate = PspGetNextProcessInJobLocked(Job, Candidate)) != NULL)
240 {
241 /*
242 * Skip processes whose deletion has begun. JobLinks remains valid
243 * while the job lock is held, allowing enumeration to continue.
244 */
245 if (ObReferenceObjectSafe(Candidate))
246 {
247 NextProcess = Candidate;
248 break;
249 }
250 }
251
253
254 /*
255 * This must occur after releasing the job lock. The dereference can invoke
256 * the process delete procedure, which removes JobLinks under the same lock.
257 */
258 if (PreviousProcess != NULL)
259 {
260 ObDereferenceObject(PreviousProcess);
261 }
262
263 return NextProcess;
264}
PVOID NTAPI ExEnterCriticalRegionAndAcquireResourceShared(IN PERESOURCE Resource)
Definition: resource.c:2223
BOOLEAN FASTCALL ObReferenceObjectSafe(IN PVOID Object)
Definition: obref.c:22

Referenced by PspEnumerateProcessesInJob().

◆ PspGetNextProcessInJobLocked()

static PEPROCESS PspGetNextProcessInJobLocked ( _In_ PEJOB  Job,
_In_opt_ PEPROCESS  PreviousProcess 
)
static

Returns the next process directly assigned to a job while the job lock is held.

Parameters
[in]JobA pointer to the job object being enumerated.
[in,optional]PreviousProcess A pointer to the process after which enumeration should continue, or NULL to return the first process.
Returns
A pointer to the next assigned process, or NULL if enumeration has completed.
Remarks
The caller must hold the job lock shared or exclusive.

Neither PreviousProcess nor the returned process is referenced by this function. The caller must ensure that PreviousProcess remains linked to the job and that direct job membership isn't modified during the enumeration.

Definition at line 158 of file job.c.

162{
165
166 ASSERT(ExIsResourceAcquiredSharedLite(&Job->JobLock) != 0 ||
167 ExIsResourceAcquiredExclusiveLite(&Job->JobLock) != 0);
168
169 /* Check if we're already starting somewhere */
170 if (PreviousProcess != NULL)
171 {
172 ASSERT(PreviousProcess->Job == Job);
173 ASSERT(!IsListEmpty(&PreviousProcess->JobLinks));
174
175 /* Start where we left off */
176 Entry = PreviousProcess->JobLinks.Flink;
177 }
178 else
179 {
180 /* Start at the beginning */
181 Entry = Job->ProcessListHead.Flink;
182 }
183
184 /* Check if enumeration has completed */
185 if (Entry == &Job->ProcessListHead)
186 {
187 return NULL;
188 }
189
190 ASSERT(Entry->Flink != NULL);
191 ASSERT(Entry->Blink != NULL);
192 ASSERT(Entry->Flink->Blink == Entry);
193 ASSERT(Entry->Blink->Flink == Entry);
194
196 ASSERT(Process->Job == Job);
197 return Process;
198}
Entry
Definition: section.c:5216
Definition: typedefs.h:120
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260

Referenced by PspEnumerateProcessesInJobLocked(), and PspGetNextProcessInJob().

◆ PspInitializeJobStructures()

VOID NTAPI PspInitializeJobStructures ( VOID  )

Definition at line 128 of file job.c.

129{
132}
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274

Referenced by PspInitPhase0().

◆ PspInvokeW32JobCallout()

NTSTATUS NTAPI PspInvokeW32JobCallout ( _In_ PEJOB  Job,
_In_ PSW32JOBCALLOUTTYPE  CalloutType,
_In_opt_ PVOID  Data 
)

Invokes the win32k job callout, if win32k has registered one.

Parameters
[in]JobA pointer to the job object the callout applies to.
[in]CalloutTypeThe operation win32k is being asked to perform.
[in,optional]Data Class specific data. For PsW32JobCalloutSetInformation this is the new UI restrictions class, for PsW32JobCalloutAddProcess the W32PROCESS of the process being added to the job.
Returns
The status returned by win32k, or STATUS_SUCCESS when no callout has been registered (i.e. the win32 subsystem is not loaded yet).
Remarks
FIXME: TODO: We do not attach to the session of the job, as win32k is only ever loaded in one session.

Definition at line 1637 of file job.c.

1642{
1644
1645 /* Nothing to do if win32k has not registered a callout */
1646 if (PspW32JobCallout == NULL)
1647 {
1648 return STATUS_SUCCESS;
1649 }
1650
1651 Parameters.Job = Job;
1652 Parameters.CalloutType = CalloutType;
1653 Parameters.Data = Data;
1654
1656}
_In_ HANDLE _In_ CONST PDXGKMDT_OPM_GET_INFO_PARAMETERS Parameters
Definition: dispmprt.h:321
PKWIN32_JOB_CALLOUT PspW32JobCallout
Definition: win32.c:20

Referenced by PspAssignProcessToJob(), PspDeleteJob(), and PspSetJobUIRestrictions().

◆ PspQueryJobBasicAccountingInfo()

static NTSTATUS PspQueryJobBasicAccountingInfo ( _In_ PEJOB  Job,
_Out_ PJOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION  BasicAndIo 
)
static

Collects accounting information, such as total user time, kernel time, page fault counts, and I/O operations, for the given job object.

Parameters
[in]JobPointer to the job object whose accounting information is being queried.
[out]BasicAndIoPointer to a structure that will be filled with basic accounting and I/O information about the job.
Returns
STATUS_SUCCESS on success. Otherwise, an appropriate NTSTATUS error code.

Definition at line 1297 of file job.c.

1301{
1302 PLIST_ENTRY NextEntry;
1303 PROCESS_VALUES Values;
1304
1305 /* Zero the basic accounting information */
1306 RtlZeroMemory(&BasicAndIo->BasicInfo, sizeof(BasicAndIo->BasicInfo));
1307
1308 /* Lock the job object */
1310
1311 /* Initialize with job's accumulated accounting data */
1312 BasicAndIo->BasicInfo.TotalUserTime.QuadPart = Job->TotalUserTime.QuadPart;
1313 BasicAndIo->BasicInfo.TotalKernelTime.QuadPart = Job->TotalKernelTime.QuadPart;
1314 BasicAndIo->BasicInfo.ThisPeriodTotalUserTime.QuadPart = Job->ThisPeriodTotalUserTime.QuadPart;
1315 BasicAndIo->BasicInfo.ThisPeriodTotalKernelTime.QuadPart = Job->ThisPeriodTotalKernelTime.QuadPart;
1316 BasicAndIo->BasicInfo.TotalPageFaultCount = Job->TotalPageFaultCount;
1317 BasicAndIo->BasicInfo.TotalProcesses = Job->TotalProcesses;
1318 BasicAndIo->BasicInfo.ActiveProcesses = Job->ActiveProcesses;
1319 BasicAndIo->BasicInfo.TotalTerminatedProcesses = Job->TotalTerminatedProcesses;
1320
1321 /* Set I/O info (even though it may not be returned in some cases) */
1322 BasicAndIo->IoInfo.ReadOperationCount = Job->ReadOperationCount;
1323 BasicAndIo->IoInfo.WriteOperationCount = Job->WriteOperationCount;
1324 BasicAndIo->IoInfo.OtherOperationCount = Job->OtherOperationCount;
1325 BasicAndIo->IoInfo.ReadTransferCount = Job->ReadTransferCount;
1326 BasicAndIo->IoInfo.WriteTransferCount = Job->WriteTransferCount;
1327 BasicAndIo->IoInfo.OtherTransferCount = Job->OtherTransferCount;
1328
1329 /* Sum up accounting data for each active process in the job */
1330 for (NextEntry = Job->ProcessListHead.Flink;
1331 NextEntry != &Job->ProcessListHead;
1332 NextEntry = NextEntry->Flink)
1333 {
1334 PEPROCESS Process = CONTAINING_RECORD(NextEntry, EPROCESS, JobLinks);
1335
1336 /* Skip folded accounting processes */
1337 if (!FlagOn(Process->JobStatus, PSP_JOB_ACCOUNTING_FOLDED))
1338 {
1339 KeQueryValuesProcess(&Process->Pcb, &Values);
1340
1341 /* Accumulate user and kernel times, and I/O counts */
1342 BasicAndIo->BasicInfo.TotalUserTime.QuadPart += Values.TotalUserTime.QuadPart;
1343 BasicAndIo->BasicInfo.TotalKernelTime.QuadPart += Values.TotalKernelTime.QuadPart;
1344 BasicAndIo->IoInfo.ReadOperationCount += Values.IoInfo.ReadOperationCount;
1345 BasicAndIo->IoInfo.WriteOperationCount += Values.IoInfo.WriteOperationCount;
1346 BasicAndIo->IoInfo.OtherOperationCount += Values.IoInfo.OtherOperationCount;
1347 BasicAndIo->IoInfo.ReadTransferCount += Values.IoInfo.ReadTransferCount;
1348 BasicAndIo->IoInfo.WriteTransferCount += Values.IoInfo.WriteTransferCount;
1349 BasicAndIo->IoInfo.OtherTransferCount += Values.IoInfo.OtherTransferCount;
1350 }
1351 }
1352
1353 /* Release the job lock */
1355
1356 return STATUS_SUCCESS;
1357}
VOID NTAPI KeQueryValuesProcess(IN PKPROCESS Process, PPROCESS_VALUES Values)
Definition: procobj.c:525
#define PSP_JOB_ACCOUNTING_FOLDED
Definition: ps.h:112
ULONGLONG ReadOperationCount
Definition: pstypes.h:83
ULONGLONG WriteTransferCount
Definition: pstypes.h:87
ULONGLONG WriteOperationCount
Definition: pstypes.h:84
ULONGLONG ReadTransferCount
Definition: pstypes.h:86
ULONGLONG OtherOperationCount
Definition: pstypes.h:85
ULONGLONG OtherTransferCount
Definition: pstypes.h:88
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
LARGE_INTEGER TotalUserTime
Definition: ke.h:47
IO_COUNTERS IoInfo
Definition: ke.h:48
LARGE_INTEGER TotalKernelTime
Definition: ke.h:46
LONGLONG QuadPart
Definition: typedefs.h:114

Referenced by NtQueryInformationJobObject().

◆ PspQueryJobLimitInformation()

static NTSTATUS PspQueryJobLimitInformation ( _In_ PEJOB  Job,
_In_ BOOLEAN  Extended,
_Out_ PJOBOBJECT_EXTENDED_LIMIT_INFORMATION  ExtendedLimit 
)
static

Retrieves basic or extended limit information for a job object.

Parameters
[in]JobPointer to the job object whose limit information is being queried.
[in]ExtendedA boolean value indicating whether extended limit information is being requested or only basic limit information.
[out]ExtendedLimitPointer to a structure that will be filled with basic or extended limit information about the job.
Returns
STATUS_SUCCESS on success. Otherwise, an appropriate NTSTATUS error code.

Definition at line 1379 of file job.c.

1384{
1385 PKTHREAD CurrentThread = KeGetCurrentThread();
1386
1387 /* Lock the job object */
1388 KeEnterGuardedRegionThread(CurrentThread);
1389 ExAcquireResourceSharedLite(&Job->JobLock, TRUE);
1390
1391 /* Copy basic limit information */
1392 ExtendedLimit->BasicLimitInformation.LimitFlags = Job->LimitFlags;
1393 ExtendedLimit->BasicLimitInformation.MinimumWorkingSetSize = Job->MinimumWorkingSetSize;
1394 ExtendedLimit->BasicLimitInformation.MaximumWorkingSetSize = Job->MaximumWorkingSetSize;
1395 ExtendedLimit->BasicLimitInformation.ActiveProcessLimit = Job->ActiveProcessLimit;
1396 ExtendedLimit->BasicLimitInformation.PriorityClass = Job->PriorityClass;
1397 ExtendedLimit->BasicLimitInformation.SchedulingClass = Job->SchedulingClass;
1398 ExtendedLimit->BasicLimitInformation.Affinity = Job->Affinity;
1399 ExtendedLimit->BasicLimitInformation.PerProcessUserTimeLimit.QuadPart = Job->PerProcessUserTimeLimit.QuadPart;
1400 ExtendedLimit->BasicLimitInformation.PerJobUserTimeLimit.QuadPart = Job->PerJobUserTimeLimit.QuadPart;
1401
1402 /* If extended limits are requested, include memory limits */
1403 if (Extended)
1404 {
1405 KeAcquireGuardedMutexUnsafe(&Job->MemoryLimitsLock);
1406
1407 ExtendedLimit->ProcessMemoryLimit = Job->ProcessMemoryLimit << PAGE_SHIFT;
1408 ExtendedLimit->JobMemoryLimit = Job->JobMemoryLimit << PAGE_SHIFT;
1409 ExtendedLimit->PeakProcessMemoryUsed = Job->PeakProcessMemoryUsed << PAGE_SHIFT;
1410 ExtendedLimit->PeakJobMemoryUsed = Job->PeakJobMemoryUsed << PAGE_SHIFT;
1411
1412 KeReleaseGuardedMutexUnsafe(&Job->MemoryLimitsLock);
1413
1414 /* Zero out IoInfo to avoid kernel memory leaks */
1415 RtlZeroMemory(&ExtendedLimit->IoInfo, sizeof(ExtendedLimit->IoInfo));
1416 }
1417
1418 /* Release the job lock */
1419 ExReleaseResourceLite(&Job->JobLock);
1420 KeLeaveGuardedRegionThread(CurrentThread);
1421
1422 return STATUS_SUCCESS;
1423}
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define ExAcquireResourceSharedLite(res, wait)
Definition: env_spec_w32.h:621
VOID FASTCALL KeReleaseGuardedMutexUnsafe(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:75
VOID FASTCALL KeAcquireGuardedMutexUnsafe(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:64

Referenced by NtQueryInformationJobObject().

◆ PspQueryJobProcessIdList()

static NTSTATUS PspQueryJobProcessIdList ( _In_ PEJOB  Job,
_Out_writes_bytes_(JobInformationLength) PJOBOBJECT_BASIC_PROCESS_ID_LIST  ProcIdList,
_In_ ULONG  JobInformationLength,
_Out_ PULONG  ReturnRequiredLength 
)
static

Collects a list of process IDs for all processes associated with a job.

Parameters
[in]JobPointer to the job object whose process IDs are being queried.
[out]ProcIdListPointer to a structure that will be filled with the list of process IDs and information about the number of assigned and returned process IDs.
[in]JobInformationLengthSpecifies the size, in bytes, of the buffer that will receive the process ID list.
[out]ReturnRequiredLengthPointer to a variable that receives the size, in bytes, of the information written to the buffer. If there is a buffer overflow, the required size is returned.
Returns
STATUS_SUCCESS on success. STATUS_BUFFER_OVERFLOW if the buffer is too small to hold all IDs. Otherwise, an appropriate NTSTATUS error code.

Definition at line 1510 of file job.c.

1516{
1519
1520 /* Check if the buffer provided is large enough to hold at least the
1521 fixed portion of JOBOBJECT_BASIC_PROCESS_ID_LIST */
1522 if (JobInformationLength < sizeof(JOBOBJECT_BASIC_PROCESS_ID_LIST))
1523 {
1525 }
1526
1527 QueryContext.ProcessIdList = ProcIdList;
1528 QueryContext.NextProcessId = &ProcIdList->ProcessIdList[0];
1529 QueryContext.RemainingLength = JobInformationLength - FIELD_OFFSET(JOBOBJECT_BASIC_PROCESS_ID_LIST,
1530 ProcessIdList);
1531
1533
1535
1536 _SEH2_TRY
1537 {
1538 ProcIdList->NumberOfAssignedProcesses = Job->ActiveProcesses;
1539 ProcIdList->NumberOfProcessIdsInList = 0;
1540
1543 &QueryContext);
1544 }
1546 {
1548 }
1549 _SEH2_END;
1550
1552
1554 {
1555 /* Report the bytes actually written */
1556 *ReturnRequiredLength = (ULONG)(JobInformationLength - QueryContext.RemainingLength);
1557 }
1558 else
1559 {
1560 *ReturnRequiredLength = 0;
1561 }
1562
1563 return Status;
1564}
static NTSTATUS NTAPI PspQueryJobProcessIdListCallback(_In_ PEPROCESS Process, _Inout_ PVOID Context)
Definition: job.c:1445
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
PJOBOBJECT_BASIC_PROCESS_ID_LIST ProcessIdList
Definition: job.c:118
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255

Referenced by NtQueryInformationJobObject().

◆ PspQueryJobProcessIdListCallback()

static NTSTATUS NTAPI PspQueryJobProcessIdListCallback ( _In_ PEPROCESS  Process,
_Inout_ PVOID  Context 
)
static

Callback function used to collect the process IDs for all active processes in a job object.

Parameters
[in]ProcessA pointer to the process whose ID is being added to the process list.
[in,out]ContextA pointer to the context structure that tracks the process ID collection. This context holds the list of process IDs, the length of the buffer, and the status of the collection operation.
Returns
STATUS_SUCCESS on successful collection of the process ID. Otherwise, an appropriate NTSTATUS error code if the buffer is insufficient or another error occurs.

Definition at line 1445 of file job.c.

1449{
1451
1452 /* Skip processes that are not really active */
1453 if (FlagOn(Process->JobStatus, PSP_JOB_NOT_REALLY_ACTIVE))
1454 {
1455 /* Continue to the next process */
1456 return STATUS_SUCCESS;
1457 }
1458
1459 /* An active process may be linked before its process identifier has been
1460 assigned - such a process is not representable in this information class */
1461 if (Process->UniqueProcessId == NULL)
1462 {
1463 ASSERT(QueryContext->ProcessIdList->NumberOfAssignedProcesses != 0);
1464
1466
1467 return STATUS_SUCCESS;
1468 }
1469
1470 if (QueryContext->RemainingLength < sizeof(ULONG_PTR))
1471 {
1473 }
1474
1475 *QueryContext->NextProcessId++ = (ULONG_PTR)Process->UniqueProcessId;
1476
1477 QueryContext->RemainingLength -= sizeof(ULONG_PTR);
1478
1479 QueryContext->ProcessIdList->NumberOfProcessIdsInList++;
1480
1481 return STATUS_SUCCESS;
1482}
#define ULONG_PTR
Definition: config.h:101
struct PSP_QUERY_JOB_PROCESS_ID_CONTEXT * PPSP_QUERY_JOB_PROCESS_ID_CONTEXT
uint32_t ULONG_PTR
Definition: typedefs.h:65

Referenced by PspQueryJobProcessIdList().

◆ PspRemoveProcessFromJob()

VOID NTAPI PspRemoveProcessFromJob ( _In_ PEPROCESS  Process)

Removes a process from its assigned job.

Parameters
[in]ProcessA pointer to the process being removed from its assigned job.
Remarks
This function is called from PspDeleteProcess() during process object deletion. The process must still be linked to its assigned job.

Definition at line 609 of file job.c.

612{
613 PEJOB Job;
614 BOOLEAN ActiveProcessZero;
615
616 Job = Process->Job;
617 ASSERT(Job != NULL);
618
620
621 ASSERT(Process->Job == Job);
622 ASSERT(Process->JobLinks.Flink != NULL);
623 ASSERT(Process->JobLinks.Blink != NULL);
624 ASSERT(!IsListEmpty(&Process->JobLinks));
625
626 /* Remove the process from the job's process list */
627 RemoveEntryList(&Process->JobLinks);
628 InitializeListHead(&Process->JobLinks);
629
630 /* Decrement the job's active process count if it is still active */
631 ActiveProcessZero = PspDeactivateProcessFromJobLocked(Job, Process);
632
633 /* TODO: Ensure that job limits are respected */
634
635 /* If no active processes remain, notify the job completion port */
636 if (ActiveProcessZero && Job->CompletionPort)
637 {
640 NULL,
641 FALSE);
642 }
643
645}

Referenced by PspDeleteProcess().

◆ PspSendJobMessageLocked()

NTSTATUS NTAPI PspSendJobMessageLocked ( _In_ PEJOB  Job,
_In_ ULONG  Message,
_In_opt_ PVOID  CompletionValue,
_In_ BOOLEAN  Quota 
)

Queues a message to a job's completion port.

Parameters
[in]JobA pointer to the job receiving the notification.
[in]MessageThe job notification message (JOB_OBJECT_MSG_*).
[in,optional]CompletionValue The message specific completion value.
[in]QuotaSpecifies whether the completion packet is charged as quota.
Returns
STATUS_SUCCESS if the message was queued successfully. Otherwise, an appropriate NTSTATUS error code.
Remarks
The caller must hold the job lock shared or exclusive. The caller must ensure that the job has an associated completion port.

Definition at line 397 of file job.c.

403{
404 ASSERT(Job->CompletionPort != NULL);
405
406 ASSERT(ExIsResourceAcquiredSharedLite(&Job->JobLock) != 0 ||
407 ExIsResourceAcquiredExclusiveLite(&Job->JobLock) != 0);
408
409 return IoSetIoCompletion(Job->CompletionPort,
410 Job->CompletionKey,
411 CompletionValue,
413 Message,
414 Quota);
415}
static const WCHAR Message[]
Definition: register.c:74
NTSTATUS NTAPI IoSetIoCompletion(IN PVOID IoCompletion, IN PVOID KeyContext, IN PVOID ApcContext, IN NTSTATUS IoStatus, IN ULONG_PTR IoStatusInformation, IN BOOLEAN Quota)
Definition: iocomp.c:147

Referenced by PspAssignProcessToJob(), PspAssociateCompletionPortCallback(), PspExitProcess(), PspExitProcessFromJob(), PspRemoveProcessFromJob(), and PspTerminateProcessCallback().

◆ PspSetJobLimitsBasicOrExtended()

static NTSTATUS PspSetJobLimitsBasicOrExtended ( _In_ PEJOB  Job,
_In_ PJOBOBJECT_EXTENDED_LIMIT_INFORMATION  ExtendedLimit,
_In_ BOOLEAN  IsExtendedLimit 
)
static

Helper function to set limit information for a job object, either basic or extended limits.

Parameters
[in]JobThe job object being modified.
[in]ExtendedLimitA pointer to the structure containing the limit information to be set.
[in]IsExtendedLimitA boolean value indicating whether the limit information is extended.
Returns
STATUS_SUCCESS if the job limits are successfully set. Otherwise, an appropriate NTSTATUS error code.

Definition at line 966 of file job.c.

971{
973 ULONG AllowedFlags;
975
977
978 AllowedFlags = IsExtendedLimit
981
982 /* Validate flags */
983 if (ExtendedLimit->BasicLimitInformation.LimitFlags & ~AllowedFlags)
984 {
985 DPRINT1("Invalid LimitFlags specified: 0x%08X\n",
986 ExtendedLimit->BasicLimitInformation.LimitFlags & ~AllowedFlags);
988 }
989
990 if (ExtendedLimit->BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_PRESERVE_JOB_TIME &&
991 ExtendedLimit->BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_JOB_TIME)
992 {
993 DPRINT1("Invalid LimitFlags combination specified "
994 "(PRESERVE_JOB_TIME and JOB_TIME are mutually exclusive)\n");
996 }
997
998 /* Acquire the job lock */
999 ExAcquireResourceExclusiveLite(&Job->JobLock, TRUE);
1000
1001 /*
1002 * Basic Limits
1003 */
1004
1005 if (ExtendedLimit->BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_WORKINGSET)
1006 {
1007 /* https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-jobobject_basic_limit_information:
1008 "If MaximumWorkingSetSize is nonzero, MinimumWorkingSetSize cannot be zero"
1009 "If MinimumWorkingSetSize is nonzero, MaximumWorkingSetSize cannot be zero"
1010 Also check that the minimum doesn't exceed the maximum or both aren't equal to zero. */
1011 if ((ExtendedLimit->BasicLimitInformation.MaximumWorkingSetSize > 0 &&
1012 ExtendedLimit->BasicLimitInformation.MinimumWorkingSetSize <= 0)
1013 ||
1014 (ExtendedLimit->BasicLimitInformation.MinimumWorkingSetSize > 0 &&
1015 ExtendedLimit->BasicLimitInformation.MaximumWorkingSetSize <= 0)
1016 ||
1017 ExtendedLimit->BasicLimitInformation.MaximumWorkingSetSize <
1018 ExtendedLimit->BasicLimitInformation.MinimumWorkingSetSize)
1019 {
1021 goto ExitFromBasicLimits;
1022 }
1023
1024 Job->MinimumWorkingSetSize = ExtendedLimit->BasicLimitInformation.MinimumWorkingSetSize;
1025 Job->MaximumWorkingSetSize = ExtendedLimit->BasicLimitInformation.MaximumWorkingSetSize;
1026 }
1027
1028 if (ExtendedLimit->BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_PROCESS_TIME)
1029 {
1030 Job->PerProcessUserTimeLimit.QuadPart =
1031 ExtendedLimit->BasicLimitInformation.PerProcessUserTimeLimit.QuadPart;
1032 }
1033
1034 if (ExtendedLimit->BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_JOB_TIME)
1035 {
1036 Job->PerJobUserTimeLimit.QuadPart =
1037 ExtendedLimit->BasicLimitInformation.PerJobUserTimeLimit.QuadPart;
1038 }
1039
1040 if (ExtendedLimit->BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_ACTIVE_PROCESS)
1041 {
1042 Job->ActiveProcessLimit = ExtendedLimit->BasicLimitInformation.ActiveProcessLimit;
1043 }
1044
1045 if (ExtendedLimit->BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_AFFINITY)
1046 {
1047 /* https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-jobobject_basic_limit_information:
1048 "The affinity must be a subset of the system affinity mask obtained
1049 by calling the GetProcessAffinityMask function"
1050 The lpSystemAffinityMask obtained with GetProcessAffinityMask() corresponds
1051 to ActiveProcessorsAffinityMask, which in turn corresponds to KeActiveProcessors */
1052 if (ExtendedLimit->BasicLimitInformation.Affinity !=
1053 (ExtendedLimit->BasicLimitInformation.Affinity & KeActiveProcessors))
1054 {
1056 goto ExitFromBasicLimits;
1057 }
1058
1059 Job->Affinity = ExtendedLimit->BasicLimitInformation.Affinity;
1060 }
1061
1062 if (ExtendedLimit->BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_PRIORITY_CLASS)
1063 {
1064 if (ExtendedLimit->BasicLimitInformation.PriorityClass > PROCESS_PRIORITY_CLASS_ABOVE_NORMAL ||
1065 ExtendedLimit->BasicLimitInformation.PriorityClass <= PROCESS_PRIORITY_CLASS_INVALID)
1066 {
1068 goto ExitFromBasicLimits;
1069 }
1070
1071 /* https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-jobobject_basic_limit_information:
1072 "The calling process must enable the SE_INC_BASE_PRIORITY_NAME
1073 privilege" */
1075 Job,
1077 PreviousMode))
1078 {
1079 Job->PriorityClass = ExtendedLimit->BasicLimitInformation.PriorityClass;
1080 }
1081 else
1082 {
1084 goto ExitFromBasicLimits;
1085 }
1086 }
1087
1088 if (ExtendedLimit->BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_SCHEDULING_CLASS)
1089 {
1090 if (ExtendedLimit->BasicLimitInformation.SchedulingClass >= PSP_JOB_SCHEDULING_CLASSES)
1091 {
1093 goto ExitFromBasicLimits;
1094 }
1095
1096 /* https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-jobobject_basic_limit_information:
1097 "To use a scheduling class greater than 5, the calling process must
1098 enable the SE_INC_BASE_PRIORITY_NAME privilege" */
1099 if (ExtendedLimit->BasicLimitInformation.SchedulingClass > PSP_JOB_SCHEDULING_CLASS_DEFAULT)
1100 {
1102 Job,
1104 PreviousMode))
1105 {
1106 Job->SchedulingClass = ExtendedLimit->BasicLimitInformation.SchedulingClass;
1107 }
1108 else
1109 {
1111 goto ExitFromBasicLimits;
1112 }
1113 }
1114 else
1115 {
1116 Job->SchedulingClass = ExtendedLimit->BasicLimitInformation.SchedulingClass;
1117 }
1118 }
1119
1120 /*
1121 * Extended Memory Limits
1122 */
1123
1124 /* Acquire the memory limits lock */
1125 KeAcquireGuardedMutexUnsafe(&Job->MemoryLimitsLock);
1126
1127 if (ExtendedLimit->BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_PROCESS_MEMORY)
1128 {
1129 Job->ProcessMemoryLimit = ExtendedLimit->ProcessMemoryLimit >> PAGE_SHIFT;
1130 }
1131
1132 if (ExtendedLimit->BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_JOB_MEMORY)
1133 {
1134 Job->JobMemoryLimit = ExtendedLimit->JobMemoryLimit >> PAGE_SHIFT;
1135 }
1136
1137 /* Update the job's limit flags with the new ones. This includes dealing
1138 with those extended limits that only set some flag */
1139 Job->LimitFlags = ExtendedLimit->BasicLimitInformation.LimitFlags;
1140
1141
1142 /* Release locks */
1143
1144 KeReleaseGuardedMutexUnsafe(&Job->MemoryLimitsLock);
1145
1146ExitFromBasicLimits:
1147
1148 ExReleaseResourceLite(&Job->JobLock);
1149
1150 return Status;
1151}
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
#define JOB_OBJECT_LIMIT_PRESERVE_JOB_TIME
Definition: pstypes.h:214
#define PROCESS_PRIORITY_CLASS_INVALID
Definition: pstypes.h:102
#define JOB_OBJECT_LIMIT_JOB_MEMORY
Definition: pstypes.h:217
#define JOB_OBJECT_LIMIT_WORKINGSET
Definition: pstypes.h:208
#define PROCESS_PRIORITY_CLASS_ABOVE_NORMAL
Definition: pstypes.h:108
#define JOB_OBJECT_LIMIT_PROCESS_MEMORY
Definition: pstypes.h:216
#define JOB_OBJECT_LIMIT_SCHEDULING_CLASS
Definition: pstypes.h:215
#define JOB_OBJECT_LIMIT_PRIORITY_CLASS
Definition: pstypes.h:213
#define JOB_OBJECT_LIMIT_JOB_TIME
Definition: pstypes.h:210
#define JOB_OBJECT_LIMIT_PROCESS_TIME
Definition: pstypes.h:209
#define JOB_OBJECT_LIMIT_AFFINITY
Definition: pstypes.h:212
KAFFINITY KeActiveProcessors
Definition: processor.c:16
BOOLEAN NTAPI SeCheckPrivilegedObject(_In_ LUID PrivilegeValue, _In_ HANDLE ObjectHandle, _In_ ACCESS_MASK DesiredAccess, _In_ KPROCESSOR_MODE PreviousMode)
Checks a privileged object if such object has the specific privilege submitted by the caller.
Definition: priv.c:803
const LUID SeIncreaseBasePriorityPrivilege
Definition: priv.c:33
#define PSP_JOB_BASIC_LIMIT_VALID_FLAGS
Definition: ps.h:78
#define PSP_JOB_SCHEDULING_CLASSES
Definition: ps.h:73
#define PSP_JOB_EXTENDED_LIMIT_VALID_FLAGS
Definition: ps.h:87

Referenced by NtSetInformationJobObject().

◆ PspSetJobUIRestrictions()

static NTSTATUS PspSetJobUIRestrictions ( _In_ PEJOB  Job,
_In_ ULONG  UIRestrictionsClass 
)
static

Applies a new basic UI restrictions class to a job object.

Parameters
[in]JobA pointer to the job object being modified.
[in]UIRestrictionsClassThe new set of JOB_OBJECT_UILIMIT_* flags.
Returns
STATUS_SUCCESS if the restrictions were applied. STATUS_INVALID_PARAMETER if unknown restriction flags were given. An appropriate NTSTATUS error code otherwise.
Remarks
The restrictions are only stored once win32k has accepted them, as it may fail to allocate the per-job state it needs to enforce them.

Definition at line 1678 of file job.c.

1682{
1684
1685 /* Reject restrictions we do not know about */
1686 if (UIRestrictionsClass & ~JOB_OBJECT_UILIMIT_ALL)
1687 {
1689 }
1690
1692
1693 /* Only bother win32k if something actually changes */
1694 if (Job->UIRestrictionsClass != UIRestrictionsClass)
1695 {
1698 UlongToPtr(UIRestrictionsClass));
1699 if (NT_SUCCESS(Status))
1700 {
1701 Job->UIRestrictionsClass = UIRestrictionsClass;
1702 }
1703 }
1704
1706
1707 return Status;
1708}
#define UlongToPtr(u)
Definition: config.h:106
#define JOB_OBJECT_UILIMIT_ALL
Definition: pstypes.h:235
@ PsW32JobCalloutSetInformation
Definition: pstypes.h:553

Referenced by NtSetInformationJobObject().

◆ PspTerminateJobObject()

NTSTATUS NTAPI PspTerminateJobObject ( _In_ PEJOB  Job,
_In_ NTSTATUS  ExitStatus 
)

Terminates all processes currently associated with the specified job object.

Parameters
[in]JobA pointer to the job object to be terminated.
[in]ExitStatusThe exit status to be used for all terminated processes.
Returns
STATUS_SUCCESS if the job object was successfully terminated. Otherwise, an appropriate NTSTATUS error code.

Definition at line 788 of file job.c.

792{
796
798
799 /* Termination is idempotent, another caller already owns the traversal */
801 {
802 return STATUS_SUCCESS;
803 }
804
805 Context.Job = Job;
806 Context.ExitStatus = ExitStatus;
807
810 &Context);
811
812 /* The termination callback always returns STATUS_SUCCESS because
813 per-process termination failures are handled locally */
815
816 InterlockedAnd((PLONG)&Job->JobFlags, ~PSP_JOB_TERMINATING);
817
818 return Status;
819}
#define InterlockedAnd
Definition: interlocked.h:77
static NTSTATUS NTAPI PspTerminateProcessCallback(_In_ PEPROCESS Process, _In_ PVOID Context)
Definition: job.c:711
NTSTATUS NTAPI PspEnumerateProcessesInJob(_In_ PEJOB Job, _In_ PJOB_ENUMERATOR_CALLBACK Callback, _In_opt_ PVOID Context)
Definition: job.c:290
_Out_ EXECUTION_STATE * PreviousFlags
Definition: ntpoapi.h:288
long LONG
Definition: pedump.c:60

Referenced by NtTerminateJobObject(), and PspCloseJob().

◆ PspTerminateProcessCallback()

static NTSTATUS NTAPI PspTerminateProcessCallback ( _In_ PEPROCESS  Process,
_In_ PVOID  Context 
)
static

Callback function to terminate a process and update the job's active process counter.

Parameters
[in]ProcessA pointer to the process object to be terminated.
[in]ContextA pointer to a PSP_TERMINATE_PROCESS_CONTEXT structure.
Returns
STATUS_SUCCESS.
Remarks
The callback is invoked without the job lock held. Process carries the reference acquired by the job enumerator for the duration of the call.

Definition at line 711 of file job.c.

715{
717 BOOLEAN ActiveProcessZero;
719 PEJOB Job = TerminateContext->Job;
720 NTSTATUS ExitStatus = TerminateContext->ExitStatus;
721
722 ASSERT(Job != NULL);
723 ASSERT(Process->Job == Job);
724
725 /* Avoid entering process termination when the process has already
726 completed its active job transition */
728
730 {
731 goto Exit;
732 }
733
734 /* Terminate the process */
736
737 /* PsTerminateProcess can return STATUS_NOTHING_TO_TERMINATE
738 when it finds no threads (the ordinary process exit remains
739 responsible for completing job accounting in that case),
740 that should be treated as a no-op for job traversal */
741 if (!NT_SUCCESS(Status))
742 {
743 goto Exit;
744 }
745
746 /* Decrement the job's active process count if the process is still active */
747 ActiveProcessZero = PspDeactivateProcessFromJobLocked(Job, Process);
748
749 /* If there are no active processes left in the job, notify anyone waiting
750 for the job object by signaling completion */
751 if (ActiveProcessZero)
752 {
753 /* It is intended that the event is set to a signaled
754 state only in the termination path */
756
757 if (Job->CompletionPort)
758 {
761 NULL,
762 FALSE);
763 }
764 }
765
766Exit:
767
769
770 return STATUS_SUCCESS;
771}
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
struct PSP_TERMINATE_PROCESS_CONTEXT * PPSP_TERMINATE_PROCESS_CONTEXT
#define IO_NO_INCREMENT
Definition: iotypes.h:598

Referenced by PspTerminateJobObject().

◆ PsSetJobUIRestrictionsClass()

VOID NTAPI PsSetJobUIRestrictionsClass ( PEJOB  Job,
ULONG  UIRestrictionsClass 
)

Definition at line 1604 of file job.c.

1608{
1609 ASSERT(Job);
1610 (void)InterlockedExchangeUL(&Job->UIRestrictionsClass, UIRestrictionsClass);
1611}
#define InterlockedExchangeUL(Target, Value)
Definition: ex.h:1547

Variable Documentation

◆ PsJobListHead

LIST_ENTRY PsJobListHead

Definition at line 25 of file job.c.

Referenced by NtCreateJobObject(), and PspInitializeJobStructures().

◆ PsJobListLock

FAST_MUTEX PsJobListLock
static

Definition at line 26 of file job.c.

Referenced by NtCreateJobObject(), PspDeleteJob(), and PspInitializeJobStructures().

◆ PsJobType

◆ PspJobInfoAlign

ULONG PspJobInfoAlign[]
Initial value:
=
{
0x0,
sizeof(ULONG),
sizeof(ULONG),
sizeof(ULONG),
sizeof(ULONG),
sizeof(ULONG),
sizeof(ULONG),
sizeof(HANDLE),
sizeof(ULONG),
sizeof(ULONG),
sizeof(ULONG)
}
PVOID HANDLE
Definition: typedefs.h:73

Definition at line 71 of file job.c.

Referenced by NtQueryInformationJobObject(), and NtSetInformationJobObject().

◆ PspJobInfoLengths

ULONG PspJobInfoLengths[]
Initial value:
=
{
0x0,
0x4
}
struct _JOBOBJECT_BASIC_PROCESS_ID_LIST JOBOBJECT_BASIC_PROCESS_ID_LIST
struct _JOBOBJECT_SECURITY_LIMIT_INFORMATION JOBOBJECT_SECURITY_LIMIT_INFORMATION
struct _JOBOBJECT_EXTENDED_LIMIT_INFORMATION JOBOBJECT_EXTENDED_LIMIT_INFORMATION
struct _JOBOBJECT_BASIC_ACCOUNTING_INFORMATION JOBOBJECT_BASIC_ACCOUNTING_INFORMATION
struct _JOBOBJECT_ASSOCIATE_COMPLETION_PORT JOBOBJECT_ASSOCIATE_COMPLETION_PORT

Definition at line 56 of file job.c.

Referenced by NtQueryInformationJobObject(), and NtSetInformationJobObject().

◆ PspJobMapping

GENERIC_MAPPING PspJobMapping
Initial value:
=
{
}
#define THREAD_ALL_ACCESS
Definition: nt_native.h:1342
#define SYNCHRONIZE
Definition: nt_native.h:61
#define STANDARD_RIGHTS_READ
Definition: nt_native.h:65
#define STANDARD_RIGHTS_ALL
Definition: nt_native.h:69
#define STANDARD_RIGHTS_WRITE
Definition: nt_native.h:66
#define STANDARD_RIGHTS_EXECUTE
Definition: nt_native.h:67

Definition at line 44 of file job.c.

Referenced by PspInitPhase0().

◆ PspJobSchedulingClasses

CHAR PspJobSchedulingClasses[PSP_JOB_SCHEDULING_CLASSES]
Initial value:
=
{
1 * 6,
2 * 6,
3 * 6,
4 * 6,
5 * 6,
6 * 6,
7 * 6,
8 * 6,
9 * 6,
10 * 6
}

Definition at line 30 of file job.c.

Referenced by PsChangeQuantumTable(), and PspComputeQuantumAndPriority().

◆ PspUseJobSchedulingClasses

BOOLEAN PspUseJobSchedulingClasses

Definition at line 28 of file job.c.

Referenced by PsChangeQuantumTable(), and PspComputeQuantumAndPriority().