-/* $Id:$
- *
+/*
* COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
+ * PROJECT: ReactOS Kernel
* FILE: ntoskrnl/ex/mutant.c
- * PURPOSE: Synchronization primitives
- *
- * PROGRAMMERS: David Welch (welch@cwcom.net)
+ * PURPOSE: Executive Management of Mutants
+ * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
+ * Thomas Weidenmueller
*/
/* INCLUDES *****************************************************************/
#define NDEBUG
#include <internal/debug.h>
+#if defined (ALLOC_PRAGMA)
+#pragma alloc_text(INIT, ExpInitializeMutantImplementation)
+#endif
+
+/* DATA **********************************************************************/
+
POBJECT_TYPE ExMutantObjectType = NULL;
-static GENERIC_MAPPING ExpMutantMapping = {
- STANDARD_RIGHTS_READ | SYNCHRONIZE | MUTANT_QUERY_STATE,
- STANDARD_RIGHTS_WRITE | SYNCHRONIZE,
- STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | MUTANT_QUERY_STATE,
- MUTANT_ALL_ACCESS};
+GENERIC_MAPPING ExpMutantMapping =
+{
+ STANDARD_RIGHTS_READ | SYNCHRONIZE | MUTANT_QUERY_STATE,
+ STANDARD_RIGHTS_WRITE | SYNCHRONIZE,
+ STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | MUTANT_QUERY_STATE,
+ MUTANT_ALL_ACCESS
+};
static const INFORMATION_CLASS_INFO ExMutantInfoClass[] =
{
- ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* MutantBasicInformation */
+ /* MutantBasicInformation */
+ ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY),
};
/* FUNCTIONS *****************************************************************/
-
-NTSTATUS STDCALL
-ExpCreateMutant(PVOID ObjectBody,
- PVOID Parent,
- PWSTR RemainingPath,
- POBJECT_ATTRIBUTES ObjectAttributes)
-{
- DPRINT("NtpCreateMutant(ObjectBody %x, Parent %x, RemainingPath %S)\n",
- ObjectBody, Parent, RemainingPath);
-
- if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
- {
- return(STATUS_UNSUCCESSFUL);
- }
-
- return(STATUS_SUCCESS);
-}
-
-
-VOID STDCALL
+VOID
+NTAPI
ExpDeleteMutant(PVOID ObjectBody)
{
- DPRINT("NtpDeleteMutant(ObjectBody %x)\n", ObjectBody);
+ DPRINT("ExpDeleteMutant(ObjectBody 0x%p)\n", ObjectBody);
- KeReleaseMutant((PKMUTANT)ObjectBody,
- MUTANT_INCREMENT,
- TRUE,
- FALSE);
+ /* Make sure to release the Mutant */
+ KeReleaseMutant((PKMUTANT)ObjectBody,
+ MUTANT_INCREMENT,
+ TRUE,
+ FALSE);
}
-
-VOID INIT_FUNCTION
+VOID
+INIT_FUNCTION
+NTAPI
ExpInitializeMutantImplementation(VOID)
{
- ExMutantObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
-
- RtlpCreateUnicodeString(&ExMutantObjectType->TypeName, L"Mutant", NonPagedPool);
-
- ExMutantObjectType->Tag = TAG('M', 'T', 'N', 'T');
- ExMutantObjectType->PeakObjects = 0;
- ExMutantObjectType->PeakHandles = 0;
- ExMutantObjectType->TotalObjects = 0;
- ExMutantObjectType->TotalHandles = 0;
- ExMutantObjectType->PagedPoolCharge = 0;
- ExMutantObjectType->NonpagedPoolCharge = sizeof(KMUTANT);
- ExMutantObjectType->Mapping = &ExpMutantMapping;
- ExMutantObjectType->Dump = NULL;
- ExMutantObjectType->Open = NULL;
- ExMutantObjectType->Close = NULL;
- ExMutantObjectType->Delete = ExpDeleteMutant;
- ExMutantObjectType->Parse = NULL;
- ExMutantObjectType->Security = NULL;
- ExMutantObjectType->QueryName = NULL;
- ExMutantObjectType->OkayToClose = NULL;
- ExMutantObjectType->Create = ExpCreateMutant;
- ExMutantObjectType->DuplicationNotify = NULL;
-
- ObpCreateTypeObject(ExMutantObjectType);
+ OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
+ UNICODE_STRING Name;
+ 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;
+ ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ExMutantObjectType);
}
-
/*
* @implemented
*/
-NTSTATUS STDCALL
+NTSTATUS
+NTAPI
NtCreateMutant(OUT PHANDLE MutantHandle,
- IN ACCESS_MASK DesiredAccess,
- IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
- IN BOOLEAN InitialOwner)
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+ IN BOOLEAN InitialOwner)
{
- KPROCESSOR_MODE PreviousMode;
- HANDLE hMutant;
- PKMUTEX Mutant;
- NTSTATUS Status = STATUS_SUCCESS;
-
- PreviousMode = ExGetPreviousMode();
-
- if(PreviousMode == UserMode)
- {
- _SEH_TRY
- {
- ProbeForWrite(MutantHandle,
- sizeof(HANDLE),
- sizeof(ULONG));
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- if(!NT_SUCCESS(Status))
- {
- return Status;
- }
- }
-
- Status = ObCreateObject(PreviousMode,
- ExMutantObjectType,
- ObjectAttributes,
- PreviousMode,
- NULL,
- sizeof(KMUTANT),
- 0,
- 0,
- (PVOID*)&Mutant);
- if(NT_SUCCESS(Status))
- {
- KeInitializeMutant(Mutant,
- InitialOwner);
-
- Status = ObInsertObject((PVOID)Mutant,
- NULL,
- DesiredAccess,
- 0,
- NULL,
- &hMutant);
- ObDereferenceObject(Mutant);
-
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ HANDLE hMutant;
+ PKMUTANT Mutant;
+ NTSTATUS Status = STATUS_SUCCESS;
+ 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 */
+ _SEH_TRY
+ {
+ /* Check handle pointer */
+ ProbeForWriteHandle(MutantHandle);
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ /* Bail out if pointer was invalid */
+ if(!NT_SUCCESS(Status)) return Status;
+ }
+
+ /* Create the Mutant Object*/
+ Status = ObCreateObject(PreviousMode,
+ ExMutantObjectType,
+ ObjectAttributes,
+ PreviousMode,
+ NULL,
+ sizeof(KMUTANT),
+ 0,
+ 0,
+ (PVOID*)&Mutant);
+
+ /* Check for success */
if(NT_SUCCESS(Status))
{
- _SEH_TRY
- {
- *MutantHandle = hMutant;
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
+ /* Initalize the Kernel Mutant */
+ DPRINT("Initializing the Mutant\n");
+ KeInitializeMutant(Mutant, InitialOwner);
+
+ /* Insert the Object */
+ Status = ObInsertObject((PVOID)Mutant,
+ NULL,
+ DesiredAccess,
+ 0,
+ NULL,
+ &hMutant);
+ ObDereferenceObject(Mutant);
+
+ /* Check for success */
+ if(NT_SUCCESS(Status))
+ {
+ /* Enter SEH for return */
+ _SEH_TRY
+ {
+ /* Return the handle to the caller */
+ *MutantHandle = hMutant;
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
}
- }
- return Status;
+ /* Return Status */
+ return Status;
}
-
/*
* @implemented
*/
-NTSTATUS STDCALL
+NTSTATUS
+NTAPI
NtOpenMutant(OUT PHANDLE MutantHandle,
- IN ACCESS_MASK DesiredAccess,
- IN POBJECT_ATTRIBUTES ObjectAttributes)
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes)
{
- HANDLE hMutant;
- KPROCESSOR_MODE PreviousMode;
- NTSTATUS Status = STATUS_SUCCESS;
-
- DPRINT("NtOpenMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle, DesiredAccess, ObjectAttributes);
-
- PreviousMode = ExGetPreviousMode();
-
- if(PreviousMode == UserMode)
- {
- _SEH_TRY
+ HANDLE hMutant;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ NTSTATUS Status = STATUS_SUCCESS;
+ 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)
{
- ProbeForWrite(MutantHandle,
- sizeof(HANDLE),
- sizeof(ULONG));
+ /* Enter SEH Block */
+ _SEH_TRY
+ {
+ /* Check handle pointer */
+ ProbeForWriteHandle(MutantHandle);
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ /* Bail out if pointer was invalid */
+ if(!NT_SUCCESS(Status)) return Status;
}
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- if(!NT_SUCCESS(Status))
- {
- return Status;
- }
- }
-
- Status = ObOpenObjectByName(ObjectAttributes,
- ExMutantObjectType,
- NULL,
- PreviousMode,
- DesiredAccess,
- NULL,
- &hMutant);
-
- if(NT_SUCCESS(Status))
- {
- _SEH_TRY
- {
- *MutantHandle = hMutant;
- }
- _SEH_HANDLE
+ /* Open the Object */
+ Status = ObOpenObjectByName(ObjectAttributes,
+ ExMutantObjectType,
+ NULL,
+ PreviousMode,
+ DesiredAccess,
+ NULL,
+ &hMutant);
+
+ /* Check for success */
+ if(NT_SUCCESS(Status))
{
- Status = _SEH_GetExceptionCode();
+ /* Enter SEH for return */
+ _SEH_TRY
+ {
+ /* Return the handle to the caller */
+ *MutantHandle = hMutant;
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
}
- _SEH_END;
- }
- return Status;
+ /* Return Status */
+ return Status;
}
-
/*
* @implemented
*/
-NTSTATUS STDCALL
+NTSTATUS
+NTAPI
NtQueryMutant(IN HANDLE MutantHandle,
- IN MUTANT_INFORMATION_CLASS MutantInformationClass,
- OUT PVOID MutantInformation,
- IN ULONG MutantInformationLength,
- OUT PULONG ResultLength OPTIONAL)
+ IN MUTANT_INFORMATION_CLASS MutantInformationClass,
+ OUT PVOID MutantInformation,
+ IN ULONG MutantInformationLength,
+ OUT PULONG ResultLength OPTIONAL)
{
- PKMUTANT Mutant;
- KPROCESSOR_MODE PreviousMode;
- NTSTATUS Status = STATUS_SUCCESS;
-
- PreviousMode = ExGetPreviousMode();
-
- DefaultQueryInfoBufferCheck(MutantInformationClass,
- ExMutantInfoClass,
- MutantInformation,
- MutantInformationLength,
- ResultLength,
- PreviousMode,
- &Status);
- if(!NT_SUCCESS(Status))
- {
- DPRINT1("NtQueryMutant() failed, Status: 0x%x\n", Status);
- return Status;
- }
-
- Status = ObReferenceObjectByHandle(MutantHandle,
- MUTANT_QUERY_STATE,
- ExMutantObjectType,
- PreviousMode,
- (PVOID*)&Mutant,
- NULL);
- if(NT_SUCCESS(Status))
- {
- switch(MutantInformationClass)
- {
- case MutantBasicInformation:
- {
- PMUTANT_BASIC_INFORMATION BasicInfo = (PMUTANT_BASIC_INFORMATION)MutantInformation;
+ PKMUTANT Mutant;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ NTSTATUS Status = STATUS_SUCCESS;
+ 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,
+ 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 */
_SEH_TRY
{
- BasicInfo->Count = KeReadStateMutant(Mutant);
- BasicInfo->Owned = (Mutant->OwnerThread != NULL);
- BasicInfo->Abandoned = Mutant->Abandoned;
-
- if(ResultLength != NULL)
- {
- *ResultLength = sizeof(MUTANT_BASIC_INFORMATION);
- }
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- break;
- }
-
- default:
- Status = STATUS_NOT_IMPLEMENTED;
- break;
- }
-
- ObDereferenceObject(Mutant);
- }
+ /* 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);
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ /* Release the Object */
+ ObDereferenceObject(Mutant);
+ }
- return Status;
+ /* Return Status */
+ return Status;
}
-
/*
* @implemented
*/
-NTSTATUS STDCALL
+NTSTATUS
+NTAPI
NtReleaseMutant(IN HANDLE MutantHandle,
- IN PLONG PreviousCount OPTIONAL)
+ IN PLONG PreviousCount OPTIONAL)
{
- PKMUTANT Mutant;
- KPROCESSOR_MODE PreviousMode;
- NTSTATUS Status = STATUS_SUCCESS;
-
- DPRINT("NtReleaseMutant(MutantHandle 0%x PreviousCount 0%x)\n",
- MutantHandle, PreviousCount);
-
- PreviousMode = ExGetPreviousMode();
-
- if(PreviousCount != NULL && PreviousMode == UserMode)
- {
- _SEH_TRY
- {
- ProbeForWrite(PreviousCount,
- sizeof(LONG),
- sizeof(ULONG));
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- if(!NT_SUCCESS(Status))
- {
- return Status;
- }
- }
-
- Status = ObReferenceObjectByHandle(MutantHandle,
- MUTANT_QUERY_STATE,
- ExMutantObjectType,
- PreviousMode,
- (PVOID*)&Mutant,
- NULL);
- if(NT_SUCCESS(Status))
- {
- LONG Prev = KeReleaseMutant(Mutant, MUTANT_INCREMENT, 0, FALSE);
- ObDereferenceObject(Mutant);
-
- if(PreviousCount != NULL)
- {
- _SEH_TRY
- {
- *PreviousCount = Prev;
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- }
- }
-
- return Status;
+ PKMUTANT Mutant;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ NTSTATUS Status = STATUS_SUCCESS;
+ 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 */
+ _SEH_TRY
+ {
+ /* Make sure the state pointer is valid */
+ ProbeForWriteLong(PreviousCount);
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ /* Bail out if pointer was invalid */
+ if(!NT_SUCCESS(Status)) return Status;
+ }
+
+ /* Open the Object */
+ Status = ObReferenceObjectByHandle(MutantHandle,
+ MUTANT_QUERY_STATE,
+ 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!
+ */
+ _SEH_TRY
+ {
+ /* Release the mutant */
+ LONG Prev = KeReleaseMutant(Mutant,
+ MUTANT_INCREMENT,
+ FALSE,
+ FALSE);
+
+ /* Return the previous count if requested */
+ if(PreviousCount) *PreviousCount = Prev;
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ /* Dereference it */
+ ObDereferenceObject(Mutant);
+ }
+
+ /* Return Status */
+ return Status;
}
/* EOF */