mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 01:24:38 +00:00
use tags for pool allocations, and reformat code
svn path=/trunk/; revision=14547
This commit is contained in:
parent
18cff7ccc9
commit
601ea5384b
1 changed files with 441 additions and 420 deletions
|
@ -1,10 +1,10 @@
|
|||
/* $Id$
|
||||
*
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/ps/job.c
|
||||
* PURPOSE: Job Native Functions
|
||||
*
|
||||
*
|
||||
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net) (stubs)
|
||||
* Thomas Weidenmueller <w3seek@reactos.com>
|
||||
*/
|
||||
|
@ -17,281 +17,293 @@
|
|||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
#define TAG_EJOB TAG('E', 'J', 'O', 'B') /* EJOB */
|
||||
|
||||
POBJECT_TYPE EXPORTED PsJobType = NULL;
|
||||
|
||||
LIST_ENTRY PsJobListHead;
|
||||
static FAST_MUTEX PsJobListLock;
|
||||
|
||||
static GENERIC_MAPPING PiJobMapping = {STANDARD_RIGHTS_READ | JOB_OBJECT_QUERY,
|
||||
STANDARD_RIGHTS_WRITE | JOB_OBJECT_ASSIGN_PROCESS | JOB_OBJECT_SET_ATTRIBUTES | JOB_OBJECT_TERMINATE | JOB_OBJECT_SET_SECURITY_ATTRIBUTES,
|
||||
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
|
||||
STANDARD_RIGHTS_ALL | JOB_OBJECT_ALL_ACCESS};
|
||||
static GENERIC_MAPPING PiJobMapping =
|
||||
{
|
||||
STANDARD_RIGHTS_READ | JOB_OBJECT_QUERY,
|
||||
STANDARD_RIGHTS_WRITE | JOB_OBJECT_ASSIGN_PROCESS | JOB_OBJECT_SET_ATTRIBUTES | JOB_OBJECT_TERMINATE | JOB_OBJECT_SET_SECURITY_ATTRIBUTES,
|
||||
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
|
||||
STANDARD_RIGHTS_ALL | JOB_OBJECT_ALL_ACCESS
|
||||
};
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
VOID STDCALL
|
||||
PiDeleteJob(PVOID ObjectBody)
|
||||
PiDeleteJob ( PVOID ObjectBody )
|
||||
{
|
||||
PEJOB Job = (PEJOB)ObjectBody;
|
||||
|
||||
/* remove the reference to the completion port if associated */
|
||||
if(Job->CompletionPort != NULL)
|
||||
{
|
||||
ObDereferenceObject(Job->CompletionPort);
|
||||
}
|
||||
PEJOB Job = (PEJOB)ObjectBody;
|
||||
|
||||
/* unlink the job object */
|
||||
if(Job->JobLinks.Flink != NULL)
|
||||
{
|
||||
ExAcquireFastMutex(&PsJobListLock);
|
||||
RemoveEntryList(&Job->JobLinks);
|
||||
ExReleaseFastMutex(&PsJobListLock);
|
||||
}
|
||||
|
||||
ExDeleteResource(&Job->JobLock);
|
||||
/* remove the reference to the completion port if associated */
|
||||
if(Job->CompletionPort != NULL)
|
||||
{
|
||||
ObDereferenceObject(Job->CompletionPort);
|
||||
}
|
||||
|
||||
/* unlink the job object */
|
||||
if(Job->JobLinks.Flink != NULL)
|
||||
{
|
||||
ExAcquireFastMutex(&PsJobListLock);
|
||||
RemoveEntryList(&Job->JobLinks);
|
||||
ExReleaseFastMutex(&PsJobListLock);
|
||||
}
|
||||
|
||||
ExDeleteResource(&Job->JobLock);
|
||||
}
|
||||
|
||||
VOID INIT_FUNCTION
|
||||
PsInitJobManagment(VOID)
|
||||
PsInitJobManagment ( VOID )
|
||||
{
|
||||
PsJobType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
|
||||
PsJobType = ExAllocatePoolWithTag (
|
||||
NonPagedPool, sizeof(OBJECT_TYPE), TAG_EJOB );
|
||||
|
||||
PsJobType->Tag = TAG('E', 'J', 'O', 'B');
|
||||
PsJobType->TotalObjects = 0;
|
||||
PsJobType->TotalHandles = 0;
|
||||
PsJobType->PeakObjects = 0;
|
||||
PsJobType->PeakHandles = 0;
|
||||
PsJobType->PagedPoolCharge = 0;
|
||||
PsJobType->NonpagedPoolCharge = sizeof(EJOB);
|
||||
PsJobType->Mapping = &PiJobMapping;
|
||||
PsJobType->Dump = NULL;
|
||||
PsJobType->Open = NULL;
|
||||
PsJobType->Close = NULL;
|
||||
PsJobType->Delete = PiDeleteJob;
|
||||
PsJobType->Parse = NULL;
|
||||
PsJobType->Security = NULL;
|
||||
PsJobType->QueryName = NULL;
|
||||
PsJobType->OkayToClose = NULL;
|
||||
PsJobType->Create = NULL;
|
||||
PsJobType->DuplicationNotify = NULL;
|
||||
|
||||
RtlInitUnicodeString(&PsJobType->TypeName, L"Job");
|
||||
|
||||
ObpCreateTypeObject(PsJobType);
|
||||
|
||||
InitializeListHead(&PsJobListHead);
|
||||
ExInitializeFastMutex(&PsJobListLock);
|
||||
PsJobType->Tag = TAG_EJOB;
|
||||
PsJobType->TotalObjects = 0;
|
||||
PsJobType->TotalHandles = 0;
|
||||
PsJobType->PeakObjects = 0;
|
||||
PsJobType->PeakHandles = 0;
|
||||
PsJobType->PagedPoolCharge = 0;
|
||||
PsJobType->NonpagedPoolCharge = sizeof(EJOB);
|
||||
PsJobType->Mapping = &PiJobMapping;
|
||||
PsJobType->Dump = NULL;
|
||||
PsJobType->Open = NULL;
|
||||
PsJobType->Close = NULL;
|
||||
PsJobType->Delete = PiDeleteJob;
|
||||
PsJobType->Parse = NULL;
|
||||
PsJobType->Security = NULL;
|
||||
PsJobType->QueryName = NULL;
|
||||
PsJobType->OkayToClose = NULL;
|
||||
PsJobType->Create = NULL;
|
||||
PsJobType->DuplicationNotify = NULL;
|
||||
|
||||
RtlInitUnicodeString(&PsJobType->TypeName, L"Job");
|
||||
|
||||
ObpCreateTypeObject(PsJobType);
|
||||
|
||||
InitializeListHead(&PsJobListHead);
|
||||
ExInitializeFastMutex(&PsJobListLock);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
PspAssignProcessToJob(PEPROCESS Process,
|
||||
PEJOB Job)
|
||||
PspAssignProcessToJob (
|
||||
PEPROCESS Process,
|
||||
PEJOB Job)
|
||||
{
|
||||
DPRINT("PspAssignProcessToJob() is unimplemented!\n");
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
DPRINT("PspAssignProcessToJob() is unimplemented!\n");
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
PspTerminateJobObject(PEJOB Job,
|
||||
KPROCESSOR_MODE AccessMode,
|
||||
NTSTATUS ExitStatus)
|
||||
PspTerminateJobObject (
|
||||
PEJOB Job,
|
||||
KPROCESSOR_MODE AccessMode,
|
||||
NTSTATUS ExitStatus )
|
||||
{
|
||||
DPRINT("PspTerminateJobObject() is unimplemented!\n");
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
DPRINT("PspTerminateJobObject() is unimplemented!\n");
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtAssignProcessToJobObject(HANDLE JobHandle,
|
||||
HANDLE ProcessHandle)
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtAssignProcessToJobObject (
|
||||
HANDLE JobHandle,
|
||||
HANDLE ProcessHandle)
|
||||
{
|
||||
PEPROCESS Process;
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
NTSTATUS Status;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
/* make sure we're having a handle with enough rights, especially the to
|
||||
terminate the process. otherwise one could abuse the job objects to
|
||||
terminate processes without having rights granted to do so! The reason
|
||||
I open the process handle before the job handle is that a simple test showed
|
||||
that it first complains about a invalid process handle! The other way around
|
||||
would be simpler though... */
|
||||
Status = ObReferenceObjectByHandle(ProcessHandle,
|
||||
PROCESS_TERMINATE,
|
||||
PsProcessType,
|
||||
PreviousMode,
|
||||
(PVOID*)&Process,
|
||||
NULL);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
if(Process->Job == NULL)
|
||||
{
|
||||
PEJOB Job;
|
||||
|
||||
Status = ObReferenceObjectByHandle(JobHandle,
|
||||
JOB_OBJECT_ASSIGN_PROCESS,
|
||||
PsJobType,
|
||||
PreviousMode,
|
||||
(PVOID*)&Job,
|
||||
NULL);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
/* lock the process so we can safely assign the process. Note that in the
|
||||
meanwhile another thread could have assigned this process to a job! */
|
||||
PEPROCESS Process;
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = PsLockProcess(Process, FALSE);
|
||||
if(NT_SUCCESS(Status))
|
||||
PAGED_CODE();
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
/* make sure we're having a handle with enough rights, especially the to
|
||||
terminate the process. otherwise one could abuse the job objects to
|
||||
terminate processes without having rights granted to do so! The reason
|
||||
I open the process handle before the job handle is that a simple test showed
|
||||
that it first complains about a invalid process handle! The other way around
|
||||
would be simpler though... */
|
||||
Status = ObReferenceObjectByHandle(
|
||||
ProcessHandle,
|
||||
PROCESS_TERMINATE,
|
||||
PsProcessType,
|
||||
PreviousMode,
|
||||
(PVOID*)&Process,
|
||||
NULL);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
if(Process->Job == NULL)
|
||||
{
|
||||
PEJOB Job;
|
||||
|
||||
Status = ObReferenceObjectByHandle(
|
||||
JobHandle,
|
||||
JOB_OBJECT_ASSIGN_PROCESS,
|
||||
PsJobType,
|
||||
PreviousMode,
|
||||
(PVOID*)&Job,
|
||||
NULL);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
/* lock the process so we can safely assign the process. Note that in the
|
||||
meanwhile another thread could have assigned this process to a job! */
|
||||
|
||||
Status = PsLockProcess(Process, FALSE);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
if(Process->Job == NULL && Process->SessionId == Job->SessionId)
|
||||
{
|
||||
/* Just store the pointer to the job object in the process, we'll
|
||||
assign it later. The reason we can't do this here is that locking
|
||||
the job object might require it to wait, which is a bad thing
|
||||
while holding the process lock! */
|
||||
Process->Job = Job;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* process is already assigned to a job or session id differs! */
|
||||
Status = STATUS_ACCESS_DENIED;
|
||||
}
|
||||
PsUnlockProcess(Process);
|
||||
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
/* let's actually assign the process to the job as we're not holding
|
||||
the process lock anymore! */
|
||||
Status = PspAssignProcessToJob(Process, Job);
|
||||
}
|
||||
}
|
||||
|
||||
ObDereferenceObject(Job);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(Process->Job == NULL && Process->SessionId == Job->SessionId)
|
||||
{
|
||||
/* Just store the pointer to the job object in the process, we'll
|
||||
assign it later. The reason we can't do this here is that locking
|
||||
the job object might require it to wait, which is a bad thing
|
||||
while holding the process lock! */
|
||||
Process->Job = Job;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* process is already assigned to a job or session id differs! */
|
||||
Status = STATUS_ACCESS_DENIED;
|
||||
}
|
||||
PsUnlockProcess(Process);
|
||||
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
/* let's actually assign the process to the job as we're not holding
|
||||
the process lock anymore! */
|
||||
Status = PspAssignProcessToJob(Process, Job);
|
||||
}
|
||||
}
|
||||
|
||||
ObDereferenceObject(Job);
|
||||
}
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* process is already assigned to a job or session id differs! */
|
||||
Status = STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
|
||||
return Status;
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtCreateJobObject(PHANDLE JobHandle,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes)
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtCreateJobObject (
|
||||
PHANDLE JobHandle,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes )
|
||||
{
|
||||
HANDLE hJob;
|
||||
PEJOB Job;
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
PEPROCESS CurrentProcess;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
PAGED_CODE();
|
||||
HANDLE hJob;
|
||||
PEJOB Job;
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
PEPROCESS CurrentProcess;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
CurrentProcess = PsGetCurrentProcess();
|
||||
PAGED_CODE();
|
||||
|
||||
/* check for valid buffers */
|
||||
if(PreviousMode == UserMode)
|
||||
{
|
||||
_SEH_TRY
|
||||
{
|
||||
/* probe with 32bit alignment */
|
||||
ProbeForWrite(JobHandle,
|
||||
sizeof(HANDLE),
|
||||
sizeof(ULONG));
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
CurrentProcess = PsGetCurrentProcess();
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
/* check for valid buffers */
|
||||
if(PreviousMode == UserMode)
|
||||
{
|
||||
return Status;
|
||||
_SEH_TRY
|
||||
{
|
||||
/* probe with 32bit alignment */
|
||||
ProbeForWrite(JobHandle,
|
||||
sizeof(HANDLE),
|
||||
sizeof(ULONG));
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Status = ObCreateObject(PreviousMode,
|
||||
PsJobType,
|
||||
ObjectAttributes,
|
||||
PreviousMode,
|
||||
NULL,
|
||||
sizeof(EJOB),
|
||||
0,
|
||||
0,
|
||||
(PVOID*)&Job);
|
||||
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
/* FIXME - Zero all fields as we don't yet implement all of them */
|
||||
RtlZeroMemory(Job, sizeof(EJOB));
|
||||
|
||||
/* make sure that early destruction doesn't attempt to remove the object from
|
||||
the list before it even gets added! */
|
||||
Job->JobLinks.Flink = NULL;
|
||||
|
||||
/* setup the job object */
|
||||
InitializeListHead(&Job->ProcessListHead);
|
||||
Job->SessionId = CurrentProcess->SessionId; /* inherit the session id from the caller */
|
||||
|
||||
Status = ExInitializeResource(&Job->JobLock);
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to initialize job lock!!!\n");
|
||||
ObDereferenceObject(Job);
|
||||
return Status;
|
||||
}
|
||||
KeInitializeEvent(&Job->Event, NotificationEvent, FALSE);
|
||||
|
||||
/* link the object into the global job list */
|
||||
ExAcquireFastMutex(&PsJobListLock);
|
||||
InsertTailList(&PsJobListHead, &Job->JobLinks);
|
||||
ExReleaseFastMutex(&PsJobListLock);
|
||||
|
||||
Status = ObInsertObject(Job,
|
||||
NULL,
|
||||
DesiredAccess,
|
||||
0,
|
||||
NULL,
|
||||
&hJob);
|
||||
|
||||
Status = ObCreateObject(PreviousMode,
|
||||
PsJobType,
|
||||
ObjectAttributes,
|
||||
PreviousMode,
|
||||
NULL,
|
||||
sizeof(EJOB),
|
||||
0,
|
||||
0,
|
||||
(PVOID*)&Job);
|
||||
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
/* pass the handle back to the caller */
|
||||
_SEH_TRY
|
||||
{
|
||||
/* NOTE: if the caller passed invalid buffers to receive the handle it's his
|
||||
own fault! the object will still be created and live... It's possible
|
||||
to find the handle using ObFindHandleForObject()! */
|
||||
*JobHandle = hJob;
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
/* FIXME - Zero all fields as we don't yet implement all of them */
|
||||
RtlZeroMemory(Job, sizeof(EJOB));
|
||||
|
||||
/* make sure that early destruction doesn't attempt to remove the object from
|
||||
the list before it even gets added! */
|
||||
Job->JobLinks.Flink = NULL;
|
||||
|
||||
/* setup the job object */
|
||||
InitializeListHead(&Job->ProcessListHead);
|
||||
Job->SessionId = CurrentProcess->SessionId; /* inherit the session id from the caller */
|
||||
|
||||
Status = ExInitializeResource(&Job->JobLock);
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to initialize job lock!!!\n");
|
||||
ObDereferenceObject(Job);
|
||||
return Status;
|
||||
}
|
||||
KeInitializeEvent(&Job->Event, NotificationEvent, FALSE);
|
||||
|
||||
/* link the object into the global job list */
|
||||
ExAcquireFastMutex(&PsJobListLock);
|
||||
InsertTailList(&PsJobListHead, &Job->JobLinks);
|
||||
ExReleaseFastMutex(&PsJobListLock);
|
||||
|
||||
Status = ObInsertObject(Job,
|
||||
NULL,
|
||||
DesiredAccess,
|
||||
0,
|
||||
NULL,
|
||||
&hJob);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
/* pass the handle back to the caller */
|
||||
_SEH_TRY
|
||||
{
|
||||
/* NOTE: if the caller passed invalid buffers to receive the handle it's his
|
||||
own fault! the object will still be created and live... It's possible
|
||||
to find the handle using ObFindHandleForObject()! */
|
||||
*JobHandle = hJob;
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
|
@ -300,207 +312,203 @@ NtCreateJobObject(PHANDLE JobHandle,
|
|||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtIsProcessInJob(IN HANDLE ProcessHandle,
|
||||
IN HANDLE JobHandle OPTIONAL)
|
||||
NtIsProcessInJob (
|
||||
IN HANDLE ProcessHandle,
|
||||
IN HANDLE JobHandle OPTIONAL )
|
||||
{
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
PEPROCESS Process;
|
||||
NTSTATUS Status;
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
Status = ObReferenceObjectByHandle(ProcessHandle,
|
||||
PROCESS_QUERY_INFORMATION,
|
||||
PsProcessType,
|
||||
PreviousMode,
|
||||
(PVOID*)&Process,
|
||||
NULL);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
/* FIXME - make sure the job object doesn't get exchanged or deleted while trying to
|
||||
reference it, e.g. by locking it somehow until it is referenced... */
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
PEPROCESS Process;
|
||||
NTSTATUS Status;
|
||||
|
||||
PEJOB ProcessJob = Process->Job;
|
||||
|
||||
if(ProcessJob != NULL)
|
||||
{
|
||||
if(JobHandle == NULL)
|
||||
{
|
||||
/* the process is assigned to a job */
|
||||
Status = STATUS_PROCESS_IN_JOB;
|
||||
}
|
||||
else /* JobHandle != NULL */
|
||||
{
|
||||
PEJOB JobObject;
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
/* get the job object and compare the object pointer with the one assigned to the process */
|
||||
Status = ObReferenceObjectByHandle(JobHandle,
|
||||
JOB_OBJECT_QUERY,
|
||||
PsJobType,
|
||||
PreviousMode,
|
||||
(PVOID*)&JobObject,
|
||||
NULL);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
Status = ((ProcessJob == JobObject) ? STATUS_PROCESS_IN_JOB : STATUS_PROCESS_NOT_IN_JOB);
|
||||
ObDereferenceObject(JobObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* the process is not assigned to any job */
|
||||
Status = STATUS_PROCESS_NOT_IN_JOB;
|
||||
}
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
PAGED_CODE();
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtOpenJobObject(PHANDLE JobHandle,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes)
|
||||
{
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
HANDLE hJob;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
/* check for valid buffers */
|
||||
if(PreviousMode == UserMode)
|
||||
{
|
||||
_SEH_TRY
|
||||
{
|
||||
/* probe with 32bit alignment */
|
||||
ProbeForWrite(JobHandle,
|
||||
sizeof(HANDLE),
|
||||
sizeof(ULONG));
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
Status = ObOpenObjectByName(ObjectAttributes,
|
||||
PsJobType,
|
||||
NULL,
|
||||
PreviousMode,
|
||||
DesiredAccess,
|
||||
NULL,
|
||||
&hJob);
|
||||
Status = ObReferenceObjectByHandle(
|
||||
ProcessHandle,
|
||||
PROCESS_QUERY_INFORMATION,
|
||||
PsProcessType,
|
||||
PreviousMode,
|
||||
(PVOID*)&Process,
|
||||
NULL);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
_SEH_TRY
|
||||
{
|
||||
*JobHandle = hJob;
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
/* FIXME - make sure the job object doesn't get exchanged or deleted while trying to
|
||||
reference it, e.g. by locking it somehow until it is referenced... */
|
||||
|
||||
PEJOB ProcessJob = Process->Job;
|
||||
|
||||
if(ProcessJob != NULL)
|
||||
{
|
||||
if(JobHandle == NULL)
|
||||
{
|
||||
/* the process is assigned to a job */
|
||||
Status = STATUS_PROCESS_IN_JOB;
|
||||
}
|
||||
else /* JobHandle != NULL */
|
||||
{
|
||||
PEJOB JobObject;
|
||||
|
||||
/* get the job object and compare the object pointer with the one assigned to the process */
|
||||
Status = ObReferenceObjectByHandle(JobHandle,
|
||||
JOB_OBJECT_QUERY,
|
||||
PsJobType,
|
||||
PreviousMode,
|
||||
(PVOID*)&JobObject,
|
||||
NULL);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
Status = ((ProcessJob == JobObject) ? STATUS_PROCESS_IN_JOB : STATUS_PROCESS_NOT_IN_JOB);
|
||||
ObDereferenceObject(JobObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* the process is not assigned to any job */
|
||||
Status = STATUS_PROCESS_NOT_IN_JOB;
|
||||
}
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtQueryInformationJobObject(HANDLE JobHandle,
|
||||
JOBOBJECTINFOCLASS JobInformationClass,
|
||||
PVOID JobInformation,
|
||||
ULONG JobInformationLength,
|
||||
PULONG ReturnLength)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtSetInformationJobObject(HANDLE JobHandle,
|
||||
JOBOBJECTINFOCLASS JobInformationClass,
|
||||
PVOID JobInformation,
|
||||
ULONG JobInformationLength)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtTerminateJobObject(HANDLE JobHandle,
|
||||
NTSTATUS ExitStatus)
|
||||
{
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
PEJOB Job;
|
||||
NTSTATUS Status;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
Status = ObReferenceObjectByHandle(JobHandle,
|
||||
JOB_OBJECT_TERMINATE,
|
||||
PsJobType,
|
||||
PreviousMode,
|
||||
(PVOID*)&Job,
|
||||
NULL);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
Status = PspTerminateJobObject(Job,
|
||||
PreviousMode,
|
||||
ExitStatus);
|
||||
ObDereferenceObject(Job);
|
||||
}
|
||||
|
||||
return Status;
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
PVOID
|
||||
STDCALL
|
||||
PsGetJobLock(PEJOB Job)
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtOpenJobObject (
|
||||
PHANDLE JobHandle,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes)
|
||||
{
|
||||
ASSERT(Job);
|
||||
return (PVOID)&Job->JobLock;
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
HANDLE hJob;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
/* check for valid buffers */
|
||||
if(PreviousMode == UserMode)
|
||||
{
|
||||
_SEH_TRY
|
||||
{
|
||||
/* probe with 32bit alignment */
|
||||
ProbeForWrite(JobHandle,
|
||||
sizeof(HANDLE),
|
||||
sizeof(ULONG));
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
Status = ObOpenObjectByName(ObjectAttributes,
|
||||
PsJobType,
|
||||
NULL,
|
||||
PreviousMode,
|
||||
DesiredAccess,
|
||||
NULL,
|
||||
&hJob);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
_SEH_TRY
|
||||
{
|
||||
*JobHandle = hJob;
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtQueryInformationJobObject (
|
||||
HANDLE JobHandle,
|
||||
JOBOBJECTINFOCLASS JobInformationClass,
|
||||
PVOID JobInformation,
|
||||
ULONG JobInformationLength,
|
||||
PULONG ReturnLength )
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtSetInformationJobObject (
|
||||
HANDLE JobHandle,
|
||||
JOBOBJECTINFOCLASS JobInformationClass,
|
||||
PVOID JobInformation,
|
||||
ULONG JobInformationLength)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtTerminateJobObject (
|
||||
HANDLE JobHandle,
|
||||
NTSTATUS ExitStatus )
|
||||
{
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
PEJOB Job;
|
||||
NTSTATUS Status;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
Status = ObReferenceObjectByHandle(
|
||||
JobHandle,
|
||||
JOB_OBJECT_TERMINATE,
|
||||
PsJobType,
|
||||
PreviousMode,
|
||||
(PVOID*)&Job,
|
||||
NULL);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
Status = PspTerminateJobObject(
|
||||
Job,
|
||||
PreviousMode,
|
||||
ExitStatus);
|
||||
ObDereferenceObject(Job);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
|
@ -509,10 +517,22 @@ PsGetJobLock(PEJOB Job)
|
|||
*/
|
||||
PVOID
|
||||
STDCALL
|
||||
PsGetJobSessionId(PEJOB Job)
|
||||
PsGetJobLock ( PEJOB Job )
|
||||
{
|
||||
ASSERT(Job);
|
||||
return (PVOID)Job->SessionId;
|
||||
ASSERT(Job);
|
||||
return (PVOID)&Job->JobLock;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
PVOID
|
||||
STDCALL
|
||||
PsGetJobSessionId ( PEJOB Job )
|
||||
{
|
||||
ASSERT(Job);
|
||||
return (PVOID)Job->SessionId;
|
||||
}
|
||||
|
||||
|
||||
|
@ -521,10 +541,10 @@ PsGetJobSessionId(PEJOB Job)
|
|||
*/
|
||||
ULONG
|
||||
STDCALL
|
||||
PsGetJobUIRestrictionsClass(PEJOB Job)
|
||||
PsGetJobUIRestrictionsClass ( PEJOB Job )
|
||||
{
|
||||
ASSERT(Job);
|
||||
return Job->UIRestrictionsClass;
|
||||
ASSERT(Job);
|
||||
return Job->UIRestrictionsClass;
|
||||
}
|
||||
|
||||
|
||||
|
@ -533,12 +553,13 @@ PsGetJobUIRestrictionsClass(PEJOB Job)
|
|||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
PsSetJobUIRestrictionsClass(PEJOB Job,
|
||||
ULONG UIRestrictionsClass)
|
||||
PsSetJobUIRestrictionsClass (
|
||||
PEJOB Job,
|
||||
ULONG UIRestrictionsClass)
|
||||
{
|
||||
ASSERT(Job);
|
||||
InterlockedExchangeUL(&Job->UIRestrictionsClass, UIRestrictionsClass);
|
||||
/* FIXME - walk through the job process list and update the restrictions? */
|
||||
ASSERT(Job);
|
||||
InterlockedExchangeUL(&Job->UIRestrictionsClass, UIRestrictionsClass);
|
||||
/* FIXME - walk through the job process list and update the restrictions? */
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
Loading…
Reference in a new issue