From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/os2/client/dllmuxwt.c | 1423 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1423 insertions(+) create mode 100644 private/os2/client/dllmuxwt.c (limited to 'private/os2/client/dllmuxwt.c') 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; iCountMuxWaitRecords; 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; iCountMuxWaitRecords; 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 (; iCountMuxWaitRecords; 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; iulUser = 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; iHandleIndex + // + + 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; iCountMuxWaitRecords; 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; iCountMuxWaitRecords; i++) { + MuxWaitEntries->hsemCur = MuxWaitRecord->SemHandle; + MuxWaitEntries->ulUser = MuxWaitRecord->UserKey; + MuxWaitEntries++; + MuxWaitRecord++; + } + + rc = NO_ERROR; + } + + *CountMuxWaitEntries = (ULONG)MuxWait->CountMuxWaitRecords; + } + + ReleaseHandleTableLock( SemaphoreTable ); + + return( rc ); +} -- cgit v1.2.3