/*++ Copyright (c) 1997 - 1999 Microsoft Corporation Module Name: queue.cpp Abstract: Implementation of the Queue object for TAPI 3.0. CQueue class Author: noela - 11/04/97 Notes: optional-notes Revision History: --*/ #include "stdafx.h" ///////////////////////////////////////////////////////////////////////////// // CQueue //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CQueue // Method : Constructor // // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ CQueue::CQueue() { Lock(); m_dwHandle = 0; m_bRequiresUpdating = TRUE; m_dwMeasurementPeriod = 0; m_dwTotalCallsQueued = 0; m_dwCurrentCallsQueued = 0; m_dwTotalCallsAdandoned = 0; m_dwTotalCallsFlowedIn = 0; m_dwTotalCallsFlowedOut = 0; m_dwLongestEverWaitTime = 0; m_dwCurrentLongestWaitTime = 0; m_dwAverageWaitTime = 0; m_dwFinalDisposition = 0; Unlock(); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CQueue // Method : UpdateInfo // // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CQueue::UpdateInfo() { HRESULT hr = S_OK; LINEQUEUEINFO QueueInfo; LOG((TL_TRACE, "UpdateInfo - enter" )); QueueInfo.dwTotalSize = sizeof(LINEQUEUEINFO); QueueInfo.dwNeededSize = sizeof(LINEQUEUEINFO); QueueInfo.dwUsedSize = sizeof(LINEQUEUEINFO); // ************************************************** // Get Queue Info from Proxy hr = lineGetQueueInfo( m_pHandler->getHLine(), m_dwHandle, &QueueInfo); if( SUCCEEDED(hr) ) { // wait for async reply hr = WaitForReply( hr ); if ( SUCCEEDED(hr) ) { Lock(); m_dwMeasurementPeriod = QueueInfo.dwMeasurementPeriod; m_dwTotalCallsQueued = QueueInfo.dwTotalCallsQueued; m_dwCurrentCallsQueued = QueueInfo.dwCurrentCallsQueued; m_dwTotalCallsAdandoned = QueueInfo.dwTotalCallsAbandoned; m_dwTotalCallsFlowedIn = QueueInfo.dwTotalCallsFlowedIn; m_dwTotalCallsFlowedOut = QueueInfo.dwTotalCallsFlowedOut; m_dwLongestEverWaitTime = QueueInfo.dwLongestEverWaitTime; m_dwCurrentLongestWaitTime = QueueInfo.dwCurrentLongestWaitTime; m_dwAverageWaitTime = QueueInfo.dwAverageWaitTime; m_dwFinalDisposition = QueueInfo.dwFinalDisposition; m_bRequiresUpdating = FALSE; Unlock(); } else { LOG((TL_ERROR, "UpdateInfo - call to LineGetQueueInfo failed async" )); } } else { LOG((TL_ERROR, "UpdateInfo - call to LineGetQueueInfo failed" )); } LOG((TL_TRACE, hr, "UpdateInfo - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CQueue // Method : CheckIfUpToDate // // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CQueue::CheckIfUpToDate() { HRESULT hr = S_OK; if (m_bRequiresUpdating) { hr = UpdateInfo(); } return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CQueue // Method : Initialize // // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CQueue::Initialize ( DWORD dwQueueID, PWSTR pszName, CAgentHandler * pHandler ) { HRESULT hr = S_OK; LOG((TL_TRACE, "Initialize - enter" )); m_dwHandle = dwQueueID; m_pHandler = pHandler; m_bRequiresUpdating = TRUE; // copy the destination address if (pszName != NULL) { m_szName = (PWSTR) ClientAlloc((lstrlenW(pszName) + 1) * sizeof (WCHAR)); if (m_szName != NULL) { lstrcpyW(m_szName,pszName); } else { LOG((TL_ERROR, "Initialize - Alloc m_szName failed" )); hr = E_OUTOFMEMORY; } } else { LOG((TL_ERROR, "Initialize - name is NULL" )); m_szName = NULL; } // Add this object into the Agnet Handler Hash table m_pHandler->AddQueueToHash(m_dwHandle, this); // Get Queue Info from Proxy // UpdateInfo(); if ( SUCCEEDED(hr) ) { CQueueEvent::FireEvent(this, ACDQE_NEW_QUEUE); } LOG((TL_TRACE, hr, "Initialize - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CQueue // Method : FinalRelease // // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void CQueue::FinalRelease() { LOG((TL_TRACE, "FinalRelease Queue - %S", m_szName )); if ( m_szName != NULL ) { ClientFree(m_szName); } // Add this object into the Agnet Handler Hash table m_pHandler->RemoveQueueFromHash(m_dwHandle); LOG((TL_TRACE, "FinalRelease Queue - exit")); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CQueue // Interface : ITQueue // Method : get_Name // // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CQueue::get_Name(BSTR * Name) { HRESULT hr = S_OK; LOG((TL_TRACE, "Name - enter" )); Lock(); if (!TAPIIsBadWritePtr( Name, sizeof(BSTR ) ) ) { *Name = SysAllocString(m_szName); if (*Name == NULL) { hr = E_OUTOFMEMORY; } } else { LOG((TL_ERROR, "Name - bad Name pointer")); hr = E_POINTER; } Unlock(); LOG((TL_TRACE, hr, "Name - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CQueue // Interface : ITQueue // Method : put_MeasurementPeriod // // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CQueue::put_MeasurementPeriod(long ulPeriod) { HRESULT hr = S_OK; LOG((TL_TRACE, "put_MeasurementPeriod - enter" )); // *************************************************** // Tell Proxy hr = lineSetQueueMeasurementPeriod( m_pHandler->getHLine(), m_dwHandle, ulPeriod); if( SUCCEEDED(hr) ) { // wait for async reply hr = WaitForReply( hr ); if ( SUCCEEDED(hr) ) { Lock(); m_dwMeasurementPeriod = ulPeriod; Unlock(); } else { LOG((TL_ERROR, "put_MeasurementPeriod - call to LineSetQueueMeasurementPeriod failed async" )); } } else { LOG((TL_ERROR, "put_MeasurementPeriod - call to LineSetQueueMeasurementPeriod failed" )); } LOG((TL_TRACE, hr, "put_MeasurementPeriod - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CQueue // Interface : ITQueue // Method : get_MeasurementPeriod // // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CQueue::get_MeasurementPeriod (long * pulPeriod) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_MeasurementPeriod - enter" )); if (!TAPIIsBadWritePtr( pulPeriod, sizeof(long) ) ) { hr = CheckIfUpToDate(); if ( SUCCEEDED(hr) ) { Lock(); *pulPeriod = m_dwMeasurementPeriod; Unlock(); } else { LOG((TL_ERROR, "get_MeasurementPeriod - Object update failed")); } } else { LOG((TL_ERROR, "get_MeasurementPeriod - bad pulPeriod pointer")); hr = E_POINTER; } LOG((TL_TRACE, hr, "get_MeasurementPeriod - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CQueue // Interface : ITQueue // Method : TotalCallsQueued // // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CQueue::get_TotalCallsQueued (long * pulCalls) { HRESULT hr = S_OK; LOG((TL_TRACE, "TotalCallsQueued - enter" )); if (!TAPIIsBadWritePtr( pulCalls, sizeof(long) ) ) { hr = CheckIfUpToDate(); if ( SUCCEEDED(hr) ) { Lock(); *pulCalls = m_dwTotalCallsQueued; Unlock(); } else { LOG((TL_ERROR, "get_TotalCallsQueued - Object update failed")); } } else { LOG((TL_ERROR, "get_TotalCallsQueued - bad pulCalls pointer")); hr = E_POINTER; } LOG((TL_TRACE, hr, "TotalCallsQueued - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CQueue // Interface : ITQueue // Method : CurrentCallsQueued // // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CQueue::get_CurrentCallsQueued (long * pulCalls) { HRESULT hr = S_OK; LOG((TL_TRACE, "CurrentCallsQueued - enter" )); if (!TAPIIsBadWritePtr( pulCalls, sizeof(long) ) ) { hr = CheckIfUpToDate(); if ( SUCCEEDED(hr) ) { Lock(); *pulCalls = m_dwCurrentCallsQueued; Unlock(); } else { LOG((TL_ERROR, "get_CurrentCallsQueued - Object update failed")); } } else { LOG((TL_ERROR, "get_CurrentCallsQueued - bad pulCalls pointer")); hr = E_POINTER; } LOG((TL_TRACE, hr, "CurrentCallsQueued - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CQueue // Interface : ITQueue // Method : TotalCallsAbandoned // // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CQueue::get_TotalCallsAbandoned (long * pulCalls) { HRESULT hr = S_OK; LOG((TL_TRACE, "TotalCallsAbandoned - enter" )); if (!TAPIIsBadWritePtr( pulCalls, sizeof(long) ) ) { hr = CheckIfUpToDate(); if (SUCCEEDED(hr) ) { Lock(); *pulCalls = m_dwTotalCallsAdandoned; Unlock(); } else { LOG((TL_ERROR, "get_TotalCallsAbandoned - Object update failed")); } } else { LOG((TL_ERROR, "get_TotalCallsAbandoned - bad pulCalls pointer")); hr = E_POINTER; } LOG((TL_TRACE, hr, "TotalCallsAbandoned - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CQueue // Interface : ITQueue // Method : TotalCallsFlowedIn // // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CQueue::get_TotalCallsFlowedIn (long * pulCalls) { HRESULT hr = S_OK; LOG((TL_TRACE, "TotalCallsFlowedIn - enter" )); if (!TAPIIsBadWritePtr( pulCalls, sizeof(long) ) ) { hr = CheckIfUpToDate(); if (SUCCEEDED(hr) ) { Lock(); *pulCalls = m_dwTotalCallsFlowedIn; Unlock(); } else { LOG((TL_ERROR, "get_TotalCallsFlowedIn - Object update failed")); } } else { LOG((TL_ERROR, "get_TotalCallsFlowedIn - bad pulCalls pointer")); hr = E_POINTER; } LOG((TL_TRACE, hr, "TotalCallsFlowedIn - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CQueue // Interface : ITQueue // Method : TotalCallsFlowedIn // // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CQueue::get_TotalCallsFlowedOut (long * pulCalls) { HRESULT hr = S_OK; LOG((TL_TRACE, "TotalCallsFlowedOut - enter" )); if (!TAPIIsBadWritePtr( pulCalls, sizeof(long) ) ) { hr = CheckIfUpToDate(); if (SUCCEEDED(hr) ) { Lock(); *pulCalls = m_dwTotalCallsFlowedOut; Unlock(); } else { LOG((TL_ERROR, "get_TotalCallsFlowedOut - Object update failed")); } } else { LOG((TL_ERROR, "get_TotalCallsFlowedOut - bad pulCalls pointer")); hr = E_POINTER; } LOG((TL_TRACE, hr, "TotalCallsFlowedOut - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CQueue // Interface : ITQueue // Method : LongestEverWaitTime // // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CQueue::get_LongestEverWaitTime (long * pulWaitTime) { HRESULT hr = S_OK; LOG((TL_TRACE, "LongestEverWaitTime - enter" )); if (!TAPIIsBadWritePtr( pulWaitTime, sizeof(long) ) ) { hr = CheckIfUpToDate(); if (SUCCEEDED(hr) ) { Lock(); *pulWaitTime = m_dwLongestEverWaitTime; Unlock(); } else { LOG((TL_ERROR, "get_LongestEverWaitTime - Object update failed")); } } else { LOG((TL_ERROR, "get_LongestEverWaitTime - bad pulWaitTime pointer")); hr = E_POINTER; } LOG((TL_TRACE, hr, "LongestEverWaitTime - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CQueue // Interface : ITQueue // Method : CurrentLongestWaitTime // // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CQueue::get_CurrentLongestWaitTime (long * pulWaitTime) { HRESULT hr = S_OK; LOG((TL_TRACE, "CurrentLongestWaitTime - enter" )); if (!TAPIIsBadWritePtr( pulWaitTime, sizeof(long) ) ) { hr = CheckIfUpToDate(); if (SUCCEEDED(hr) ) { Lock(); *pulWaitTime = m_dwCurrentLongestWaitTime; Unlock(); } else { LOG((TL_ERROR, "get_CurrentLongestWaitTime - Object update failed")); } } else { LOG((TL_ERROR, "get_CurrentLongestWaitTime - bad pulWaitTime pointer")); hr = E_POINTER; } LOG((TL_TRACE, hr, "CurrentLongestWaitTime - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CQueue // Interface : ITQueue // Method : AverageWaitTime // // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CQueue::get_AverageWaitTime (long * pulWaitTime) { HRESULT hr = S_OK; LOG((TL_TRACE, "AverageWaitTime - enter" )); if (!TAPIIsBadWritePtr( pulWaitTime, sizeof(long) ) ) { hr = CheckIfUpToDate(); if (SUCCEEDED(hr) ) { Lock(); *pulWaitTime = m_dwAverageWaitTime; Unlock(); } else { LOG((TL_ERROR, "get_AverageWaitTime - Object update failed")); } } else { LOG((TL_ERROR, "get_AverageWaitTime - bad pulWaitTime pointer")); hr = E_POINTER; } LOG((TL_TRACE, hr, "AverageWaitTime - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CQueue // Interface : ITQueue // Method : FinalDisposition // // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CQueue::get_FinalDisposition (long * pulCalls) { HRESULT hr = S_OK; LOG((TL_TRACE, "FinalDisposition - enter" )); if (!TAPIIsBadWritePtr( pulCalls, sizeof(long) ) ) { hr = CheckIfUpToDate(); if (SUCCEEDED(hr) ) { Lock(); *pulCalls = m_dwFinalDisposition; Unlock(); } else { LOG((TL_ERROR, "get_FinalDisposition - Object update failed")); } } else { LOG((TL_ERROR, "get_FinalDisposition - bad pulCalls pointer")); hr = E_POINTER; } LOG((TL_TRACE, hr, "FinalDisposition - exit" )); return hr; } ///////////////////////////////////////////////////////////////////////////// // CQueueEvent //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CQueueEvent // Method : FireEvent // // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CQueueEvent::FireEvent(CQueue* pQueue, ACDQUEUE_EVENT Event) { HRESULT hr = S_OK; CComObject * pEvent; IDispatch * pIDispatch; if ( IsBadReadPtr(pQueue, sizeof(CQueue)) ) { STATICLOG((TL_ERROR, "FireEvent - pQueue is an invalid pointer")); return E_POINTER; } // // create event // hr = CComObject::CreateInstance( &pEvent ); if ( SUCCEEDED(hr) ) { // // initialize // pEvent->m_QueueEvent = Event; pEvent->m_pQueue= dynamic_cast(pQueue); pEvent->m_pQueue->AddRef(); // // get idisp interface // hr = pEvent->QueryInterface( IID_IDispatch, (void **)&pIDispatch ); if ( SUCCEEDED(hr) ) { // // get callback & fire event // CTAPI *pTapi = (pQueue->GetAgentHandler() )->GetTapi(); pTapi->Event( TE_QUEUE, pIDispatch ); // release stuff // pIDispatch->Release(); } else { STATICLOG((TL_ERROR, "FireEvent - Could not get disp interface of QueueEvent object")); delete pEvent; } } else { STATICLOG((TL_ERROR, "FireEvent - Could not create QueueEvent object")); } STATICLOG((TL_TRACE, hr, "FireEvent - exit")); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CQueueEvent // Method : FinalRelease // // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void CQueueEvent::FinalRelease() { m_pQueue->Release(); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CQueueEvent // Interface : ITQueueEvent // Method : Queue // // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CQueueEvent::get_Queue(ITQueue ** ppQueue) { HRESULT hr = S_OK; LOG((TL_TRACE, "(Event)Queue - enter" )); if (!TAPIIsBadWritePtr( ppQueue, sizeof(ITQueue *) ) ) { *ppQueue = m_pQueue; m_pQueue->AddRef(); } else { LOG((TL_ERROR, "(Event)Queue - bad ppQueue pointer")); hr = E_POINTER; } LOG((TL_TRACE, hr, "(Event)Queue - exit")); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CQueueEvent // Interface : ITQueueEvent // Method : Event // // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CQueueEvent::get_Event(ACDQUEUE_EVENT * pEvent) { HRESULT hr = S_OK; LOG((TL_TRACE, "Event - enter" )); if (!TAPIIsBadWritePtr( pEvent, sizeof(ACDQUEUE_EVENT) ) ) { *pEvent = m_QueueEvent; } else { LOG((TL_ERROR, "Event - bad pEvent pointer")); hr = E_POINTER; } LOG((TL_TRACE, hr, "Event - exit")); return hr; }