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
,
44 STANDARD_RIGHTS_WRITE
| JOB_OBJECT_ASSIGN_PROCESS
|
45 JOB_OBJECT_SET_ATTRIBUTES
| JOB_OBJECT_TERMINATE
,
47 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
,
49 STANDARD_RIGHTS_ALL
| THREAD_ALL_ACCESS
// bug fixed only in vista
52 /* FUNCTIONS *****************************************************************/
56 PspDeleteJob ( PVOID ObjectBody
)
58 PEJOB Job
= (PEJOB
)ObjectBody
;
60 /* remove the reference to the completion port if associated */
61 if(Job
->CompletionPort
!= NULL
)
63 ObDereferenceObject(Job
->CompletionPort
);
66 /* unlink the job object */
67 if(Job
->JobLinks
.Flink
!= NULL
)
69 ExAcquireFastMutex(&PsJobListLock
);
70 RemoveEntryList(&Job
->JobLinks
);
71 ExReleaseFastMutex(&PsJobListLock
);
74 ExDeleteResource(&Job
->JobLock
);
80 PspInitializeJobStructures(VOID
)
82 InitializeListHead(&PsJobListHead
);
83 ExInitializeFastMutex(&PsJobListLock
);
88 PspAssignProcessToJob(PEPROCESS Process
,
91 DPRINT("PspAssignProcessToJob() is unimplemented!\n");
92 return STATUS_NOT_IMPLEMENTED
;
97 PspTerminateJobObject(PEJOB Job
,
98 KPROCESSOR_MODE AccessMode
,
101 DPRINT("PspTerminateJobObject() is unimplemented!\n");
102 return STATUS_NOT_IMPLEMENTED
;
107 PspRemoveProcessFromJob(IN PEPROCESS Process
,
115 PspExitProcessFromJob(IN PEJOB Job
,
116 IN PEPROCESS Process
)
126 NtAssignProcessToJobObject (
128 HANDLE ProcessHandle
)
131 KPROCESSOR_MODE PreviousMode
;
136 PreviousMode
= ExGetPreviousMode();
138 /* make sure we're having a handle with enough rights, especially the to
139 terminate the process. otherwise one could abuse the job objects to
140 terminate processes without having rights granted to do so! The reason
141 I open the process handle before the job handle is that a simple test showed
142 that it first complains about a invalid process handle! The other way around
143 would be simpler though... */
144 Status
= ObReferenceObjectByHandle(
151 if(NT_SUCCESS(Status
))
153 if(Process
->Job
== NULL
)
157 Status
= ObReferenceObjectByHandle(
159 JOB_OBJECT_ASSIGN_PROCESS
,
164 if(NT_SUCCESS(Status
))
166 /* lock the process so we can safely assign the process. Note that in the
167 meanwhile another thread could have assigned this process to a job! */
169 if(ExAcquireRundownProtection(&Process
->RundownProtect
))
171 if(Process
->Job
== NULL
&& PsGetProcessSessionId(Process
) == Job
->SessionId
)
173 /* Just store the pointer to the job object in the process, we'll
174 assign it later. The reason we can't do this here is that locking
175 the job object might require it to wait, which is a bad thing
176 while holding the process lock! */
178 ObReferenceObject(Job
);
182 /* process is already assigned to a job or session id differs! */
183 Status
= STATUS_ACCESS_DENIED
;
185 ExReleaseRundownProtection(&Process
->RundownProtect
);
187 if(NT_SUCCESS(Status
))
189 /* let's actually assign the process to the job as we're not holding
190 the process lock anymore! */
191 Status
= PspAssignProcessToJob(Process
, Job
);
195 ObDereferenceObject(Job
);
200 /* process is already assigned to a job or session id differs! */
201 Status
= STATUS_ACCESS_DENIED
;
204 ObDereferenceObject(Process
);
212 NtCreateJobSet(IN ULONG NumJob
,
213 IN PJOB_SET_ARRAY UserJobSet
,
217 return STATUS_NOT_IMPLEMENTED
;
227 ACCESS_MASK DesiredAccess
,
228 POBJECT_ATTRIBUTES ObjectAttributes
)
232 KPROCESSOR_MODE PreviousMode
;
233 PEPROCESS CurrentProcess
;
238 PreviousMode
= ExGetPreviousMode();
239 CurrentProcess
= PsGetCurrentProcess();
241 /* check for valid buffers */
242 if (PreviousMode
!= KernelMode
)
246 ProbeForWriteHandle(JobHandle
);
248 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
250 _SEH2_YIELD(return _SEH2_GetExceptionCode());
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 - FIXME: More to do! */
275 InitializeListHead(&Job
->JobSetLinks
);
276 InitializeListHead(&Job
->ProcessListHead
);
278 /* inherit the session id from the caller */
279 Job
->SessionId
= PsGetProcessSessionId(CurrentProcess
);
281 Status
= ExInitializeResource(&Job
->JobLock
);
282 if(!NT_SUCCESS(Status
))
284 DPRINT1("Failed to initialize job lock!!!\n");
285 ObDereferenceObject(Job
);
288 KeInitializeEvent(&Job
->Event
, NotificationEvent
, FALSE
);
290 /* link the object into the global job list */
291 ExAcquireFastMutex(&PsJobListLock
);
292 InsertTailList(&PsJobListHead
, &Job
->JobLinks
);
293 ExReleaseFastMutex(&PsJobListLock
);
295 Status
= ObInsertObject(Job
,
301 if(NT_SUCCESS(Status
))
303 /* pass the handle back to the caller */
306 /* NOTE: if the caller passed invalid buffers to receive the handle it's his
307 own fault! the object will still be created and live... It's possible
308 to find the handle using ObFindHandleForObject()! */
311 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
313 Status
= _SEH2_GetExceptionCode();
329 IN HANDLE ProcessHandle
,
330 IN HANDLE JobHandle OPTIONAL
)
332 KPROCESSOR_MODE PreviousMode
;
336 PreviousMode
= ExGetPreviousMode();
340 Status
= ObReferenceObjectByHandle(
342 PROCESS_QUERY_INFORMATION
,
347 if(NT_SUCCESS(Status
))
349 /* FIXME - make sure the job object doesn't get exchanged or deleted while trying to
350 reference it, e.g. by locking it somehow until it is referenced... */
352 PEJOB ProcessJob
= Process
->Job
;
354 if(ProcessJob
!= NULL
)
356 if(JobHandle
== NULL
)
358 /* the process is assigned to a job */
359 Status
= STATUS_PROCESS_IN_JOB
;
361 else /* JobHandle != NULL */
365 /* get the job object and compare the object pointer with the one assigned to the process */
366 Status
= ObReferenceObjectByHandle(JobHandle
,
372 if(NT_SUCCESS(Status
))
374 Status
= ((ProcessJob
== JobObject
) ? STATUS_PROCESS_IN_JOB
: STATUS_PROCESS_NOT_IN_JOB
);
375 ObDereferenceObject(JobObject
);
381 /* the process is not assigned to any job */
382 Status
= STATUS_PROCESS_NOT_IN_JOB
;
384 ObDereferenceObject(Process
);
398 ACCESS_MASK DesiredAccess
,
399 POBJECT_ATTRIBUTES ObjectAttributes
)
401 KPROCESSOR_MODE PreviousMode
;
407 PreviousMode
= ExGetPreviousMode();
409 /* check for valid buffers */
410 if (PreviousMode
!= KernelMode
)
414 ProbeForWriteHandle(JobHandle
);
416 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
418 _SEH2_YIELD(return _SEH2_GetExceptionCode());
423 Status
= ObOpenObjectByName(ObjectAttributes
,
430 if(NT_SUCCESS(Status
))
436 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
438 Status
= _SEH2_GetExceptionCode();
452 NtQueryInformationJobObject (
454 JOBOBJECTINFOCLASS JobInformationClass
,
455 PVOID JobInformation
,
456 ULONG JobInformationLength
,
457 PULONG ReturnLength
)
460 return STATUS_NOT_IMPLEMENTED
;
469 NtSetInformationJobObject (
471 JOBOBJECTINFOCLASS JobInformationClass
,
472 PVOID JobInformation
,
473 ULONG JobInformationLength
)
476 return STATUS_NOT_IMPLEMENTED
;
485 NtTerminateJobObject (
487 NTSTATUS ExitStatus
)
489 KPROCESSOR_MODE PreviousMode
;
495 PreviousMode
= ExGetPreviousMode();
497 Status
= ObReferenceObjectByHandle(
499 JOB_OBJECT_TERMINATE
,
504 if(NT_SUCCESS(Status
))
506 Status
= PspTerminateJobObject(
510 ObDereferenceObject(Job
);
522 PsGetJobLock ( PEJOB Job
)
525 return (PVOID
)&Job
->JobLock
;
534 PsGetJobSessionId ( PEJOB Job
)
537 return Job
->SessionId
;
546 PsGetJobUIRestrictionsClass ( PEJOB Job
)
549 return Job
->UIRestrictionsClass
;
558 PsSetJobUIRestrictionsClass(PEJOB Job
,
559 ULONG UIRestrictionsClass
)
562 (void)InterlockedExchangeUL(&Job
->UIRestrictionsClass
, UIRestrictionsClass
);
563 /* FIXME - walk through the job process list and update the restrictions? */