3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ps/job.c
6 * PURPOSE: Job Native Functions
8 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) (stubs)
9 * Thomas Weidenmueller <w3seek@reactos.com>
12 /* Note: Jobs are only supported on Win2K+ */
13 /* INCLUDES *****************************************************************/
17 #include <internal/debug.h>
19 /* GLOBALS *******************************************************************/
21 POBJECT_TYPE EXPORTED PsJobType
= NULL
;
23 LIST_ENTRY PsJobListHead
;
24 static FAST_MUTEX PsJobListLock
;
26 static GENERIC_MAPPING PiJobMapping
=
28 STANDARD_RIGHTS_READ
| JOB_OBJECT_QUERY
,
29 STANDARD_RIGHTS_WRITE
| JOB_OBJECT_ASSIGN_PROCESS
| JOB_OBJECT_SET_ATTRIBUTES
| JOB_OBJECT_TERMINATE
| JOB_OBJECT_SET_SECURITY_ATTRIBUTES
,
30 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
,
31 STANDARD_RIGHTS_ALL
| JOB_OBJECT_ALL_ACCESS
34 /* FUNCTIONS *****************************************************************/
37 PiDeleteJob ( PVOID ObjectBody
)
39 PEJOB Job
= (PEJOB
)ObjectBody
;
41 /* remove the reference to the completion port if associated */
42 if(Job
->CompletionPort
!= NULL
)
44 ObDereferenceObject(Job
->CompletionPort
);
47 /* unlink the job object */
48 if(Job
->JobLinks
.Flink
!= NULL
)
50 ExAcquireFastMutex(&PsJobListLock
);
51 RemoveEntryList(&Job
->JobLinks
);
52 ExReleaseFastMutex(&PsJobListLock
);
55 ExDeleteResource(&Job
->JobLock
);
61 PsInitJobManagment ( VOID
)
64 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
66 DPRINT("Creating Job Object Type\n");
68 /* Initialize the Job type */
69 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
70 RtlInitUnicodeString(&Name
, L
"Job");
71 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
72 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(EJOB
);
73 ObjectTypeInitializer
.GenericMapping
= PiJobMapping
;
74 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
75 ObjectTypeInitializer
.ValidAccessMask
= JOB_OBJECT_ALL_ACCESS
;
76 ObjectTypeInitializer
.UseDefaultObject
= TRUE
;
77 ObjectTypeInitializer
.DeleteProcedure
= PiDeleteJob
;
78 ObpCreateTypeObject(&ObjectTypeInitializer
, &Name
, &PsJobType
);
80 InitializeListHead(&PsJobListHead
);
81 ExInitializeFastMutex(&PsJobListLock
);
86 PspAssignProcessToJob (
90 DPRINT("PspAssignProcessToJob() is unimplemented!\n");
91 return STATUS_NOT_IMPLEMENTED
;
96 PspTerminateJobObject (
98 KPROCESSOR_MODE AccessMode
,
101 DPRINT("PspTerminateJobObject() is unimplemented!\n");
102 return STATUS_NOT_IMPLEMENTED
;
111 NtAssignProcessToJobObject (
113 HANDLE ProcessHandle
)
116 KPROCESSOR_MODE PreviousMode
;
121 PreviousMode
= ExGetPreviousMode();
123 /* make sure we're having a handle with enough rights, especially the to
124 terminate the process. otherwise one could abuse the job objects to
125 terminate processes without having rights granted to do so! The reason
126 I open the process handle before the job handle is that a simple test showed
127 that it first complains about a invalid process handle! The other way around
128 would be simpler though... */
129 Status
= ObReferenceObjectByHandle(
136 if(NT_SUCCESS(Status
))
138 if(Process
->Job
== NULL
)
142 Status
= ObReferenceObjectByHandle(
144 JOB_OBJECT_ASSIGN_PROCESS
,
149 if(NT_SUCCESS(Status
))
151 /* lock the process so we can safely assign the process. Note that in the
152 meanwhile another thread could have assigned this process to a job! */
154 Status
= PsLockProcess(Process
, FALSE
);
155 if(NT_SUCCESS(Status
))
157 if(Process
->Job
== NULL
&& Process
->Session
== Job
->SessionId
)
159 /* Just store the pointer to the job object in the process, we'll
160 assign it later. The reason we can't do this here is that locking
161 the job object might require it to wait, which is a bad thing
162 while holding the process lock! */
167 /* process is already assigned to a job or session id differs! */
168 Status
= STATUS_ACCESS_DENIED
;
170 PsUnlockProcess(Process
);
172 if(NT_SUCCESS(Status
))
174 /* let's actually assign the process to the job as we're not holding
175 the process lock anymore! */
176 Status
= PspAssignProcessToJob(Process
, Job
);
180 ObDereferenceObject(Job
);
185 /* process is already assigned to a job or session id differs! */
186 Status
= STATUS_ACCESS_DENIED
;
189 ObDereferenceObject(Process
);
203 ACCESS_MASK DesiredAccess
,
204 POBJECT_ATTRIBUTES ObjectAttributes
)
208 KPROCESSOR_MODE PreviousMode
;
209 PEPROCESS CurrentProcess
;
210 NTSTATUS Status
= STATUS_SUCCESS
;
214 PreviousMode
= ExGetPreviousMode();
215 CurrentProcess
= PsGetCurrentProcess();
217 /* check for valid buffers */
218 if(PreviousMode
!= KernelMode
)
222 ProbeForWriteHandle(JobHandle
);
226 Status
= _SEH_GetExceptionCode();
230 if(!NT_SUCCESS(Status
))
236 Status
= ObCreateObject(PreviousMode
,
246 if(NT_SUCCESS(Status
))
248 /* FIXME - Zero all fields as we don't yet implement all of them */
249 RtlZeroMemory(Job
, sizeof(EJOB
));
251 /* make sure that early destruction doesn't attempt to remove the object from
252 the list before it even gets added! */
253 Job
->JobLinks
.Flink
= NULL
;
255 /* setup the job object */
256 InitializeListHead(&Job
->ProcessListHead
);
257 Job
->SessionId
= CurrentProcess
->Session
; /* inherit the session id from the caller */
259 Status
= ExInitializeResource(&Job
->JobLock
);
260 if(!NT_SUCCESS(Status
))
262 DPRINT1("Failed to initialize job lock!!!\n");
263 ObDereferenceObject(Job
);
266 KeInitializeEvent(&Job
->Event
, NotificationEvent
, FALSE
);
268 /* link the object into the global job list */
269 ExAcquireFastMutex(&PsJobListLock
);
270 InsertTailList(&PsJobListHead
, &Job
->JobLinks
);
271 ExReleaseFastMutex(&PsJobListLock
);
273 Status
= ObInsertObject(Job
,
279 if(NT_SUCCESS(Status
))
281 /* pass the handle back to the caller */
284 /* NOTE: if the caller passed invalid buffers to receive the handle it's his
285 own fault! the object will still be created and live... It's possible
286 to find the handle using ObFindHandleForObject()! */
291 Status
= _SEH_GetExceptionCode();
307 IN HANDLE ProcessHandle
,
308 IN HANDLE JobHandle OPTIONAL
)
310 KPROCESSOR_MODE PreviousMode
;
314 PreviousMode
= ExGetPreviousMode();
318 Status
= ObReferenceObjectByHandle(
320 PROCESS_QUERY_INFORMATION
,
325 if(NT_SUCCESS(Status
))
327 /* FIXME - make sure the job object doesn't get exchanged or deleted while trying to
328 reference it, e.g. by locking it somehow until it is referenced... */
330 PEJOB ProcessJob
= Process
->Job
;
332 if(ProcessJob
!= NULL
)
334 if(JobHandle
== NULL
)
336 /* the process is assigned to a job */
337 Status
= STATUS_PROCESS_IN_JOB
;
339 else /* JobHandle != NULL */
343 /* get the job object and compare the object pointer with the one assigned to the process */
344 Status
= ObReferenceObjectByHandle(JobHandle
,
350 if(NT_SUCCESS(Status
))
352 Status
= ((ProcessJob
== JobObject
) ? STATUS_PROCESS_IN_JOB
: STATUS_PROCESS_NOT_IN_JOB
);
353 ObDereferenceObject(JobObject
);
359 /* the process is not assigned to any job */
360 Status
= STATUS_PROCESS_NOT_IN_JOB
;
362 ObDereferenceObject(Process
);
376 ACCESS_MASK DesiredAccess
,
377 POBJECT_ATTRIBUTES ObjectAttributes
)
379 KPROCESSOR_MODE PreviousMode
;
381 NTSTATUS Status
= STATUS_SUCCESS
;
385 PreviousMode
= ExGetPreviousMode();
387 /* check for valid buffers */
388 if(PreviousMode
!= KernelMode
)
392 ProbeForWriteHandle(JobHandle
);
396 Status
= _SEH_GetExceptionCode();
400 if(!NT_SUCCESS(Status
))
406 if(NT_SUCCESS(Status
))
408 Status
= ObOpenObjectByName(ObjectAttributes
,
415 if(NT_SUCCESS(Status
))
423 Status
= _SEH_GetExceptionCode();
438 NtQueryInformationJobObject (
440 JOBOBJECTINFOCLASS JobInformationClass
,
441 PVOID JobInformation
,
442 ULONG JobInformationLength
,
443 PULONG ReturnLength
)
446 return STATUS_NOT_IMPLEMENTED
;
455 NtSetInformationJobObject (
457 JOBOBJECTINFOCLASS JobInformationClass
,
458 PVOID JobInformation
,
459 ULONG JobInformationLength
)
462 return STATUS_NOT_IMPLEMENTED
;
471 NtTerminateJobObject (
473 NTSTATUS ExitStatus
)
475 KPROCESSOR_MODE PreviousMode
;
481 PreviousMode
= ExGetPreviousMode();
483 Status
= ObReferenceObjectByHandle(
485 JOB_OBJECT_TERMINATE
,
490 if(NT_SUCCESS(Status
))
492 Status
= PspTerminateJobObject(
496 ObDereferenceObject(Job
);
508 PsGetJobLock ( PEJOB Job
)
511 return (PVOID
)&Job
->JobLock
;
520 PsGetJobSessionId ( PEJOB Job
)
523 return (PVOID
)Job
->SessionId
;
532 PsGetJobUIRestrictionsClass ( PEJOB Job
)
535 return Job
->UIRestrictionsClass
;
544 PsSetJobUIRestrictionsClass (
546 ULONG UIRestrictionsClass
)
549 InterlockedExchangeUL(&Job
->UIRestrictionsClass
, UIRestrictionsClass
);
550 /* FIXME - walk through the job process list and update the restrictions? */