2005-05-09 09:38:29 +08:00
|
|
|
/*
|
2005-01-07 14:54:27 +08:00
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
2005-12-30 02:47:14 +08:00
|
|
|
* PROJECT: ReactOS Kernel
|
2005-01-07 14:54:27 +08:00
|
|
|
* FILE: ntoskrnl/ex/mutant.c
|
2005-03-14 10:08:17 +08:00
|
|
|
* PURPOSE: Executive Management of Mutants
|
2005-12-30 02:47:14 +08:00
|
|
|
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
|
|
|
|
* Thomas Weidenmueller
|
2005-01-07 14:54:27 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
|
|
|
#include <ntoskrnl.h>
|
|
|
|
#define NDEBUG
|
2008-08-31 00:31:06 +08:00
|
|
|
#include <debug.h>
|
2005-01-07 14:54:27 +08:00
|
|
|
|
2005-12-30 02:47:14 +08:00
|
|
|
/* DATA **********************************************************************/
|
2005-06-19 02:32:29 +08:00
|
|
|
|
2005-01-07 14:54:27 +08:00
|
|
|
POBJECT_TYPE ExMutantObjectType = NULL;
|
|
|
|
|
2005-12-30 02:47:14 +08:00
|
|
|
GENERIC_MAPPING ExpMutantMapping =
|
|
|
|
{
|
2012-09-03 06:06:42 +08:00
|
|
|
STANDARD_RIGHTS_READ | MUTANT_QUERY_STATE,
|
|
|
|
STANDARD_RIGHTS_WRITE,
|
|
|
|
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
|
2005-12-30 02:47:14 +08:00
|
|
|
MUTANT_ALL_ACCESS
|
|
|
|
};
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2005-12-30 02:47:14 +08:00
|
|
|
static const INFORMATION_CLASS_INFO ExMutantInfoClass[] =
|
|
|
|
{
|
2005-03-14 10:08:17 +08:00
|
|
|
/* MutantBasicInformation */
|
2021-05-03 03:00:51 +08:00
|
|
|
IQS_SAME(MUTANT_BASIC_INFORMATION, ULONG, ICIF_QUERY),
|
2005-01-22 11:54:23 +08:00
|
|
|
};
|
|
|
|
|
2005-01-07 14:54:27 +08:00
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
|
2005-05-09 09:38:29 +08:00
|
|
|
VOID
|
2005-12-30 02:47:14 +08:00
|
|
|
NTAPI
|
2005-03-01 01:40:15 +08:00
|
|
|
ExpDeleteMutant(PVOID ObjectBody)
|
2005-01-07 14:54:27 +08:00
|
|
|
{
|
2005-07-05 06:11:00 +08:00
|
|
|
DPRINT("ExpDeleteMutant(ObjectBody 0x%p)\n", ObjectBody);
|
2005-01-07 14:54:27 +08:00
|
|
|
|
2005-03-14 10:08:17 +08:00
|
|
|
/* Make sure to release the Mutant */
|
|
|
|
KeReleaseMutant((PKMUTANT)ObjectBody,
|
|
|
|
MUTANT_INCREMENT,
|
|
|
|
TRUE,
|
|
|
|
FALSE);
|
|
|
|
}
|
2005-03-01 01:40:15 +08:00
|
|
|
|
2020-10-07 03:44:01 +08:00
|
|
|
CODE_SEG("INIT")
|
2020-05-23 21:56:10 +08:00
|
|
|
BOOLEAN
|
2005-12-30 02:47:14 +08:00
|
|
|
NTAPI
|
2005-03-01 01:40:15 +08:00
|
|
|
ExpInitializeMutantImplementation(VOID)
|
|
|
|
{
|
2005-05-16 01:59:33 +08:00
|
|
|
OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
|
|
|
|
UNICODE_STRING Name;
|
2012-09-03 09:12:58 +08:00
|
|
|
NTSTATUS Status;
|
2005-05-22 00:33:23 +08:00
|
|
|
DPRINT("Creating Mutant Object Type\n");
|
2005-12-30 02:47:14 +08:00
|
|
|
|
2005-05-16 01:59:33 +08:00
|
|
|
/* 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;
|
2015-02-01 20:24:03 +08:00
|
|
|
ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
|
2012-09-03 09:12:58 +08:00
|
|
|
Status = ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ExMutantObjectType);
|
|
|
|
if (!NT_SUCCESS(Status)) return FALSE;
|
|
|
|
return TRUE;
|
2005-03-14 10:08:17 +08:00
|
|
|
}
|
2005-03-01 01:40:15 +08:00
|
|
|
|
2005-01-22 11:54:23 +08:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-05-09 09:38:29 +08:00
|
|
|
NTSTATUS
|
2005-12-30 02:47:14 +08:00
|
|
|
NTAPI
|
2005-01-07 14:54:27 +08:00
|
|
|
NtCreateMutant(OUT PHANDLE MutantHandle,
|
2005-03-14 10:08:17 +08:00
|
|
|
IN ACCESS_MASK DesiredAccess,
|
|
|
|
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
|
|
|
IN BOOLEAN InitialOwner)
|
2005-01-07 14:54:27 +08:00
|
|
|
{
|
2005-03-14 10:08:17 +08:00
|
|
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
|
|
|
HANDLE hMutant;
|
|
|
|
PKMUTANT Mutant;
|
2009-08-27 01:31:02 +08:00
|
|
|
NTSTATUS Status;
|
2005-03-14 10:08:17 +08:00
|
|
|
PAGED_CODE();
|
2005-12-30 02:47:14 +08:00
|
|
|
DPRINT("NtCreateMutant(0x%p, 0x%x, 0x%p)\n",
|
|
|
|
MutantHandle, DesiredAccess, ObjectAttributes);
|
|
|
|
|
|
|
|
/* Check if we were called from user-mode */
|
2009-08-27 01:31:02 +08:00
|
|
|
if (PreviousMode != KernelMode)
|
2005-12-30 02:47:14 +08:00
|
|
|
{
|
|
|
|
/* Enter SEH Block */
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_TRY
|
2005-12-30 02:47:14 +08:00
|
|
|
{
|
|
|
|
/* Check handle pointer */
|
2005-08-22 01:38:07 +08:00
|
|
|
ProbeForWriteHandle(MutantHandle);
|
2005-12-30 02:47:14 +08:00
|
|
|
}
|
2009-08-27 01:31:02 +08:00
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
2005-12-30 02:47:14 +08:00
|
|
|
{
|
2009-08-27 01:31:02 +08:00
|
|
|
/* Return the exception code */
|
|
|
|
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
2005-12-30 02:47:14 +08:00
|
|
|
}
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_END;
|
2005-02-23 06:19:14 +08:00
|
|
|
}
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2005-03-14 10:08:17 +08:00
|
|
|
/* Create the Mutant Object*/
|
|
|
|
Status = ObCreateObject(PreviousMode,
|
|
|
|
ExMutantObjectType,
|
|
|
|
ObjectAttributes,
|
|
|
|
PreviousMode,
|
|
|
|
NULL,
|
|
|
|
sizeof(KMUTANT),
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
(PVOID*)&Mutant);
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2005-03-14 10:08:17 +08:00
|
|
|
/* Check for success */
|
2005-12-30 02:47:14 +08:00
|
|
|
if(NT_SUCCESS(Status))
|
|
|
|
{
|
2013-04-05 04:11:17 +08:00
|
|
|
/* Initialize the Kernel Mutant */
|
2005-03-14 10:08:17 +08:00
|
|
|
DPRINT("Initializing the Mutant\n");
|
|
|
|
KeInitializeMutant(Mutant, InitialOwner);
|
|
|
|
|
|
|
|
/* Insert the Object */
|
|
|
|
Status = ObInsertObject((PVOID)Mutant,
|
|
|
|
NULL,
|
|
|
|
DesiredAccess,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
&hMutant);
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2005-12-30 02:47:14 +08:00
|
|
|
/* Check for success */
|
2009-08-27 01:31:02 +08:00
|
|
|
if (NT_SUCCESS(Status))
|
2005-12-30 02:47:14 +08:00
|
|
|
{
|
|
|
|
/* Enter SEH for return */
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_TRY
|
2005-12-30 02:47:14 +08:00
|
|
|
{
|
|
|
|
/* Return the handle to the caller */
|
2005-03-14 10:08:17 +08:00
|
|
|
*MutantHandle = hMutant;
|
2005-12-30 02:47:14 +08:00
|
|
|
}
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_EXCEPT(ExSystemExceptionFilter())
|
2005-12-30 02:47:14 +08:00
|
|
|
{
|
2009-08-27 01:31:02 +08:00
|
|
|
/* Get the exception code */
|
2008-11-24 21:40:26 +08:00
|
|
|
Status = _SEH2_GetExceptionCode();
|
2005-12-30 02:47:14 +08:00
|
|
|
}
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_END;
|
2005-03-14 10:08:17 +08:00
|
|
|
}
|
2005-01-07 14:54:27 +08:00
|
|
|
}
|
|
|
|
|
2005-03-14 10:08:17 +08:00
|
|
|
/* Return Status */
|
|
|
|
return Status;
|
2005-01-07 14:54:27 +08:00
|
|
|
}
|
|
|
|
|
2005-01-22 11:54:23 +08:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-05-09 09:38:29 +08:00
|
|
|
NTSTATUS
|
2005-12-30 02:47:14 +08:00
|
|
|
NTAPI
|
2005-01-07 14:54:27 +08:00
|
|
|
NtOpenMutant(OUT PHANDLE MutantHandle,
|
2005-03-14 10:08:17 +08:00
|
|
|
IN ACCESS_MASK DesiredAccess,
|
|
|
|
IN POBJECT_ATTRIBUTES ObjectAttributes)
|
2005-01-07 14:54:27 +08:00
|
|
|
{
|
2005-03-14 10:08:17 +08:00
|
|
|
HANDLE hMutant;
|
|
|
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
2009-08-27 01:31:02 +08:00
|
|
|
NTSTATUS Status;
|
2005-03-14 10:08:17 +08:00
|
|
|
PAGED_CODE();
|
2005-12-30 02:47:14 +08:00
|
|
|
DPRINT("NtOpenMutant(0x%p, 0x%x, 0x%p)\n",
|
|
|
|
MutantHandle, DesiredAccess, ObjectAttributes);
|
|
|
|
|
|
|
|
/* Check if we were called from user-mode */
|
2009-08-27 01:31:02 +08:00
|
|
|
if (PreviousMode != KernelMode)
|
2005-12-30 02:47:14 +08:00
|
|
|
{
|
|
|
|
/* Enter SEH Block */
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_TRY
|
2005-12-30 02:47:14 +08:00
|
|
|
{
|
|
|
|
/* Check handle pointer */
|
2005-08-22 01:38:07 +08:00
|
|
|
ProbeForWriteHandle(MutantHandle);
|
2005-12-30 02:47:14 +08:00
|
|
|
}
|
2009-08-27 01:31:02 +08:00
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
2005-12-30 02:47:14 +08:00
|
|
|
{
|
2009-08-27 01:31:02 +08:00
|
|
|
/* Return the exception code */
|
|
|
|
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
2005-12-30 02:47:14 +08:00
|
|
|
}
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_END;
|
2005-03-01 01:40:15 +08:00
|
|
|
}
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2005-03-14 10:08:17 +08:00
|
|
|
/* Open the Object */
|
|
|
|
Status = ObOpenObjectByName(ObjectAttributes,
|
|
|
|
ExMutantObjectType,
|
|
|
|
PreviousMode,
|
2006-05-26 04:50:58 +08:00
|
|
|
NULL,
|
2005-03-14 10:08:17 +08:00
|
|
|
DesiredAccess,
|
|
|
|
NULL,
|
|
|
|
&hMutant);
|
|
|
|
|
2005-12-30 02:47:14 +08:00
|
|
|
/* Check for success */
|
|
|
|
if(NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Enter SEH for return */
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_TRY
|
2005-12-30 02:47:14 +08:00
|
|
|
{
|
|
|
|
/* Return the handle to the caller */
|
2005-03-14 10:08:17 +08:00
|
|
|
*MutantHandle = hMutant;
|
2005-12-30 02:47:14 +08:00
|
|
|
}
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_EXCEPT(ExSystemExceptionFilter())
|
2005-12-30 02:47:14 +08:00
|
|
|
{
|
2008-11-24 21:40:26 +08:00
|
|
|
Status = _SEH2_GetExceptionCode();
|
2005-12-30 02:47:14 +08:00
|
|
|
}
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_END;
|
2005-01-07 14:54:27 +08:00
|
|
|
}
|
|
|
|
|
2005-03-14 10:08:17 +08:00
|
|
|
/* Return Status */
|
|
|
|
return Status;
|
2005-01-07 14:54:27 +08:00
|
|
|
}
|
|
|
|
|
2005-01-22 11:54:23 +08:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-05-09 09:38:29 +08:00
|
|
|
NTSTATUS
|
2005-12-30 02:47:14 +08:00
|
|
|
NTAPI
|
2005-01-22 11:54:23 +08:00
|
|
|
NtQueryMutant(IN HANDLE MutantHandle,
|
2005-03-14 10:08:17 +08:00
|
|
|
IN MUTANT_INFORMATION_CLASS MutantInformationClass,
|
|
|
|
OUT PVOID MutantInformation,
|
|
|
|
IN ULONG MutantInformationLength,
|
|
|
|
OUT PULONG ResultLength OPTIONAL)
|
2005-01-07 14:54:27 +08:00
|
|
|
{
|
2005-03-14 10:08:17 +08:00
|
|
|
PKMUTANT Mutant;
|
|
|
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
2009-08-27 01:31:02 +08:00
|
|
|
NTSTATUS Status;
|
2005-12-30 02:47:14 +08:00
|
|
|
PMUTANT_BASIC_INFORMATION BasicInfo =
|
|
|
|
(PMUTANT_BASIC_INFORMATION)MutantInformation;
|
2005-03-14 10:08:17 +08:00
|
|
|
PAGED_CODE();
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2005-03-14 10:08:17 +08:00
|
|
|
/* Check buffers and parameters */
|
2005-10-10 21:03:55 +08:00
|
|
|
Status = DefaultQueryInfoBufferCheck(MutantInformationClass,
|
|
|
|
ExMutantInfoClass,
|
2005-12-30 02:47:14 +08:00
|
|
|
sizeof(ExMutantInfoClass) /
|
|
|
|
sizeof(ExMutantInfoClass[0]),
|
2022-06-11 19:19:51 +08:00
|
|
|
ICIF_PROBE_READ_WRITE,
|
2005-10-10 21:03:55 +08:00
|
|
|
MutantInformation,
|
|
|
|
MutantInformationLength,
|
|
|
|
ResultLength,
|
2010-01-14 06:35:43 +08:00
|
|
|
NULL,
|
2022-06-11 19:19:51 +08:00
|
|
|
PreviousMode);
|
2005-12-30 02:47:14 +08:00
|
|
|
if(!NT_SUCCESS(Status))
|
|
|
|
{
|
2005-03-14 10:08:17 +08:00
|
|
|
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 */
|
2009-08-27 01:31:02 +08:00
|
|
|
if (NT_SUCCESS(Status))
|
2005-12-30 02:47:14 +08:00
|
|
|
{
|
|
|
|
/* Enter SEH Block for return */
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_TRY
|
2005-12-30 02:47:14 +08:00
|
|
|
{
|
2005-03-14 10:08:17 +08:00
|
|
|
/* Fill out the Basic Information Requested */
|
|
|
|
DPRINT("Returning Mutant Information\n");
|
|
|
|
BasicInfo->CurrentCount = KeReadStateMutant(Mutant);
|
2005-12-30 02:47:14 +08:00
|
|
|
BasicInfo->OwnedByCaller = (Mutant->OwnerThread ==
|
|
|
|
KeGetCurrentThread());
|
2005-03-14 10:08:17 +08:00
|
|
|
BasicInfo->AbandonedState = Mutant->Abandoned;
|
|
|
|
|
|
|
|
/* Return the Result Length if requested */
|
2009-08-27 01:31:02 +08:00
|
|
|
if (ResultLength) *ResultLength = sizeof(MUTANT_BASIC_INFORMATION);
|
2005-12-30 02:47:14 +08:00
|
|
|
}
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_EXCEPT(ExSystemExceptionFilter())
|
2005-12-30 02:47:14 +08:00
|
|
|
{
|
2008-11-24 21:40:26 +08:00
|
|
|
Status = _SEH2_GetExceptionCode();
|
2005-12-30 02:47:14 +08:00
|
|
|
}
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_END;
|
2005-03-14 10:08:17 +08:00
|
|
|
|
|
|
|
/* Release the Object */
|
|
|
|
ObDereferenceObject(Mutant);
|
|
|
|
}
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2005-03-14 10:08:17 +08:00
|
|
|
/* Return Status */
|
|
|
|
return Status;
|
2005-01-22 11:54:23 +08:00
|
|
|
}
|
2005-01-07 14:54:27 +08:00
|
|
|
|
2005-01-22 11:54:23 +08:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-05-09 09:38:29 +08:00
|
|
|
NTSTATUS
|
2005-12-30 02:47:14 +08:00
|
|
|
NTAPI
|
2005-01-22 11:54:23 +08:00
|
|
|
NtReleaseMutant(IN HANDLE MutantHandle,
|
2005-12-30 02:47:14 +08:00
|
|
|
IN PLONG PreviousCount OPTIONAL)
|
2005-01-22 11:54:23 +08:00
|
|
|
{
|
2005-03-14 10:08:17 +08:00
|
|
|
PKMUTANT Mutant;
|
2005-12-30 02:47:14 +08:00
|
|
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
2009-08-27 01:31:02 +08:00
|
|
|
NTSTATUS Status;
|
2005-03-14 10:08:17 +08:00
|
|
|
PAGED_CODE();
|
2005-07-05 06:11:00 +08:00
|
|
|
DPRINT("NtReleaseMutant(MutantHandle 0x%p PreviousCount 0x%p)\n",
|
2005-05-09 09:38:29 +08:00
|
|
|
MutantHandle,
|
2005-03-14 10:08:17 +08:00
|
|
|
PreviousCount);
|
|
|
|
|
2005-12-30 02:47:14 +08:00
|
|
|
/* Check if we were called from user-mode */
|
2009-08-27 01:31:02 +08:00
|
|
|
if ((PreviousCount) && (PreviousMode != KernelMode))
|
2005-12-30 02:47:14 +08:00
|
|
|
{
|
|
|
|
/* Entry SEH Block */
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_TRY
|
2005-12-30 02:47:14 +08:00
|
|
|
{
|
|
|
|
/* Make sure the state pointer is valid */
|
2005-08-22 01:38:07 +08:00
|
|
|
ProbeForWriteLong(PreviousCount);
|
2005-12-30 02:47:14 +08:00
|
|
|
}
|
2009-08-27 01:31:02 +08:00
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
2005-12-30 02:47:14 +08:00
|
|
|
{
|
2009-08-27 01:31:02 +08:00
|
|
|
/* Return the exception code */
|
|
|
|
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
2005-12-30 02:47:14 +08:00
|
|
|
}
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_END;
|
2005-05-09 09:38:29 +08:00
|
|
|
}
|
2005-03-14 10:08:17 +08:00
|
|
|
|
|
|
|
/* Open the Object */
|
|
|
|
Status = ObReferenceObjectByHandle(MutantHandle,
|
2014-05-15 04:27:18 +08:00
|
|
|
0, /* No access rights required */
|
2005-03-14 10:08:17 +08:00
|
|
|
ExMutantObjectType,
|
|
|
|
PreviousMode,
|
|
|
|
(PVOID*)&Mutant,
|
|
|
|
NULL);
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2005-03-14 10:08:17 +08:00
|
|
|
/* Check for Success and release if such */
|
2009-08-27 01:31:02 +08:00
|
|
|
if (NT_SUCCESS(Status))
|
2005-12-30 02:47:14 +08:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Release the mutant. doing so might raise an exception which we're
|
|
|
|
* required to catch!
|
|
|
|
*/
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_TRY
|
2005-12-30 02:47:14 +08:00
|
|
|
{
|
|
|
|
/* Release the mutant */
|
|
|
|
LONG Prev = KeReleaseMutant(Mutant,
|
|
|
|
MUTANT_INCREMENT,
|
|
|
|
FALSE,
|
|
|
|
FALSE);
|
|
|
|
|
|
|
|
/* Return the previous count if requested */
|
2009-08-27 01:31:02 +08:00
|
|
|
if (PreviousCount) *PreviousCount = Prev;
|
2005-12-30 02:47:14 +08:00
|
|
|
}
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_EXCEPT(ExSystemExceptionFilter())
|
2005-12-30 02:47:14 +08:00
|
|
|
{
|
2009-08-27 01:31:02 +08:00
|
|
|
/* Get the exception code */
|
2008-11-24 21:40:26 +08:00
|
|
|
Status = _SEH2_GetExceptionCode();
|
2005-12-30 02:47:14 +08:00
|
|
|
}
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_END;
|
2005-03-28 23:17:54 +08:00
|
|
|
|
2005-12-30 02:47:14 +08:00
|
|
|
/* Dereference it */
|
2005-03-14 10:08:17 +08:00
|
|
|
ObDereferenceObject(Mutant);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return Status */
|
|
|
|
return Status;
|
2005-01-07 14:54:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* EOF */
|