reactos/ntoskrnl/ex/mutant.c

369 lines
11 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel
* FILE: ntoskrnl/ex/mutant.c
* PURPOSE: Executive Management of Mutants
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
* Thomas Weidenmueller
*/
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
#if defined (ALLOC_PRAGMA)
#pragma alloc_text(INIT, ExpInitializeMutantImplementation)
#endif
/* DATA **********************************************************************/
POBJECT_TYPE ExMutantObjectType = NULL;
GENERIC_MAPPING ExpMutantMapping =
{
STANDARD_RIGHTS_READ | MUTANT_QUERY_STATE,
STANDARD_RIGHTS_WRITE,
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
MUTANT_ALL_ACCESS
};
static const INFORMATION_CLASS_INFO ExMutantInfoClass[] =
{
/* MutantBasicInformation */
ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY),
};
/* FUNCTIONS *****************************************************************/
VOID
NTAPI
ExpDeleteMutant(PVOID ObjectBody)
{
DPRINT("ExpDeleteMutant(ObjectBody 0x%p)\n", ObjectBody);
/* Make sure to release the Mutant */
KeReleaseMutant((PKMUTANT)ObjectBody,
MUTANT_INCREMENT,
TRUE,
FALSE);
}
BOOLEAN
INIT_FUNCTION
NTAPI
ExpInitializeMutantImplementation(VOID)
{
OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
UNICODE_STRING Name;
NTSTATUS Status;
DPRINT("Creating Mutant Object Type\n");
/* Create the Event Pair Object Type */
RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
RtlInitUnicodeString(&Name, L"Mutant");
ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(KMUTANT);
ObjectTypeInitializer.GenericMapping = ExpMutantMapping;
ObjectTypeInitializer.PoolType = NonPagedPool;
ObjectTypeInitializer.DeleteProcedure = ExpDeleteMutant;
ObjectTypeInitializer.ValidAccessMask = MUTANT_ALL_ACCESS;
ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
Status = ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ExMutantObjectType);
if (!NT_SUCCESS(Status)) return FALSE;
return TRUE;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
NtCreateMutant(OUT PHANDLE MutantHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN BOOLEAN InitialOwner)
{
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
HANDLE hMutant;
PKMUTANT Mutant;
NTSTATUS Status;
PAGED_CODE();
DPRINT("NtCreateMutant(0x%p, 0x%x, 0x%p)\n",
MutantHandle, DesiredAccess, ObjectAttributes);
/* Check if we were called from user-mode */
if (PreviousMode != KernelMode)
{
/* Enter SEH Block */
_SEH2_TRY
{
/* Check handle pointer */
ProbeForWriteHandle(MutantHandle);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Return the exception code */
_SEH2_YIELD(return _SEH2_GetExceptionCode());
}
_SEH2_END;
}
/* Create the Mutant Object*/
Status = ObCreateObject(PreviousMode,
ExMutantObjectType,
ObjectAttributes,
PreviousMode,
NULL,
sizeof(KMUTANT),
0,
0,
(PVOID*)&Mutant);
/* Check for success */
if(NT_SUCCESS(Status))
{
/* Initialize the Kernel Mutant */
DPRINT("Initializing the Mutant\n");
KeInitializeMutant(Mutant, InitialOwner);
/* Insert the Object */
Status = ObInsertObject((PVOID)Mutant,
NULL,
DesiredAccess,
0,
NULL,
&hMutant);
/* Check for success */
if (NT_SUCCESS(Status))
{
/* Enter SEH for return */
_SEH2_TRY
{
/* Return the handle to the caller */
*MutantHandle = hMutant;
}
_SEH2_EXCEPT(ExSystemExceptionFilter())
{
/* Get the exception code */
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
}
}
/* Return Status */
return Status;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
NtOpenMutant(OUT PHANDLE MutantHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes)
{
HANDLE hMutant;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status;
PAGED_CODE();
DPRINT("NtOpenMutant(0x%p, 0x%x, 0x%p)\n",
MutantHandle, DesiredAccess, ObjectAttributes);
/* Check if we were called from user-mode */
if (PreviousMode != KernelMode)
{
/* Enter SEH Block */
_SEH2_TRY
{
/* Check handle pointer */
ProbeForWriteHandle(MutantHandle);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Return the exception code */
_SEH2_YIELD(return _SEH2_GetExceptionCode());
}
_SEH2_END;
}
/* Open the Object */
Status = ObOpenObjectByName(ObjectAttributes,
ExMutantObjectType,
PreviousMode,
NULL,
DesiredAccess,
NULL,
&hMutant);
/* Check for success */
if(NT_SUCCESS(Status))
{
/* Enter SEH for return */
_SEH2_TRY
{
/* Return the handle to the caller */
*MutantHandle = hMutant;
}
_SEH2_EXCEPT(ExSystemExceptionFilter())
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
}
/* Return Status */
return Status;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
NtQueryMutant(IN HANDLE MutantHandle,
IN MUTANT_INFORMATION_CLASS MutantInformationClass,
OUT PVOID MutantInformation,
IN ULONG MutantInformationLength,
OUT PULONG ResultLength OPTIONAL)
{
PKMUTANT Mutant;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status;
PMUTANT_BASIC_INFORMATION BasicInfo =
(PMUTANT_BASIC_INFORMATION)MutantInformation;
PAGED_CODE();
/* Check buffers and parameters */
Status = DefaultQueryInfoBufferCheck(MutantInformationClass,
ExMutantInfoClass,
sizeof(ExMutantInfoClass) /
sizeof(ExMutantInfoClass[0]),
MutantInformation,
MutantInformationLength,
ResultLength,
NULL,
PreviousMode);
if(!NT_SUCCESS(Status))
{
DPRINT("NtQueryMutant() failed, Status: 0x%x\n", Status);
return Status;
}
/* Open the Object */
Status = ObReferenceObjectByHandle(MutantHandle,
MUTANT_QUERY_STATE,
ExMutantObjectType,
PreviousMode,
(PVOID*)&Mutant,
NULL);
/* Check for Status */
if (NT_SUCCESS(Status))
{
/* Enter SEH Block for return */
_SEH2_TRY
{
/* Fill out the Basic Information Requested */
DPRINT("Returning Mutant Information\n");
BasicInfo->CurrentCount = KeReadStateMutant(Mutant);
BasicInfo->OwnedByCaller = (Mutant->OwnerThread ==
KeGetCurrentThread());
BasicInfo->AbandonedState = Mutant->Abandoned;
/* Return the Result Length if requested */
if (ResultLength) *ResultLength = sizeof(MUTANT_BASIC_INFORMATION);
}
_SEH2_EXCEPT(ExSystemExceptionFilter())
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
/* Release the Object */
ObDereferenceObject(Mutant);
}
/* Return Status */
return Status;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
NtReleaseMutant(IN HANDLE MutantHandle,
IN PLONG PreviousCount OPTIONAL)
{
PKMUTANT Mutant;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status;
PAGED_CODE();
DPRINT("NtReleaseMutant(MutantHandle 0x%p PreviousCount 0x%p)\n",
MutantHandle,
PreviousCount);
/* Check if we were called from user-mode */
if ((PreviousCount) && (PreviousMode != KernelMode))
{
/* Entry SEH Block */
_SEH2_TRY
{
/* Make sure the state pointer is valid */
ProbeForWriteLong(PreviousCount);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Return the exception code */
_SEH2_YIELD(return _SEH2_GetExceptionCode());
}
_SEH2_END;
}
/* Open the Object */
Status = ObReferenceObjectByHandle(MutantHandle,
0, /* No access rights required */
ExMutantObjectType,
PreviousMode,
(PVOID*)&Mutant,
NULL);
/* Check for Success and release if such */
if (NT_SUCCESS(Status))
{
/*
* Release the mutant. doing so might raise an exception which we're
* required to catch!
*/
_SEH2_TRY
{
/* Release the mutant */
LONG Prev = KeReleaseMutant(Mutant,
MUTANT_INCREMENT,
FALSE,
FALSE);
/* Return the previous count if requested */
if (PreviousCount) *PreviousCount = Prev;
}
_SEH2_EXCEPT(ExSystemExceptionFilter())
{
/* Get the exception code */
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
/* Dereference it */
ObDereferenceObject(Mutant);
}
/* Return Status */
return Status;
}
/* EOF */