Visual C++ backend for rbuild (for now just a hacked mingw backend) and related compi...
[reactos.git] / dll / win32 / kernel32 / process / job.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/kernel32/process/job.c
6 * PURPOSE: Job functions
7 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
8 * UPDATE HISTORY:
9 * Created 9/23/2004
10 */
11
12 /* INCLUDES ****************************************************************/
13
14 #include <k32.h>
15
16 #define NDEBUG
17 #include <debug.h>
18
19 /* FUNCTIONS ****************************************************************/
20
21
22 /*
23 * @implemented
24 */
25 HANDLE
26 STDCALL
27 CreateJobObjectA(LPSECURITY_ATTRIBUTES lpJobAttributes,
28 LPCSTR lpName)
29 {
30 HANDLE hJob;
31 ANSI_STRING AnsiName;
32 UNICODE_STRING UnicodeName;
33
34 if(lpName != NULL)
35 {
36 NTSTATUS Status;
37
38 RtlInitAnsiString(&AnsiName, lpName);
39 Status = RtlAnsiStringToUnicodeString(&UnicodeName, &AnsiName, TRUE);
40 if(!NT_SUCCESS(Status))
41 {
42 SetLastErrorByStatus(Status);
43 return FALSE;
44 }
45 }
46
47 hJob = CreateJobObjectW(lpJobAttributes,
48 ((lpName != NULL) ? UnicodeName.Buffer : NULL));
49
50 if(lpName != NULL)
51 {
52 RtlFreeUnicodeString(&UnicodeName);
53 }
54 return hJob;
55 }
56
57
58 /*
59 * @implemented
60 */
61 HANDLE
62 STDCALL
63 CreateJobObjectW(LPSECURITY_ATTRIBUTES lpJobAttributes,
64 LPCWSTR lpName)
65 {
66 UNICODE_STRING JobName;
67 OBJECT_ATTRIBUTES ObjectAttributes;
68 ULONG Attributes = 0;
69 PVOID SecurityDescriptor;
70 HANDLE hJob;
71 NTSTATUS Status;
72
73 if(lpName != NULL)
74 {
75 RtlInitUnicodeString(&JobName, lpName);
76 }
77
78 if(lpJobAttributes != NULL)
79 {
80 if(lpJobAttributes->bInheritHandle)
81 {
82 Attributes |= OBJ_INHERIT;
83 }
84 SecurityDescriptor = lpJobAttributes->lpSecurityDescriptor;
85 }
86 else
87 {
88 SecurityDescriptor = NULL;
89 }
90
91 InitializeObjectAttributes(&ObjectAttributes,
92 ((lpName != NULL) ? &JobName : NULL),
93 Attributes,
94 NULL,
95 SecurityDescriptor);
96
97 Status = NtCreateJobObject(&hJob,
98 JOB_OBJECT_ALL_ACCESS,
99 &ObjectAttributes);
100 if(!NT_SUCCESS(Status))
101 {
102 SetLastErrorByStatus(Status);
103 return NULL;
104 }
105
106 return hJob;
107 }
108
109
110 /*
111 * @implemented
112 */
113 HANDLE
114 STDCALL
115 OpenJobObjectW(DWORD dwDesiredAccess,
116 BOOL bInheritHandle,
117 LPCWSTR lpName)
118 {
119 OBJECT_ATTRIBUTES ObjectAttributes;
120 UNICODE_STRING JobName;
121 HANDLE hJob;
122 NTSTATUS Status;
123
124 if(lpName == NULL)
125 {
126 SetLastError(ERROR_INVALID_PARAMETER);
127 return NULL;
128 }
129
130 RtlInitUnicodeString(&JobName, lpName);
131
132 InitializeObjectAttributes(&ObjectAttributes,
133 &JobName,
134 (bInheritHandle ? OBJ_INHERIT : 0),
135 NULL,
136 NULL);
137
138 Status = NtOpenJobObject(&hJob,
139 dwDesiredAccess,
140 &ObjectAttributes);
141
142 if(!NT_SUCCESS(Status))
143 {
144 SetLastErrorByStatus(Status);
145 return NULL;
146 }
147
148 return hJob;
149 }
150
151
152 /*
153 * @implemented
154 */
155 HANDLE
156 STDCALL
157 OpenJobObjectA(DWORD dwDesiredAccess,
158 BOOL bInheritHandle,
159 LPCSTR lpName)
160 {
161 ANSI_STRING AnsiName;
162 UNICODE_STRING UnicodeName;
163 HANDLE hJob;
164 NTSTATUS Status;
165
166 if(lpName == NULL)
167 {
168 SetLastError(ERROR_INVALID_PARAMETER);
169 return NULL;
170 }
171
172 RtlInitAnsiString(&AnsiName, lpName);
173 Status = RtlAnsiStringToUnicodeString(&UnicodeName, &AnsiName, TRUE);
174 if(!NT_SUCCESS(Status))
175 {
176 SetLastErrorByStatus(Status);
177 return FALSE;
178 }
179
180 hJob = OpenJobObjectW(dwDesiredAccess,
181 bInheritHandle,
182 UnicodeName.Buffer);
183
184 RtlFreeUnicodeString(&UnicodeName);
185 return hJob;
186 }
187
188
189 /*
190 * @implemented
191 */
192 BOOL
193 STDCALL
194 IsProcessInJob(HANDLE ProcessHandle,
195 HANDLE JobHandle,
196 PBOOL Result)
197 {
198 NTSTATUS Status;
199
200 Status = NtIsProcessInJob(ProcessHandle, JobHandle);
201 if(NT_SUCCESS(Status))
202 {
203 *Result = (Status == STATUS_PROCESS_IN_JOB);
204 return TRUE;
205 }
206
207 SetLastErrorByStatus(Status);
208 return FALSE;
209 }
210
211
212 /*
213 * @implemented
214 */
215 BOOL
216 STDCALL
217 AssignProcessToJobObject(HANDLE hJob,
218 HANDLE hProcess)
219 {
220 NTSTATUS Status;
221
222 Status = NtAssignProcessToJobObject(hJob, hProcess);
223 if(!NT_SUCCESS(Status))
224 {
225 SetLastErrorByStatus(Status);
226 return FALSE;
227 }
228 return TRUE;
229 }
230
231
232 /*
233 * @implemented
234 */
235 BOOL
236 STDCALL
237 QueryInformationJobObject(HANDLE hJob,
238 JOBOBJECTINFOCLASS JobObjectInformationClass,
239 LPVOID lpJobObjectInformation,
240 DWORD cbJobObjectInformationLength,
241 LPDWORD lpReturnLength)
242 {
243 NTSTATUS Status;
244
245 Status = NtQueryInformationJobObject(hJob,
246 JobObjectInformationClass,
247 lpJobObjectInformation,
248 cbJobObjectInformationLength,
249 lpReturnLength);
250 if(NT_SUCCESS(Status))
251 {
252 PJOBOBJECT_BASIC_LIMIT_INFORMATION BasicInfo;
253 switch(JobObjectInformationClass)
254 {
255 case JobObjectBasicLimitInformation:
256 BasicInfo = (PJOBOBJECT_BASIC_LIMIT_INFORMATION)lpJobObjectInformation;
257 break;
258 case JobObjectExtendedLimitInformation:
259 BasicInfo = &((PJOBOBJECT_EXTENDED_LIMIT_INFORMATION)lpJobObjectInformation)->BasicLimitInformation;
260 break;
261
262 default:
263 BasicInfo = NULL;
264 break;
265 }
266
267 if(BasicInfo != NULL)
268 {
269 /* we need to convert the process priority classes in the
270 JOBOBJECT_BASIC_LIMIT_INFORMATION structure the same way as
271 GetPriorityClass() converts it! */
272 switch(BasicInfo->PriorityClass)
273 {
274 case PROCESS_PRIORITY_CLASS_IDLE:
275 BasicInfo->PriorityClass = IDLE_PRIORITY_CLASS;
276 break;
277 case PROCESS_PRIORITY_CLASS_BELOW_NORMAL:
278 BasicInfo->PriorityClass = BELOW_NORMAL_PRIORITY_CLASS;
279 break;
280 case PROCESS_PRIORITY_CLASS_NORMAL:
281 BasicInfo->PriorityClass = NORMAL_PRIORITY_CLASS;
282 break;
283 case PROCESS_PRIORITY_CLASS_ABOVE_NORMAL:
284 BasicInfo->PriorityClass = ABOVE_NORMAL_PRIORITY_CLASS;
285 break;
286 case PROCESS_PRIORITY_CLASS_HIGH:
287 BasicInfo->PriorityClass = HIGH_PRIORITY_CLASS;
288 break;
289 case PROCESS_PRIORITY_CLASS_REALTIME:
290 BasicInfo->PriorityClass = REALTIME_PRIORITY_CLASS;
291 break;
292 default:
293 BasicInfo->PriorityClass = NORMAL_PRIORITY_CLASS;
294 break;
295 }
296 }
297
298 return TRUE;
299 }
300
301 SetLastErrorByStatus(Status);
302 return FALSE;
303 }
304
305
306 /*
307 * @implemented
308 */
309 BOOL
310 STDCALL
311 SetInformationJobObject(HANDLE hJob,
312 JOBOBJECTINFOCLASS JobObjectInformationClass,
313 LPVOID lpJobObjectInformation,
314 DWORD cbJobObjectInformationLength)
315 {
316 JOBOBJECT_EXTENDED_LIMIT_INFORMATION ExtendedLimitInfo;
317 PJOBOBJECT_BASIC_LIMIT_INFORMATION BasicInfo;
318 PVOID ObjectInfo;
319 NTSTATUS Status;
320
321 switch(JobObjectInformationClass)
322 {
323 case JobObjectBasicLimitInformation:
324 if(cbJobObjectInformationLength != sizeof(JOBOBJECT_BASIC_LIMIT_INFORMATION))
325 {
326 SetLastError(ERROR_BAD_LENGTH);
327 return FALSE;
328 }
329 ObjectInfo = &ExtendedLimitInfo.BasicLimitInformation;
330 BasicInfo = (PJOBOBJECT_BASIC_LIMIT_INFORMATION)ObjectInfo;
331 RtlCopyMemory(ObjectInfo, lpJobObjectInformation, cbJobObjectInformationLength);
332 break;
333
334 case JobObjectExtendedLimitInformation:
335 if(cbJobObjectInformationLength != sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION))
336 {
337 SetLastError(ERROR_BAD_LENGTH);
338 return FALSE;
339 }
340 ObjectInfo = &ExtendedLimitInfo;
341 BasicInfo = &ExtendedLimitInfo.BasicLimitInformation;
342 RtlCopyMemory(ObjectInfo, lpJobObjectInformation, cbJobObjectInformationLength);
343 break;
344
345 default:
346 ObjectInfo = lpJobObjectInformation;
347 BasicInfo = NULL;
348 break;
349 }
350
351 if(BasicInfo != NULL)
352 {
353 /* we need to convert the process priority classes in the
354 JOBOBJECT_BASIC_LIMIT_INFORMATION structure the same way as
355 SetPriorityClass() converts it! */
356 switch(BasicInfo->PriorityClass)
357 {
358 case IDLE_PRIORITY_CLASS:
359 BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_IDLE;
360 break;
361 case BELOW_NORMAL_PRIORITY_CLASS:
362 BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_BELOW_NORMAL;
363 break;
364 case NORMAL_PRIORITY_CLASS:
365 BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL;
366 break;
367 case ABOVE_NORMAL_PRIORITY_CLASS:
368 BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_ABOVE_NORMAL;
369 break;
370 case HIGH_PRIORITY_CLASS:
371 BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_HIGH;
372 break;
373 case REALTIME_PRIORITY_CLASS:
374 BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_REALTIME;
375 break;
376 default:
377 BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL;
378 break;
379 }
380 }
381
382 Status = NtSetInformationJobObject(hJob,
383 JobObjectInformationClass,
384 ObjectInfo,
385 cbJobObjectInformationLength);
386 if(!NT_SUCCESS(Status))
387 {
388 SetLastErrorByStatus(Status);
389 return FALSE;
390 }
391
392 return TRUE;
393 }
394
395
396 /*
397 * @implemented
398 */
399 BOOL
400 STDCALL
401 TerminateJobObject(HANDLE hJob,
402 UINT uExitCode)
403 {
404 NTSTATUS Status;
405
406 Status = NtTerminateJobObject(hJob, uExitCode);
407 if(!NT_SUCCESS(Status))
408 {
409 SetLastErrorByStatus(Status);
410 return FALSE;
411 }
412
413 return TRUE;
414 }
415
416
417 /* EOF */