mirror of
https://github.com/reactos/reactos.git
synced 2024-09-12 05:43:24 +00:00
435 lines
11 KiB
C
435 lines
11 KiB
C
/* $Id$
|
|
*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS system libraries
|
|
* FILE: lib/kernel32/process/job.c
|
|
* PURPOSE: Job functions
|
|
* PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
|
|
* UPDATE HISTORY:
|
|
* Created 9/23/2004
|
|
*/
|
|
|
|
/* INCLUDES ****************************************************************/
|
|
|
|
#include <k32.h>
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
HANDLE
|
|
WINAPI
|
|
CreateJobObjectA(LPSECURITY_ATTRIBUTES lpJobAttributes,
|
|
LPCSTR lpName)
|
|
{
|
|
HANDLE hJob;
|
|
ANSI_STRING AnsiName;
|
|
UNICODE_STRING UnicodeName;
|
|
|
|
if (lpName != NULL)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
RtlInitAnsiString(&AnsiName, lpName);
|
|
Status = RtlAnsiStringToUnicodeString(&UnicodeName, &AnsiName, TRUE);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SetLastErrorByStatus(Status);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
hJob = CreateJobObjectW(lpJobAttributes,
|
|
((lpName != NULL) ? UnicodeName.Buffer : NULL));
|
|
|
|
if (lpName != NULL)
|
|
{
|
|
RtlFreeUnicodeString(&UnicodeName);
|
|
}
|
|
|
|
return hJob;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
HANDLE
|
|
WINAPI
|
|
CreateJobObjectW(LPSECURITY_ATTRIBUTES lpJobAttributes,
|
|
LPCWSTR lpName)
|
|
{
|
|
UNICODE_STRING JobName;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
ULONG Attributes = 0;
|
|
PVOID SecurityDescriptor;
|
|
HANDLE hJob;
|
|
NTSTATUS Status;
|
|
|
|
if (lpName != NULL)
|
|
{
|
|
RtlInitUnicodeString(&JobName, lpName);
|
|
}
|
|
|
|
if (lpJobAttributes != NULL)
|
|
{
|
|
if (lpJobAttributes->bInheritHandle)
|
|
{
|
|
Attributes |= OBJ_INHERIT;
|
|
}
|
|
|
|
SecurityDescriptor = lpJobAttributes->lpSecurityDescriptor;
|
|
}
|
|
else
|
|
{
|
|
SecurityDescriptor = NULL;
|
|
}
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
((lpName != NULL) ? &JobName : NULL),
|
|
Attributes,
|
|
NULL,
|
|
SecurityDescriptor);
|
|
|
|
Status = NtCreateJobObject(&hJob,
|
|
JOB_OBJECT_ALL_ACCESS,
|
|
&ObjectAttributes);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SetLastErrorByStatus(Status);
|
|
return NULL;
|
|
}
|
|
|
|
return hJob;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
HANDLE
|
|
WINAPI
|
|
OpenJobObjectW(DWORD dwDesiredAccess,
|
|
BOOL bInheritHandle,
|
|
LPCWSTR lpName)
|
|
{
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING JobName;
|
|
HANDLE hJob;
|
|
NTSTATUS Status;
|
|
|
|
if (lpName == NULL)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return NULL;
|
|
}
|
|
|
|
RtlInitUnicodeString(&JobName, lpName);
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&JobName,
|
|
(bInheritHandle ? OBJ_INHERIT : 0),
|
|
NULL,
|
|
NULL);
|
|
|
|
Status = NtOpenJobObject(&hJob,
|
|
dwDesiredAccess,
|
|
&ObjectAttributes);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SetLastErrorByStatus(Status);
|
|
return NULL;
|
|
}
|
|
|
|
return hJob;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
HANDLE
|
|
WINAPI
|
|
OpenJobObjectA(DWORD dwDesiredAccess,
|
|
BOOL bInheritHandle,
|
|
LPCSTR lpName)
|
|
{
|
|
ANSI_STRING AnsiName;
|
|
UNICODE_STRING UnicodeName;
|
|
HANDLE hJob;
|
|
NTSTATUS Status;
|
|
|
|
if (lpName == NULL)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return NULL;
|
|
}
|
|
|
|
RtlInitAnsiString(&AnsiName, lpName);
|
|
Status = RtlAnsiStringToUnicodeString(&UnicodeName, &AnsiName, TRUE);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SetLastErrorByStatus(Status);
|
|
return FALSE;
|
|
}
|
|
|
|
hJob = OpenJobObjectW(dwDesiredAccess,
|
|
bInheritHandle,
|
|
UnicodeName.Buffer);
|
|
|
|
RtlFreeUnicodeString(&UnicodeName);
|
|
return hJob;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOL
|
|
WINAPI
|
|
IsProcessInJob(HANDLE ProcessHandle,
|
|
HANDLE JobHandle,
|
|
PBOOL Result)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
Status = NtIsProcessInJob(ProcessHandle, JobHandle);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
*Result = (Status == STATUS_PROCESS_IN_JOB);
|
|
return TRUE;
|
|
}
|
|
|
|
SetLastErrorByStatus(Status);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOL
|
|
WINAPI
|
|
AssignProcessToJobObject(HANDLE hJob,
|
|
HANDLE hProcess)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
Status = NtAssignProcessToJobObject(hJob, hProcess);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SetLastErrorByStatus(Status);
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOL
|
|
WINAPI
|
|
QueryInformationJobObject(HANDLE hJob,
|
|
JOBOBJECTINFOCLASS JobObjectInformationClass,
|
|
LPVOID lpJobObjectInformation,
|
|
DWORD cbJobObjectInformationLength,
|
|
LPDWORD lpReturnLength)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
Status = NtQueryInformationJobObject(hJob,
|
|
JobObjectInformationClass,
|
|
lpJobObjectInformation,
|
|
cbJobObjectInformationLength,
|
|
lpReturnLength);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
PJOBOBJECT_BASIC_LIMIT_INFORMATION BasicInfo;
|
|
|
|
switch (JobObjectInformationClass)
|
|
{
|
|
case JobObjectBasicLimitInformation:
|
|
BasicInfo = (PJOBOBJECT_BASIC_LIMIT_INFORMATION)lpJobObjectInformation;
|
|
break;
|
|
|
|
case JobObjectExtendedLimitInformation:
|
|
BasicInfo = &((PJOBOBJECT_EXTENDED_LIMIT_INFORMATION)lpJobObjectInformation)->BasicLimitInformation;
|
|
break;
|
|
|
|
default:
|
|
BasicInfo = NULL;
|
|
break;
|
|
}
|
|
|
|
if (BasicInfo != NULL)
|
|
{
|
|
/* we need to convert the process priority classes in the
|
|
JOBOBJECT_BASIC_LIMIT_INFORMATION structure the same way as
|
|
GetPriorityClass() converts it! */
|
|
switch (BasicInfo->PriorityClass)
|
|
{
|
|
case PROCESS_PRIORITY_CLASS_IDLE:
|
|
BasicInfo->PriorityClass = IDLE_PRIORITY_CLASS;
|
|
break;
|
|
|
|
case PROCESS_PRIORITY_CLASS_BELOW_NORMAL:
|
|
BasicInfo->PriorityClass = BELOW_NORMAL_PRIORITY_CLASS;
|
|
break;
|
|
|
|
case PROCESS_PRIORITY_CLASS_NORMAL:
|
|
BasicInfo->PriorityClass = NORMAL_PRIORITY_CLASS;
|
|
break;
|
|
|
|
case PROCESS_PRIORITY_CLASS_ABOVE_NORMAL:
|
|
BasicInfo->PriorityClass = ABOVE_NORMAL_PRIORITY_CLASS;
|
|
break;
|
|
|
|
case PROCESS_PRIORITY_CLASS_HIGH:
|
|
BasicInfo->PriorityClass = HIGH_PRIORITY_CLASS;
|
|
break;
|
|
|
|
case PROCESS_PRIORITY_CLASS_REALTIME:
|
|
BasicInfo->PriorityClass = REALTIME_PRIORITY_CLASS;
|
|
break;
|
|
|
|
default:
|
|
BasicInfo->PriorityClass = NORMAL_PRIORITY_CLASS;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
SetLastErrorByStatus(Status);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOL
|
|
WINAPI
|
|
SetInformationJobObject(HANDLE hJob,
|
|
JOBOBJECTINFOCLASS JobObjectInformationClass,
|
|
LPVOID lpJobObjectInformation,
|
|
DWORD cbJobObjectInformationLength)
|
|
{
|
|
JOBOBJECT_EXTENDED_LIMIT_INFORMATION ExtendedLimitInfo;
|
|
PJOBOBJECT_BASIC_LIMIT_INFORMATION BasicInfo;
|
|
PVOID ObjectInfo;
|
|
NTSTATUS Status;
|
|
|
|
switch (JobObjectInformationClass)
|
|
{
|
|
case JobObjectBasicLimitInformation:
|
|
if (cbJobObjectInformationLength != sizeof(JOBOBJECT_BASIC_LIMIT_INFORMATION))
|
|
{
|
|
SetLastError(ERROR_BAD_LENGTH);
|
|
return FALSE;
|
|
}
|
|
|
|
ObjectInfo = &ExtendedLimitInfo.BasicLimitInformation;
|
|
BasicInfo = (PJOBOBJECT_BASIC_LIMIT_INFORMATION)ObjectInfo;
|
|
RtlCopyMemory(ObjectInfo, lpJobObjectInformation, cbJobObjectInformationLength);
|
|
break;
|
|
|
|
case JobObjectExtendedLimitInformation:
|
|
if (cbJobObjectInformationLength != sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION))
|
|
{
|
|
SetLastError(ERROR_BAD_LENGTH);
|
|
return FALSE;
|
|
}
|
|
|
|
ObjectInfo = &ExtendedLimitInfo;
|
|
BasicInfo = &ExtendedLimitInfo.BasicLimitInformation;
|
|
RtlCopyMemory(ObjectInfo, lpJobObjectInformation, cbJobObjectInformationLength);
|
|
break;
|
|
|
|
default:
|
|
ObjectInfo = lpJobObjectInformation;
|
|
BasicInfo = NULL;
|
|
break;
|
|
}
|
|
|
|
if (BasicInfo != NULL)
|
|
{
|
|
/* we need to convert the process priority classes in the
|
|
JOBOBJECT_BASIC_LIMIT_INFORMATION structure the same way as
|
|
SetPriorityClass() converts it! */
|
|
switch(BasicInfo->PriorityClass)
|
|
{
|
|
case IDLE_PRIORITY_CLASS:
|
|
BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_IDLE;
|
|
break;
|
|
|
|
case BELOW_NORMAL_PRIORITY_CLASS:
|
|
BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_BELOW_NORMAL;
|
|
break;
|
|
|
|
case NORMAL_PRIORITY_CLASS:
|
|
BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL;
|
|
break;
|
|
|
|
case ABOVE_NORMAL_PRIORITY_CLASS:
|
|
BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_ABOVE_NORMAL;
|
|
break;
|
|
|
|
case HIGH_PRIORITY_CLASS:
|
|
BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_HIGH;
|
|
break;
|
|
|
|
case REALTIME_PRIORITY_CLASS:
|
|
BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_REALTIME;
|
|
break;
|
|
|
|
default:
|
|
BasicInfo->PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
Status = NtSetInformationJobObject(hJob,
|
|
JobObjectInformationClass,
|
|
ObjectInfo,
|
|
cbJobObjectInformationLength);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SetLastErrorByStatus(Status);
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOL
|
|
WINAPI
|
|
TerminateJobObject(HANDLE hJob,
|
|
UINT uExitCode)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
Status = NtTerminateJobObject(hJob, uExitCode);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SetLastErrorByStatus(Status);
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* EOF */
|