6401ce4e2f0b6c6ba61b0e888757ed641f7b463a
[reactos.git] / reactos / ntoskrnl / ps / job.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ps/jobs.c
5 * PURPOSE: Job Native Functions
6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
7 * UPDATE HISTORY:
8 * Created 16/07/04
9 */
10
11 /* Note: Jobs are only supported on Win2K+ */
12 /* INCLUDES *****************************************************************/
13
14 #include <ntoskrnl.h>
15 #include <internal/debug.h>
16
17 /* GLOBALS *******************************************************************/
18
19 POBJECT_TYPE EXPORTED PsJobType = NULL;
20
21 LIST_ENTRY PsJobListHead;
22 static KSPIN_LOCK PsJobListLock;
23
24 static GENERIC_MAPPING PiJobMapping = {STANDARD_RIGHTS_READ | JOB_OBJECT_QUERY,
25 STANDARD_RIGHTS_WRITE | JOB_OBJECT_ASSIGN_PROCESS | JOB_OBJECT_SET_ATTRIBUTES | JOB_OBJECT_TERMINATE | JOB_OBJECT_SET_SECURITY_ATTRIBUTES,
26 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
27 STANDARD_RIGHTS_ALL | JOB_OBJECT_ALL_ACCESS};
28
29 /* FUNCTIONS *****************************************************************/
30
31 VOID STDCALL
32 PiDeleteJob(PVOID ObjectBody)
33 {
34 KIRQL oldIrql;
35 PEJOB Job = (PEJOB)ObjectBody;
36
37 KeAcquireSpinLock(&PsJobListLock, &oldIrql);
38 RemoveEntryList(&Job->JobLinks);
39 KeReleaseSpinLock(&PsJobListLock, oldIrql);
40 }
41
42 VOID INIT_FUNCTION
43 PsInitJobManagment(VOID)
44 {
45 PsJobType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
46
47 PsJobType->Tag = TAG('E', 'J', 'O', 'B');
48 PsJobType->TotalObjects = 0;
49 PsJobType->TotalHandles = 0;
50 PsJobType->MaxObjects = ULONG_MAX;
51 PsJobType->MaxHandles = ULONG_MAX;
52 PsJobType->PagedPoolCharge = 0;
53 PsJobType->NonpagedPoolCharge = sizeof(EJOB);
54 PsJobType->Mapping = &PiJobMapping;
55 PsJobType->Dump = NULL;
56 PsJobType->Open = NULL;
57 PsJobType->Close = NULL;
58 PsJobType->Delete = PiDeleteJob;
59 PsJobType->Parse = NULL;
60 PsJobType->Security = NULL;
61 PsJobType->QueryName = NULL;
62 PsJobType->OkayToClose = NULL;
63 PsJobType->Create = NULL;
64 PsJobType->DuplicationNotify = NULL;
65
66 RtlRosInitUnicodeStringFromLiteral(&PsJobType->TypeName, L"Job");
67
68 ObpCreateTypeObject(PsJobType);
69
70 InitializeListHead(&PsJobListHead);
71 KeInitializeSpinLock(&PsJobListLock);
72 }
73
74 /*
75 * @unimplemented
76 */
77 NTSTATUS
78 STDCALL
79 NtAssignProcessToJobObject(HANDLE JobHandle,
80 HANDLE ProcessHandle)
81 {
82 UNIMPLEMENTED;
83 return STATUS_NOT_IMPLEMENTED;
84 }
85
86
87 /*
88 * @unimplemented
89 */
90 NTSTATUS
91 STDCALL
92 NtCreateJobObject(PHANDLE JobHandle,
93 ACCESS_MASK DesiredAccess,
94 POBJECT_ATTRIBUTES ObjectAttributes)
95 {
96 UNIMPLEMENTED;
97 return STATUS_NOT_IMPLEMENTED;
98 }
99
100
101 /*
102 * @implemented
103 */
104 NTSTATUS
105 STDCALL
106 NtIsProcessInJob(IN HANDLE ProcessHandle,
107 IN HANDLE JobHandle OPTIONAL)
108 {
109 KPROCESSOR_MODE PreviousMode;
110 PEPROCESS Process;
111 NTSTATUS Status;
112
113 PreviousMode = ExGetPreviousMode();
114
115 Status = ObReferenceObjectByHandle(ProcessHandle,
116 PROCESS_QUERY_INFORMATION,
117 PsProcessType,
118 PreviousMode,
119 (PVOID*)&Process,
120 NULL);
121 if(NT_SUCCESS(Status))
122 {
123 /* FIXME - make sure the job object doesn't get exchanged or deleted while trying to
124 reference it, e.g. by locking it somehow until it is referenced... */
125
126 PEJOB ProcessJob = Process->Job;
127
128 if(ProcessJob != NULL)
129 {
130 if(JobHandle == NULL)
131 {
132 /* the process is assigned to a job */
133 Status = STATUS_PROCESS_IN_JOB;
134 }
135 else /* JobHandle != NULL */
136 {
137 PEJOB JobObject;
138
139 /* get the job object and compare the object pointer with the one assigned to the process */
140 Status = ObReferenceObjectByHandle(JobHandle,
141 JOB_OBJECT_QUERY,
142 PsJobType,
143 PreviousMode,
144 (PVOID*)&JobObject,
145 NULL);
146 if(NT_SUCCESS(Status))
147 {
148 Status = ((ProcessJob == JobObject) ? STATUS_PROCESS_IN_JOB : STATUS_PROCESS_NOT_IN_JOB);
149 ObDereferenceObject(JobObject);
150 }
151 }
152 }
153 else
154 {
155 /* the process is not assigned to any job */
156 Status = STATUS_PROCESS_NOT_IN_JOB;
157 }
158 ObDereferenceObject(Process);
159 }
160
161 return Status;
162 }
163
164
165 /*
166 * @unimplemented
167 */
168 NTSTATUS
169 STDCALL
170 NtOpenJobObject(PHANDLE JobHandle,
171 ACCESS_MASK DesiredAccess,
172 POBJECT_ATTRIBUTES ObjectAttributes)
173 {
174 UNIMPLEMENTED;
175 return STATUS_NOT_IMPLEMENTED;
176 }
177
178
179 /*
180 * @unimplemented
181 */
182 NTSTATUS
183 STDCALL
184 NtQueryInformationJobObject(HANDLE JobHandle,
185 JOBOBJECTINFOCLASS JobInformationClass,
186 PVOID JobInformation,
187 ULONG JobInformationLength,
188 PULONG ReturnLength)
189 {
190 UNIMPLEMENTED;
191 return STATUS_NOT_IMPLEMENTED;
192 }
193
194
195 /*
196 * @unimplemented
197 */
198 NTSTATUS
199 STDCALL
200 NtSetInformationJobObject(HANDLE JobHandle,
201 JOBOBJECTINFOCLASS JobInformationClass,
202 PVOID JobInformation,
203 ULONG JobInformationLength)
204 {
205 UNIMPLEMENTED;
206 return STATUS_NOT_IMPLEMENTED;
207 }
208
209
210 /*
211 * @unimplemented
212 */
213 NTSTATUS
214 STDCALL
215 NtTerminateJobObject(HANDLE JobHandle,
216 NTSTATUS ExitStatus)
217 {
218 UNIMPLEMENTED;
219 return STATUS_NOT_IMPLEMENTED;
220 }
221
222
223 /*
224 * @implemented
225 */
226 PVOID
227 STDCALL
228 PsGetJobLock(PEJOB Job)
229 {
230 ASSERT(Job);
231 return (PVOID)&Job->JobLock;
232 }
233
234
235 /*
236 * @implemented
237 */
238 PVOID
239 STDCALL
240 PsGetJobSessionId(PEJOB Job)
241 {
242 ASSERT(Job);
243 return (PVOID)Job->SessionId;
244 }
245
246
247 /*
248 * @implemented
249 */
250 ULONG
251 STDCALL
252 PsGetJobUIRestrictionsClass(PEJOB Job)
253 {
254 ASSERT(Job);
255 return Job->UIRestrictionsClass;
256 }
257
258
259 /*
260 * @unimplemented
261 */
262 VOID
263 STDCALL
264 PsSetJobUIRestrictionsClass(PEJOB Job,
265 ULONG UIRestrictionsClass)
266 {
267 ASSERT(Job);
268 InterlockedExchangeUL(&Job->UIRestrictionsClass, UIRestrictionsClass);
269 /* FIXME - walk through the job process list and update the restrictions? */
270 }
271
272 /* EOF */