xref: /reactos/dll/win32/kernel32/client/job.c (revision 9592728f)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS system libraries
4  * FILE:            dll/win32/kernel32/client/job.c
5  * PURPOSE:         Job functions
6  * PROGRAMMER:      Thomas Weidenmueller <w3seek@reactos.com>
7  * UPDATE HISTORY:
8  *                  Created 9/23/2004
9  */
10 
11 /* INCLUDES *******************************************************************/
12 
13 #include <k32.h>
14 #include <winspool.h>
15 
16 #define NDEBUG
17 #include <debug.h>
18 
19 /* FUNCTIONS ******************************************************************/
20 
21 /*
22  * @implemented
23  */
24 HANDLE
25 WINAPI
26 CreateJobObjectA(IN LPSECURITY_ATTRIBUTES lpJobAttributes,
27                  IN LPCSTR lpName)
28 {
29     /* Call the W(ide) function */
30     ConvertWin32AnsiObjectApiToUnicodeApi(JobObject, lpName, lpJobAttributes);
31 }
32 
33 /*
34  * @implemented
35  */
36 HANDLE
37 WINAPI
38 CreateJobObjectW(IN LPSECURITY_ATTRIBUTES lpJobAttributes,
39                  IN LPCWSTR lpName)
40 {
41     /* Create the NT object */
42     CreateNtObjectFromWin32Api(JobObject, JobObject, JOB_OBJECT_ALL_ACCESS, lpJobAttributes, lpName);
43 }
44 
45 /*
46  * @implemented
47  */
48 HANDLE
49 WINAPI
50 OpenJobObjectW(IN DWORD dwDesiredAccess,
51                IN BOOL bInheritHandle,
52                IN LPCWSTR lpName)
53 {
54     /* Open the NT object */
55     OpenNtObjectFromWin32Api(JobObject, dwDesiredAccess, bInheritHandle, lpName);
56 }
57 
58 
59 /*
60  * @implemented
61  */
62 HANDLE
63 WINAPI
64 OpenJobObjectA(IN DWORD dwDesiredAccess,
65                IN BOOL bInheritHandle,
66                IN LPCSTR lpName)
67 {
68     /* Call the W(ide) function */
69     ConvertOpenWin32AnsiObjectApiToUnicodeApi(JobObject, dwDesiredAccess, bInheritHandle, lpName);
70 }
71 
72 /*
73  * @implemented
74  */
75 BOOL
76 WINAPI
77 IsProcessInJob(IN HANDLE ProcessHandle,
78                IN HANDLE JobHandle,
79                OUT PBOOL Result)
80 {
81     NTSTATUS Status;
82 
83     Status = NtIsProcessInJob(ProcessHandle, JobHandle);
84     if (NT_SUCCESS(Status))
85     {
86         *Result = (Status == STATUS_PROCESS_IN_JOB);
87         return TRUE;
88     }
89 
90     BaseSetLastNTError(Status);
91     return FALSE;
92 }
93 
94 /*
95  * @implemented
96  */
97 BOOL
98 WINAPI
99 AssignProcessToJobObject(IN HANDLE hJob,
100                          IN HANDLE hProcess)
101 {
102     NTSTATUS Status;
103 
104     Status = NtAssignProcessToJobObject(hJob, hProcess);
105     if (!NT_SUCCESS(Status))
106     {
107         BaseSetLastNTError(Status);
108         return FALSE;
109     }
110 
111     return TRUE;
112 }
113 
114 /*
115  * @implemented
116  */
117 BOOL
118 WINAPI
119 QueryInformationJobObject(IN HANDLE hJob,
120                           IN JOBOBJECTINFOCLASS JobObjectInformationClass,
121                           IN LPVOID lpJobObjectInformation,
122                           IN DWORD cbJobObjectInformationLength,
123                           OUT LPDWORD lpReturnLength)
124 {
125     NTSTATUS Status;
126     PVOID JobInfo;
127     JOBOBJECT_EXTENDED_LIMIT_INFORMATION LocalInfo;
128     ULONG ExpectedSize;
129 
130     if (JobObjectInformationClass == JobObjectBasicLimitInformation)
131     {
132         ExpectedSize = sizeof(JOBOBJECT_BASIC_LIMIT_INFORMATION);
133         JobInfo = &LocalInfo;
134     }
135     else if (JobObjectInformationClass == JobObjectExtendedLimitInformation)
136     {
137         ExpectedSize = sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION);
138         JobInfo = &LocalInfo;
139     }
140     else
141     {
142         ExpectedSize = cbJobObjectInformationLength;
143         JobInfo = lpJobObjectInformation;
144     }
145 
146     if (cbJobObjectInformationLength != ExpectedSize)
147     {
148         BaseSetLastNTError(STATUS_INFO_LENGTH_MISMATCH);
149         return FALSE;
150     }
151 
152     Status = NtQueryInformationJobObject(hJob,
153                                          JobObjectInformationClass,
154                                          JobInfo,
155                                          ExpectedSize,
156                                          lpReturnLength);
157     if (NT_SUCCESS(Status))
158     {
159         if (JobInfo != &LocalInfo) return TRUE;
160 
161         switch (LocalInfo.BasicLimitInformation.PriorityClass)
162         {
163             case PROCESS_PRIORITY_CLASS_IDLE:
164                 LocalInfo.BasicLimitInformation.PriorityClass =
165                 IDLE_PRIORITY_CLASS;
166                 break;
167 
168             case PROCESS_PRIORITY_CLASS_BELOW_NORMAL:
169                 LocalInfo.BasicLimitInformation.PriorityClass =
170                 BELOW_NORMAL_PRIORITY_CLASS;
171                 break;
172 
173             case PROCESS_PRIORITY_CLASS_NORMAL:
174                 LocalInfo.BasicLimitInformation.PriorityClass =
175                 NORMAL_PRIORITY_CLASS;
176                 break;
177 
178             case PROCESS_PRIORITY_CLASS_ABOVE_NORMAL:
179                 LocalInfo.BasicLimitInformation.PriorityClass =
180                 ABOVE_NORMAL_PRIORITY_CLASS;
181                 break;
182 
183             case PROCESS_PRIORITY_CLASS_HIGH:
184                 LocalInfo.BasicLimitInformation.PriorityClass =
185                 HIGH_PRIORITY_CLASS;
186                 break;
187 
188             case PROCESS_PRIORITY_CLASS_REALTIME:
189                 LocalInfo.BasicLimitInformation.PriorityClass =
190                 REALTIME_PRIORITY_CLASS;
191                 break;
192 
193             default:
194                 LocalInfo.BasicLimitInformation.PriorityClass =
195                 NORMAL_PRIORITY_CLASS;
196                 break;
197         }
198 
199         RtlCopyMemory(lpJobObjectInformation, &LocalInfo, ExpectedSize);
200         return TRUE;
201     }
202 
203     BaseSetLastNTError(Status);
204     return FALSE;
205 }
206 
207 /*
208  * @implemented
209  */
210 BOOL
211 WINAPI
212 SetInformationJobObject(IN HANDLE hJob,
213                         IN JOBOBJECTINFOCLASS JobObjectInformationClass,
214                         IN LPVOID lpJobObjectInformation,
215                         IN DWORD cbJobObjectInformationLength)
216 {
217     NTSTATUS Status;
218     PVOID JobInfo;
219     JOBOBJECT_EXTENDED_LIMIT_INFORMATION LocalInfo;
220     ULONG ExpectedSize;
221     PVOID State = NULL;
222     ULONG Privilege = SE_INC_BASE_PRIORITY_PRIVILEGE;
223 
224     if (JobObjectInformationClass == JobObjectBasicLimitInformation)
225     {
226         ExpectedSize = sizeof(JOBOBJECT_BASIC_LIMIT_INFORMATION);
227         JobInfo = &LocalInfo;
228     }
229     else if (JobObjectInformationClass == JobObjectExtendedLimitInformation)
230     {
231         ExpectedSize = sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION);
232         JobInfo = &LocalInfo;
233     }
234     else
235     {
236         ExpectedSize = cbJobObjectInformationLength;
237         JobInfo = lpJobObjectInformation;
238     }
239 
240     if (cbJobObjectInformationLength != ExpectedSize)
241     {
242         BaseSetLastNTError(STATUS_INFO_LENGTH_MISMATCH);
243         return FALSE;
244     }
245 
246     if (JobInfo == &LocalInfo)
247     {
248         RtlCopyMemory(&LocalInfo, lpJobObjectInformation, ExpectedSize);
249 
250         if (LocalInfo.BasicLimitInformation.LimitFlags &
251             JOB_OBJECT_LIMIT_PRIORITY_CLASS)
252         {
253             switch (LocalInfo.BasicLimitInformation.PriorityClass)
254             {
255                 case IDLE_PRIORITY_CLASS:
256                     LocalInfo.BasicLimitInformation.PriorityClass =
257                     PROCESS_PRIORITY_CLASS_IDLE;
258                     break;
259 
260                 case BELOW_NORMAL_PRIORITY_CLASS:
261                     LocalInfo.BasicLimitInformation.PriorityClass =
262                     PROCESS_PRIORITY_CLASS_BELOW_NORMAL;
263                     break;
264 
265                 case NORMAL_PRIORITY_CLASS:
266                     LocalInfo.BasicLimitInformation.PriorityClass =
267                     PROCESS_PRIORITY_CLASS_NORMAL;
268                     break;
269 
270                 case ABOVE_NORMAL_PRIORITY_CLASS:
271                     LocalInfo.BasicLimitInformation.PriorityClass =
272                     PROCESS_PRIORITY_CLASS_ABOVE_NORMAL;
273                     break;
274 
275                 case HIGH_PRIORITY_CLASS:
276                     LocalInfo.BasicLimitInformation.PriorityClass =
277                     PROCESS_PRIORITY_CLASS_HIGH;
278                     break;
279 
280                 case REALTIME_PRIORITY_CLASS:
281                     LocalInfo.BasicLimitInformation.PriorityClass =
282                     PROCESS_PRIORITY_CLASS_REALTIME;
283                     break;
284 
285                 default:
286                     LocalInfo.BasicLimitInformation.PriorityClass =
287                     PROCESS_PRIORITY_CLASS_NORMAL;
288                     break;
289             }
290         }
291 
292         if (LocalInfo.BasicLimitInformation.LimitFlags &
293             JOB_OBJECT_LIMIT_WORKINGSET)
294         {
295             Status = RtlAcquirePrivilege(&Privilege, 1, 0, &State);
296         }
297     }
298 
299     Status = NtSetInformationJobObject(hJob,
300                                        JobObjectInformationClass,
301                                        JobInfo,
302                                        ExpectedSize);
303     if (NT_SUCCESS(Status))
304     {
305         if (State != NULL) RtlReleasePrivilege(State);
306         return TRUE;
307     }
308 
309     BaseSetLastNTError(Status);
310     return FALSE;
311 }
312 
313 /*
314  * @implemented
315  */
316 BOOL
317 WINAPI
318 TerminateJobObject(IN HANDLE hJob,
319                    IN UINT uExitCode)
320 {
321     NTSTATUS Status;
322 
323     Status = NtTerminateJobObject(hJob, uExitCode);
324     if (!NT_SUCCESS(Status))
325     {
326         BaseSetLastNTError(Status);
327         return FALSE;
328     }
329 
330     return TRUE;
331 }
332 
333 /*
334  * @implemented
335  */
336 BOOL
337 WINAPI
338 CreateJobSet(IN ULONG NumJob,
339              IN PJOB_SET_ARRAY UserJobSet,
340              IN ULONG Flags)
341 {
342     NTSTATUS Status;
343 
344     Status = NtCreateJobSet(NumJob, UserJobSet, Flags);
345     if (!NT_SUCCESS(Status))
346     {
347         BaseSetLastNTError(Status);
348         return FALSE;
349     }
350 
351     return TRUE;
352 }
353 
354 /* EOF */
355