-/*
+/*
* COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
+ * PROJECT: ReactOS Kernel
* FILE: ntoskrnl/ex/mutant.c
* PURPOSE: Executive Management of Mutants
- *
- * PROGRAMMERS: Alex Ionescu - Fix tab/space mismatching, tiny fixes to query function and
- * add more debug output.
- * David Welch (welch@cwcom.net)
+ * 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 = {
+GENERIC_MAPPING ExpMutantMapping =
+{
STANDARD_RIGHTS_READ | SYNCHRONIZE | MUTANT_QUERY_STATE,
STANDARD_RIGHTS_WRITE | SYNCHRONIZE,
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | MUTANT_QUERY_STATE,
- MUTANT_ALL_ACCESS};
+ MUTANT_ALL_ACCESS
+};
-static const INFORMATION_CLASS_INFO ExMutantInfoClass[] = {
-
+static const INFORMATION_CLASS_INFO ExMutantInfoClass[] =
+{
/* MutantBasicInformation */
- ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ),
+ ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY),
};
/* FUNCTIONS *****************************************************************/
-VOID
-STDCALL
+VOID
+NTAPI
ExpDeleteMutant(PVOID ObjectBody)
{
-
- DPRINT("ExpDeleteMutant(ObjectBody %x)\n", ObjectBody);
+ DPRINT("ExpDeleteMutant(ObjectBody 0x%p)\n", ObjectBody);
/* Make sure to release the Mutant */
KeReleaseMutant((PKMUTANT)ObjectBody,
FALSE);
}
-VOID
+VOID
INIT_FUNCTION
+NTAPI
ExpInitializeMutantImplementation(VOID)
{
-
- /* Allocate the Object Type */
- ExMutantObjectType = ExAllocatePoolWithTag(NonPagedPool, sizeof(OBJECT_TYPE), TAG('M', 't', 'n', 't'));
-
- /* Create the Object Type */
- RtlInitUnicodeString(&ExMutantObjectType->TypeName, L"Mutant");
- 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 = NULL;
- 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,
HANDLE hMutant;
PKMUTANT Mutant;
NTSTATUS Status = STATUS_SUCCESS;
-
PAGED_CODE();
- DPRINT("NtCreateMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle, DesiredAccess, ObjectAttributes);
-
- /* Check Output Safety */
- if(PreviousMode == UserMode) {
-
- _SEH_TRY {
-
- ProbeForWrite(MutantHandle,
- sizeof(HANDLE),
- sizeof(ULONG));
- } _SEH_HANDLE {
-
+ 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;
+ }
+ _SEH_END;
+ /* Bail out if pointer was invalid */
if(!NT_SUCCESS(Status)) return Status;
}
-
+
/* Create the Mutant Object*/
Status = ObCreateObject(PreviousMode,
ExMutantObjectType,
0,
0,
(PVOID*)&Mutant);
-
+
/* Check for success */
- if(NT_SUCCESS(Status)) {
-
+ if(NT_SUCCESS(Status))
+ {
/* Initalize the Kernel Mutant */
DPRINT("Initializing the Mutant\n");
KeInitializeMutant(Mutant, InitialOwner);
NULL,
&hMutant);
ObDereferenceObject(Mutant);
-
- /* Check for success and return handle */
- if(NT_SUCCESS(Status)) {
-
- _SEH_TRY {
-
+
+ /* Check for success */
+ if(NT_SUCCESS(Status))
+ {
+ /* Enter SEH for return */
+ _SEH_TRY
+ {
+ /* Return the handle to the caller */
*MutantHandle = hMutant;
-
- } _SEH_HANDLE {
-
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
Status = _SEH_GetExceptionCode();
-
- } _SEH_END;
+ }
+ _SEH_END;
}
}
/*
* @implemented
*/
-NTSTATUS
-STDCALL
+NTSTATUS
+NTAPI
NtOpenMutant(OUT PHANDLE MutantHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes)
HANDLE hMutant;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
-
PAGED_CODE();
- DPRINT("NtOpenMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle, DesiredAccess, ObjectAttributes);
-
- /* Check Output Safety */
- if(PreviousMode == UserMode) {
-
- _SEH_TRY {
-
- ProbeForWrite(MutantHandle,
- sizeof(HANDLE),
- sizeof(ULONG));
- } _SEH_HANDLE {
-
+ 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 */
+ _SEH_TRY
+ {
+ /* Check handle pointer */
+ ProbeForWriteHandle(MutantHandle);
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
Status = _SEH_GetExceptionCode();
-
- } _SEH_END;
-
+ }
+ _SEH_END;
+
+ /* Bail out if pointer was invalid */
if(!NT_SUCCESS(Status)) return Status;
}
-
+
/* Open the Object */
Status = ObOpenObjectByName(ObjectAttributes,
ExMutantObjectType,
NULL,
&hMutant);
- /* Check for success and return handle */
- if(NT_SUCCESS(Status)) {
-
- _SEH_TRY {
-
+ /* Check for success */
+ if(NT_SUCCESS(Status))
+ {
+ /* Enter SEH for return */
+ _SEH_TRY
+ {
+ /* Return the handle to the caller */
*MutantHandle = hMutant;
-
- } _SEH_HANDLE {
-
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
Status = _SEH_GetExceptionCode();
-
- } _SEH_END;
+ }
+ _SEH_END;
}
/* Return Status */
/*
* @implemented
*/
-NTSTATUS
-STDCALL
+NTSTATUS
+NTAPI
NtQueryMutant(IN HANDLE MutantHandle,
IN MUTANT_INFORMATION_CLASS MutantInformationClass,
OUT PVOID MutantInformation,
PKMUTANT Mutant;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
- PMUTANT_BASIC_INFORMATION BasicInfo = (PMUTANT_BASIC_INFORMATION)MutantInformation;
-
+ PMUTANT_BASIC_INFORMATION BasicInfo =
+ (PMUTANT_BASIC_INFORMATION)MutantInformation;
PAGED_CODE();
-
+
/* Check buffers and parameters */
- DefaultQueryInfoBufferCheck(MutantInformationClass,
- ExMutantInfoClass,
- MutantInformation,
- MutantInformationLength,
- ResultLength,
- PreviousMode,
- &Status);
- if(!NT_SUCCESS(Status)) {
-
+ 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;
}
(PVOID*)&Mutant,
NULL);
/* Check for Status */
- if(NT_SUCCESS(Status)) {
-
- _SEH_TRY {
-
+ if(NT_SUCCESS(Status))
+ {
+ /* Enter SEH Block for return */
+ _SEH_TRY
+ {
/* Fill out the Basic Information Requested */
DPRINT("Returning Mutant Information\n");
BasicInfo->CurrentCount = KeReadStateMutant(Mutant);
- BasicInfo->OwnedByCaller = (Mutant->OwnerThread == KeGetCurrentThread());
+ BasicInfo->OwnedByCaller = (Mutant->OwnerThread ==
+ KeGetCurrentThread());
BasicInfo->AbandonedState = Mutant->Abandoned;
/* Return the Result Length if requested */
if(ResultLength) *ResultLength = sizeof(MUTANT_BASIC_INFORMATION);
-
- } _SEH_HANDLE {
-
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
Status = _SEH_GetExceptionCode();
-
- } _SEH_END;
+ }
+ _SEH_END;
/* Release the Object */
ObDereferenceObject(Mutant);
}
-
+
/* 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 = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
-
PAGED_CODE();
- DPRINT("NtReleaseMutant(MutantHandle 0%x PreviousCount 0%x)\n",
- MutantHandle,
+ DPRINT("NtReleaseMutant(MutantHandle 0x%p PreviousCount 0x%p)\n",
+ MutantHandle,
PreviousCount);
- /* Check Output Safety */
- if(PreviousMode == UserMode && PreviousCount) {
-
- _SEH_TRY {
-
- ProbeForWrite(PreviousCount,
- sizeof(LONG),
- sizeof(ULONG));
- } _SEH_HANDLE {
-
+ /* 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;
-
+ }
+ _SEH_END;
+
+ /* Bail out if pointer was invalid */
if(!NT_SUCCESS(Status)) return Status;
- }
+ }
/* Open the Object */
Status = ObReferenceObjectByHandle(MutantHandle,
PreviousMode,
(PVOID*)&Mutant,
NULL);
-
- /* Check for Success and release if such */
- if(NT_SUCCESS(Status)) {
-
- LONG Prev;
-
- /* Save the Old State */
- DPRINT("Releasing Mutant\n");
- Prev = KeReleaseMutant(Mutant, MUTANT_INCREMENT, FALSE, FALSE);
- ObDereferenceObject(Mutant);
- /* Return it */
- if(PreviousCount) {
-
- _SEH_TRY {
-
- *PreviousCount = Prev;
-
- } _SEH_HANDLE {
-
- Status = _SEH_GetExceptionCode();
-
- } _SEH_END;
+ /* 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 */