Beispiel #1
0
//-----------------------------------------------------------------------------
// Wrap an unsafe call in a mutex to assure safety
// Biggest error issues are:
// 1. Timeout (probably handler doesn't exist)
// 2. Handler can be destroyed at any time.
//-----------------------------------------------------------------------------
IPCFuncCallSource::EError IPCFuncCallSource::DoThreadSafeCall()
{
    DWORD dwErr;
    EError err = Ok;

#if defined(ENABLE_TIMING)
    g_time.Reset();
    g_time.Start();
#endif

    HANDLE hStartEnum = NULL;
    HANDLE hDoneEnum = NULL;
    HANDLE hWrapCall = NULL;
    DWORD dwWaitRet;

    // Check if we have a handler (handler creates the events) and
    // abort if not.  Do this check asap to optimize the most common
    // case of no handler.
    hStartEnum = WszOpenEvent(EVENT_ALL_ACCESS,	
                                FALSE,
                                FixupName(StartEnumEventName));
    if (hStartEnum == NULL) 
    {
        dwErr = GetLastError();
        err = Fail_NoHandler;
        goto errExit;
    }

    hDoneEnum = WszOpenEvent(EVENT_ALL_ACCESS,
                                FALSE,
                                FixupName(DoneEnumEventName));
    if (hDoneEnum == NULL) 
    {
        dwErr = GetLastError();
        err = Fail_NoHandler;
        goto errExit;
    }

    // Need to create the mutex
    hWrapCall = WszCreateMutex(NULL, FALSE, FixupName(WrapMutexName));
    if (hWrapCall == NULL)
    {
        dwErr = GetLastError();
        err = Fail_CreateMutex;
        goto errExit;
    }


// Wait for our turn	
    dwWaitRet = WaitForSingleObject(hWrapCall, START_ENUM_TIMEOUT);
    dwErr = GetLastError();
    switch(dwWaitRet) {
    case WAIT_OBJECT_0:
        // Good case. All other cases are errors and goto errExit.
        break;

    case WAIT_TIMEOUT:
        err = Fail_Timeout_Lock;
        goto errExit;
        break;
    default:
        err = Failed;
        goto errExit;
        break;
    }

    // Our turn: Make the function call
    {
        BOOL fSetOK = 0;

    // Reset the 'Done event' to make sure that Handler sets it after they start.
        ResetEvent(hDoneEnum);
        dwErr = GetLastError();

    // Signal Handler to execute callback   
        fSetOK = SetEvent(hStartEnum);
        dwErr = GetLastError();

    // Now wait for handler to finish.
        
        dwWaitRet = WaitForSingleObject(hDoneEnum, START_ENUM_TIMEOUT);
        dwErr = GetLastError();
        switch (dwWaitRet)
        {   
        case WAIT_OBJECT_0:
            break;
        case WAIT_TIMEOUT:
            err = Fail_Timeout_Call;
            break;      
        default:
            err = Failed;
            break;
        }
        

        ReleaseMutex(hWrapCall);
        dwErr = GetLastError();

    } // End function call



errExit:
// Close all handles
    if (hStartEnum != NULL) 
    {
        CloseHandle(hStartEnum);
        hStartEnum = NULL;
        
    }
    if (hDoneEnum != NULL) 
    {
        CloseHandle(hDoneEnum);
        hDoneEnum = NULL;
    }
    if (hWrapCall != NULL) 
    {
        CloseHandle(hWrapCall);
        hWrapCall = NULL;
    }

#if defined(ENABLE_TIMING)
    g_time.End();
    DWORD dwTime = g_time.GetEllapsedMS();
#endif


    return err;

}