/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
dllmuxwt.c
Abstract:
This module implements the OS/2 V2.0 MuxWait Semaphore API Calls.
Author:
Steve Wood (stevewo) 07-Feb-1990
Revision History:
--*/
#define INCL_OS2V20_SEMAPHORES
#define INCL_OS2V20_ERRORS
#include "os2dll.h"
APIRET
Od2AddMuxWait(
IN POD2_MUXWAIT_SEMAPHORE MuxWait,
IN PSEMRECORD MuxWaitEntry
)
{
POD2_MUXWAIT_RECORD MuxWaitRecord;
APIRET rc;
BOOLEAN SharedSem;
POR2_HANDLE_TABLE SemaphoreTable;
POD2_SEMAPHORE Semaphore;
ULONG Handle;
USHORT i;
if (MuxWait->CountMuxWaitRecords == DCMW_MAX_SEMRECORDS) {
return( ERROR_TOO_MANY_SEMAPHORES );
}
//
// 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( MuxWaitEntry->hsemCur,
&SharedSem,
&Handle
);
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,
Handle,
TRUE
);
if (Semaphore == NULL) {
return( ERROR_INVALID_HANDLE );
}
//
// Now see if this semaphore is already in the MuxWait semaphore.
// Return an error if it is.
//
MuxWaitRecord = &MuxWait->MuxWaitRecords[ 0 ];
for (i=0; i<MuxWait->CountMuxWaitRecords; i++) {
if (MuxWaitRecord->Semaphore == Semaphore) {
return( ERROR_DUPLICATE_HANDLE );
}
MuxWaitRecord++;
}
//
// Entry in semaphore table exists, so make sure it is not a MuxWait
// semaphore. Also make sure it is that same type of semaphore as the
// first semaphore. Also make sure if the MuxWait semaphore that all
// the component semaphores are also shared. Return an error if any
// of these conditions are not met.
//
if (Semaphore->Type == Od2MuxWaitSem) {
return( ERROR_WRONG_TYPE );
}
if (MuxWait->CountMuxWaitRecords == 0) {
MuxWait->Type = Semaphore->Type;
}
else
if (Semaphore->Type != MuxWait->Type) {
return( ERROR_WRONG_TYPE );
}
//
// At this point everything is copasetic, so fill in the next available
// record in the MuxWait semaphore.
//
MuxWaitRecord->SemHandle = MuxWaitEntry->hsemCur;
MuxWaitRecord->UserKey = MuxWaitEntry->ulUser;
MuxWaitRecord->Semaphore = Od2ReferenceSemaphore( Semaphore );
MuxWait->CountMuxWaitRecords++;
return( NO_ERROR );
}
APIRET
Od2DeleteMuxWait(
IN POD2_MUXWAIT_SEMAPHORE MuxWait,
IN ULONG MuxWaitEntryIndex,
IN HSEM MuxWaitEntrySem OPTIONAL
)
{
POD2_MUXWAIT_RECORD MuxWaitRecord;
USHORT i;
if (MuxWait->CountMuxWaitRecords == 0) {
return( ERROR_EMPTY_MUXWAIT );
}
MuxWaitRecord = &MuxWait->MuxWaitRecords[ 0 ];
for (i=0; i<MuxWait->CountMuxWaitRecords; i++) {
if (ARGUMENT_PRESENT( MuxWaitEntrySem )) {
if (MuxWaitRecord->SemHandle == MuxWaitEntrySem) {
break;
}
}
else
if (i == (USHORT)MuxWaitEntryIndex) {
break;
}
MuxWaitRecord++;
}
if (i == MuxWait->CountMuxWaitRecords) {
return( ERROR_INVALID_HANDLE );
}
Od2DereferenceSemaphore( MuxWaitRecord->Semaphore );
MuxWait->CountMuxWaitRecords -= 1;
for (; i<MuxWait->CountMuxWaitRecords; i++) {
*MuxWaitRecord = *(MuxWaitRecord+1);
MuxWaitRecord++;
}
MuxWaitRecord->Semaphore = NULL;
MuxWaitRecord->SemHandle = 0;
MuxWaitRecord->UserKey = 0;
return( NO_ERROR );
}
APIRET
DosCreateMuxWaitSem(
IN PSZ ObjectName,
IN OUT PHMUX MuxWaitHandle,
IN ULONG CountMuxWaitEntries,
IN SEMRECORD MuxWaitEntries[],
IN ULONG CreateAttributes
)
{
OS2_API_MSG m;
POS2_DOSCREATEMUXWAITSEM_MSG a = &m.u.DosCreateMuxWaitSem;
POS2_DOSCLOSEMUXWAITSEM_MSG a1 = &m.u.DosCloseMuxWaitSem;
POS2_CAPTURE_HEADER CaptureBuffer;
PSEMRECORD CapturedMuxWaitEntries;
APIRET rc;
ULONG i;
BOOLEAN SharedSem;
ULONG MuxWaitType;
POR2_HANDLE_TABLE SemaphoreTable;
OD2_SEMAPHORE Semaphore;
POD2_MUXWAIT_SEMAPHORE MuxWait;
//
// Validate the simple parameters
//
MuxWaitType = CreateAttributes & (DCMW_WAIT_ANY | DCMW_WAIT_ALL);
if (MuxWaitType == 0 ||
!(MuxWaitType ^ (DCMW_WAIT_ANY | DCMW_WAIT_ALL)) ||
CreateAttributes & ~(DC_SEM_SHARED | DCMW_WAIT_ANY | DCMW_WAIT_ALL)
) {
return( ERROR_INVALID_PARAMETER );
}
if (CountMuxWaitEntries > DCMW_MAX_SEMRECORDS) {
return( ERROR_TOO_MANY_SEMAPHORES );
}
//
// probe handle pointer and MuxWaitEntries buffer
//
try {
Od2ProbeForWrite( (PVOID)MuxWaitHandle, sizeof( MuxWaitHandle ), 1 );
Od2ProbeForRead(MuxWaitEntries,sizeof(SEMRECORD)*CountMuxWaitEntries,1);
} except( EXCEPTION_EXECUTE_HANDLER ) {
Od2ExitGP();
}
//
// Capture and validate any semaphore name.
//
rc = Od2CaptureObjectName( ObjectName,
CANONICALIZE_SEMAPHORE,
sizeof( OD2_MUXWAIT_SEMAPHORE ),
&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. Lock the table for the duration of this
// API call.
//
SemaphoreTable = Od2GetSemaphoreTable( SharedSem, TRUE );
if (!SemaphoreTable) {
if (CaptureBuffer != NULL) {
Od2FreeCaptureBuffer( CaptureBuffer );
}
return( ERROR_NOT_ENOUGH_MEMORY );
}
//
// Initialize the Client OS/2 Semaphore Structure
//
Semaphore.Type = Od2MuxWaitSem;
Semaphore.Shared = SharedSem;
Semaphore.PointerCount = 0;
Semaphore.OpenCount = 1;
Semaphore.u.MuxWait = MuxWait = NULL;
//
// Mark the fact that we are creating a semaphore handle.
//
a->HandleIndex = 0xFFFFFFFF;
if (SharedSem) {
//
// For shared semaphores, we need to pass the create to OS/2 Subsystem
// so that it can manager adds and deletes.
//
//
// If one or more SEMRECORDs then allocate space for a copy in the
// CaptureBuffer so we can pass the array to the server.
//
if (CountMuxWaitEntries != 0) {
if (CaptureBuffer == NULL) {
CaptureBuffer = Od2AllocateCaptureBuffer(
1,
0,
(sizeof( OD2_MUXWAIT_SEMAPHORE ) + 3) & ~3
);
if (CaptureBuffer == NULL) {
return( ERROR_NOT_ENOUGH_MEMORY );
}
}
Od2AllocateMessagePointer( CaptureBuffer,
CountMuxWaitEntries * sizeof( SEMRECORD ),
(PVOID *)&(a->MuxWaitEntries)
);
CapturedMuxWaitEntries = a->MuxWaitEntries;
for (i=0; i<CountMuxWaitEntries; i++) {
CapturedMuxWaitEntries->ulUser = MuxWaitEntries->ulUser;
rc = Od2ValidateSemaphoreHandle(
MuxWaitEntries->hsemCur,
&SharedSem,
(PULONG)&CapturedMuxWaitEntries->hsemCur
);
if (rc != NO_ERROR) {
break;
}
else
if (!SharedSem) {
rc = ERROR_WRONG_TYPE;
break;
}
else {
MuxWaitEntries++;
CapturedMuxWaitEntries++;
}
}
}
else {
a->MuxWaitEntries = NULL;
}
if (rc != NO_ERROR) {
if (CaptureBuffer != NULL) {
Od2FreeCaptureBuffer( CaptureBuffer );
}
return( rc );
}
//
// Pass the call to the OS/2 subsystem to create the system wide
// semaphore handle value.
//
a->CreateAttributes = CreateAttributes | DC_SEM_SHARED;
a->CountMuxWaitEntries = CountMuxWaitEntries;
rc = Od2CallSubsystem( &m,
CaptureBuffer,
Os2CreateMuxWaitSem,
sizeof( *a )
);
//
// Free any capture buffer, since the subsystem has saved away any
// semaphore name in its table.
//
if (CaptureBuffer != NULL) {
Od2FreeCaptureBuffer( CaptureBuffer );
}
//
// At this point, the semaphore handle index has been stored in
// a->HandleIndex by the OS/2 subsystem, if rc is NO_ERROR
//
}
else {
//
// Private semaphore. Allocate the muxwait semaphore structure.
// Return an error if not enough memory to allocate the structure.
//
MuxWait = RtlAllocateHeap( Od2Heap, 0, sizeof( *MuxWait ) );
if (MuxWait == NULL) {
return( ERROR_NOT_ENOUGH_MEMORY );
}
//
// Initialize the muxwait semaphore sturcture to contain zero records.
//
MuxWait->CountMuxWaitRecords = 0;
MuxWait->Type = 0;
MuxWait->WaitAll = (BOOLEAN)((CreateAttributes & DCMW_WAIT_ALL) != 0);
MuxWait->Reserved = 0;
//
// Loop over the input array of SEMRECORDs adding them one at a time
// to the muxwait semaphore. Bail out of loop if any errors occur.
// Lock the semaphore table prior to entering the loop so that things
// change change out from under us.
//
AcquireHandleTableLock( SemaphoreTable );
for (i=0; i<CountMuxWaitEntries; i++) {
rc = Od2AddMuxWait( MuxWait,
MuxWaitEntries
);
if (rc != NO_ERROR) {
break;
}
else {
MuxWaitEntries++;
}
}
//
// All done. If successful, store the address of the muxwait structure
// in the semaphore structure.
//
if (rc == NO_ERROR) {
Semaphore.u.MuxWait = MuxWait;
}
}
//
// 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 (rc != NO_ERROR ||
!Or2CreateHandle( SemaphoreTable,
&a->HandleIndex,
(PVOID)&Semaphore
)
) {
//
// Error occurred. Cleanup any partial results.
//
if (!SharedSem) {
if (MuxWait != NULL) {
//
// For a private muxwait semaphore, deconstruct whatever
// portion of the muxwait semaphore that was successfully
// constructed and then free the allocated memory and release
// the lock we acquired at the beginning of the construction
// process.
//
while (Od2DeleteMuxWait( MuxWait, 0, 0 ) == NO_ERROR) {
;
}
RtlFreeHeap( Od2Heap, 0, MuxWait );
}
ReleaseHandleTableLock( SemaphoreTable );
}
else
if (a->HandleIndex != -1) {
//
// If this is a shared semaphore that successfully created the
// handle in the OS/2 subsystem, then call the subsystem to
// close our reference to this shared OS/2 semaphore.
//
a1->HandleIndex = a->HandleIndex;
Od2CallSubsystem( &m, NULL, Os2CloseMuxWaitSem, sizeof( *a1 ) );
}
//
// Return the error code to the caller.
//
if (rc == NO_ERROR) {
return( ERROR_NOT_ENOUGH_MEMORY );
}
else {
return( rc );
}
}
//
// Okay to release the lock we held while building the private muxwait
// semaphore.
//
if (!SharedSem) {
ReleaseHandleTableLock( SemaphoreTable );
}
//
// Success. Store a valid OS/2 2.0 Semaphore handle in the location
// specified by the caller and return success to the caller.
//
*MuxWaitHandle = Od2ConstructSemaphoreHandle( SharedSem,
a->HandleIndex
);
return( NO_ERROR );
}
APIRET
DosOpenMuxWaitSem(
IN PSZ ObjectName,
IN OUT PHMUX MuxWaitHandle
)
{
OS2_API_MSG m;
POS2_DOSOPENMUXWAITSEM_MSG a = &m.u.DosOpenMuxWaitSem;
POS2_DOSCLOSEMUXWAITSEM_MSG a1 = &m.u.DosCloseMuxWaitSem;
POS2_CAPTURE_HEADER CaptureBuffer;
POR2_HANDLE_TABLE SemaphoreTable;
OD2_SEMAPHORE NewSemaphore;
POD2_SEMAPHORE Semaphore;
BOOLEAN SharedSem;
APIRET rc;
//
// probe handle pointer
//
try {
Od2ProbeForWrite( (PVOID)MuxWaitHandle, sizeof( MuxWaitHandle ), 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,
Os2OpenMuxWaitSem,
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. 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 (*MuxWaitHandle != NULL &&
*MuxWaitHandle != Od2ConstructSemaphoreHandle( SharedSem,
a->HandleIndex
)
) {
return( ERROR_INVALID_PARAMETER );
}
}
else {
//
// Opening by handle. Validate the handle and get the shared/private
// flag.
//
rc = Od2ValidateSemaphoreHandle( *MuxWaitHandle,
&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,
Os2OpenMuxWaitSem,
sizeof( *a )
);
if (rc == NO_ERROR) {
//
// If we succeeded, then the semaphore was not deleted
// in between the two calls to the subsystem, so add an
// entry for this handle in the semaphore table.
//
NewSemaphore.Type = Od2MuxWaitSem;
NewSemaphore.Shared = TRUE;
NewSemaphore.PointerCount = 0;
NewSemaphore.OpenCount = 1;
NewSemaphore.u.MuxWait = 0;
if (!Or2CreateHandle( SemaphoreTable,
&a->HandleIndex,
(PVOID)&NewSemaphore
)
) {
//
// Unable to create the entry. Call the OS/2 subsystem
// to close our reference to this shared OS/2 semaphore.
// Set the appropriate error code.
//
a1->HandleIndex = a->HandleIndex;
Od2CallSubsystem( &m,
NULL,
Os2CloseMuxWaitSem,
sizeof( *a1 )
);
rc = ERROR_NOT_ENOUGH_MEMORY;
}
}
}
}
//
// Entry in semaphore table exists, so make sure it is a MuxWait semaphore.
// Set the appropriate error code if not.
//
else
if (Semaphore->Type != Od2MuxWaitSem) {
rc = ERROR_INVALID_HANDLE;
}
//
// Entry in semaphore table is for a MuxWait 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) {
*MuxWaitHandle = Od2ConstructSemaphoreHandle( SharedSem,
a->HandleIndex
);
}
//
// Return an error code to the caller.
//
return( rc );
}
APIRET
DosCloseMuxWaitSem(
IN HMUX MuxWaitHandle
)
{
OS2_API_MSG m;
POS2_DOSCLOSEMUXWAITSEM_MSG a = &m.u.DosCloseMuxWaitSem;
POD2_MUXWAIT_SEMAPHORE MuxWait;
POR2_HANDLE_TABLE SemaphoreTable;
POD2_SEMAPHORE Semaphore;
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( MuxWaitHandle,
&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 MuxWait semaphore.
// Return an error if not, after unlock the table first.
//
if (Semaphore->Type != Od2MuxWaitSem) {
ReleaseHandleTableLock( SemaphoreTable );
return( ERROR_INVALID_HANDLE );
}
//
// Entry in semaphore table is for a MuxWait 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.
//
//
// First make sure that no thread in this process is waiting on this
// muxwait semaphore. If there is one waiting on it, increment the
// open count and return an error.
//
if (Od2SearchForWaitingThread( Semaphore )) {
Semaphore->OpenCount++;
ReleaseHandleTableLock( SemaphoreTable );
rc = ERROR_SEM_BUSY;
}
else {
//
// Okay to really close this muxwait semaphore. First destroy
// the handle, which will unlock the handle table.
//
MuxWait = Semaphore->u.MuxWait;
Or2DestroyHandle( SemaphoreTable, a->HandleIndex );
if (!SharedSem) {
//
// If not a shared semaphore, free the muxwait structure
// associated with this muxwait semaphore.
//
if (MuxWait != NULL) {
while (Od2DeleteMuxWait( MuxWait, 0, 0 ) == NO_ERROR) {
;
}
RtlFreeHeap( Od2Heap, 0, MuxWait );
}
}
else {
//
// If this is a shared semaphore, call the subsystem so that it
// can decrement its open count, as this process is no longer
// using the shared semaphore handle.
//
rc = Od2CallSubsystem( &m,
NULL,
Os2CloseMuxWaitSem,
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
DosWaitMuxWaitSem(
IN HMUX MuxWaitHandle,
IN ULONG Timeout,
OUT PULONG UserValue
)
{
NTSTATUS Status;
OS2_API_MSG m;
POS2_DOSWAITMUXWAITSEM_MSG a = &m.u.DosWaitMuxWaitSem;
POD2_MUXWAIT_SEMAPHORE MuxWait;
POD2_MUXWAIT_RECORD MuxWaitRecord;
POR2_HANDLE_TABLE SemaphoreTable;
POD2_SEMAPHORE Semaphore;
OD2_SEMAPHORE_TYPE MuxWaitType;
BOOLEAN SharedSem;
APIRET rc;
USHORT i;
HANDLE NtHandles[ MAXIMUM_WAIT_OBJECTS ];
PLARGE_INTEGER NtTimeout;
try {
*UserValue = 0;
}
except( EXCEPTION_EXECUTE_HANDLER ) {
Od2ExitGP();
}
//
// Capture the timeout value and convert it into an NT timeout value.
//
NtTimeout = Od2CaptureTimeout( Timeout, (PLARGE_INTEGER)&a->Timeout );
//
// 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.
//
retry:
rc = Od2ValidateSemaphoreHandle( MuxWaitHandle,
&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 MuxWait semaphore.
// Return an error if not, after unlock the table first.
//
if (Semaphore->Type != Od2MuxWaitSem) {
ReleaseHandleTableLock( SemaphoreTable );
return( ERROR_INVALID_HANDLE );
}
if (SharedSem) {
Od2ThreadWaitingOnSemaphore( SemaphoreTable, Semaphore, TRUE );
rc = Od2CallSubsystem( &m,
NULL,
Os2WaitMuxWaitSem,
sizeof( *a )
);
Od2ThreadWaitingOnSemaphore( SemaphoreTable, Semaphore, FALSE );
}
else {
MuxWait = Semaphore->u.MuxWait;
if (MuxWait->CountMuxWaitRecords == 0) {
ReleaseHandleTableLock( SemaphoreTable );
return( ERROR_EMPTY_MUXWAIT );
}
MuxWaitRecord = &MuxWait->MuxWaitRecords[ 0 ];
MuxWaitType = MuxWait->Type;
for (i=0; i<MuxWait->CountMuxWaitRecords; i++) {
if (MuxWaitType == Od2EventSem) {
NtHandles[ i ] = MuxWaitRecord->Semaphore->u.EventHandle;
}
else
if (MuxWaitType == Od2MutexSem) {
NtHandles[ i ] = MuxWaitRecord->Semaphore->u.Mutex->MutantHandle;
}
else {
ReleaseHandleTableLock( SemaphoreTable );
return( ERROR_INVALID_HANDLE );
}
MuxWaitRecord++;
}
Od2ThreadWaitingOnSemaphore( SemaphoreTable, Semaphore, TRUE );
Status = NtWaitForMultipleObjects(
(CHAR)i,
NtHandles,
MuxWait->WaitAll ? WaitAll : WaitAny,
TRUE,
NtTimeout
);
if (NT_SUCCESS( Status )) {
if (Status <= STATUS_WAIT_63) {
*UserValue = MuxWait->MuxWaitRecords[ (ULONG)(Status & 0x3F)
].UserKey;
rc = NO_ERROR;
}
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_SS_RETRY;
}
else {
rc = Or2MapStatus( Status );
}
}
else {
rc = Or2MapStatus( Status );
}
Od2ThreadWaitingOnSemaphore( SemaphoreTable, Semaphore, FALSE );
if (rc == ERROR_SS_RETRY) {
goto retry;
}
}
return( rc );
}
APIRET
DosAddMuxWaitSem(
IN HMUX MuxWaitHandle,
IN PSEMRECORD MuxWaitEntry
)
{
OS2_API_MSG m, m1;
POS2_DOSADDMUXWAITSEM_MSG a = &m.u.DosAddMuxWaitSem;
POS2_ALERTMUXWAITER_MSG a1 = &m1.u.AlertMuxWaiter;
POR2_HANDLE_TABLE SemaphoreTable;
POD2_SEMAPHORE Semaphore;
POD2_THREAD Thread;
BOOLEAN SharedSem;
APIRET rc;
//
// probe MuxWaitEntry buffer
//
try {
Od2ProbeForRead(MuxWaitEntry,sizeof(SEMRECORD),1);
} except( EXCEPTION_EXECUTE_HANDLER ) {
Od2ExitGP();
}
//
// 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( MuxWaitHandle,
&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 MuxWait semaphore.
// Return an error if not, after unlock the table first.
//
if (Semaphore->Type != Od2MuxWaitSem) {
ReleaseHandleTableLock( SemaphoreTable );
return( ERROR_INVALID_HANDLE );
}
if (SharedSem) {
a->MuxWaitEntry.ulUser = MuxWaitEntry->ulUser;
rc = Od2ValidateSemaphoreHandle( MuxWaitEntry->hsemCur,
&SharedSem,
(PULONG)&a->MuxWaitEntry.hsemCur
);
if (rc == NO_ERROR && !SharedSem) {
rc = ERROR_WRONG_TYPE;
}
if (rc == NO_ERROR) {
rc = Od2CallSubsystem( &m,
NULL,
Os2AddMuxWaitSem,
sizeof( *a )
);
}
}
else {
rc = Od2AddMuxWait( Semaphore->u.MuxWait, MuxWaitEntry );
if (rc == NO_ERROR &&
(Thread = Od2SearchForWaitingThread( Semaphore ))
) {
rc = Od2CallSubsystem( &m1,
NULL,
Oi2AlertMuxWaiter,
sizeof( *a1 )
);
}
}
ReleaseHandleTableLock( SemaphoreTable );
return( rc );
}
APIRET
DosDeleteMuxWaitSem(
IN HMUX MuxWaitHandle,
IN HSEM MuxWaitEntrySem
)
{
OS2_API_MSG m;
POS2_DOSDELETEMUXWAITSEM_MSG a = &m.u.DosDeleteMuxWaitSem;
POR2_HANDLE_TABLE SemaphoreTable;
POD2_SEMAPHORE Semaphore;
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( MuxWaitHandle,
&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 MuxWait semaphore.
// Return an error if not, after unlock the table first.
//
if (Semaphore->Type != Od2MuxWaitSem) {
ReleaseHandleTableLock( SemaphoreTable );
return( ERROR_INVALID_HANDLE );
}
if (SharedSem) {
rc = Od2ValidateSemaphoreHandle( MuxWaitEntrySem,
&SharedSem,
&a->EntryHandleIndex
);
if (!SharedSem) {
rc = ERROR_INVALID_HANDLE;
}
if (rc == NO_ERROR) {
rc = Od2CallSubsystem( &m,
NULL,
Os2DeleteMuxWaitSem,
sizeof( *a )
);
}
}
else {
rc = Od2DeleteMuxWait( Semaphore->u.MuxWait, 0, MuxWaitEntrySem );
}
ReleaseHandleTableLock( SemaphoreTable );
return( rc );
}
APIRET
DosQueryMuxWaitSem(
IN HMUX MuxWaitHandle,
IN OUT PULONG CountMuxWaitEntries,
OUT SEMRECORD MuxWaitEntries[],
OUT PULONG CreateAttributes
)
{
OS2_API_MSG m;
POS2_DOSQUERYMUXWAITSEM_MSG a = &m.u.DosQueryMuxWaitSem;
POS2_CAPTURE_HEADER CaptureBuffer;
PSEMRECORD CapturedMuxWaitEntries;
POD2_MUXWAIT_SEMAPHORE MuxWait;
POD2_MUXWAIT_RECORD MuxWaitRecord;
POR2_HANDLE_TABLE SemaphoreTable;
POD2_SEMAPHORE Semaphore;
BOOLEAN SharedSem;
APIRET rc;
USHORT i;
//
// probe CreateAttributes, CountMuxWaitEntries, and MuxWaitEntries buffer
//
try {
Od2ProbeForWrite( CountMuxWaitEntries, sizeof( CountMuxWaitEntries ), 1 );
Od2ProbeForWrite( CreateAttributes, sizeof( CreateAttributes ), 1 );
Od2ProbeForWrite(MuxWaitEntries,*CountMuxWaitEntries * sizeof(SEMRECORD),1);
} except( EXCEPTION_EXECUTE_HANDLER ) {
Od2ExitGP();
}
//
// 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( MuxWaitHandle,
&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 MuxWait semaphore.
// Return an error if not, after unlock the table first.
//
if (Semaphore->Type != Od2MuxWaitSem) {
ReleaseHandleTableLock( SemaphoreTable );
return( ERROR_INVALID_HANDLE );
}
if (SharedSem) {
a->CountMuxWaitEntries = *CountMuxWaitEntries;
i = (USHORT)(((a->CountMuxWaitEntries * sizeof( SEMRECORD )) + 3) & ~3);
CaptureBuffer = Od2AllocateCaptureBuffer( 1, 0, i );
if (CaptureBuffer == NULL) {
rc = ERROR_NOT_ENOUGH_MEMORY;
}
else {
Od2AllocateMessagePointer( CaptureBuffer,
i,
&(PVOID)(a->MuxWaitEntries)
);
rc = Od2CallSubsystem( &m,
CaptureBuffer,
Os2QueryMuxWaitSem,
sizeof( *a )
);
if (rc == NO_ERROR) {
*CreateAttributes = a->CreateAttributes;
*CountMuxWaitEntries = a->CountMuxWaitEntries;
CapturedMuxWaitEntries = a->MuxWaitEntries;
for (i=0; i<(USHORT)a->CountMuxWaitEntries; i++) {
MuxWaitEntries->hsemCur =
Od2ConstructSemaphoreHandle(
TRUE, (ULONG)CapturedMuxWaitEntries->hsemCur
);
MuxWaitEntries->ulUser = CapturedMuxWaitEntries->ulUser;
MuxWaitEntries++;
CapturedMuxWaitEntries++;
}
}
else
if (rc == ERROR_PARAM_TOO_SMALL) {
*CountMuxWaitEntries = a->CountMuxWaitEntries;
}
Od2FreeCaptureBuffer( CaptureBuffer );
}
}
else {
MuxWait = Semaphore->u.MuxWait;
if (*CountMuxWaitEntries < (ULONG)MuxWait->CountMuxWaitRecords) {
rc = ERROR_PARAM_TOO_SMALL;
}
else {
*CreateAttributes =
(Semaphore->Shared ? DC_SEM_SHARED : 0) |
(MuxWait->WaitAll ? DCMW_WAIT_ALL : DCMW_WAIT_ANY);
MuxWaitRecord = &MuxWait->MuxWaitRecords[ 0 ];
for (i=0; i<MuxWait->CountMuxWaitRecords; i++) {
MuxWaitEntries->hsemCur = MuxWaitRecord->SemHandle;
MuxWaitEntries->ulUser = MuxWaitRecord->UserKey;
MuxWaitEntries++;
MuxWaitRecord++;
}
rc = NO_ERROR;
}
*CountMuxWaitEntries = (ULONG)MuxWait->CountMuxWaitRecords;
}
ReleaseHandleTableLock( SemaphoreTable );
return( rc );
}