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 *****************************************************************/
14 #include <internal/debug.h>
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
);
75 PspInitializeJobStructures(VOID
)
77 InitializeListHead(&PsJobListHead
);
78 ExInitializeFastMutex(&PsJobListLock
);
83 PspAssignProcessToJob(PEPROCESS Process
,
86 DPRINT("PspAssignProcessToJob() is unimplemented!\n");
87 return STATUS_NOT_IMPLEMENTED
;
92 PspTerminateJobObject(PEJOB Job
,
93 KPROCESSOR_MODE AccessMode
,
96 DPRINT("PspTerminateJobObject() is unimplemented!\n");
97 return STATUS_NOT_IMPLEMENTED
;
102 PspRemoveProcessFromJob(IN PEPROCESS Process
,
110 PspExitProcessFromJob(IN PEJOB Job
,
111 IN PEPROCESS Process
)
121 NtAssignProcessToJobObject (
123 HANDLE ProcessHandle
)
126 KPROCESSOR_MODE PreviousMode
;
131 PreviousMode
= ExGetPreviousMode();
133 /* make sure we're having a handle with enough rights, especially the to
134 terminate the process. otherwise one could abuse the job objects to
135 terminate processes without having rights granted to do so! The reason
136 I open the process handle before the job handle is that a simple test showed
137 that it first complains about a invalid process handle! The other way around
138 would be simpler though... */
139 Status
= ObReferenceObjectByHandle(
146 if(NT_SUCCESS(Status
))
148 if(Process
->Job
== NULL
)
152 Status
= ObReferenceObjectByHandle(
154 JOB_OBJECT_ASSIGN_PROCESS
,
159 if(NT_SUCCESS(Status
))
161 /* lock the process so we can safely assign the process. Note that in the
162 meanwhile another thread could have assigned this process to a job! */
164 ExAcquireRundownProtection(&Process
->RundownProtect
);
165 if(NT_SUCCESS(Status
))
167 if(Process
->Job
== NULL
&& Process
->Session
== Job
->SessionId
)
169 /* Just store the pointer to the job object in the process, we'll
170 assign it later. The reason we can't do this here is that locking
171 the job object might require it to wait, which is a bad thing
172 while holding the process lock! */
177 /* process is already assigned to a job or session id differs! */
178 Status
= STATUS_ACCESS_DENIED
;
180 ExReleaseRundownProtection(&Process
->RundownProtect
);
182 if(NT_SUCCESS(Status
))
184 /* let's actually assign the process to the job as we're not holding
185 the process lock anymore! */
186 Status
= PspAssignProcessToJob(Process
, Job
);
190 ObDereferenceObject(Job
);
195 /* process is already assigned to a job or session id differs! */
196 Status
= STATUS_ACCESS_DENIED
;
199 ObDereferenceObject(Process
);
207 NtCreateJobSet(IN ULONG NumJob
,
208 IN PJOB_SET_ARRAY UserJobSet
,
212 return STATUS_NOT_IMPLEMENTED
;
222 ACCESS_MASK DesiredAccess
,
223 POBJECT_ATTRIBUTES ObjectAttributes
)
227 KPROCESSOR_MODE PreviousMode
;
228 PEPROCESS CurrentProcess
;
229 NTSTATUS Status
= STATUS_SUCCESS
;
233 PreviousMode
= ExGetPreviousMode();
234 CurrentProcess
= PsGetCurrentProcess();
236 /* check for valid buffers */
237 if(PreviousMode
!= KernelMode
)
241 ProbeForWriteHandle(JobHandle
);
245 Status
= _SEH_GetExceptionCode();
249 if(!NT_SUCCESS(Status
))
255 Status
= ObCreateObject(PreviousMode
,
265 if(NT_SUCCESS(Status
))
267 /* FIXME - Zero all fields as we don't yet implement all of them */
268 RtlZeroMemory(Job
, sizeof(EJOB
));
270 /* make sure that early destruction doesn't attempt to remove the object from
271 the list before it even gets added! */
272 Job
->JobLinks
.Flink
= NULL
;
274 /* setup the job object */
275 InitializeListHead(&Job
->ProcessListHead
);
276 Job
->SessionId
= CurrentProcess
->Session
; /* inherit the session id from the caller */
278 Status
= ExInitializeResource(&Job
->JobLock
);
279 if(!NT_SUCCESS(Status
))
281 DPRINT1("Failed to initialize job lock!!!\n");
282 ObDereferenceObject(Job
);
285 KeInitializeEvent(&Job
->Event
, NotificationEvent
, FALSE
);
287 /* link the object into the global job list */
288 ExAcquireFastMutex(&PsJobListLock
);
289 InsertTailList(&PsJobListHead
, &Job
->JobLinks
);
290 ExReleaseFastMutex(&PsJobListLock
);
292 Status
= ObInsertObject(Job
,
298 if(NT_SUCCESS(Status
))
300 /* pass the handle back to the caller */
303 /* NOTE: if the caller passed invalid buffers to receive the handle it's his
304 own fault! the object will still be created and live... It's possible
305 to find the handle using ObFindHandleForObject()! */
310 Status
= _SEH_GetExceptionCode();
326 IN HANDLE ProcessHandle
,
327 IN HANDLE JobHandle OPTIONAL
)
329 KPROCESSOR_MODE PreviousMode
;
333 PreviousMode
= ExGetPreviousMode();
337 Status
= ObReferenceObjectByHandle(
339 PROCESS_QUERY_INFORMATION
,
344 if(NT_SUCCESS(Status
))
346 /* FIXME - make sure the job object doesn't get exchanged or deleted while trying to
347 reference it, e.g. by locking it somehow until it is referenced... */
349 PEJOB ProcessJob
= Process
->Job
;
351 if(ProcessJob
!= NULL
)
353 if(JobHandle
== NULL
)
355 /* the process is assigned to a job */
356 Status
= STATUS_PROCESS_IN_JOB
;
358 else /* JobHandle != NULL */
362 /* get the job object and compare the object pointer with the one assigned to the process */
363 Status
= ObReferenceObjectByHandle(JobHandle
,
369 if(NT_SUCCESS(Status
))
371 Status
= ((ProcessJob
== JobObject
) ? STATUS_PROCESS_IN_JOB
: STATUS_PROCESS_NOT_IN_JOB
);
372 ObDereferenceObject(JobObject
);
378 /* the process is not assigned to any job */
379 Status
= STATUS_PROCESS_NOT_IN_JOB
;
381 ObDereferenceObject(Process
);
395 ACCESS_MASK DesiredAccess
,
396 POBJECT_ATTRIBUTES ObjectAttributes
)
398 KPROCESSOR_MODE PreviousMode
;
400 NTSTATUS Status
= STATUS_SUCCESS
;
404 PreviousMode
= ExGetPreviousMode();
406 /* check for valid buffers */
407 if(PreviousMode
!= KernelMode
)
411 ProbeForWriteHandle(JobHandle
);
415 Status
= _SEH_GetExceptionCode();
419 if(!NT_SUCCESS(Status
))
425 if(NT_SUCCESS(Status
))
427 Status
= ObOpenObjectByName(ObjectAttributes
,
434 if(NT_SUCCESS(Status
))
442 Status
= _SEH_GetExceptionCode();
457 NtQueryInformationJobObject (
459 JOBOBJECTINFOCLASS JobInformationClass
,
460 PVOID JobInformation
,
461 ULONG JobInformationLength
,
462 PULONG ReturnLength
)
465 return STATUS_NOT_IMPLEMENTED
;
474 NtSetInformationJobObject (
476 JOBOBJECTINFOCLASS JobInformationClass
,
477 PVOID JobInformation
,
478 ULONG JobInformationLength
)
481 return STATUS_NOT_IMPLEMENTED
;
490 NtTerminateJobObject (
492 NTSTATUS ExitStatus
)
494 KPROCESSOR_MODE PreviousMode
;
500 PreviousMode
= ExGetPreviousMode();
502 Status
= ObReferenceObjectByHandle(
504 JOB_OBJECT_TERMINATE
,
509 if(NT_SUCCESS(Status
))
511 Status
= PspTerminateJobObject(
515 ObDereferenceObject(Job
);
527 PsGetJobLock ( PEJOB Job
)
530 return (PVOID
)&Job
->JobLock
;
539 PsGetJobSessionId ( PEJOB Job
)
542 return (PVOID
)Job
->SessionId
;
551 PsGetJobUIRestrictionsClass ( PEJOB Job
)
554 return Job
->UIRestrictionsClass
;
563 PsSetJobUIRestrictionsClass(PEJOB Job
,
564 ULONG UIRestrictionsClass
)
567 (void)InterlockedExchangeUL(&Job
->UIRestrictionsClass
, UIRestrictionsClass
);
568 /* FIXME - walk through the job process list and update the restrictions? */