Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

464 lines
12 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. job.c
  5. Abstract:
  6. Support for the Job Object
  7. Author:
  8. Mark Lucovsky (markl) 12-Jun-1997
  9. Revision History:
  10. --*/
  11. #include "basedll.h"
  12. #pragma hdrstop
  13. HANDLE
  14. WINAPI
  15. CreateJobObjectA(
  16. LPSECURITY_ATTRIBUTES lpJobAttributes,
  17. LPCSTR lpName
  18. )
  19. {
  20. PUNICODE_STRING Unicode;
  21. ANSI_STRING AnsiString;
  22. NTSTATUS Status;
  23. LPCWSTR NameBuffer;
  24. NameBuffer = NULL;
  25. if ( ARGUMENT_PRESENT(lpName) ) {
  26. Unicode = &NtCurrentTeb()->StaticUnicodeString;
  27. RtlInitAnsiString(&AnsiString,lpName);
  28. Status = RtlAnsiStringToUnicodeString(Unicode,&AnsiString,FALSE);
  29. if ( !NT_SUCCESS(Status) ) {
  30. if ( Status == STATUS_BUFFER_OVERFLOW ) {
  31. SetLastError(ERROR_FILENAME_EXCED_RANGE);
  32. }
  33. else {
  34. BaseSetLastNTError(Status);
  35. }
  36. return NULL;
  37. }
  38. NameBuffer = (LPCWSTR)Unicode->Buffer;
  39. }
  40. return CreateJobObjectW(
  41. lpJobAttributes,
  42. NameBuffer
  43. );
  44. }
  45. HANDLE
  46. WINAPI
  47. CreateJobObjectW(
  48. LPSECURITY_ATTRIBUTES lpJobAttributes,
  49. LPCWSTR lpName
  50. )
  51. {
  52. NTSTATUS Status;
  53. OBJECT_ATTRIBUTES Obja;
  54. POBJECT_ATTRIBUTES pObja;
  55. HANDLE Handle;
  56. UNICODE_STRING ObjectName;
  57. if ( ARGUMENT_PRESENT(lpName) ) {
  58. RtlInitUnicodeString(&ObjectName,lpName);
  59. pObja = BaseFormatObjectAttributes(&Obja,lpJobAttributes,&ObjectName);
  60. }
  61. else {
  62. pObja = BaseFormatObjectAttributes(&Obja,lpJobAttributes,NULL);
  63. }
  64. Status = NtCreateJobObject(
  65. &Handle,
  66. JOB_OBJECT_ALL_ACCESS,
  67. pObja
  68. );
  69. if ( NT_SUCCESS(Status) ) {
  70. if ( Status == STATUS_OBJECT_NAME_EXISTS ) {
  71. SetLastError(ERROR_ALREADY_EXISTS);
  72. }
  73. else {
  74. SetLastError(0);
  75. }
  76. return Handle;
  77. }
  78. else {
  79. BaseSetLastNTError(Status);
  80. return NULL;
  81. }
  82. }
  83. HANDLE
  84. WINAPI
  85. OpenJobObjectA(
  86. DWORD dwDesiredAccess,
  87. BOOL bInheritHandle,
  88. LPCSTR lpName
  89. )
  90. {
  91. PUNICODE_STRING Unicode;
  92. ANSI_STRING AnsiString;
  93. NTSTATUS Status;
  94. if ( ARGUMENT_PRESENT(lpName) ) {
  95. Unicode = &NtCurrentTeb()->StaticUnicodeString;
  96. RtlInitAnsiString(&AnsiString,lpName);
  97. Status = RtlAnsiStringToUnicodeString(Unicode,&AnsiString,FALSE);
  98. if ( !NT_SUCCESS(Status) ) {
  99. if ( Status == STATUS_BUFFER_OVERFLOW ) {
  100. SetLastError(ERROR_FILENAME_EXCED_RANGE);
  101. }
  102. else {
  103. BaseSetLastNTError(Status);
  104. }
  105. return NULL;
  106. }
  107. }
  108. else {
  109. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  110. return NULL;
  111. }
  112. return OpenJobObjectW(
  113. dwDesiredAccess,
  114. bInheritHandle,
  115. (LPCWSTR)Unicode->Buffer
  116. );
  117. }
  118. HANDLE
  119. WINAPI
  120. OpenJobObjectW(
  121. DWORD dwDesiredAccess,
  122. BOOL bInheritHandle,
  123. LPCWSTR lpName
  124. )
  125. {
  126. OBJECT_ATTRIBUTES Obja;
  127. UNICODE_STRING ObjectName;
  128. NTSTATUS Status;
  129. HANDLE Object;
  130. if ( !lpName ) {
  131. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  132. return NULL;
  133. }
  134. RtlInitUnicodeString(&ObjectName,lpName);
  135. InitializeObjectAttributes(
  136. &Obja,
  137. &ObjectName,
  138. (bInheritHandle ? OBJ_INHERIT : 0),
  139. BaseGetNamedObjectDirectory(),
  140. NULL
  141. );
  142. Status = NtOpenJobObject(
  143. &Object,
  144. dwDesiredAccess,
  145. &Obja
  146. );
  147. if ( !NT_SUCCESS(Status) ) {
  148. BaseSetLastNTError(Status);
  149. return NULL;
  150. }
  151. return Object;
  152. }
  153. BOOL
  154. WINAPI
  155. AssignProcessToJobObject(
  156. HANDLE hJob,
  157. HANDLE hProcess
  158. )
  159. {
  160. NTSTATUS Status;
  161. BOOL rv;
  162. rv = TRUE;
  163. Status = NtAssignProcessToJobObject(hJob,hProcess);
  164. if ( !NT_SUCCESS(Status) ) {
  165. rv = FALSE;
  166. BaseSetLastNTError(Status);
  167. }
  168. return rv;
  169. }
  170. BOOL
  171. WINAPI
  172. TerminateJobObject(
  173. HANDLE hJob,
  174. UINT uExitCode
  175. )
  176. {
  177. NTSTATUS Status;
  178. BOOL rv;
  179. rv = TRUE;
  180. Status = NtTerminateJobObject(hJob,uExitCode);
  181. if ( !NT_SUCCESS(Status) ) {
  182. rv = FALSE;
  183. BaseSetLastNTError(Status);
  184. }
  185. return rv;
  186. }
  187. BOOL
  188. WINAPI
  189. QueryInformationJobObject(
  190. HANDLE hJob,
  191. JOBOBJECTINFOCLASS JobObjectInformationClass,
  192. LPVOID lpJobObjectInformation,
  193. DWORD cbJobObjectInformationLength,
  194. LPDWORD lpReturnLength
  195. )
  196. {
  197. NTSTATUS Status;
  198. BOOL rv;
  199. JOBOBJECT_EXTENDED_LIMIT_INFORMATION ExtendedLimitInfo;
  200. PVOID LimitInfo;
  201. if ( JobObjectInformationClass == JobObjectBasicLimitInformation ) {
  202. LimitInfo = &ExtendedLimitInfo;
  203. if ( cbJobObjectInformationLength != sizeof(JOBOBJECT_BASIC_LIMIT_INFORMATION) ) {
  204. BaseSetLastNTError(STATUS_INFO_LENGTH_MISMATCH);
  205. return FALSE;
  206. }
  207. }
  208. else if ( JobObjectInformationClass == JobObjectExtendedLimitInformation ) {
  209. LimitInfo = &ExtendedLimitInfo;
  210. if ( cbJobObjectInformationLength != sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION) ) {
  211. BaseSetLastNTError(STATUS_INFO_LENGTH_MISMATCH);
  212. return FALSE;
  213. }
  214. }
  215. else {
  216. LimitInfo = lpJobObjectInformation;
  217. }
  218. rv = TRUE;
  219. Status = NtQueryInformationJobObject(
  220. hJob,
  221. JobObjectInformationClass,
  222. LimitInfo,
  223. cbJobObjectInformationLength,
  224. lpReturnLength
  225. );
  226. if ( !NT_SUCCESS(Status) ) {
  227. rv = FALSE;
  228. BaseSetLastNTError(Status);
  229. }
  230. else {
  231. if (LimitInfo == &ExtendedLimitInfo ) {
  232. switch (ExtendedLimitInfo.BasicLimitInformation.PriorityClass) {
  233. case PROCESS_PRIORITY_CLASS_IDLE :
  234. ExtendedLimitInfo.BasicLimitInformation.PriorityClass = IDLE_PRIORITY_CLASS;
  235. break;
  236. case PROCESS_PRIORITY_CLASS_BELOW_NORMAL:
  237. ExtendedLimitInfo.BasicLimitInformation.PriorityClass = BELOW_NORMAL_PRIORITY_CLASS;
  238. break;
  239. case PROCESS_PRIORITY_CLASS_NORMAL :
  240. ExtendedLimitInfo.BasicLimitInformation.PriorityClass = NORMAL_PRIORITY_CLASS;
  241. break;
  242. case PROCESS_PRIORITY_CLASS_ABOVE_NORMAL:
  243. ExtendedLimitInfo.BasicLimitInformation.PriorityClass = ABOVE_NORMAL_PRIORITY_CLASS;
  244. break;
  245. case PROCESS_PRIORITY_CLASS_HIGH :
  246. ExtendedLimitInfo.BasicLimitInformation.PriorityClass = HIGH_PRIORITY_CLASS;
  247. break;
  248. case PROCESS_PRIORITY_CLASS_REALTIME :
  249. ExtendedLimitInfo.BasicLimitInformation.PriorityClass = REALTIME_PRIORITY_CLASS;
  250. break;
  251. default:
  252. ExtendedLimitInfo.BasicLimitInformation.PriorityClass = NORMAL_PRIORITY_CLASS;
  253. }
  254. CopyMemory(lpJobObjectInformation,&ExtendedLimitInfo,cbJobObjectInformationLength);
  255. }
  256. }
  257. return rv;
  258. }
  259. BOOL
  260. WINAPI
  261. SetInformationJobObject(
  262. HANDLE hJob,
  263. JOBOBJECTINFOCLASS JobObjectInformationClass,
  264. LPVOID lpJobObjectInformation,
  265. DWORD cbJobObjectInformationLength
  266. )
  267. {
  268. NTSTATUS Status;
  269. BOOL rv;
  270. JOBOBJECT_EXTENDED_LIMIT_INFORMATION ExtendedLimitInfo;
  271. PVOID LimitInfo;
  272. NTSTATUS PrivStatus = STATUS_UNSUCCESSFUL;
  273. PVOID State;
  274. rv = TRUE;
  275. if (JobObjectInformationClass == JobObjectBasicLimitInformation ||
  276. JobObjectInformationClass == JobObjectExtendedLimitInformation ) {
  277. if ( JobObjectInformationClass == JobObjectBasicLimitInformation ) {
  278. if ( cbJobObjectInformationLength != sizeof(JOBOBJECT_BASIC_LIMIT_INFORMATION) ) {
  279. BaseSetLastNTError(STATUS_INFO_LENGTH_MISMATCH);
  280. return FALSE;
  281. }
  282. } else {
  283. if ( cbJobObjectInformationLength != sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION) ) {
  284. BaseSetLastNTError(STATUS_INFO_LENGTH_MISMATCH);
  285. return FALSE;
  286. }
  287. }
  288. LimitInfo = &ExtendedLimitInfo;
  289. CopyMemory(&ExtendedLimitInfo,lpJobObjectInformation,cbJobObjectInformationLength);
  290. if ( ExtendedLimitInfo.BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_PRIORITY_CLASS ) {
  291. switch (ExtendedLimitInfo.BasicLimitInformation.PriorityClass) {
  292. case IDLE_PRIORITY_CLASS :
  293. ExtendedLimitInfo.BasicLimitInformation.PriorityClass = PROCESS_PRIORITY_CLASS_IDLE;
  294. break;
  295. case BELOW_NORMAL_PRIORITY_CLASS :
  296. ExtendedLimitInfo.BasicLimitInformation.PriorityClass = PROCESS_PRIORITY_CLASS_BELOW_NORMAL;
  297. break;
  298. case NORMAL_PRIORITY_CLASS :
  299. ExtendedLimitInfo.BasicLimitInformation.PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL;
  300. break;
  301. case ABOVE_NORMAL_PRIORITY_CLASS :
  302. ExtendedLimitInfo.BasicLimitInformation.PriorityClass = PROCESS_PRIORITY_CLASS_ABOVE_NORMAL;
  303. break;
  304. case HIGH_PRIORITY_CLASS :
  305. ExtendedLimitInfo.BasicLimitInformation.PriorityClass = PROCESS_PRIORITY_CLASS_HIGH;
  306. break;
  307. case REALTIME_PRIORITY_CLASS :
  308. ExtendedLimitInfo.BasicLimitInformation.PriorityClass = PROCESS_PRIORITY_CLASS_REALTIME;
  309. break;
  310. default:
  311. ExtendedLimitInfo.BasicLimitInformation.PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL;
  312. }
  313. }
  314. if (ExtendedLimitInfo.BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_WORKINGSET) {
  315. //
  316. // Attempt to acquire the appropriate privilege. If this
  317. // fails, it's no big deal -- we'll attempt to make the
  318. // NtSetInformationProcess call anyway, in case it turns out
  319. // to be a decrease operation (which will succeed anyway).
  320. //
  321. PrivStatus = BasepAcquirePrivilegeEx( SE_INC_BASE_PRIORITY_PRIVILEGE, &State );
  322. }
  323. } else {
  324. LimitInfo = lpJobObjectInformation;
  325. }
  326. Status = NtSetInformationJobObject(
  327. hJob,
  328. JobObjectInformationClass,
  329. LimitInfo,
  330. cbJobObjectInformationLength
  331. );
  332. if (NT_SUCCESS(PrivStatus)) {
  333. //
  334. // We successfully acquired the privilege above; we need to relinquish it.
  335. //
  336. ASSERT (State != NULL);
  337. BasepReleasePrivilege (State);
  338. State = NULL;
  339. }
  340. if ( !NT_SUCCESS(Status) ) {
  341. rv = FALSE;
  342. BaseSetLastNTError(Status);
  343. }
  344. return rv;
  345. }
  346. BOOL
  347. WINAPI
  348. IsProcessInJob (
  349. IN HANDLE ProcessHandle,
  350. IN HANDLE JobHandle,
  351. OUT PBOOL Result
  352. )
  353. /*++
  354. Routine Description:
  355. This routine finds out if a process is in a specific or any job
  356. Arguments:
  357. ProcessHandle - Handle to process to be checked
  358. JobHandle - Handle of job to check process against, May be NULL to do general query.
  359. Result - TRUE if the process is part of the job FALSE otherwise.
  360. Return Value:
  361. BOOL - TRUE the call was successfull, FALSE the call failed
  362. --*/
  363. {
  364. NTSTATUS Status;
  365. Status = NtIsProcessInJob (ProcessHandle,
  366. JobHandle);
  367. if (!NT_SUCCESS (Status)) {
  368. BaseSetLastNTError (Status);
  369. return FALSE;
  370. }
  371. if (Status == STATUS_PROCESS_NOT_IN_JOB) {
  372. *Result = FALSE;
  373. } else {
  374. *Result = TRUE;
  375. }
  376. return TRUE;
  377. }
  378. BOOL
  379. WINAPI
  380. CreateJobSet (
  381. IN ULONG NumJob,
  382. IN PJOB_SET_ARRAY UserJobSet,
  383. IN ULONG Flags)
  384. /*++
  385. Routine Description:
  386. This function creates a job set from multiple job objects.
  387. Arguments:
  388. NumJob - Number of jobs in JobSet
  389. UserJobSet - Pointer to array of jobs to combine
  390. Flags - Flags mask for future expansion
  391. Return Value:
  392. BOOL - TRUE the call was successfull, FALSE the call failed
  393. --*/
  394. {
  395. NTSTATUS Status;
  396. Status = NtCreateJobSet (NumJob,
  397. UserJobSet,
  398. Flags);
  399. if (!NT_SUCCESS (Status)) {
  400. BaseSetLastNTError (Status);
  401. return FALSE;
  402. }
  403. return TRUE;
  404. }