286 lines
6.6 KiB
C
286 lines
6.6 KiB
C
/*++
|
|
|
|
Copyright (c) 1989-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
mutant.c
|
|
|
|
Abstract:
|
|
|
|
This module implements the executive mutant object. Functions are
|
|
provided to create, open, release, and query mutant objects.
|
|
|
|
--*/
|
|
|
|
#include "exp.h"
|
|
|
|
//
|
|
// Define private function prototypes.
|
|
//
|
|
|
|
VOID
|
|
ExpDeleteMutant (
|
|
IN PVOID Mutant
|
|
);
|
|
|
|
//
|
|
// Mutant object type information.
|
|
//
|
|
|
|
DECLSPEC_RDATA OBJECT_TYPE ExMutantObjectType = {
|
|
ExAllocatePoolWithTag,
|
|
ExFreePool,
|
|
NULL,
|
|
ExpDeleteMutant,
|
|
NULL,
|
|
(PVOID)FIELD_OFFSET(KMUTANT, Header),
|
|
'atuM'
|
|
};
|
|
|
|
VOID
|
|
ExpDeleteMutant (
|
|
IN PVOID Mutant
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called when an executive mutant object is about to
|
|
be deleted. The mutant object is released with an abandoned status to
|
|
ensure that it is removed from the owner thread's mutant list if the
|
|
mutant object is currently owned by a thread.
|
|
|
|
Arguments:
|
|
|
|
Mutant - Supplies a pointer to an executive mutant object.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// Release the mutant object with an abandoned status to ensure that it
|
|
// is removed from the owner thread's mutant list if the mutant is
|
|
// currently owned by a thread.
|
|
//
|
|
|
|
KeReleaseMutant((PKMUTANT)Mutant, MUTANT_INCREMENT, TRUE, FALSE);
|
|
return;
|
|
}
|
|
|
|
NTSTATUS
|
|
NtCreateMutant (
|
|
OUT PHANDLE MutantHandle,
|
|
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
|
IN BOOLEAN InitialOwner
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function creates a mutant object, sets its initial count to one
|
|
(signaled), and opens a handle to the object with the specified desired
|
|
access.
|
|
|
|
Arguments:
|
|
|
|
MutantHandle - Supplies a pointer to a variable that will receive the
|
|
mutant object handle.
|
|
|
|
ObjectAttributes - Supplies a pointer to an object attributes structure.
|
|
|
|
InitialOwner - Supplies a boolean value that determines whether the
|
|
creator of the object desires immediate ownership of the object.
|
|
|
|
Return Value:
|
|
|
|
TBS
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PVOID Mutant;
|
|
NTSTATUS Status;
|
|
|
|
//
|
|
// Allocate mutant object.
|
|
//
|
|
|
|
Status = ObCreateObject(&ExMutantObjectType,
|
|
ObjectAttributes,
|
|
sizeof(KMUTANT),
|
|
(PVOID *)&Mutant);
|
|
|
|
//
|
|
// If the mutant object was successfully allocated, then initialize
|
|
// the mutant object and attempt to insert the mutant object in the
|
|
// current process' handle table.
|
|
//
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
KeInitializeMutant((PKMUTANT)Mutant, InitialOwner);
|
|
Status = ObInsertObject(Mutant,
|
|
ObjectAttributes,
|
|
0,
|
|
MutantHandle);
|
|
}
|
|
|
|
//
|
|
// Return service status.
|
|
//
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
NtQueryMutant (
|
|
IN HANDLE MutantHandle,
|
|
OUT PMUTANT_BASIC_INFORMATION MutantInformation
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function queries the state of a mutant object and returns the
|
|
requested information in the specified record structure.
|
|
|
|
Arguments:
|
|
|
|
MutantHandle - Supplies a handle to a mutant object.
|
|
|
|
MutantInformation - Supplies a pointer to a record that is to receive
|
|
the requested information.
|
|
|
|
Return Value:
|
|
|
|
TBS
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
BOOLEAN Abandoned;
|
|
BOOLEAN OwnedByCaller;
|
|
LONG Count;
|
|
PVOID Mutant;
|
|
NTSTATUS Status;
|
|
|
|
//
|
|
// Reference mutant object by handle.
|
|
//
|
|
|
|
Status = ObReferenceObjectByHandle(MutantHandle,
|
|
&ExMutantObjectType,
|
|
&Mutant);
|
|
|
|
//
|
|
// If the reference was successful, then read the current state and
|
|
// abandoned status of the mutant object, dereference mutant object,
|
|
// fill in the information structure, and return the length of the
|
|
// information structure if specified. If the write of the mutant
|
|
// information or the return length fails, then do not report an error.
|
|
// When the caller accesses the information structure or length an
|
|
// access violation will occur.
|
|
//
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
Count = KeReadStateMutant((PKMUTANT)Mutant);
|
|
Abandoned = ((PKMUTANT)Mutant)->Abandoned;
|
|
OwnedByCaller = (BOOLEAN)((((PKMUTANT)Mutant)->OwnerThread ==
|
|
KeGetCurrentThread()));
|
|
|
|
ObDereferenceObject(Mutant);
|
|
|
|
MutantInformation->CurrentCount = Count;
|
|
MutantInformation->OwnedByCaller = OwnedByCaller;
|
|
MutantInformation->AbandonedState = Abandoned;
|
|
}
|
|
|
|
//
|
|
// Return service status.
|
|
//
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
NtReleaseMutant (
|
|
IN HANDLE MutantHandle,
|
|
OUT PLONG PreviousCount OPTIONAL
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function releases a mutant object.
|
|
|
|
Arguments:
|
|
|
|
Mutant - Supplies a handle to a mutant object.
|
|
|
|
PreviousCount - Supplies an optional pointer to a variable that will
|
|
receive the previous mutant count.
|
|
|
|
Return Value:
|
|
|
|
TBS
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
LONG Count;
|
|
PVOID Mutant;
|
|
NTSTATUS Status;
|
|
|
|
//
|
|
// Reference mutant object by handle.
|
|
//
|
|
// Note that the desired access is specified as zero since only the
|
|
// owner can release a mutant object.
|
|
//
|
|
|
|
Status = ObReferenceObjectByHandle(MutantHandle,
|
|
&ExMutantObjectType,
|
|
&Mutant);
|
|
|
|
//
|
|
// If the reference was successful, then release the mutant object. If
|
|
// an exception occurs because the caller is not the owner of the mutant
|
|
// object, then dereference mutant object and return the exception code
|
|
// as the service status. Otherise write the previous count value if
|
|
// specified. If the write of the previous count fails, then do not
|
|
// report an error. When the caller attempts to access the previous
|
|
// count value, an access violation will occur.
|
|
//
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
try {
|
|
Count = KeReleaseMutant((PKMUTANT)Mutant, MUTANT_INCREMENT, FALSE, FALSE);
|
|
ObDereferenceObject(Mutant);
|
|
if (ARGUMENT_PRESENT(PreviousCount)) {
|
|
*PreviousCount = Count;
|
|
}
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|
ObDereferenceObject(Mutant);
|
|
return GetExceptionCode();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Return service status.
|
|
//
|
|
|
|
return Status;
|
|
}
|