Esempio n. 1
0
PAL_ERROR
CorUnix::InternalReleaseSemaphore(
    CPalThread *pthr,
    HANDLE hSemaphore,
    LONG lReleaseCount,
    LPLONG lpPreviousCount
    )
{
    PAL_ERROR palError = NO_ERROR;
    IPalObject *pobjSemaphore = NULL;
    ISynchStateController *pssc = NULL;
    SemaphoreImmutableData *pSemaphoreData;
    LONG lOldCount;

    _ASSERTE(NULL != pthr);

    ENTRY("InternalReleaseSempahore(pthr=%p, hSemaphore=%p, lReleaseCount=%d, "
        "lpPreviousCount=%p)\n",
        pthr,
        hSemaphore,
        lReleaseCount,
        lpPreviousCount
        );

    if (0 >= lReleaseCount)
    {
        palError = ERROR_INVALID_PARAMETER;
        goto InternalReleaseSemaphoreExit;
    }

    palError = g_pObjectManager->ReferenceObjectByHandle(
        pthr,
        hSemaphore,
        &aotSempahore, 
        0, // Should be SEMAPHORE_MODIFY_STATE; currently ignored (no Win32 security)
        &pobjSemaphore
        );

    if (NO_ERROR != palError)
    {
        ERROR("Unable to obtain object for handle %p (error %d)!\n", hSemaphore, palError);
        goto InternalReleaseSemaphoreExit;
    }

    palError = pobjSemaphore->GetImmutableData(reinterpret_cast<void**>(&pSemaphoreData));
    
    if (NO_ERROR != palError)
    {
        ASSERT("Error %d obtaining object data\n", palError);
        goto InternalReleaseSemaphoreExit;
    }

    palError = pobjSemaphore->GetSynchStateController(
        pthr,
        &pssc
        );

    if (NO_ERROR != palError)
    {
        ASSERT("Error %d obtaining synch state controller\n", palError);
        goto InternalReleaseSemaphoreExit;
    }

    palError = pssc->GetSignalCount(&lOldCount);

    if (NO_ERROR != palError)
    {
        ASSERT("Error %d obtaining current signal count\n", palError);
        goto InternalReleaseSemaphoreExit;
    }

    _ASSERTE(lOldCount <= pSemaphoreData->lMaximumCount);
    if (lReleaseCount > pSemaphoreData->lMaximumCount - lOldCount)
    {
        palError = ERROR_INVALID_PARAMETER;
        goto InternalReleaseSemaphoreExit;
    }

    palError = pssc->IncrementSignalCount(lReleaseCount);
    
    if (NO_ERROR != palError)
    {
        ASSERT("Error %d incrementing signal count\n", palError);
        goto InternalReleaseSemaphoreExit;
    }

    if (NULL != lpPreviousCount)
    {
        *lpPreviousCount = lOldCount;
    }

InternalReleaseSemaphoreExit:

    if (NULL != pssc)
    {
        pssc->ReleaseController();
    }

    if (NULL != pobjSemaphore)
    {
        pobjSemaphore->ReleaseReference(pthr);
    }

    LOGEXIT("InternalReleaseSemaphore returns %d\n", palError);

    return palError;
}