|
|
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
job.c
Abstract:
Support for the Job Object
Author:
Mark Lucovsky (markl) 12-Jun-1997
Revision History:
--*/
#include "basedll.h"
#pragma hdrstop
HANDLE WINAPI CreateJobObjectA( LPSECURITY_ATTRIBUTES lpJobAttributes, LPCSTR lpName ) { PUNICODE_STRING Unicode; ANSI_STRING AnsiString; NTSTATUS Status; LPCWSTR NameBuffer;
NameBuffer = NULL; if ( ARGUMENT_PRESENT(lpName) ) { Unicode = &NtCurrentTeb()->StaticUnicodeString; RtlInitAnsiString(&AnsiString,lpName); Status = RtlAnsiStringToUnicodeString(Unicode,&AnsiString,FALSE); if ( !NT_SUCCESS(Status) ) { if ( Status == STATUS_BUFFER_OVERFLOW ) { SetLastError(ERROR_FILENAME_EXCED_RANGE); } else { BaseSetLastNTError(Status); } return NULL; } NameBuffer = (LPCWSTR)Unicode->Buffer; }
return CreateJobObjectW( lpJobAttributes, NameBuffer ); }
HANDLE WINAPI CreateJobObjectW( LPSECURITY_ATTRIBUTES lpJobAttributes, LPCWSTR lpName ) { NTSTATUS Status; OBJECT_ATTRIBUTES Obja; POBJECT_ATTRIBUTES pObja; HANDLE Handle; UNICODE_STRING ObjectName;
if ( ARGUMENT_PRESENT(lpName) ) { RtlInitUnicodeString(&ObjectName,lpName); pObja = BaseFormatObjectAttributes(&Obja,lpJobAttributes,&ObjectName); } else { pObja = BaseFormatObjectAttributes(&Obja,lpJobAttributes,NULL); }
Status = NtCreateJobObject( &Handle, JOB_OBJECT_ALL_ACCESS, pObja ); if ( NT_SUCCESS(Status) ) { if ( Status == STATUS_OBJECT_NAME_EXISTS ) { SetLastError(ERROR_ALREADY_EXISTS); } else { SetLastError(0); } return Handle; } else { BaseSetLastNTError(Status); return NULL; } }
HANDLE WINAPI OpenJobObjectA( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName ) { PUNICODE_STRING Unicode; ANSI_STRING AnsiString; NTSTATUS Status;
if ( ARGUMENT_PRESENT(lpName) ) { Unicode = &NtCurrentTeb()->StaticUnicodeString; RtlInitAnsiString(&AnsiString,lpName); Status = RtlAnsiStringToUnicodeString(Unicode,&AnsiString,FALSE); if ( !NT_SUCCESS(Status) ) { if ( Status == STATUS_BUFFER_OVERFLOW ) { SetLastError(ERROR_FILENAME_EXCED_RANGE); } else { BaseSetLastNTError(Status); } return NULL; } } else { BaseSetLastNTError(STATUS_INVALID_PARAMETER); return NULL; }
return OpenJobObjectW( dwDesiredAccess, bInheritHandle, (LPCWSTR)Unicode->Buffer ); }
HANDLE WINAPI OpenJobObjectW( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName ) { OBJECT_ATTRIBUTES Obja; UNICODE_STRING ObjectName; NTSTATUS Status; HANDLE Object;
if ( !lpName ) { BaseSetLastNTError(STATUS_INVALID_PARAMETER); return NULL; } RtlInitUnicodeString(&ObjectName,lpName);
InitializeObjectAttributes( &Obja, &ObjectName, (bInheritHandle ? OBJ_INHERIT : 0), BaseGetNamedObjectDirectory(), NULL );
Status = NtOpenJobObject( &Object, dwDesiredAccess, &Obja ); if ( !NT_SUCCESS(Status) ) { BaseSetLastNTError(Status); return NULL; } return Object; }
BOOL WINAPI AssignProcessToJobObject( HANDLE hJob, HANDLE hProcess ) { NTSTATUS Status; BOOL rv;
rv = TRUE; Status = NtAssignProcessToJobObject(hJob,hProcess); if ( !NT_SUCCESS(Status) ) { rv = FALSE; BaseSetLastNTError(Status); } return rv; }
BOOL WINAPI TerminateJobObject( HANDLE hJob, UINT uExitCode ) { NTSTATUS Status; BOOL rv;
rv = TRUE; Status = NtTerminateJobObject(hJob,uExitCode); if ( !NT_SUCCESS(Status) ) { rv = FALSE; BaseSetLastNTError(Status); } return rv; }
BOOL WINAPI QueryInformationJobObject( HANDLE hJob, JOBOBJECTINFOCLASS JobObjectInformationClass, LPVOID lpJobObjectInformation, DWORD cbJobObjectInformationLength, LPDWORD lpReturnLength ) { NTSTATUS Status; BOOL rv; JOBOBJECT_EXTENDED_LIMIT_INFORMATION ExtendedLimitInfo; PVOID LimitInfo;
if ( JobObjectInformationClass == JobObjectBasicLimitInformation ) { LimitInfo = &ExtendedLimitInfo; if ( cbJobObjectInformationLength != sizeof(JOBOBJECT_BASIC_LIMIT_INFORMATION) ) { BaseSetLastNTError(STATUS_INFO_LENGTH_MISMATCH); return FALSE; } } else if ( JobObjectInformationClass == JobObjectExtendedLimitInformation ) { LimitInfo = &ExtendedLimitInfo; if ( cbJobObjectInformationLength != sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION) ) { BaseSetLastNTError(STATUS_INFO_LENGTH_MISMATCH); return FALSE; } } else { LimitInfo = lpJobObjectInformation; }
rv = TRUE; Status = NtQueryInformationJobObject( hJob, JobObjectInformationClass, LimitInfo, cbJobObjectInformationLength, lpReturnLength ); if ( !NT_SUCCESS(Status) ) { rv = FALSE; BaseSetLastNTError(Status); } else { if (LimitInfo == &ExtendedLimitInfo ) { switch (ExtendedLimitInfo.BasicLimitInformation.PriorityClass) { case PROCESS_PRIORITY_CLASS_IDLE : ExtendedLimitInfo.BasicLimitInformation.PriorityClass = IDLE_PRIORITY_CLASS; break; case PROCESS_PRIORITY_CLASS_BELOW_NORMAL: ExtendedLimitInfo.BasicLimitInformation.PriorityClass = BELOW_NORMAL_PRIORITY_CLASS; break; case PROCESS_PRIORITY_CLASS_NORMAL : ExtendedLimitInfo.BasicLimitInformation.PriorityClass = NORMAL_PRIORITY_CLASS; break; case PROCESS_PRIORITY_CLASS_ABOVE_NORMAL: ExtendedLimitInfo.BasicLimitInformation.PriorityClass = ABOVE_NORMAL_PRIORITY_CLASS; break; case PROCESS_PRIORITY_CLASS_HIGH : ExtendedLimitInfo.BasicLimitInformation.PriorityClass = HIGH_PRIORITY_CLASS; break; case PROCESS_PRIORITY_CLASS_REALTIME : ExtendedLimitInfo.BasicLimitInformation.PriorityClass = REALTIME_PRIORITY_CLASS; break; default: ExtendedLimitInfo.BasicLimitInformation.PriorityClass = NORMAL_PRIORITY_CLASS;
} CopyMemory(lpJobObjectInformation,&ExtendedLimitInfo,cbJobObjectInformationLength); } } return rv; }
BOOL WINAPI SetInformationJobObject( HANDLE hJob, JOBOBJECTINFOCLASS JobObjectInformationClass, LPVOID lpJobObjectInformation, DWORD cbJobObjectInformationLength ) { NTSTATUS Status; BOOL rv; JOBOBJECT_EXTENDED_LIMIT_INFORMATION ExtendedLimitInfo; PVOID LimitInfo; NTSTATUS PrivStatus = STATUS_UNSUCCESSFUL; PVOID State;
rv = TRUE; if (JobObjectInformationClass == JobObjectBasicLimitInformation || JobObjectInformationClass == JobObjectExtendedLimitInformation ) {
if ( JobObjectInformationClass == JobObjectBasicLimitInformation ) { if ( cbJobObjectInformationLength != sizeof(JOBOBJECT_BASIC_LIMIT_INFORMATION) ) { BaseSetLastNTError(STATUS_INFO_LENGTH_MISMATCH); return FALSE; } } else { if ( cbJobObjectInformationLength != sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION) ) { BaseSetLastNTError(STATUS_INFO_LENGTH_MISMATCH); return FALSE; } }
LimitInfo = &ExtendedLimitInfo;
CopyMemory(&ExtendedLimitInfo,lpJobObjectInformation,cbJobObjectInformationLength);
if ( ExtendedLimitInfo.BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_PRIORITY_CLASS ) { switch (ExtendedLimitInfo.BasicLimitInformation.PriorityClass) {
case IDLE_PRIORITY_CLASS : ExtendedLimitInfo.BasicLimitInformation.PriorityClass = PROCESS_PRIORITY_CLASS_IDLE; break; case BELOW_NORMAL_PRIORITY_CLASS : ExtendedLimitInfo.BasicLimitInformation.PriorityClass = PROCESS_PRIORITY_CLASS_BELOW_NORMAL; break; case NORMAL_PRIORITY_CLASS : ExtendedLimitInfo.BasicLimitInformation.PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL; break; case ABOVE_NORMAL_PRIORITY_CLASS : ExtendedLimitInfo.BasicLimitInformation.PriorityClass = PROCESS_PRIORITY_CLASS_ABOVE_NORMAL; break; case HIGH_PRIORITY_CLASS : ExtendedLimitInfo.BasicLimitInformation.PriorityClass = PROCESS_PRIORITY_CLASS_HIGH; break; case REALTIME_PRIORITY_CLASS : ExtendedLimitInfo.BasicLimitInformation.PriorityClass = PROCESS_PRIORITY_CLASS_REALTIME; break; default: ExtendedLimitInfo.BasicLimitInformation.PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL;
} } if (ExtendedLimitInfo.BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_WORKINGSET) { //
// Attempt to acquire the appropriate privilege. If this
// fails, it's no big deal -- we'll attempt to make the
// NtSetInformationProcess call anyway, in case it turns out
// to be a decrease operation (which will succeed anyway).
//
PrivStatus = BasepAcquirePrivilegeEx( SE_INC_BASE_PRIORITY_PRIVILEGE, &State ); } } else { LimitInfo = lpJobObjectInformation; }
Status = NtSetInformationJobObject( hJob, JobObjectInformationClass, LimitInfo, cbJobObjectInformationLength );
if (NT_SUCCESS(PrivStatus)) { //
// We successfully acquired the privilege above; we need to relinquish it.
//
ASSERT (State != NULL); BasepReleasePrivilege (State); State = NULL; }
if ( !NT_SUCCESS(Status) ) { rv = FALSE; BaseSetLastNTError(Status); } return rv; }
BOOL WINAPI IsProcessInJob ( IN HANDLE ProcessHandle, IN HANDLE JobHandle, OUT PBOOL Result ) /*++
Routine Description:
This routine finds out if a process is in a specific or any job
Arguments:
ProcessHandle - Handle to process to be checked JobHandle - Handle of job to check process against, May be NULL to do general query. Result - TRUE if the process is part of the job FALSE otherwise.
Return Value:
BOOL - TRUE the call was successfull, FALSE the call failed
--*/ { NTSTATUS Status;
Status = NtIsProcessInJob (ProcessHandle, JobHandle); if (!NT_SUCCESS (Status)) { BaseSetLastNTError (Status); return FALSE; } if (Status == STATUS_PROCESS_NOT_IN_JOB) { *Result = FALSE; } else { *Result = TRUE; } return TRUE; }
BOOL WINAPI CreateJobSet ( IN ULONG NumJob, IN PJOB_SET_ARRAY UserJobSet, IN ULONG Flags) /*++
Routine Description:
This function creates a job set from multiple job objects. Arguments:
NumJob - Number of jobs in JobSet UserJobSet - Pointer to array of jobs to combine Flags - Flags mask for future expansion
Return Value:
BOOL - TRUE the call was successfull, FALSE the call failed
--*/ { NTSTATUS Status;
Status = NtCreateJobSet (NumJob, UserJobSet, Flags); if (!NT_SUCCESS (Status)) { BaseSetLastNTError (Status); return FALSE; } return TRUE; }
|