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 ExAcquireRundownProtection(&Process
->RundownProtect
);
170 if(NT_SUCCESS(Status
))
172 // FIXME: This is broken
173 if(Process
->Job
== NULL
&& PtrToUlong(Process
->Session
) == Job
->SessionId
)
175 /* Just store the pointer to the job object in the process, we'll
176 assign it later. The reason we can't do this here is that locking
177 the job object might require it to wait, which is a bad thing
178 while holding the process lock! */
183 /* process is already assigned to a job or session id differs! */
184 Status
= STATUS_ACCESS_DENIED
;
186 ExReleaseRundownProtection(&Process
->RundownProtect
);
188 if(NT_SUCCESS(Status
))
190 /* let's actually assign the process to the job as we're not holding
191 the process lock anymore! */
192 Status
= PspAssignProcessToJob(Process
, Job
);
196 ObDereferenceObject(Job
);
201 /* process is already assigned to a job or session id differs! */
202 Status
= STATUS_ACCESS_DENIED
;
205 ObDereferenceObject(Process
);
213 NtCreateJobSet(IN ULONG NumJob
,
214 IN PJOB_SET_ARRAY UserJobSet
,
218 return STATUS_NOT_IMPLEMENTED
;
228 ACCESS_MASK DesiredAccess
,
229 POBJECT_ATTRIBUTES ObjectAttributes
)
233 KPROCESSOR_MODE PreviousMode
;
234 PEPROCESS CurrentProcess
;
239 PreviousMode
= ExGetPreviousMode();
240 CurrentProcess
= PsGetCurrentProcess();
242 /* check for valid buffers */
243 if (PreviousMode
!= KernelMode
)
247 ProbeForWriteHandle(JobHandle
);
249 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
251 _SEH2_YIELD(return _SEH2_GetExceptionCode());
256 Status
= ObCreateObject(PreviousMode
,
266 if(NT_SUCCESS(Status
))
268 /* FIXME - Zero all fields as we don't yet implement all of them */
269 RtlZeroMemory(Job
, sizeof(EJOB
));
271 /* make sure that early destruction doesn't attempt to remove the object from
272 the list before it even gets added! */
273 Job
->JobLinks
.Flink
= NULL
;
275 /* setup the job object */
276 InitializeListHead(&Job
->ProcessListHead
);
277 Job
->SessionId
= PtrToUlong(CurrentProcess
->Session
); /* inherit the session id from the caller, FIXME: broken */
279 Status
= ExInitializeResource(&Job
->JobLock
);
280 if(!NT_SUCCESS(Status
))
282 DPRINT1("Failed to initialize job lock!!!\n");
283 ObDereferenceObject(Job
);
286 KeInitializeEvent(&Job
->Event
, NotificationEvent
, FALSE
);
288 /* link the object into the global job list */
289 ExAcquireFastMutex(&PsJobListLock
);
290 InsertTailList(&PsJobListHead
, &Job
->JobLinks
);
291 ExReleaseFastMutex(&PsJobListLock
);
293 Status
= ObInsertObject(Job
,
299 if(NT_SUCCESS(Status
))
301 /* pass the handle back to the caller */
304 /* NOTE: if the caller passed invalid buffers to receive the handle it's his
305 own fault! the object will still be created and live... It's possible
306 to find the handle using ObFindHandleForObject()! */
309 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
311 Status
= _SEH2_GetExceptionCode();
327 IN HANDLE ProcessHandle
,
328 IN HANDLE JobHandle OPTIONAL
)
330 KPROCESSOR_MODE PreviousMode
;
334 PreviousMode
= ExGetPreviousMode();
338 Status
= ObReferenceObjectByHandle(
340 PROCESS_QUERY_INFORMATION
,
345 if(NT_SUCCESS(Status
))
347 /* FIXME - make sure the job object doesn't get exchanged or deleted while trying to
348 reference it, e.g. by locking it somehow until it is referenced... */
350 PEJOB ProcessJob
= Process
->Job
;
352 if(ProcessJob
!= NULL
)
354 if(JobHandle
== NULL
)
356 /* the process is assigned to a job */
357 Status
= STATUS_PROCESS_IN_JOB
;
359 else /* JobHandle != NULL */
363 /* get the job object and compare the object pointer with the one assigned to the process */
364 Status
= ObReferenceObjectByHandle(JobHandle
,
370 if(NT_SUCCESS(Status
))
372 Status
= ((ProcessJob
== JobObject
) ? STATUS_PROCESS_IN_JOB
: STATUS_PROCESS_NOT_IN_JOB
);
373 ObDereferenceObject(JobObject
);
379 /* the process is not assigned to any job */
380 Status
= STATUS_PROCESS_NOT_IN_JOB
;
382 ObDereferenceObject(Process
);
396 ACCESS_MASK DesiredAccess
,
397 POBJECT_ATTRIBUTES ObjectAttributes
)
399 KPROCESSOR_MODE PreviousMode
;
405 PreviousMode
= ExGetPreviousMode();
407 /* check for valid buffers */
408 if (PreviousMode
!= KernelMode
)
412 ProbeForWriteHandle(JobHandle
);
414 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
416 _SEH2_YIELD(return _SEH2_GetExceptionCode());
421 Status
= ObOpenObjectByName(ObjectAttributes
,
428 if(NT_SUCCESS(Status
))
434 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
436 Status
= _SEH2_GetExceptionCode();
450 NtQueryInformationJobObject (
452 JOBOBJECTINFOCLASS JobInformationClass
,
453 PVOID JobInformation
,
454 ULONG JobInformationLength
,
455 PULONG ReturnLength
)
458 return STATUS_NOT_IMPLEMENTED
;
467 NtSetInformationJobObject (
469 JOBOBJECTINFOCLASS JobInformationClass
,
470 PVOID JobInformation
,
471 ULONG JobInformationLength
)
474 return STATUS_NOT_IMPLEMENTED
;
483 NtTerminateJobObject (
485 NTSTATUS ExitStatus
)
487 KPROCESSOR_MODE PreviousMode
;
493 PreviousMode
= ExGetPreviousMode();
495 Status
= ObReferenceObjectByHandle(
497 JOB_OBJECT_TERMINATE
,
502 if(NT_SUCCESS(Status
))
504 Status
= PspTerminateJobObject(
508 ObDereferenceObject(Job
);
520 PsGetJobLock ( PEJOB Job
)
523 return (PVOID
)&Job
->JobLock
;
532 PsGetJobSessionId ( PEJOB Job
)
535 return (PVOID
)Job
->SessionId
;
544 PsGetJobUIRestrictionsClass ( PEJOB Job
)
547 return Job
->UIRestrictionsClass
;
556 PsSetJobUIRestrictionsClass(PEJOB Job
,
557 ULONG UIRestrictionsClass
)
560 (void)InterlockedExchangeUL(&Job
->UIRestrictionsClass
, UIRestrictionsClass
);
561 /* FIXME - walk through the job process list and update the restrictions? */