/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
dllmutex.c
Abstract:
This module implements the OS/2 V2.0 Mutex Semaphore API Calls.
Author:
Steve Wood (stevewo) 07-Feb-1990
Revision History:
--*/
#define INCL_OS2V20_SEMAPHORES
#define INCL_OS2V20_ERRORS
#include "os2dll.h"
APIRET
DosCreateMutexSem(
IN PSZ ObjectName,
IN OUT PHMTX MutexHandle,
IN ULONG CreateAttributes,
IN BOOL32 InitialState
)
{
NTSTATUS Status;
OS2_API_MSG m;
POS2_DOSCREATEMUTEXSEM_MSG a = &m.u.DosCreateMutexSem;
POS2_DOSCLOSEMUTEXSEM_MSG a1 = &m.u.DosCloseMutexSem;
POS2_CAPTURE_HEADER CaptureBuffer;
APIRET rc;
BOOLEAN SharedSem;
POR2_HANDLE_TABLE SemaphoreTable;
OD2_SEMAPHORE Semaphore;
POD2_MUTEX_SEMAPHORE Mutex;
//
// Validate the simple parameters
//
if ((CreateAttributes & ~DC_SEM_SHARED) ||
((InitialState != TRUE) && (InitialState != FALSE))
) {
return( ERROR_INVALID_PARAMETER );
}
//
// probe handle pointer
//
try {
Od2ProbeForWrite( (PVOID)MutexHandle, sizeof( MutexHandle ), 1 );
} except( EXCEPTION_EXECUTE_HANDLER ) {
Od2ExitGP();
}
//
// Capture and validate any semaphore name.
//
rc = Od2CaptureObjectName( ObjectName,
CANONICALIZE_SEMAPHORE,
0,
&CaptureBuffer,
&a->ObjectName
);
if (rc != NO_ERROR) {
return( rc );
}
//
// Determine if a shared or private semaphore.
//
if (CaptureBuffer != NULL || CreateAttributes & DC_SEM_SHARED) {
SharedSem = TRUE;
}
else {
SharedSem = FALSE;
}
//
// Get the pointer to either the shared or private semaphore table,
// creating it if necessary.
//
SemaphoreTable = Od2GetSemaphoreTable( SharedSem, TRUE );
if (!SemaphoreTable) {
if (CaptureBuffer != NULL) {
Od2FreeCaptureBuffer( CaptureBuffer );
}
return( ERROR_NOT_ENOUGH_MEMORY );
}
Mutex = RtlAllocateHeap( Od2Heap, 0, sizeof( *Mutex ) );
if (Mutex == NULL) {
if (CaptureBuffer != NULL) {
Od2FreeCaptureBuffer( CaptureBuffer );
}
return( ERROR_NOT_ENOUGH_MEMORY );
}
//
// Create an NT Mutant that will be used to implement the semantics
// of an OS/2 2.0 Mutex Semaphore. Must always do this in the client so
// the initial owner gets marked correctly.
//
Status = NtCreateMutant( &a->NtMutantHandle,
MUTANT_ALL_ACCESS,
NULL,
(BOOLEAN)InitialState
);
//
// Return an error if unable to create the NT Mutant.
//
if (!NT_SUCCESS( Status )) {
if (CaptureBuffer != NULL) {
Od2FreeCaptureBuffer( CaptureBuffer );
}
RtlFreeHeap( Od2Heap, 0, Mutex );
return( ERROR_NOT_ENOUGH_MEMORY );
}
//
// Mark the fact that we are creating a semaphore handle.
//
a->HandleIndex = 0xFFFFFFFF;
if (SharedSem) {
//
// Shared semaphore. Set the shared semaphore attribute and pass
// the call to the OS/2 subsystem to create the system wide semaphore
// handle value.
//
a->InitialState = (BOOLEAN) InitialState;
rc = Od2CallSubsystem( &m,
CaptureBuffer,
Os2CreateMutexSem,
sizeof( *a )
);
//
// Free any capture buffer, since the subsystem has saved away any
// semaphore name in its table.
//
if (CaptureBuffer != NULL) {
Od2FreeCaptureBuffer( CaptureBuffer );
}
//
// Return if an error was discovered.
//
if (rc != NO_ERROR) {
RtlFreeHeap( Od2Heap, 0, Mutex );
NtClose( a->NtMutantHandle );
return( rc );
}
//
// At this point, the semaphore handle index has been stored in
// a->HandleIndex by the OS/2 subsystem and it has made a copy of
// the NT Mutant handle we created.
//
}
//
// Initialize the OS/2 Semaphore structure.
//
Semaphore.Type = Od2MutexSem;
Semaphore.Shared = SharedSem;
Semaphore.PointerCount = 0;
Semaphore.OpenCount = 1;
Mutex->MutantHandle = a->NtMutantHandle;
if (InitialState) {
Mutex->OwnerRequestLevel = 1;
Mutex->OwnerTid = (TID)Od2CurrentThreadId();
}
else {
Mutex->OwnerRequestLevel = 0;
Mutex->OwnerTid = 0;
}
Semaphore.u.Mutex = Mutex;
//
// Create an entry in the appropriate semaphore table, which will copy
// the semaphore structure into the table entry and return an index to
// the entry in a->HandleIndex
//
if (!Or2CreateHandle( SemaphoreTable,
&a->HandleIndex,
(PVOID)&Semaphore
)
) {
//
// Unable to create the entry. Close the NT Mutant handle, as
// it will not be used. If this is a shared semaphore created, then
// call the OS/2 subsystem to close our reference to this shared
// OS/2 semaphore.
//
RtlFreeHeap( Od2Heap, 0, Mutex );
NtClose( a->NtMutantHandle );
if (SharedSem) {
a1->HandleIndex = a->HandleIndex;
Od2CallSubsystem( &m, NULL, Os2CloseMutexSem, sizeof( *a1 ) );
}
//
// Return an error.
//
return( ERROR_NOT_ENOUGH_MEMORY );
}
//
// Success. Store a valid OS/2 2.0 Semaphore handle in the location
// specified by the caller and return success to the caller.
//
*MutexHandle = Od2ConstructSemaphoreHandle( SharedSem,
a->HandleIndex
);
return( NO_ERROR );
}
APIRET
DosOpenMutexSem(
IN PSZ ObjectName,
IN OUT PHMTX MutexHandle
)
{
OS2_API_MSG m;
POS2_DOSOPENMUTEXSEM_MSG a = &m.u.DosOpenMutexSem;
POS2_DOSCLOSEMUTEXSEM_MSG a1 = &m.u.DosCloseMutexSem;
POS2_CAPTURE_HEADER CaptureBuffer;
POR2_HANDLE_TABLE SemaphoreTable;
OD2_SEMAPHORE NewSemaphore;
POD2_SEMAPHORE Semaphore;
POD2_MUTEX_SEMAPHORE Mutex;
BOOLEAN SharedSem;
APIRET rc;
//
// probe handle pointer
//
try {
Od2ProbeForWrite( (PVOID)MutexHandle, sizeof( MutexHandle ), 1 );
} except( EXCEPTION_EXECUTE_HANDLER ) {
Od2ExitGP();
}
//
// Capture and validate any semaphore name.
//
rc = Od2CaptureObjectName( ObjectName,
CANONICALIZE_SEMAPHORE,
0,
&CaptureBuffer,
&a->ObjectName
);
if (rc != NO_ERROR) {
return( rc );
}
//
// Determine if opening the semaphore by name or by handle.
//
if (CaptureBuffer != NULL) {
//
// If a semaphore name was given, then we are opening the semaphore
// by name, so call the OS/2 Subsystem to do the name lookup.
//
a->HandleIndex = 0xFFFFFFFF;
rc = Od2CallSubsystem( &m,
CaptureBuffer,
Os2OpenMutexSem,
sizeof( *a )
);
//
// Free any capture buffer, since the name has served its purpose
// at this point.
//
if (CaptureBuffer != NULL) {
Od2FreeCaptureBuffer( CaptureBuffer );
RtlZeroMemory( &a->ObjectName, sizeof( a->ObjectName ) );
}
//
// Return if an error was discovered.
//
if (rc != NO_ERROR) {
return( rc );
}
//
// At this point, the semaphore handle index has been stored in
// a->HandleIndex by the OS/2 subsystem but a->NtMutantHandle is still
// uninitialized, since we don't know if this is the first reference
// to this shared semaphore by this process. Set the shared semaphore
// flag.
//
SharedSem = TRUE;
//
// If the caller specified both the name and the handle, make sure
// the named mapped to the same handle value that they specified.
//
if (*MutexHandle != NULL &&
*MutexHandle != Od2ConstructSemaphoreHandle( SharedSem,
a->HandleIndex
)
) {
return( ERROR_INVALID_PARAMETER );
}
}
else {
//
// Opening by handle. Validate the handle and get the shared/private
// flag.
//
rc = Od2ValidateSemaphoreHandle( *MutexHandle,
&SharedSem,
&a->HandleIndex
);
//
// Return if invalid handle.
//
if (rc != NO_ERROR) {
return( rc );
}
}
//
// Get the pointer to either the shared or private semaphore table.
// Creating is okay if this is a shared semaphore open. Return the
// appropriate error code if table does not exist or cant be created.
//
SemaphoreTable = Od2GetSemaphoreTable( SharedSem, SharedSem );
if (!SemaphoreTable) {
return( SharedSem ? ERROR_NOT_ENOUGH_MEMORY : ERROR_INVALID_HANDLE );
}
//
// Now lock the semaphore table while we figure out what we are doing and
// do it.
//
AcquireHandleTableLock( SemaphoreTable );
//
// See if the semaphore handle maps to an allocated entry in the table.
//
Semaphore = (POD2_SEMAPHORE)Or2MapHandle( SemaphoreTable,
a->HandleIndex,
TRUE
);
if (Semaphore == NULL || *(PULONG)Semaphore == 0) {
//
// No entry in the table for this semaphore handle. Error if not
// a shared semaphore.
//
if (!SharedSem) {
rc = ERROR_INVALID_HANDLE;
}
else {
//
// This is the first usage of this shared semaphore handle by
// the calling process, so call the OS/2 subsystem so that it
// can bump its reference count.
//
rc = Od2CallSubsystem( &m,
NULL,
Os2OpenMutexSem,
sizeof( *a )
);
if (rc == NO_ERROR) {
//
// If we succeeded, then the semaphore was not deleted
// inbetween the two calls to the subsystem, so add an
// entry for this handle in the semaphore table, using the
// NT Mutant handle we got from the subsystem.
//
NewSemaphore.Type = Od2MutexSem;
NewSemaphore.Shared = TRUE;
NewSemaphore.PointerCount = 0;
NewSemaphore.OpenCount = 1;
Mutex = RtlAllocateHeap( Od2Heap, 0, sizeof( *Mutex ) );
if (Mutex == NULL) {
NtClose( a->NtMutantHandle );
a1->HandleIndex = a->HandleIndex;
Od2CallSubsystem( &m,
NULL,
Os2CloseMutexSem,
sizeof( *a1 )
);
return( ERROR_NOT_ENOUGH_MEMORY );
}
Mutex->MutantHandle = a->NtMutantHandle;
Mutex->OwnerRequestLevel = 0;
Mutex->OwnerTid = 0;
NewSemaphore.u.Mutex = Mutex;
if (!Or2CreateHandle( SemaphoreTable,
&a->HandleIndex,
(PVOID)&NewSemaphore
)
) {
//
// Unable to create the entry. Close the NT Mutant
// handle, as it will not be used. Then call the
// OS/2 subsystem to close our reference to this shared
// OS/2 semaphore. Set the appropriate error code.
//
RtlFreeHeap( Od2Heap, 0, Mutex );
NtClose( a->NtMutantHandle );
a1->HandleIndex = a->HandleIndex;
Od2CallSubsystem( &m,
NULL,
Os2CloseMutexSem,
sizeof( *a1 )
);
rc = ERROR_NOT_ENOUGH_MEMORY;
}
}
}
}
//
// Entry in semaphore table exists, so make sure it is a Mutex semaphore.
// Set the appropriate error code if not.
//
else
if (Semaphore->Type != Od2MutexSem) {
rc = ERROR_INVALID_HANDLE;
}
//
// Entry in semaphore table is for a Mutex semaphore, see if the OpenCount
// is about to overflow, and set the appropriate error code if it is.
//
else
if (Semaphore->OpenCount == 0xFFFF) {
rc = ERROR_TOO_MANY_OPENS;
}
//
// Everything is okay, so bump the open count in the semaphore table entry.
//
else {
Semaphore->OpenCount++;
}
//
// All done mucking about, so release the semaphore table lock.
//
ReleaseHandleTableLock( SemaphoreTable );
//
// If no errors, store a valid OS/2 2.0 Semaphore handle in the location
// specified by the caller and return success to the caller.
//
if (rc == NO_ERROR) {
*MutexHandle = Od2ConstructSemaphoreHandle( SharedSem,
a->HandleIndex
);
}
//
// Return an error code to the caller.
//
return( rc );
}
APIRET
DosCloseMutexSem(
IN HMTX MutexHandle
)
{
OS2_API_MSG m;
POS2_DOSCLOSEMUTEXSEM_MSG a = &m.u.DosCloseMutexSem;
POR2_HANDLE_TABLE SemaphoreTable;
POD2_SEMAPHORE Semaphore;
POD2_MUTEX_SEMAPHORE Mutex;
BOOLEAN SharedSem;
APIRET rc;
//
// Validate the passed OS/2 2.0 semaphore handle and extract the
// shared/private flag and the index field. Return an error if
// not a valid handle.
//
rc = Od2ValidateSemaphoreHandle( MutexHandle,
&SharedSem,
&a->HandleIndex
);
if (rc != NO_ERROR) {
return( rc );
}
//
// Get the pointer to either the shared or private semaphore table.
// Table must exist. Return an error if it does not.
//
SemaphoreTable = Od2GetSemaphoreTable( SharedSem, FALSE );
if (!SemaphoreTable) {
return( ERROR_INVALID_HANDLE );
}
//
// Map the semaphore handle into a pointer to the semaphore structure
// contained in the table. Return an error if the handle is outside
// the current limits of the table. If the mapping is successful then
// the semaphore table is left locked while we use the pointer.
//
Semaphore = (POD2_SEMAPHORE)Or2MapHandle( SemaphoreTable,
a->HandleIndex,
FALSE
);
if (Semaphore == NULL) {
return( ERROR_INVALID_HANDLE );
}
//
// Entry in semaphore table exists, so make sure it is a Mutex semaphore.
// Return an error if not, after unlock the table first.
//
if (Semaphore->Type != Od2MutexSem) {
ReleaseHandleTableLock( SemaphoreTable );
return( ERROR_INVALID_HANDLE );
}
//
// Entry in semaphore table is for a Mutex semaphore, so decrement the
// OpenCount and see if it has gone to zero.
//
if (--Semaphore->OpenCount == 0) {
//
// OpenCount is now zero, so we can really close the semaphore
// and delete the entry in the semaphore table.
//
Mutex = Semaphore->u.Mutex;
//
// First make sure the mutex is not owned by a thread in this process
// If it is, increment the open count and return an error. Otherwise
// make sure that no thread in this process is waiting on this mutex
// If there is one waiting on it, increment the open count and return
// an error.
//
if (Mutex->OwnerTid != 0 || Od2SearchForWaitingThread( Semaphore )) {
Semaphore->OpenCount++;
ReleaseHandleTableLock( SemaphoreTable );
rc = ERROR_SEM_BUSY;
}
else {
//
// Okay to really close this mutex semaphore. First destroy
// the handle, which will unlock the handle table.
//
Or2DestroyHandle( SemaphoreTable, a->HandleIndex );
NtClose( Mutex->MutantHandle );
RtlFreeHeap( Od2Heap, 0, Mutex );
//
// If this is a shared semaphore, call the subsystem so that it
// can decrement its open count, as this process is not longer
// using the shared semaphore handle.
//
if (SharedSem) {
rc = Od2CallSubsystem( &m,
NULL,
Os2CloseMutexSem,
sizeof( *a )
);
}
}
}
else {
//
// OpenCount is still non-zero, so just release the semaphore table
// lock.
//
ReleaseHandleTableLock( SemaphoreTable );
}
//
// Return any error code to the caller.
//
return( rc );
}
APIRET
DosRequestMutexSem(
IN HMTX MutexHandle,
IN ULONG Timeout
)
{
POR2_HANDLE_TABLE SemaphoreTable;
POD2_SEMAPHORE Semaphore;
POD2_MUTEX_SEMAPHORE Mutex;
BOOLEAN SharedSem;
ULONG HandleIndex;
APIRET rc;
NTSTATUS Status;
HANDLE NtMutantHandle;
LARGE_INTEGER CapturedTimeout;
PLARGE_INTEGER NtTimeout;
//
// Validate the passed OS/2 2.0 semaphore handle and extract the
// shared/private flag and the index field. Return an error if
// not a valid handle.
//
rc = Od2ValidateSemaphoreHandle( MutexHandle,
&SharedSem,
&HandleIndex
);
if (rc != NO_ERROR) {
return( rc );
}
//
// Capture the timeout value and convert it into an NT timeout value.
//
NtTimeout = Od2CaptureTimeout( Timeout, (PLARGE_INTEGER)&CapturedTimeout );
//
// Get the pointer to either the shared or private semaphore table.
// Table must exist. Return an error if it does not.
//
SemaphoreTable = Od2GetSemaphoreTable( SharedSem, FALSE );
if (!SemaphoreTable) {
return( ERROR_INVALID_HANDLE );
}
//
// Map the semaphore handle into a pointer to the semaphore structure
// contained in the table. Return an error if the handle is outside
// the current limits of the table. If the mapping is successful then
// the semaphore table is left locked while we use the pointer.
//
Semaphore = (POD2_SEMAPHORE)Or2MapHandle( SemaphoreTable,
HandleIndex,
FALSE
);
if (Semaphore == NULL) {
return( ERROR_INVALID_HANDLE );
}
//
// Entry in semaphore table exists, so make sure it is a Mutex semaphore.
// Return an error if not, after unlock the table first.
//
if (Semaphore->Type != Od2MutexSem) {
ReleaseHandleTableLock( SemaphoreTable );
return( ERROR_INVALID_HANDLE );
}
//
// Entry in semaphore table is for a Mutex semaphore, so extract the
// NT Mutant handle from the record and release the lock, so we are
// not holding the lock while we are waiting.
//
Mutex = Semaphore->u.Mutex;
//
// Entry in semaphore table is for a Mutex semaphore, so extract the
// NT Mutant handle from the record and release the lock, so we are
// not holding the lock when the semaphore is released.
//
//
// Entry in semaphore table is for a Mutex semaphore, so see if the calling
// thread is already the owner. If so, just increment the request level.
// If the calling thread does not own the mutex, then we need to block
// attempting to acquire the mutant object that is backing this semaphore.
//
Mutex = Semaphore->u.Mutex;
if (Mutex->OwnerTid == (TID)Od2CurrentThreadId()) {
Mutex->OwnerRequestLevel += 1;
ReleaseHandleTableLock( SemaphoreTable );
return( NO_ERROR );
}
//
// Call the NT system service to wait for this Mutant to be released.
// This is an alertable wait, since by definition all OS/2 waits are
// alertable.
//
NtMutantHandle = Semaphore->u.Mutex->MutantHandle;
Od2ThreadWaitingOnSemaphore( SemaphoreTable, Semaphore, TRUE );
Status = NtWaitForSingleObject( Mutex->MutantHandle, TRUE, NtTimeout );
if (NT_SUCCESS( Status )) {
if (Status == STATUS_SUCCESS) {
Mutex->OwnerTid = (TID)Od2CurrentThreadId();
Mutex->OwnerRequestLevel = 1;
}
else
if (Status == STATUS_ABANDONED) {
rc = ERROR_SEM_OWNER_DIED;
}
else
if (Status == STATUS_TIMEOUT) {
rc = ERROR_TIMEOUT;
}
else
if (Status == STATUS_USER_APC || Status == STATUS_ALERTED) {
rc = ERROR_INTERRUPT;
}
}
else {
//
// If the NT system service failed, then some other thread must
// have closed the semaphore so return an error or this thread was
// alerted out of the wait. Return the appropriate error code.
//
if (Status == STATUS_INVALID_HANDLE) {
rc = ERROR_INVALID_HANDLE;
}
else {
rc = Or2MapStatus( Status );
}
}
Od2ThreadWaitingOnSemaphore( SemaphoreTable, Semaphore, FALSE );
//
// Return any error code to the caller.
//
return( rc );
}
APIRET
DosReleaseMutexSem(
IN HMTX MutexHandle
)
{
POR2_HANDLE_TABLE SemaphoreTable;
POD2_SEMAPHORE Semaphore;
POD2_MUTEX_SEMAPHORE Mutex;
BOOLEAN SharedSem;
ULONG HandleIndex;
APIRET rc;
NTSTATUS Status;
LONG NtMutantCount;
//
// Validate the passed OS/2 2.0 semaphore handle and extract the
// shared/private flag and the index field. Return an error if
// not a valid handle.
//
rc = Od2ValidateSemaphoreHandle( MutexHandle,
&SharedSem,
&HandleIndex
);
if (rc != NO_ERROR) {
return( rc );
}
//
// Get the pointer to either the shared or private semaphore table.
// Table must exist. Return an error if it does not.
//
SemaphoreTable = Od2GetSemaphoreTable( SharedSem, FALSE );
if (!SemaphoreTable) {
return( ERROR_INVALID_HANDLE );
}
//
// Map the semaphore handle into a pointer to the semaphore structure
// contained in the table. Return an error if the handle is outside
// the current limits of the table. If the mapping is successful then
// the semaphore table is left locked while we use the pointer.
//
Semaphore = (POD2_SEMAPHORE)Or2MapHandle( SemaphoreTable,
HandleIndex,
FALSE
);
if (Semaphore == NULL) {
return( ERROR_INVALID_HANDLE );
}
//
// Entry in semaphore table exists, so make sure it is a Mutex semaphore.
// Return an error if not, after unlock the table first.
//
if (Semaphore->Type != Od2MutexSem) {
ReleaseHandleTableLock( SemaphoreTable );
return( ERROR_INVALID_HANDLE );
}
//
// Entry in semaphore table is for a Mutex semaphore, so see if the calling
// thread is already the owner. If so, just decrement the request level
// and if the request level goes to zero we need to release the mutant
// that is backing this mutex. If the calling thread does not own the
// mutex, return an error.
//
Mutex = Semaphore->u.Mutex;
if (Mutex->OwnerTid != (TID)Od2CurrentThreadId()) {
rc = ERROR_NOT_OWNER;
}
else
//
// If the calling thread is the owner and this release will be their
// last, do the work to really release it.
//
if ((Mutex->OwnerRequestLevel -= 1) == 0) {
//
// Mark the mutex as unowned.
//
Mutex->OwnerTid = NULL;
//
// Call the NT system service to release the Mutant
//
Status = NtReleaseMutant( Semaphore->u.Mutex->MutantHandle,
&NtMutantCount
);
//
// Okay to release the semaphore handle table lock
//
ReleaseHandleTableLock( SemaphoreTable );
if (!NT_SUCCESS( Status )) {
//
// If the NT system service failed, then some other thread must
// have closed the semaphore so return an error.
//
if (Status == STATUS_MUTANT_NOT_OWNED) {
rc = ERROR_NOT_OWNER;
}
else {
rc = ERROR_INVALID_HANDLE;
}
}
else
if (Status == STATUS_ABANDONED) {
rc = ERROR_SEM_OWNER_DIED;
}
}
else {
//
// All the work is done, as they still own the mutex or were not
// the owner in the first place, so okay to release the semaphore
// handle table lock
//
ReleaseHandleTableLock( SemaphoreTable );
}
//
// Return any error code to the caller.
//
return( rc );
}
APIRET
DosQueryMutexSem(
IN HMTX MutexHandle,
OUT PPID OwnerPid,
OUT PTID OwnerTid,
OUT PULONG OwnerRequestLevel
)
{
POR2_HANDLE_TABLE SemaphoreTable;
POD2_SEMAPHORE Semaphore;
POD2_MUTEX_SEMAPHORE Mutex;
BOOLEAN SharedSem;
ULONG HandleIndex;
APIRET rc;
//
// Validate the passed OS/2 2.0 semaphore handle and extract the
// shared/private flag and the index field. Return an error if
// not a valid handle.
//
rc = Od2ValidateSemaphoreHandle( MutexHandle,
&SharedSem,
&HandleIndex
);
if (rc != NO_ERROR) {
return( rc );
}
//
// Get the pointer to either the shared or private semaphore table.
// Table must exist. Return an error if it does not.
//
SemaphoreTable = Od2GetSemaphoreTable( SharedSem, FALSE );
if (!SemaphoreTable) {
return( ERROR_INVALID_HANDLE );
}
//
// Map the semaphore handle into a pointer to the semaphore structure
// contained in the table. Return an error if the handle is outside
// the current limits of the table. If the mapping is successful then
// the semaphore table is left locked while we use the pointer.
//
Semaphore = (POD2_SEMAPHORE)Or2MapHandle( SemaphoreTable,
HandleIndex,
FALSE
);
if (Semaphore == NULL) {
return( ERROR_INVALID_HANDLE );
}
//
// Entry in semaphore table exists, so make sure it is a Mutex semaphore.
// Return an error if not, after unlock the table first.
//
if (Semaphore->Type != Od2MutexSem) {
ReleaseHandleTableLock( SemaphoreTable );
return( ERROR_INVALID_HANDLE );
}
//
// Entry in semaphore table is for a Mutex semaphore, so extract the
// NT Mutant handle from the record, along with the current owning
// thread.
//
Mutex = Semaphore->u.Mutex;
try {
if (Mutex->OwnerTid != 0) {
*OwnerTid = Mutex->OwnerTid;
*OwnerPid = Od2Process->Pib.ProcessId;
*OwnerRequestLevel = Mutex->OwnerRequestLevel;
}
else {
*OwnerPid = 0;
*OwnerTid = 0;
*OwnerRequestLevel = 0;
}
}
except( EXCEPTION_EXECUTE_HANDLER ) {
Od2ExitGP();
}
//
// Release the semaphore table lock and return any error code.
//
ReleaseHandleTableLock( SemaphoreTable );
return( rc );
}