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 // FIXME: This is broken
169 if(Process
->Job
== NULL
&& PtrToUlong(Process
->Session
) == Job
->SessionId
)
171 /* Just store the pointer to the job object in the process, we'll
172 assign it later. The reason we can't do this here is that locking
173 the job object might require it to wait, which is a bad thing
174 while holding the process lock! */
179 /* process is already assigned to a job or session id differs! */
180 Status
= STATUS_ACCESS_DENIED
;
182 ExReleaseRundownProtection(&Process
->RundownProtect
);
184 if(NT_SUCCESS(Status
))
186 /* let's actually assign the process to the job as we're not holding
187 the process lock anymore! */
188 Status
= PspAssignProcessToJob(Process
, Job
);
192 ObDereferenceObject(Job
);
197 /* process is already assigned to a job or session id differs! */
198 Status
= STATUS_ACCESS_DENIED
;
201 ObDereferenceObject(Process
);
209 NtCreateJobSet(IN ULONG NumJob
,
210 IN PJOB_SET_ARRAY UserJobSet
,
214 return STATUS_NOT_IMPLEMENTED
;
224 ACCESS_MASK DesiredAccess
,
225 POBJECT_ATTRIBUTES ObjectAttributes
)
229 KPROCESSOR_MODE PreviousMode
;
230 PEPROCESS CurrentProcess
;
235 PreviousMode
= ExGetPreviousMode();
236 CurrentProcess
= PsGetCurrentProcess();
238 /* check for valid buffers */
239 if (PreviousMode
!= KernelMode
)
243 ProbeForWriteHandle(JobHandle
);
245 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
247 _SEH2_YIELD(return _SEH2_GetExceptionCode());
252 Status
= ObCreateObject(PreviousMode
,
262 if(NT_SUCCESS(Status
))
264 /* FIXME - Zero all fields as we don't yet implement all of them */
265 RtlZeroMemory(Job
, sizeof(EJOB
));
267 /* make sure that early destruction doesn't attempt to remove the object from
268 the list before it even gets added! */
269 Job
->JobLinks
.Flink
= NULL
;
271 /* setup the job object */
272 InitializeListHead(&Job
->ProcessListHead
);
273 Job
->SessionId
= PtrToUlong(CurrentProcess
->Session
); /* inherit the session id from the caller, FIXME: broken */
275 Status
= ExInitializeResource(&Job
->JobLock
);
276 if(!NT_SUCCESS(Status
))
278 DPRINT1("Failed to initialize job lock!!!\n");
279 ObDereferenceObject(Job
);
282 KeInitializeEvent(&Job
->Event
, NotificationEvent
, FALSE
);
284 /* link the object into the global job list */
285 ExAcquireFastMutex(&PsJobListLock
);
286 InsertTailList(&PsJobListHead
, &Job
->JobLinks
);
287 ExReleaseFastMutex(&PsJobListLock
);
289 Status
= ObInsertObject(Job
,
295 if(NT_SUCCESS(Status
))
297 /* pass the handle back to the caller */
300 /* NOTE: if the caller passed invalid buffers to receive the handle it's his
301 own fault! the object will still be created and live... It's possible
302 to find the handle using ObFindHandleForObject()! */
305 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
307 Status
= _SEH2_GetExceptionCode();
323 IN HANDLE ProcessHandle
,
324 IN HANDLE JobHandle OPTIONAL
)
326 KPROCESSOR_MODE PreviousMode
;
330 PreviousMode
= ExGetPreviousMode();
334 Status
= ObReferenceObjectByHandle(
336 PROCESS_QUERY_INFORMATION
,
341 if(NT_SUCCESS(Status
))
343 /* FIXME - make sure the job object doesn't get exchanged or deleted while trying to
344 reference it, e.g. by locking it somehow until it is referenced... */
346 PEJOB ProcessJob
= Process
->Job
;
348 if(ProcessJob
!= NULL
)
350 if(JobHandle
== NULL
)
352 /* the process is assigned to a job */
353 Status
= STATUS_PROCESS_IN_JOB
;
355 else /* JobHandle != NULL */
359 /* get the job object and compare the object pointer with the one assigned to the process */
360 Status
= ObReferenceObjectByHandle(JobHandle
,
366 if(NT_SUCCESS(Status
))
368 Status
= ((ProcessJob
== JobObject
) ? STATUS_PROCESS_IN_JOB
: STATUS_PROCESS_NOT_IN_JOB
);
369 ObDereferenceObject(JobObject
);
375 /* the process is not assigned to any job */
376 Status
= STATUS_PROCESS_NOT_IN_JOB
;
378 ObDereferenceObject(Process
);
392 ACCESS_MASK DesiredAccess
,
393 POBJECT_ATTRIBUTES ObjectAttributes
)
395 KPROCESSOR_MODE PreviousMode
;
401 PreviousMode
= ExGetPreviousMode();
403 /* check for valid buffers */
404 if (PreviousMode
!= KernelMode
)
408 ProbeForWriteHandle(JobHandle
);
410 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
412 _SEH2_YIELD(return _SEH2_GetExceptionCode());
417 Status
= ObOpenObjectByName(ObjectAttributes
,
424 if(NT_SUCCESS(Status
))
430 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
432 Status
= _SEH2_GetExceptionCode();
446 NtQueryInformationJobObject (
448 JOBOBJECTINFOCLASS JobInformationClass
,
449 PVOID JobInformation
,
450 ULONG JobInformationLength
,
451 PULONG ReturnLength
)
454 return STATUS_NOT_IMPLEMENTED
;
463 NtSetInformationJobObject (
465 JOBOBJECTINFOCLASS JobInformationClass
,
466 PVOID JobInformation
,
467 ULONG JobInformationLength
)
470 return STATUS_NOT_IMPLEMENTED
;
479 NtTerminateJobObject (
481 NTSTATUS ExitStatus
)
483 KPROCESSOR_MODE PreviousMode
;
489 PreviousMode
= ExGetPreviousMode();
491 Status
= ObReferenceObjectByHandle(
493 JOB_OBJECT_TERMINATE
,
498 if(NT_SUCCESS(Status
))
500 Status
= PspTerminateJobObject(
504 ObDereferenceObject(Job
);
516 PsGetJobLock ( PEJOB Job
)
519 return (PVOID
)&Job
->JobLock
;
528 PsGetJobSessionId ( PEJOB Job
)
531 return (PVOID
)Job
->SessionId
;
540 PsGetJobUIRestrictionsClass ( PEJOB Job
)
543 return Job
->UIRestrictionsClass
;
552 PsSetJobUIRestrictionsClass(PEJOB Job
,
553 ULONG UIRestrictionsClass
)
556 (void)InterlockedExchangeUL(&Job
->UIRestrictionsClass
, UIRestrictionsClass
);
557 /* FIXME - walk through the job process list and update the restrictions? */