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
);
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
;
233 PreviousMode
= ExGetPreviousMode();
234 CurrentProcess
= PsGetCurrentProcess();
236 /* check for valid buffers */
237 if (PreviousMode
!= KernelMode
)
241 ProbeForWriteHandle(JobHandle
);
243 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
245 _SEH2_YIELD(return _SEH2_GetExceptionCode());
250 Status
= ObCreateObject(PreviousMode
,
260 if(NT_SUCCESS(Status
))
262 /* FIXME - Zero all fields as we don't yet implement all of them */
263 RtlZeroMemory(Job
, sizeof(EJOB
));
265 /* make sure that early destruction doesn't attempt to remove the object from
266 the list before it even gets added! */
267 Job
->JobLinks
.Flink
= NULL
;
269 /* setup the job object */
270 InitializeListHead(&Job
->ProcessListHead
);
271 Job
->SessionId
= CurrentProcess
->Session
; /* inherit the session id from the caller */
273 Status
= ExInitializeResource(&Job
->JobLock
);
274 if(!NT_SUCCESS(Status
))
276 DPRINT1("Failed to initialize job lock!!!\n");
277 ObDereferenceObject(Job
);
280 KeInitializeEvent(&Job
->Event
, NotificationEvent
, FALSE
);
282 /* link the object into the global job list */
283 ExAcquireFastMutex(&PsJobListLock
);
284 InsertTailList(&PsJobListHead
, &Job
->JobLinks
);
285 ExReleaseFastMutex(&PsJobListLock
);
287 Status
= ObInsertObject(Job
,
293 if(NT_SUCCESS(Status
))
295 /* pass the handle back to the caller */
298 /* NOTE: if the caller passed invalid buffers to receive the handle it's his
299 own fault! the object will still be created and live... It's possible
300 to find the handle using ObFindHandleForObject()! */
303 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
305 Status
= _SEH2_GetExceptionCode();
321 IN HANDLE ProcessHandle
,
322 IN HANDLE JobHandle OPTIONAL
)
324 KPROCESSOR_MODE PreviousMode
;
328 PreviousMode
= ExGetPreviousMode();
332 Status
= ObReferenceObjectByHandle(
334 PROCESS_QUERY_INFORMATION
,
339 if(NT_SUCCESS(Status
))
341 /* FIXME - make sure the job object doesn't get exchanged or deleted while trying to
342 reference it, e.g. by locking it somehow until it is referenced... */
344 PEJOB ProcessJob
= Process
->Job
;
346 if(ProcessJob
!= NULL
)
348 if(JobHandle
== NULL
)
350 /* the process is assigned to a job */
351 Status
= STATUS_PROCESS_IN_JOB
;
353 else /* JobHandle != NULL */
357 /* get the job object and compare the object pointer with the one assigned to the process */
358 Status
= ObReferenceObjectByHandle(JobHandle
,
364 if(NT_SUCCESS(Status
))
366 Status
= ((ProcessJob
== JobObject
) ? STATUS_PROCESS_IN_JOB
: STATUS_PROCESS_NOT_IN_JOB
);
367 ObDereferenceObject(JobObject
);
373 /* the process is not assigned to any job */
374 Status
= STATUS_PROCESS_NOT_IN_JOB
;
376 ObDereferenceObject(Process
);
390 ACCESS_MASK DesiredAccess
,
391 POBJECT_ATTRIBUTES ObjectAttributes
)
393 KPROCESSOR_MODE PreviousMode
;
399 PreviousMode
= ExGetPreviousMode();
401 /* check for valid buffers */
402 if (PreviousMode
!= KernelMode
)
406 ProbeForWriteHandle(JobHandle
);
408 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
410 _SEH2_YIELD(return _SEH2_GetExceptionCode());
415 Status
= ObOpenObjectByName(ObjectAttributes
,
422 if(NT_SUCCESS(Status
))
428 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
430 Status
= _SEH2_GetExceptionCode();
444 NtQueryInformationJobObject (
446 JOBOBJECTINFOCLASS JobInformationClass
,
447 PVOID JobInformation
,
448 ULONG JobInformationLength
,
449 PULONG ReturnLength
)
452 return STATUS_NOT_IMPLEMENTED
;
461 NtSetInformationJobObject (
463 JOBOBJECTINFOCLASS JobInformationClass
,
464 PVOID JobInformation
,
465 ULONG JobInformationLength
)
468 return STATUS_NOT_IMPLEMENTED
;
477 NtTerminateJobObject (
479 NTSTATUS ExitStatus
)
481 KPROCESSOR_MODE PreviousMode
;
487 PreviousMode
= ExGetPreviousMode();
489 Status
= ObReferenceObjectByHandle(
491 JOB_OBJECT_TERMINATE
,
496 if(NT_SUCCESS(Status
))
498 Status
= PspTerminateJobObject(
502 ObDereferenceObject(Job
);
514 PsGetJobLock ( PEJOB Job
)
517 return (PVOID
)&Job
->JobLock
;
526 PsGetJobSessionId ( PEJOB Job
)
529 return (PVOID
)Job
->SessionId
;
538 PsGetJobUIRestrictionsClass ( PEJOB Job
)
541 return Job
->UIRestrictionsClass
;
550 PsSetJobUIRestrictionsClass(PEJOB Job
,
551 ULONG UIRestrictionsClass
)
554 (void)InterlockedExchangeUL(&Job
->UIRestrictionsClass
, UIRestrictionsClass
);
555 /* FIXME - walk through the job process list and update the restrictions? */