windows-nt/Source/XPSP1/NT/net/tapi/skywalker/tapi3/callhub.cpp
2020-09-26 16:20:57 +08:00

1490 lines
32 KiB
C++

/*++
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 <ITBasicCallControl *> 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<CCall *>(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<CCallHub> * p;
CComObject<CCallHub> * p;
STATICLOG((TL_TRACE, "CreateTapisrvCallHub - enter"));
STATICLOG((TL_INFO, " hCallHub ---> %lx", hCallHub));
//
// create the object
//
//p = new CTAPIComObjectWithExtraRef<CCallHub>;
hr = CComObject<CCallHub>::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<CCallHub> * p;
STATICLOG((TL_TRACE, "CreateFakeCallHub - enter"));
//
// create the object
//
//p = new CTAPIComObjectWithExtraRef<CCallHub>;
try
{
//
// inside try in case critical section fails to be allocated
//
hr = CComObject<CCallHub>::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<CCallHubEvent> * 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<CCallHubEvent>::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<CCall *>((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;
}