/*++ Copyright (c) 1997-1999 Microsoft Corporation Module Name: callhub.cpp Abstract: Implements all the methods on callhub interfaces. Author: mquinton - 11-21-97 Notes: Revision History: --*/ #include "stdafx.h" extern CHashTable * gpCallHubHashTable; extern CHashTable * gpCallHashTable; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // callhub.cpp // // this module implements the callhub object // // the callhub object is the "third party" view of a call. // // callhubs can be created in four different ways: // // 1 - the service provider supports them. they indicate this through // the linedevcapsflag_callhub bit in LINEDEVCAPS. this means // that the sp used the dwCallID field to associate calls. // tapisrv will synthesize the callhubs based on this information // // 2 - almost the same as 1, except that the sp does not set the // the linedevcapsflag_callhub bit (because it is a tapi2.x // sp). tapisrv and tapi3 have to guess whether or not the sp // supports callhubs. it does this simply by seeing if the // dwcallid field is non-zero. however, this creates a problem // before a call is made, since we can't get to the dwcallid // field. in this case, i set a flag in the address object // ADDRESSFLAG_CALLHUB or _NOCALLHUB to flag whether this is // supported. however, for the very first call, we won't know // until the call is actually made. // // 3 - participant based callhub (also called part based). the sp // supports participants, as indicated by the linedevcapsflag_participantinfo // tapi3 breaks out all the participants into their own participant // objects // // 4 - fake call hub. if the sp doesn't support anything, we create // a callhub, and fake the other end. // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= BOOL FindCallObject( HCALL hCall, CCall ** ppCall ); //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= HRESULT CCallHub::Initialize( CTAPI * pTapi, HCALLHUB hCallHub, DWORD dwFlags ) { HRESULT hr; LOG((TL_TRACE,"Initialize - enter" )); Lock(); m_pTAPI = pTapi; m_hCallHub = hCallHub; m_State = CHS_ACTIVE; m_dwFlags |= dwFlags; #if DBG m_pDebug = (PWSTR) ClientAlloc( 1 ); #endif m_dwRef = 2; // // save in tapi's list // pTapi->AddCallHub( this ); pTapi->AddRef(); if ( NULL != hCallHub ) { // // add it to the global hash table // hash table is only for callhubs with // hcallhub handles, because we only need // the hash table when tapi sends a message // with the tapi handle in it // gpCallHubHashTable->Lock(); hr = gpCallHubHashTable->Insert( (ULONG_PTR)hCallHub, (ULONG_PTR)this, pTapi ); gpCallHubHashTable->Unlock(); // // see if there are any existing // calls for this callhub // FindExistingTapisrvCallhubCalls(); } // // tell the app // CCallHubEvent::FireEvent( CHE_CALLHUBNEW, this, NULL, pTapi ); Unlock(); LOG((TL_TRACE, S_OK,"Initialize - exit" )); return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // Clear - clears the callhub. there is no native tapi way // to do this, so just iterate through all the calls and // try to drop them // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CCallHub::Clear() { HRESULT hr = S_OK; ITBasicCallControl * pCall; BOOL bFailure = FALSE; int iCount; CCall * pConferenceControllerCall; CTArray aLocalCalls; Lock(); LOG((TL_TRACE, "Clear - enter ")); //If there's a conference controller call - drop it if(m_pConferenceControllerCall != NULL) { LOG((TL_INFO, "Clear - disconnect conf controller call")); pConferenceControllerCall = m_pConferenceControllerCall; m_pConferenceControllerCall = NULL; Unlock(); pConferenceControllerCall->Disconnect(DC_NORMAL); pConferenceControllerCall->Release(); Lock(); } // // go through all the calls // for (iCount = 0; iCount < m_CallArray.GetSize(); iCount++ ) { // // try to get to the basic call control interface // hr = (m_CallArray[iCount])->QueryInterface( IID_ITBasicCallControl, (void **)&pCall ); if (SUCCEEDED(hr)) { // // Add it to our private list. We have to avoid doing // disconnect and release on a call while holding the // callhub lock. There is a timing window in between disconnect // and release where the disconnect call state event can lock // the call. Then it locks the callhub, which makes a deadlock. // aLocalCalls.Add(pCall); } else { bFailure = TRUE; } } Unlock(); // // Now that we've unlocked the callhub (see above), go through our // private list of calls and drop and release each one. // for ( iCount = 0; iCount < aLocalCalls.GetSize(); iCount++ ) { pCall = aLocalCalls[iCount]; // // if we can, try to disconnect. // pCall->Disconnect(DC_NORMAL); pCall->Release(); } // // clean up the list. // aLocalCalls.Shutdown(); LOG((TL_TRACE, "Clear - exit ")); return (bFailure?S_FALSE:S_OK); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // just enumerate the calls // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CCallHub::EnumerateCalls( IEnumCall ** ppEnumCall ) { HRESULT hr = S_OK; LOG((TL_TRACE, "EnumerateCalls enter" )); LOG((TL_TRACE, " ppEnumCalls----->%p", ppEnumCall )); if ( TAPIIsBadWritePtr( ppEnumCall, sizeof (IEnumCall *) ) ) { LOG((TL_ERROR, "EnumCalls - bad pointer")); return E_POINTER; } // // create the enumerator // CComObject< CTapiEnum< IEnumCall, ITCallInfo, &IID_IEnumCall > > * p; hr = CComObject< CTapiEnum< IEnumCall, ITCallInfo, &IID_IEnumCall > > ::CreateInstance( &p ); if (S_OK != hr) { LOG((TL_ERROR, "EnumerateCalls - could not create enum" )); return hr; } Lock(); // // initialize it with our call // p->Initialize( m_CallArray ); Unlock(); // // return it // *ppEnumCall = p; LOG((TL_TRACE, "EnumerateCalls exit - return S_OK" )); return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // collection of calls // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CCallHub::get_Calls( VARIANT * pVariant ) { HRESULT hr; IDispatch * pDisp; LOG((TL_TRACE, "get_Calls enter")); LOG((TL_TRACE, " pVariant ------->%p", pVariant)); if ( TAPIIsBadWritePtr( pVariant, sizeof(VARIANT) ) ) { LOG((TL_ERROR, "get_Calls - invalid pointer" )); return E_POINTER; } CComObject< CTapiCollection< ITCallInfo > > * p; CComObject< CTapiCollection< ITCallInfo > >::CreateInstance( &p ); if (NULL == p) { LOG((TL_ERROR, "get_Calls - could not create collection" )); return E_OUTOFMEMORY; } Lock(); // // initialize // hr = p->Initialize( m_CallArray ); Unlock(); if (S_OK != hr) { LOG((TL_ERROR, "get_Calls - could not initialize collection" )); delete p; return hr; } // // get the IDispatch interface // hr = p->_InternalQueryInterface( IID_IDispatch, (void **) &pDisp ); if (S_OK != hr) { LOG((TL_ERROR, "get_Calls - could not get IDispatch interface" )); delete p; return hr; } // // put it in the variant // VariantInit(pVariant); pVariant->vt = VT_DISPATCH; pVariant->pdispVal = pDisp; LOG((TL_TRACE, "get_Calls exit - return S_OK")); return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // get the current number of calls // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CCallHub::get_NumCalls( long * plCalls ) { HRESULT hr = S_OK; if ( TAPIIsBadWritePtr( plCalls, sizeof(LONG) ) ) { LOG((TL_ERROR, "get_NumCalls - bad pointer")); return E_POINTER; } Lock(); *plCalls = m_CallArray.GetSize(); Unlock(); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // get the current state // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CCallHub::get_State( CALLHUB_STATE * pState ) { HRESULT hr = S_OK; if ( TAPIIsBadWritePtr( pState, sizeof (CALLHUB_STATE) ) ) { LOG((TL_ERROR, "get_State - invalid pointer")); return E_POINTER; } Lock(); *pState = m_State; Unlock(); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // release the object // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= BOOL CCallHub::ExternalFinalRelease() { HRESULT hr; int iCount; LOG((TL_TRACE, "CCallHub - FinalRelease - enter - this %p - hCallHub - %lx", this, m_hCallHub)); Lock(); #if DBG /*NikhilB: To avoid a hang*/ if( m_pDebug != NULL ) { ClientFree( m_pDebug ); m_pDebug = NULL; } #endif m_pTAPI->RemoveCallHub( this ); m_pTAPI->Release(); for (iCount = 0; iCount < m_CallArray.GetSize(); iCount++ ) { CCall * pCCall; pCCall = dynamic_cast(m_CallArray[iCount]); if ( NULL != pCCall ) { pCCall->SetCallHub(NULL); } } m_CallArray.Shutdown(); if ( NULL != m_pPrivate ) { m_pPrivate->Release(); } Unlock(); LOG((TL_TRACE, "CCallHub - FinalRelease - exit")); return TRUE; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // FindExistingTapisrvCallhubCalls // // internal function // // this is called when creating a 'tapisrv' callhub. this function // will call lineGetHubRelatedCalls, and add any already existing calls // to this callhub // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= HRESULT CCallHub::FindExistingTapisrvCallhubCalls() { LINECALLLIST * pCallHubList; HCALL * phCalls; DWORD dwCount; HRESULT hr; // // get the list of hcalls // related to this call // hr = LineGetHubRelatedCalls( m_hCallHub, 0, &pCallHubList ); if ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "FindExistingCalls - LineGetHubRelatedCalls " "failed %lx", hr)); return hr; } // // get to the list of calls // phCalls = (HCALL *)(((LPBYTE)pCallHubList) + pCallHubList->dwCallsOffset); // // the first call is actually the callhub // that makes sense... // if (m_hCallHub != (HCALLHUB)(phCalls[0])) { LOG((TL_ERROR, "FindExistingCalls - callhub doesn't match")); _ASSERTE(0); ClientFree( pCallHubList ); return E_FAIL; } // // go through the call handles and try to find the // objects // // phCalls[0] is the callhub, so skip it // for (dwCount = 1; dwCount < pCallHubList->dwCallsNumEntries; dwCount++) { CCall * pCall; ITCallInfo * pCallInfo; // // get the tapi3 call object // if (!FindCallObject( phCalls[dwCount], &pCall )) { LOG((TL_INFO, "FindExistingCalls - call handle %lx " "does not current exist", phCalls[dwCount])); continue; } // // tell the call // pCall->SetCallHub( this ); if ( NULL == m_pAddress ) { m_pAddress = pCall->GetCAddress(); } // // get the callinfo interface // hr = pCall->QueryInterface( IID_ITCallInfo, (void **)&pCallInfo ); // // findcallobject addrefs // pCall->Release(); if ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "FindExistingCalls - can't get callinfo interface")); _ASSERTE(0); continue; } // // save the call // m_CallArray.Add(pCallInfo); // // don't save a reference // pCallInfo->Release(); } ClientFree( pCallHubList ); return S_OK; } HRESULT CCallHub::FindCallsDisconnected( BOOL * fAllCallsDisconnected ) { LINECALLLIST * pCallHubList; HCALL * phCalls; DWORD dwCount; HRESULT hr; CALL_STATE callState = CS_IDLE; *fAllCallsDisconnected = TRUE; Lock(); // // get the list of hcalls // related to this call // hr = LineGetHubRelatedCalls( m_hCallHub, 0, &pCallHubList ); if ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "FindExistingCalls - LineGetHubRelatedCalls " "failed %lx", hr)); Unlock(); return hr; } // // get to the list of calls // phCalls = (HCALL *)(((LPBYTE)pCallHubList) + pCallHubList->dwCallsOffset); // // the first call is actually the callhub // that makes sense... // if (m_hCallHub != (HCALLHUB)(phCalls[0])) { LOG((TL_ERROR, "FindExistingCalls - callhub doesn't match")); _ASSERTE(0); ClientFree( pCallHubList ); Unlock(); return E_FAIL; } // // go through the call handles and try to find the // objects // // phCalls[0] is the callhub, so skip it // for (dwCount = 1; dwCount < pCallHubList->dwCallsNumEntries; dwCount++) { CCall * pCall; // // get the tapi3 call object // if (!FindCallObject( phCalls[dwCount], &pCall )) { LOG((TL_INFO, "FindExistingCalls - call handle %lx " "does not current exist", phCalls[dwCount])); continue; } pCall->get_CallState(&callState); // // findcallobject addrefs // pCall->Release(); if( callState != CS_DISCONNECTED ) { *fAllCallsDisconnected = FALSE; break; } } ClientFree( pCallHubList ); Unlock(); return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // CreateTapisrvCallHub // // Creates a callhub that is handled by tapisrv. // // pTAPI - owning tapi object // // hCallHub - tapi's handle for the call hub. // // ppCallHub - returned call hub with ref count of 1 // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= HRESULT CCallHub::CreateTapisrvCallHub( CTAPI * pTAPI, HCALLHUB hCallHub, CCallHub ** ppCallHub ) { HRESULT hr; // CTAPIComObjectWithExtraRef * p; CComObject * p; STATICLOG((TL_TRACE, "CreateTapisrvCallHub - enter")); STATICLOG((TL_INFO, " hCallHub ---> %lx", hCallHub)); // // create the object // //p = new CTAPIComObjectWithExtraRef; hr = CComObject::CreateInstance( &p ); if (NULL == p) { STATICLOG((TL_INFO, "CreateTapisrvCallHub - createinstance failed")); return E_OUTOFMEMORY; } // // initialize it // p->Initialize( pTAPI, hCallHub, CALLHUBTYPE_CALLHUB ); // // return object // NOTE:initialize addrefs for us! // *ppCallHub = p; STATICLOG((TL_TRACE, "CreateTapisrvCallHub - exit")); return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // CreateOrFakeCallHub // // creates a fake callhub // // pTAPI - owning TAPI object // pCall - call // ppCallHub - return new callhub object - ref count of 1 // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= HRESULT CCallHub::CreateFakeCallHub( CTAPI * pTAPI, CCall * pCall, CCallHub ** ppCallHub ) { HRESULT hr; CComObject * p; STATICLOG((TL_TRACE, "CreateFakeCallHub - enter")); // // create the object // //p = new CTAPIComObjectWithExtraRef; try { // // inside try in case critical section fails to be allocated // hr = CComObject::CreateInstance( &p ); } catch(...) { STATICLOG((TL_ERROR, "CreateFakeCallHub - failed to create a callhub -- exception")); p = NULL; } if (NULL == p) { STATICLOG((TL_INFO, "CreateFakeCallHub - createinstance failed")); return E_OUTOFMEMORY; } if ( (NULL == pTAPI) || (NULL == pCall) ) { STATICLOG((TL_ERROR, "CreateFakeCallHub - invalid param")); _ASSERTE(0); delete p; return E_UNEXPECTED; } // // initialized // p->Initialize( pTAPI, NULL, CALLHUBTYPE_NONE ); // // ZoltanS fix 11-12-98 // Add the call to the fake callhub. // This in turn calls CCall::SetCallHub, which sets and addrefs the call's // member callhub pointer. When we return from here we will set the // callhub pointer again, and the reference that's released on // ExternalFinalRelease is in effect the initial reference from Initialize. // So we need to release here in order to avoid keeping an extra reference // to the callhub. // p->AddCall(pCall); ((CCallHub *) p)->Release(); // // return object // NOTE: Initialize addrefs for us! // *ppCallHub = p; STATICLOG((TL_TRACE, "CreateFakeCallHub - exit")); return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // Remove Call // // remove a call object from the callhub's list // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= void CCallHub::RemoveCall( CCall * pCall ) { HRESULT hr = S_OK; ITCallInfo * pCallInfo; hr = pCall->QueryInterface( IID_ITCallInfo, (void**)&pCallInfo ); if ( !SUCCEEDED(hr) ) { return; } Lock(); m_CallArray.Remove( pCallInfo ); Unlock(); pCallInfo->Release(); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // CheckForIdle() // // internal function // // checks the state of the calls in the hub to see if it is idle // // so, we go through all the objects that are call objects, and // see if they are disconnected. if they all are, then the // hub is idle // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= void CCallHub::CheckForIdle() { HRESULT hr; int iCount; LOG((TL_ERROR, "CCallHub::CheckForIdle -Entered :%p", this )); Lock(); // // go through the call list // for (iCount = 0; iCount < m_CallArray.GetSize() ; iCount++ ) { CALL_STATE cs; // // get the callstate // (m_CallArray[iCount])->get_CallState( &cs ); // // if anything is not disconnected, then // it's not idle // if ( CS_DISCONNECTED != cs ) { Unlock(); return; } } Unlock(); // // if we haven't returned yet, the callhub is // idle // SetState(CHS_IDLE); LOG((TL_ERROR, "CCallHub::CheckForIdle -Exited :%p", this )); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // CCallHub::SetState // // sets the state of the object. fires an event if necessary // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= void CCallHub::SetState( CALLHUB_STATE chs ) { BOOL bEvent = FALSE; LOG((TL_ERROR, "CCallHub::SetState -Entered :%p", this )); Lock(); if ( m_State != chs ) { bEvent = TRUE; m_State = chs; } Unlock(); if ( bEvent ) { CALLHUB_EVENT che; if ( CHS_IDLE == chs ) { che = CHE_CALLHUBIDLE; } else { che = CHE_CALLHUBNEW; } CCallHubEvent::FireEvent( che, this, NULL, m_pTAPI ); LOG((TL_ERROR, "CCallHub::SetState -Exited :%p", this )); } } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // CCallHubEvent::FireEvent // // create and fire a callhub event // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= HRESULT CCallHubEvent::FireEvent( CALLHUB_EVENT Event, ITCallHub * pCallHub, ITCallInfo * pCall, CTAPI * pTapi ) { CComObject * p; IDispatch * pDisp; HRESULT hr = S_OK; // // Check the event filter mask // This event is not filtered by TapiSrv because is // related with TE_CALLSTATE. // CCall* pCCall = (CCall*)pCall; if( pCCall ) { DWORD dwEventFilterMask = 0; dwEventFilterMask = pCCall->GetSubEventsMask( TE_CALLHUB ); if( !( dwEventFilterMask & GET_SUBEVENT_FLAG(Event))) { STATICLOG((TL_WARN, "FireEvent - filtering out this event [%lx]", Event)); return S_OK; } } else { // Try with pTapi if( pTapi == NULL ) { STATICLOG((TL_WARN, "FireEvent - filtering out this event [%lx]", Event)); return S_OK; } long nEventMask = 0; pTapi->get_EventFilter( &nEventMask ); if( (nEventMask & TE_CALLHUB) == 0) { STATICLOG((TL_WARN, "FireEvent - filtering out this event [%lx]", Event)); return S_OK; } } // // create object // CComObject::CreateInstance( &p ); if ( NULL == p ) { STATICLOG((TL_ERROR, "CallHubEvent - could not create object")); return E_OUTOFMEMORY; } // // initialize // p->m_Event = Event; p->m_pCallHub = pCallHub; p->m_pCall = pCall; #if DBG p->m_pDebug = (PWSTR) ClientAlloc( 1 ); #endif // // addref objects if valid // if ( NULL != pCallHub ) { pCallHub->AddRef(); } if ( NULL != pCall ) { pCall->AddRef(); } // // get the dispatch interface // hr = p->_InternalQueryInterface( IID_IDispatch, (void **)&pDisp ); if (!SUCCEEDED(hr)) { STATICLOG((TL_ERROR, "CallHubEvent - could not get dispatch interface")); delete p; return hr; } // // fire the event // pTapi->Event( TE_CALLHUB, pDisp ); // // release our reference // pDisp->Release(); return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // get_Event // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CCallHubEvent::get_Event( CALLHUB_EVENT * pEvent ) { HRESULT hr = S_OK; if ( TAPIIsBadWritePtr( pEvent, sizeof (CALLHUB_EVENT) ) ) { LOG((TL_ERROR, "get_Event - bad pointer")); return E_POINTER; } *pEvent = m_Event; return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // get_CallHub // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CCallHubEvent::get_CallHub( ITCallHub ** ppCallHub ) { HRESULT hr = S_OK; if ( TAPIIsBadWritePtr( ppCallHub, sizeof (ITCallHub *) ) ) { LOG((TL_ERROR, "get_CallHub - bad pointer")); return E_POINTER; } hr = m_pCallHub->QueryInterface( IID_ITCallHub, (void **)ppCallHub ); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // get_Call // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CCallHubEvent::get_Call( ITCallInfo ** ppCall ) { HRESULT hr = S_OK; if ( TAPIIsBadWritePtr( ppCall, sizeof(ITCallInfo *) ) ) { LOG((TL_ERROR, "get_Call - bad pointer")); return E_POINTER; } *ppCall = NULL; // // the call can be NULL // if ( NULL == m_pCall ) { return S_FALSE; } hr = m_pCall->QueryInterface( IID_ITCallInfo, (void **)ppCall ); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= void CCallHubEvent::FinalRelease() { m_pCallHub->Release(); if ( NULL != m_pCall ) { m_pCall->Release(); } #if DBG ClientFree( m_pDebug ); #endif } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // HandleCallHubClose // // handle LINE_CALLHUBCLOSE message - find the callhub object // and clear the callhub handle from it // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= void HandleCallHubClose( PASYNCEVENTMSG pParams ) { CCallHub * pCallHub; LOG((TL_INFO, "HandleCallHubClose %lx", pParams->Param1)); if ( FindCallHubObject( (HCALLHUB)pParams->Param1, &pCallHub ) ) { pCallHub->ClearCallHub(); pCallHub->Release(); } } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // ClearCallHub // // clears the callhub handle in the object and removes the object // from the callhub hash table // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= void CCallHub::ClearCallHub() { HRESULT hr; Lock(); gpCallHubHashTable->Lock(); hr = gpCallHubHashTable->Remove( (UINT_PTR) m_hCallHub ); m_hCallHub = NULL; gpCallHubHashTable->Unlock(); Unlock(); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // FindCallByHandle // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= CCall * CCallHub::FindCallByHandle(HCALL hCall) { ITBasicCallControl * pCall; CCall * pCCall; HRESULT hr; int iCount; Lock(); // // go through the call list // for ( iCount = 0; iCount < m_CallArray.GetSize(); iCount++ ) { // // try to get to the basic call control interface // hr = (m_CallArray[iCount])->QueryInterface( IID_ITBasicCallControl, (void **)&pCall ); if (SUCCEEDED(hr)) { pCCall = dynamic_cast((ITBasicCallControl *)(pCall)); if ( NULL != pCCall ) { // // does this match? // if ( pCCall->GetHCall() == hCall ) { Unlock(); return pCCall; } else { pCCall->Release(); } } } } Unlock(); // // didn't find it // return NULL; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // CreateConferenceControllerCall // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CCallHub::CreateConferenceControllerCall(HCALL hCall, CAddress * pAddress ) { HRESULT hr = S_OK; CCall * pConferenceControllerCall; LOG((TL_TRACE, "CreateConferenceController - enter")); // // create & initialize // hr = pAddress->InternalCreateCall( NULL, 0, 0, CP_OWNER, FALSE, hCall, FALSE, &pConferenceControllerCall ); if ( SUCCEEDED(hr) ) { pConferenceControllerCall->SetCallHub( this ); // // save the call // Lock(); m_pConferenceControllerCall = pConferenceControllerCall; Unlock(); } else { LOG((TL_ERROR, "CreateConferenceController - could not create call instance")); } LOG((TL_TRACE, hr, "CreateConferenceController - exit")); return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // AddCall // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void CCallHub::AddCall(CCall * pCall) { ITCallInfo * pCallInfo; HRESULT hr = S_OK; Lock(); // // tell the call // pCall->SetCallHub( this ); if ( NULL == m_pAddress ) { m_pAddress = pCall->GetCAddress(); } // // get the CallInfo interface // hr = pCall->QueryInterface( IID_ITCallInfo, (void **)&pCallInfo ); if ( !SUCCEEDED(hr) ) { _ASSERTE(0); } // // save the Call // m_CallArray.Add( pCallInfo ); // // don't save a reference // pCallInfo->Release(); Unlock(); CCallHubEvent::FireEvent( CHE_CALLJOIN, this, pCallInfo, m_pTAPI ); } CCall * CCallHub::GetConferenceControllerCall() { CCall * pCall; Lock(); pCall = m_pConferenceControllerCall; Unlock(); return pCall; }