summaryrefslogtreecommitdiffstats
path: root/private/os2/client/dllmuxwt.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/os2/client/dllmuxwt.c
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/os2/client/dllmuxwt.c')
-rw-r--r--private/os2/client/dllmuxwt.c1423
1 files changed, 1423 insertions, 0 deletions
diff --git a/private/os2/client/dllmuxwt.c b/private/os2/client/dllmuxwt.c
new file mode 100644
index 000000000..bdd6d3e81
--- /dev/null
+++ b/private/os2/client/dllmuxwt.c
@@ -0,0 +1,1423 @@
+/*++
+
+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 );
+}