2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ps/job.c
5 * PURPOSE: Job Native Functions
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) (stubs)
7 * Thomas Weidenmueller <w3seek@reactos.com>
10 /* INCLUDES *****************************************************************/
17 /* GLOBALS *******************************************************************/
19 POBJECT_TYPE PsJobType
= NULL
;
21 LIST_ENTRY PsJobListHead
;
22 static FAST_MUTEX PsJobListLock
;
24 BOOLEAN PspUseJobSchedulingClasses
;
26 CHAR PspJobSchedulingClasses
[PSP_JOB_SCHEDULING_CLASSES
] =
40 GENERIC_MAPPING PspJobMapping
=
42 STANDARD_RIGHTS_READ
| JOB_OBJECT_QUERY
,
43 STANDARD_RIGHTS_WRITE
| JOB_OBJECT_ASSIGN_PROCESS
| JOB_OBJECT_SET_ATTRIBUTES
| JOB_OBJECT_TERMINATE
| JOB_OBJECT_SET_SECURITY_ATTRIBUTES
,
44 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
,
45 STANDARD_RIGHTS_ALL
| JOB_OBJECT_ALL_ACCESS
48 /* FUNCTIONS *****************************************************************/
52 PspDeleteJob ( PVOID ObjectBody
)
54 PEJOB Job
= (PEJOB
)ObjectBody
;
56 /* remove the reference to the completion port if associated */
57 if(Job
->CompletionPort
!= NULL
)
59 ObDereferenceObject(Job
->CompletionPort
);
62 /* unlink the job object */
63 if(Job
->JobLinks
.Flink
!= NULL
)
65 ExAcquireFastMutex(&PsJobListLock
);
66 RemoveEntryList(&Job
->JobLinks
);
67 ExReleaseFastMutex(&PsJobListLock
);
70 ExDeleteResource(&Job
->JobLock
);
76 PspInitializeJobStructures(VOID
)
78 InitializeListHead(&PsJobListHead
);
79 ExInitializeFastMutex(&PsJobListLock
);
84 PspAssignProcessToJob(PEPROCESS Process
,
87 DPRINT("PspAssignProcessToJob() is unimplemented!\n");
88 return STATUS_NOT_IMPLEMENTED
;
93 PspTerminateJobObject(PEJOB Job
,
94 KPROCESSOR_MODE AccessMode
,
97 DPRINT("PspTerminateJobObject() is unimplemented!\n");
98 return STATUS_NOT_IMPLEMENTED
;
103 PspRemoveProcessFromJob(IN PEPROCESS Process
,
111 PspExitProcessFromJob(IN PEJOB Job
,
112 IN PEPROCESS Process
)
122 NtAssignProcessToJobObject (
124 HANDLE ProcessHandle
)
127 KPROCESSOR_MODE PreviousMode
;
132 PreviousMode
= ExGetPreviousMode();
134 /* make sure we're having a handle with enough rights, especially the to
135 terminate the process. otherwise one could abuse the job objects to
136 terminate processes without having rights granted to do so! The reason
137 I open the process handle before the job handle is that a simple test showed
138 that it first complains about a invalid process handle! The other way around
139 would be simpler though... */
140 Status
= ObReferenceObjectByHandle(
147 if(NT_SUCCESS(Status
))
149 if(Process
->Job
== NULL
)
153 Status
= ObReferenceObjectByHandle(
155 JOB_OBJECT_ASSIGN_PROCESS
,
160 if(NT_SUCCESS(Status
))
162 /* lock the process so we can safely assign the process. Note that in the
163 meanwhile another thread could have assigned this process to a job! */
165 ExAcquireRundownProtection(&Process
->RundownProtect
);
166 if(NT_SUCCESS(Status
))
168 if(Process
->Job
== NULL
&& Process
->Session
== Job
->SessionId
)
170 /* Just store the pointer to the job object in the process, we'll
171 assign it later. The reason we can't do this here is that locking
172 the job object might require it to wait, which is a bad thing
173 while holding the process lock! */
178 /* process is already assigned to a job or session id differs! */
179 Status
= STATUS_ACCESS_DENIED
;
181 ExReleaseRundownProtection(&Process
->RundownProtect
);
183 if(NT_SUCCESS(Status
))
185 /* let's actually assign the process to the job as we're not holding
186 the process lock anymore! */
187 Status
= PspAssignProcessToJob(Process
, Job
);
191 ObDereferenceObject(Job
);
196 /* process is already assigned to a job or session id differs! */
197 Status
= STATUS_ACCESS_DENIED
;
200 ObDereferenceObject(Process
);
208 NtCreateJobSet(IN ULONG NumJob
,
209 IN PJOB_SET_ARRAY UserJobSet
,
213 return STATUS_NOT_IMPLEMENTED
;
223 ACCESS_MASK DesiredAccess
,
224 POBJECT_ATTRIBUTES ObjectAttributes
)
228 KPROCESSOR_MODE PreviousMode
;
229 PEPROCESS CurrentProcess
;
234 PreviousMode
= ExGetPreviousMode();
235 CurrentProcess
= PsGetCurrentProcess();
237 /* check for valid buffers */
238 if (PreviousMode
!= KernelMode
)
242 ProbeForWriteHandle(JobHandle
);
244 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
246 _SEH2_YIELD(return _SEH2_GetExceptionCode());
251 Status
= ObCreateObject(PreviousMode
,
261 if(NT_SUCCESS(Status
))
263 /* FIXME - Zero all fields as we don't yet implement all of them */
264 RtlZeroMemory(Job
, sizeof(EJOB
));
266 /* make sure that early destruction doesn't attempt to remove the object from
267 the list before it even gets added! */
268 Job
->JobLinks
.Flink
= NULL
;
270 /* setup the job object */
271 InitializeListHead(&Job
->ProcessListHead
);
272 Job
->SessionId
= CurrentProcess
->Session
; /* inherit the session id from the caller */
274 Status
= ExInitializeResource(&Job
->JobLock
);
275 if(!NT_SUCCESS(Status
))
277 DPRINT1("Failed to initialize job lock!!!\n");
278 ObDereferenceObject(Job
);
281 KeInitializeEvent(&Job
->Event
, NotificationEvent
, FALSE
);
283 /* link the object into the global job list */
284 ExAcquireFastMutex(&PsJobListLock
);
285 InsertTailList(&PsJobListHead
, &Job
->JobLinks
);
286 ExReleaseFastMutex(&PsJobListLock
);
288 Status
= ObInsertObject(Job
,
294 if(NT_SUCCESS(Status
))
296 /* pass the handle back to the caller */
299 /* NOTE: if the caller passed invalid buffers to receive the handle it's his
300 own fault! the object will still be created and live... It's possible
301 to find the handle using ObFindHandleForObject()! */
304 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
306 Status
= _SEH2_GetExceptionCode();
322 IN HANDLE ProcessHandle
,
323 IN HANDLE JobHandle OPTIONAL
)
325 KPROCESSOR_MODE PreviousMode
;
329 PreviousMode
= ExGetPreviousMode();
333 Status
= ObReferenceObjectByHandle(
335 PROCESS_QUERY_INFORMATION
,
340 if(NT_SUCCESS(Status
))
342 /* FIXME - make sure the job object doesn't get exchanged or deleted while trying to
343 reference it, e.g. by locking it somehow until it is referenced... */
345 PEJOB ProcessJob
= Process
->Job
;
347 if(ProcessJob
!= NULL
)
349 if(JobHandle
== NULL
)
351 /* the process is assigned to a job */
352 Status
= STATUS_PROCESS_IN_JOB
;
354 else /* JobHandle != NULL */
358 /* get the job object and compare the object pointer with the one assigned to the process */
359 Status
= ObReferenceObjectByHandle(JobHandle
,
365 if(NT_SUCCESS(Status
))
367 Status
= ((ProcessJob
== JobObject
) ? STATUS_PROCESS_IN_JOB
: STATUS_PROCESS_NOT_IN_JOB
);
368 ObDereferenceObject(JobObject
);
374 /* the process is not assigned to any job */
375 Status
= STATUS_PROCESS_NOT_IN_JOB
;
377 ObDereferenceObject(Process
);
391 ACCESS_MASK DesiredAccess
,
392 POBJECT_ATTRIBUTES ObjectAttributes
)
394 KPROCESSOR_MODE PreviousMode
;
400 PreviousMode
= ExGetPreviousMode();
402 /* check for valid buffers */
403 if (PreviousMode
!= KernelMode
)
407 ProbeForWriteHandle(JobHandle
);
409 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
411 _SEH2_YIELD(return _SEH2_GetExceptionCode());
416 Status
= ObOpenObjectByName(ObjectAttributes
,
423 if(NT_SUCCESS(Status
))
429 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
431 Status
= _SEH2_GetExceptionCode();
445 NtQueryInformationJobObject (
447 JOBOBJECTINFOCLASS JobInformationClass
,
448 PVOID JobInformation
,
449 ULONG JobInformationLength
,
450 PULONG ReturnLength
)
453 return STATUS_NOT_IMPLEMENTED
;
462 NtSetInformationJobObject (
464 JOBOBJECTINFOCLASS JobInformationClass
,
465 PVOID JobInformation
,
466 ULONG JobInformationLength
)
469 return STATUS_NOT_IMPLEMENTED
;
478 NtTerminateJobObject (
480 NTSTATUS ExitStatus
)
482 KPROCESSOR_MODE PreviousMode
;
488 PreviousMode
= ExGetPreviousMode();
490 Status
= ObReferenceObjectByHandle(
492 JOB_OBJECT_TERMINATE
,
497 if(NT_SUCCESS(Status
))
499 Status
= PspTerminateJobObject(
503 ObDereferenceObject(Job
);
515 PsGetJobLock ( PEJOB Job
)
518 return (PVOID
)&Job
->JobLock
;
527 PsGetJobSessionId ( PEJOB Job
)
530 return (PVOID
)Job
->SessionId
;
539 PsGetJobUIRestrictionsClass ( PEJOB Job
)
542 return Job
->UIRestrictionsClass
;
551 PsSetJobUIRestrictionsClass(PEJOB Job
,
552 ULONG UIRestrictionsClass
)
555 (void)InterlockedExchangeUL(&Job
->UIRestrictionsClass
, UIRestrictionsClass
);
556 /* FIXME - walk through the job process list and update the restrictions? */