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

4617 lines
104 KiB
C++

/*++
Copyright (c) 1997 - 1999 Microsoft Corporation
Module Name:
tapiobj.cpp
Abstract:
Implementation of the TAPI object for TAPI 3.0.
The TAPI object represents the application's entry point
into TAPI - it is similar to the hLineApp / hPhoneApp.
Author:
mquinton - 4/17/97
Notes:
optional-notes
Revision History:
--*/
#include "stdafx.h"
#include "common.h"
#include "atlwin.cpp"
#include "tapievt.h"
extern "C" {
#include "..\..\inc\tapihndl.h"
}
extern CRITICAL_SECTION gcsTapiObjectArray;
extern CRITICAL_SECTION gcsGlobalInterfaceTable;
//
// handle for heap for the handle table
//
// does not need to be exported, hence static
//
static HANDLE ghTapiHeap = 0;
//
// handle table handle
//
HANDLE ghHandleTable = 0;
///////////////////////////////////////////////////////////////////////////////
//
// FreeContextCallback
//
// callback function called by the handle table when a table entry
// is removed. No need to do anything in this case.
//
VOID
CALLBACK
FreeContextCallback(
LPVOID Context,
LPVOID Context2
)
{
}
///////////////////////////////////////////////////////////////////////////////
//
// AllocateAndInitializeHandleTable
//
// this function creates heap for handle table and the handle table itself
//
// Note: this function is not thread-safe. It is only called from
// ctapi::Initialize() from ghTapiInitShutdownSerializeMutex lock
//
HRESULT AllocateAndInitializeHandleTable()
{
LOG((TL_TRACE, "AllocateAndInitializeHandleTable - entered"));
//
// heap should not exist at this point
//
_ASSERTE(NULL == ghTapiHeap);
if (NULL != ghTapiHeap)
{
LOG((TL_ERROR, "AllocateAndInitializeHandleTable() heap already exists"));
return E_UNEXPECTED;
}
//
// handle table should not exist at this point
//
_ASSERTE(NULL == ghHandleTable);
if (NULL != ghHandleTable)
{
LOG((TL_ERROR, "AllocateAndInitializeHandleTable() handle table already exists"));
return E_UNEXPECTED;
}
//
// attempt to create heap
//
if (!(ghTapiHeap = HeapCreate (0, 0x10000, 0)))
{
//
// heap creation failed, use process's heap
//
LOG((TL_WARN, "AllocateAndInitializeHandleTable() failed to allocate private heap. using process's heap"));
ghTapiHeap = GetProcessHeap();
if (NULL == ghTapiHeap)
{
LOG((TL_ERROR, "AllocateAndInitializeHandleTable failed to get process's heap"));
return E_OUTOFMEMORY;
}
} // HeapCreate()
//
// we have the heap. use it to create handle table
//
ghHandleTable = CreateHandleTable( ghTapiHeap,
FreeContextCallback,
1, // min handle value
MAX_DWORD // max handle value
);
if (NULL == ghHandleTable)
{
LOG((TL_ERROR, "AllocateAndInitializeHandleTable failed to create handle table"));
HeapDestroy (ghTapiHeap);
ghTapiHeap = NULL;
return E_OUTOFMEMORY;
}
//
// succeeded creating heap and handle table
//
LOG((TL_INFO, "AllocateAndInitializeHandleTable - succeeded"));
return S_OK;
}
///////////////////////////////////////////////////////////////////////////////
//
// ShutdownAndDeallocateHandleTable
//
// this function deletes handle table, and destroys heap on which it was
// allocated (if not process heap)
//
// Note: this function is not thread-safe. It is only called from
// ctapi::Initialize() and Shutdown() from ghTapiInitShutdownSerializeMutex lock
//
HRESULT ShutdownAndDeallocateHandleTable()
{
LOG((TL_TRACE, "ShutdownAndDeallocateHandleTable - entered"));
//
// heap should exist at this point
//
_ASSERTE(NULL != ghTapiHeap);
if (NULL == ghTapiHeap)
{
LOG((TL_ERROR, "ShutdownAndDeallocateHandleTable heap does not exist"));
return E_UNEXPECTED;
}
//
// handle table should exist at this point
//
_ASSERTE(NULL != ghHandleTable);
if (NULL == ghHandleTable)
{
LOG((TL_ERROR, "ShutdownAndDeallocateHandleTable handle table does not exist"));
return E_UNEXPECTED;
}
//
// delete handle table
//
DeleteHandleTable (ghHandleTable);
ghHandleTable = NULL;
//
// if we created heap for it, destroy it
//
if (ghTapiHeap != GetProcessHeap())
{
LOG((TL_INFO, "ShutdownAndDeallocateHandleTable destroying heap"));
HeapDestroy (ghTapiHeap);
}
else
{
LOG((TL_INFO, "ShutdownAndDeallocateHandleTable not destroyng current heap -- used process's heap"));
}
//
// in any case, loose reference to the heap.
//
ghTapiHeap = NULL;
LOG((TL_INFO, "ShutdownAndDeallocateHandleTable - succeeded"));
return S_OK;
}
IGlobalInterfaceTable * gpGIT = NULL;
LONG
WINAPI
AllocClientResources(
DWORD dwErrorClass
);
extern HRESULT mapTAPIErrorCode(long lErrorCode);
/////////////////////////////////////////////////////////////////////////////
// CTAPI
//
// Static data members
TAPIObjectArrayNR CTAPI::m_sTAPIObjectArray;
extern HANDLE ghTapiInitShutdownSerializeMutex;
extern ULONG_PTR GenerateHandleAndAddToHashTable( ULONG_PTR Element);
extern void RemoveHandleFromHashTable(ULONG_PTR dwHandle);
extern CHashTable * gpHandleHashTable;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// CTAPI::ReleaseGIT
//
// releases Global Interface Table
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
void CTAPI::ReleaseGIT()
{
EnterCriticalSection( &gcsGlobalInterfaceTable );
if ( NULL != gpGIT )
{
LOG((TL_TRACE, "Shutdown - release GIT"));
gpGIT->Release();
gpGIT = NULL;
}
LeaveCriticalSection( &gcsGlobalInterfaceTable );
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// CTAPI::AllocateInitializeAllCaches
//
// allocates and initializes cache objects (address, line, phone).
//
// returns S_OK on success or E_OUTOFMEMORY on failure
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
HRESULT CTAPI::AllocateInitializeAllCaches()
{
LOG((TL_TRACE, "AllocateInitializeAllCaches - enter"));
//
// all caches already initialized?
//
if ( (NULL != m_pAddressCapCache) &&
(NULL != m_pLineCapCache) &&
(NULL != m_pPhoneCapCache) )
{
LOG((TL_TRACE, "AllocateInitializeAllCaches - already initialized. nothing to do"));
return S_OK;
}
//
// only some caches are initialized? that's a bug!
//
if ( (NULL != m_pAddressCapCache) ||
(NULL != m_pLineCapCache) ||
(NULL != m_pPhoneCapCache) )
{
LOG((TL_ERROR, "AllocateInitializeAllCaches - already initialized"));
_ASSERTE(FALSE);
//
// we could try to complete cleanup and continue, but this would be too
// risky since we don't really know how we got here to begin with.
// simply failing is much safer.
//
return E_UNEXPECTED;
}
////////////////////////
//
// allocate address cache
//
try
{
m_pAddressCapCache = new CStructCache;
}
catch(...)
{
// Initialize critical section in the constructor most likely threw this exception
LOG((TL_ERROR, "AllocateInitializeAllCaches - m_pAddressCapCache constructor threw an exception"));
m_pAddressCapCache = NULL;
}
if (NULL == m_pAddressCapCache)
{
LOG((TL_ERROR, "AllocateInitializeAllCaches - failed to allocate m_pAddressCapCache"));
FreeAllCaches();
return E_OUTOFMEMORY;
}
//
// attempt to initialize address cache
//
HRESULT hr = m_pAddressCapCache->Initialize(5,
sizeof(LINEADDRESSCAPS) + 500,
BUFFERTYPE_ADDRCAP
);
if (FAILED(hr))
{
LOG((TL_ERROR, "AllocateInitializeAllCaches - failed to initialize m_pAddressCapCache. hr = %lx", hr));
FreeAllCaches();
return hr;
}
////////////////////////
//
// allocate line cache
//
try
{
m_pLineCapCache = new CStructCache;
}
catch(...)
{
// Initialize critical section in the constructor most likely threw this exception
LOG((TL_ERROR, "AllocateInitializeAllCaches - m_pLineCapCache constructor threw an exception"));
m_pLineCapCache = NULL;
}
if (NULL == m_pLineCapCache )
{
LOG((TL_ERROR, "AllocateInitializeAllCaches - failed to allocate m_pLineCapCache"));
FreeAllCaches();
return E_OUTOFMEMORY;
}
//
// attempt to initialize line cache
//
hr = m_pLineCapCache->Initialize(5,
sizeof(LINEDEVCAPS) + 500,
BUFFERTYPE_LINEDEVCAP
);
if (FAILED(hr))
{
LOG((TL_ERROR, "AllocateInitializeAllCaches - failed to initialize m_pLineCapCache. hr = %lx", hr));
FreeAllCaches();
return hr;
}
////////////////////////
//
// allocate phone cache
//
try
{
m_pPhoneCapCache = new CStructCache;
}
catch(...)
{
// Initialize critical section in the constructor most likely threw this exception
LOG((TL_ERROR, "AllocateInitializeAllCaches - m_pPhoneCapCache constructor threw an exception"));
m_pPhoneCapCache = NULL;
}
//
// succeeded?
//
if (NULL == m_pPhoneCapCache)
{
LOG((TL_ERROR, "AllocateInitializeAllCaches - failed to allocate m_pPhoneCapCache"));
FreeAllCaches();
return E_OUTOFMEMORY;
}
//
// initialize phone cache
//
hr = m_pPhoneCapCache->Initialize(5,
sizeof(PHONECAPS) + 500,
BUFFERTYPE_PHONECAP
);
if (FAILED(hr))
{
LOG((TL_ERROR, "AllocateInitializeAllCaches - failed to initialize m_pPhoneCapCache. hr = %lx", hr));
FreeAllCaches();
return hr;
}
LOG((TL_TRACE, "AllocateInitializeAllCaches - finish"));
return S_OK;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// CTAPI::FreeAllCaches
//
// shuts down and deletes all allocated cache objects (address, line, phone)
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
void CTAPI::FreeAllCaches()
{
LOG((TL_TRACE, "FreeAllCaches - enter"));
//
// Note: it is safe to shutdown a cache that failed initialization or was
// not initialized at all
//
if (NULL != m_pAddressCapCache)
{
LOG((TL_TRACE, "FreeAllCaches - freeing AddressCapCache"));
m_pAddressCapCache->Shutdown();
delete m_pAddressCapCache;
m_pAddressCapCache = NULL;
}
if (NULL != m_pLineCapCache)
{
LOG((TL_TRACE, "FreeAllCaches - freeing LineCapCache"));
m_pLineCapCache->Shutdown();
delete m_pLineCapCache;
m_pLineCapCache = NULL;
}
if (NULL != m_pPhoneCapCache)
{
LOG((TL_TRACE, "FreeAllCaches - freeing PhoneCapCache"));
m_pPhoneCapCache->Shutdown();
delete m_pPhoneCapCache;
m_pPhoneCapCache = NULL;
}
LOG((TL_TRACE, "FreeAllCaches - exit"));
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// CTAPI::Initialize
//
// Intialize the TAPI object
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
HRESULT
STDMETHODCALLTYPE
CTAPI::Initialize(
void
)
{
HRESULT hr;
int tapiObjectArraySize=0;
LOG((TL_TRACE, "Initialize[%p] enter", this ));
//Serialize the Init and Shutdown code
WaitForSingleObject( ghTapiInitShutdownSerializeMutex, INFINITE );
//
// if we're already initialized
// just return
//
Lock();
if ( m_dwFlags & TAPIFLAG_INITIALIZED )
{
LOG((TL_TRACE, "Already initialized - return S_FALSE"));
Unlock();
ReleaseMutex( ghTapiInitShutdownSerializeMutex );
return S_FALSE;
}
//
// start up TAPI if we haven't already
//
EnterCriticalSection( &gcsTapiObjectArray );
tapiObjectArraySize = m_sTAPIObjectArray.GetSize();
LeaveCriticalSection ( &gcsTapiObjectArray );
if ( 0 == tapiObjectArraySize )
{
//
// create handle table
//
hr = AllocateAndInitializeHandleTable();
if (FAILED(hr))
{
LOG((TL_ERROR, "Initialize failed to create handle table"));
Unlock();
ReleaseMutex( ghTapiInitShutdownSerializeMutex );
return hr;
}
hr = mapTAPIErrorCode( AllocClientResources (1) );
if ( 0 != hr )
{
LOG((TL_ERROR, "AllocClientResources failed - %lx", hr));
ShutdownAndDeallocateHandleTable();
Unlock();
ReleaseMutex( ghTapiInitShutdownSerializeMutex );
return hr;
}
EnterCriticalSection( &gcsGlobalInterfaceTable );
//
// get/create the global interface table
//
hr = CoCreateInstance(
CLSID_StdGlobalInterfaceTable,
NULL,
CLSCTX_INPROC_SERVER,
IID_IGlobalInterfaceTable,
(void **)&gpGIT
);
LeaveCriticalSection( &gcsGlobalInterfaceTable );
if ( !SUCCEEDED(hr) )
{
LOG((TL_ERROR, "Initialize - cocreate git failed - %lx", hr));
ShutdownAndDeallocateHandleTable();
Unlock();
ReleaseMutex( ghTapiInitShutdownSerializeMutex );
return hr;
}
}
//
// allocate and initialize all caches
//
// note: if something fails in Initialize later on, we don't really need
// to clean caches in initialize itself, because the caches will be freed
// in CTAPI::FinalRelease when the tapi object is destroyed.
//
hr = AllocateInitializeAllCaches();
if ( FAILED(hr))
{
LOG((TL_ERROR, "Initialize - failed to create and initialize caches"));
if ( 0 == tapiObjectArraySize )
{
EnterCriticalSection( &gcsGlobalInterfaceTable );
if ( NULL != gpGIT )
{
LOG((TL_TRACE, "Shutdown - release GIT"));
gpGIT->Release();
gpGIT = NULL;
}
LeaveCriticalSection( &gcsGlobalInterfaceTable );
ShutdownAndDeallocateHandleTable();
}
Unlock();
ReleaseMutex( ghTapiInitShutdownSerializeMutex );
return E_OUTOFMEMORY;
}
//
// Call LineInitialize
//
hr = NewInitialize();
if (S_OK != hr)
{
LOG((TL_ERROR, "Initialize - NewInitialize returned %lx", hr));
if ( 0 == tapiObjectArraySize )
{
EnterCriticalSection( &gcsGlobalInterfaceTable );
if ( NULL != gpGIT )
{
LOG((TL_TRACE, "Shutdown - release GIT"));
gpGIT->Release();
gpGIT = NULL;
}
LeaveCriticalSection( &gcsGlobalInterfaceTable );
ShutdownAndDeallocateHandleTable();
}
FreeAllCaches();
Unlock();
ReleaseMutex( ghTapiInitShutdownSerializeMutex );
return hr;
}
//
// create the address objects
//
hr = CreateAllAddressesOnAllLines();
if (S_OK != hr)
{
LOG((TL_INFO, "Initialize - CreateAddresses returned %lx", hr));
NewShutdown();
if ( 0 == tapiObjectArraySize )
{
EnterCriticalSection( &gcsGlobalInterfaceTable );
if ( NULL != gpGIT )
{
LOG((TL_TRACE, "Shutdown - release GIT"));
gpGIT->Release();
gpGIT = NULL;
}
LeaveCriticalSection( &gcsGlobalInterfaceTable );
ShutdownAndDeallocateHandleTable();
}
FreeAllCaches();
Unlock();
ReleaseMutex( ghTapiInitShutdownSerializeMutex );
return hr;
}
//
// create the phone objects
//
hr = CreateAllPhones();
if (S_OK != hr)
{
LOG((TL_INFO, "Initialize - CreateAllPhones returned %lx", hr));
NewShutdown();
m_AddressArray.Shutdown ();
if ( 0 == tapiObjectArraySize )
{
EnterCriticalSection( &gcsGlobalInterfaceTable );
if ( NULL != gpGIT )
{
LOG((TL_TRACE, "Shutdown - release GIT"));
gpGIT->Release();
gpGIT = NULL;
}
LeaveCriticalSection( &gcsGlobalInterfaceTable );
ShutdownAndDeallocateHandleTable();
}
FreeAllCaches();
Unlock();
ReleaseMutex( ghTapiInitShutdownSerializeMutex );
return hr;
}
//
// create the connectionpoint object
//
CComObject< CTAPIConnectionPoint > * p;
hr = CComObject< CTAPIConnectionPoint >::CreateInstance( &p );
if ( FAILED(hr) )
{
LOG((TL_ERROR, "new CTAPIConnectionPoint failed"));
NewShutdown();
m_AddressArray.Shutdown ();
m_PhoneArray.Shutdown ();
if ( 0 == tapiObjectArraySize )
{
EnterCriticalSection( &gcsGlobalInterfaceTable );
if ( NULL != gpGIT )
{
LOG((TL_TRACE, "Shutdown - release GIT"));
gpGIT->Release();
gpGIT = NULL;
}
LeaveCriticalSection( &gcsGlobalInterfaceTable );
ShutdownAndDeallocateHandleTable();
}
FreeAllCaches();
Unlock();
ReleaseMutex( ghTapiInitShutdownSerializeMutex );
return hr;
}
//
// init the connection point
//
hr = p->Initialize(
(IConnectionPointContainer *)this,
IID_ITTAPIEventNotification
);
if ( FAILED(hr) )
{
LOG((TL_ERROR, "initialize CTAPIConnectionPoint failed"));
delete p;
NewShutdown();
m_AddressArray.Shutdown ();
m_PhoneArray.Shutdown ();
if ( 0 == tapiObjectArraySize )
{
EnterCriticalSection( &gcsGlobalInterfaceTable );
if ( NULL != gpGIT )
{
LOG((TL_TRACE, "Shutdown - release GIT"));
gpGIT->Release();
gpGIT = NULL;
}
LeaveCriticalSection( &gcsGlobalInterfaceTable );
ShutdownAndDeallocateHandleTable();
}
FreeAllCaches();
Unlock();
ReleaseMutex( ghTapiInitShutdownSerializeMutex );
return hr;
}
m_pCP = p;
//
// this object is initialized
//
m_dwFlags = TAPIFLAG_INITIALIZED;
//
// save object in global list
//
CTAPI * pTapi = this;
EnterCriticalSection( &gcsTapiObjectArray );
m_sTAPIObjectArray.Add( pTapi );
// Set the event filter mask
// Always ask for
// TE_CALLSTATE,
// TE_CALLNOTIFICATION,
// TE_PHONEVENET,
// TE_CALLHUB,
// TE_CALLINFOCHANGE
// events. These events are used internally by Tapi3
ULONG64 ulMask =
EM_LINE_CALLSTATE | // TE_CALLSTATE
EM_LINE_APPNEWCALL | // TE_CALLNOTIFICATION
EM_PHONE_CLOSE | // TE_PHONEEVENT
EM_PHONE_STATE | // TE_PHONEEVENT
EM_PHONE_BUTTONMODE | // TE_PHONEEVENT
EM_PHONE_BUTTONSTATE | // TE_PHONEVENT
EM_LINE_APPNEWCALLHUB | // TE_CALLHUB
EM_LINE_CALLHUBCLOSE | // TE_CALLHUB
EM_LINE_CALLINFO | // TE_CALLINFOCHANGE
EM_LINE_CREATE | // TE_TAPIOBJECT
EM_LINE_REMOVE | // TE_TAPIOBJECT
EM_LINE_CLOSE | // TE_TAPIOBJECT
EM_PHONE_CREATE | // TE_TAPIOBJECT
EM_PHONE_REMOVE | // TE_TAPIOBJECT
EM_LINE_DEVSPECIFICEX | // TE_ADDRESSDEVSPECIFIC
EM_LINE_DEVSPECIFIC | // TE_ADDRESSDEVSPECIFIC
EM_PHONE_DEVSPECIFIC; // TE_PHONEDEVSPECIFIC
DWORD dwLineDevStateSubMasks =
LINEDEVSTATE_REINIT | // TE_TAPIOBJECT
LINEDEVSTATE_TRANSLATECHANGE ; // TE_TAPIOBJECT
tapiSetEventFilterMasks (
TAPIOBJ_NULL,
NULL,
ulMask
);
tapiSetEventFilterSubMasks (
TAPIOBJ_NULL,
NULL,
EM_LINE_LINEDEVSTATE,
dwLineDevStateSubMasks
);
LeaveCriticalSection ( &gcsTapiObjectArray );
Unlock();
ReleaseMutex( ghTapiInitShutdownSerializeMutex );
LOG((TL_TRACE, "Initialize exit - return SUCCESS"));
return S_OK;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// CTAPI::get_Addresses
//
// Creates & returns the collection of address objects
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
HRESULT
STDMETHODCALLTYPE
CTAPI::get_Addresses(VARIANT * pVariant)
{
LOG((TL_TRACE, "get_Addresses enter"));
LOG((TL_TRACE, " pVariant ------->%p", pVariant));
HRESULT hr;
IDispatch * pDisp;
Lock();
if (!( m_dwFlags & TAPIFLAG_INITIALIZED ) )
{
LOG((TL_ERROR, "get_Addresses - tapi object must be initialized first" ));
Unlock();
return E_INVALIDARG;
}
Unlock();
if (TAPIIsBadWritePtr( pVariant, sizeof (VARIANT) ) )
{
LOG((TL_ERROR, "get_Addresses - bad pointer"));
return E_POINTER;
}
CComObject< CTapiCollection< ITAddress > > * p;
CComObject< CTapiCollection< ITAddress > >::CreateInstance( &p );
if (NULL == p)
{
LOG((TL_ERROR, "get_Addresses - could not create collection" ));
return E_OUTOFMEMORY;
}
Lock();
// initialize
hr = p->Initialize( m_AddressArray );
Unlock();
if (S_OK != hr)
{
LOG((TL_ERROR, "get_Addresses - 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_Addresses - 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_Addressess exit - return %lx", hr ));
return hr;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// CTAPI::EnumerateAddresses
//
// Create & return an address enumerator
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
HRESULT
STDMETHODCALLTYPE
CTAPI::EnumerateAddresses(
IEnumAddress ** ppEnumAddresses
)
{
HRESULT hr = S_OK;
CComObject< CTapiEnum<IEnumAddress, ITAddress, &IID_IEnumAddress> > * pEnum;
LOG((TL_TRACE, "EnumerateAddresses enter"));
Lock();
if (!( m_dwFlags & TAPIFLAG_INITIALIZED ))
{
LOG((TL_ERROR, "EnumerateAddresses - tapi object must be initialized first" ));
Unlock();
return TAPI_E_REINIT;
}
Unlock();
if ( TAPIIsBadWritePtr( ppEnumAddresses, sizeof (IEnumAddress *) ) )
{
LOG((TL_ERROR, "EnumerateAddresses - bad pointer"));
return E_POINTER;
}
// create the object
hr = CComObject< CTapiEnum<IEnumAddress, ITAddress, &IID_IEnumAddress> >::CreateInstance( &pEnum );
if (S_OK != hr)
{
LOG((TL_ERROR, "EnumerateAddresses - could not create enum - return %lx", hr));
return hr;
}
// initialize
Lock();
hr = pEnum->Initialize( m_AddressArray );
Unlock();
if (S_OK != hr)
{
pEnum->Release();
LOG((TL_ERROR, "EnumerateAddresses - could not initialize enum - return %lx", hr));
return hr;
}
*ppEnumAddresses = pEnum;
LOG((TL_TRACE, "EnumerateAddresses exit - return %lx", hr));
return hr;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// CTAPI::GetPhoneArray
//
// Fill a phone array. The array will have references to all
// of the phone objects it contains.
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
HRESULT
CTAPI::GetPhoneArray(
PhoneArray *pPhoneArray
)
{
HRESULT hr = S_OK;
LOG((TL_TRACE, "GetPhoneArray enter"));
Lock();
if (!( m_dwFlags & TAPIFLAG_INITIALIZED ))
{
LOG((TL_ERROR, "GetPhoneArray - tapi object must be initialized first" ));
Unlock();
return E_INVALIDARG;
}
Unlock();
if ( IsBadReadPtr( pPhoneArray, sizeof (PhoneArray) ) )
{
LOG((TL_ERROR, "GetPhoneArray - bad pointer"));
return E_POINTER;
}
Lock();
// initialize the array
for(int iCount = 0; iCount < m_PhoneArray.GetSize(); iCount++)
{
pPhoneArray->Add(m_PhoneArray[iCount]);
}
Unlock();
LOG((TL_TRACE, "GetPhoneArray exit - return %lx", hr));
return hr;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// CTAPI::RegisterCallHubNotifications
//
// This method is used to tell TAPI that the application is interested in
// receiving callhub events.
//
// RETURNS
//
// S_OK
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HRESULT
STDMETHODCALLTYPE
CTAPI::RegisterCallHubNotifications(
VARIANT_BOOL bNotify
)
{
LOG((TL_TRACE, "RegisterCallHubNotifications - enter"));
Lock();
if (!( m_dwFlags & TAPIFLAG_INITIALIZED ))
{
LOG((TL_ERROR, "RCHN - tapi object must be initialized first" ));
Unlock();
return E_INVALIDARG;
}
if ( bNotify )
{
LOG((TL_INFO, "RCHN - callhub notify on"));
m_dwFlags |= TAPIFLAG_CALLHUBNOTIFY;
}
else
{
LOG((TL_INFO, "RCHN - callhub notify off"));
m_dwFlags &= ~TAPIFLAG_CALLHUBNOTIFY;
}
Unlock();
LOG((TL_TRACE, "RegisterCallHubNotifications - exit - success"));
return S_OK;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// SetCallHubTracking
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HRESULT
CTAPI::SetCallHubTracking(
VARIANT pAddresses,
VARIANT_BOOL bSet
)
{
HRESULT hr = S_OK;
SAFEARRAY * pAddressArray;
LONG llBound, luBound;
int iCount;
LOG((TL_TRACE, "SetCallHubTracking - enter"));
Lock();
if (!( m_dwFlags & TAPIFLAG_INITIALIZED ))
{
LOG((TL_ERROR, "SCHT - tapi object must be initialized first" ));
Unlock();
return E_INVALIDARG;
}
Unlock();
hr = VerifyAndGetArrayBounds(
pAddresses,
&pAddressArray,
&llBound,
&luBound
);
if (!SUCCEEDED(hr))
{
LOG((TL_ERROR, "SCHT - invalid address array - return %lx", hr));
return hr;
}
//
// all addresses
//
if (NULL == pAddressArray)
{
Lock();
//
// go through all the addresses
//
for (iCount = 0; iCount < m_AddressArray.GetSize(); iCount++ )
{
CAddress * pCAddress;
//
// register
//
pCAddress = dynamic_cast<CAddress *>(m_AddressArray[iCount]);
if (NULL == pCAddress)
{
LOG((TL_ERROR, "SCHT - out of memory"));
Unlock();
return E_OUTOFMEMORY;
}
hr = (pCAddress)->SetCallHubTracking( bSet );
if (!SUCCEEDED(hr))
{
LOG((TL_WARN,
"SCHT failed %lx on address %lx",
hr,
iCount
));
}
}
m_dwFlags |= TAPIFLAG_ALLCALLHUBTRACKING;
Unlock();
return S_OK;
}
//
// if here, only registering addresses
// from array
//
// go through array
//
for ( ; llBound <=luBound; llBound++ )
{
ITAddress * pAddress;
CAddress * pCAddress;
hr = SafeArrayGetElement(
pAddressArray,
&llBound,
&pAddress
);
if ( (!SUCCEEDED(hr)) || (NULL == pAddress) )
{
continue;
}
pCAddress = dynamic_cast<CAddress *>(pAddress);
hr = pCAddress->SetCallHubTracking( bSet );
//
// safearragetelement addrefs
//
pAddress->Release();
if (!SUCCEEDED(hr))
{
LOG((
TL_WARN,
"SCHT failed %lx on address %p",
hr,
pAddress
));
return hr;
}
}
LOG((TL_TRACE, "SetCallHubTracking - exit - success"));
return S_OK;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// CTAPI::RegisterCallNotifications
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HRESULT
STDMETHODCALLTYPE
CTAPI::RegisterCallNotifications(
ITAddress * pAddress,
VARIANT_BOOL fMonitor,
VARIANT_BOOL fOwner,
long lMediaTypes,
long lCallbackInstance,
long * plRegister
)
{
HRESULT hr = S_OK;
PVOID pRegister;
DWORD dwMediaModes = 0, dwPrivs = 0;
REGISTERITEM * pRegisterItem;
CAddress * pCAddress;
LOG((TL_TRACE, "RegisterCallNotifications - enter"));
Lock();
if (!( m_dwFlags & TAPIFLAG_INITIALIZED ))
{
LOG((TL_ERROR, "RegisterCallNotifications - tapi object must be initialized first" ));
Unlock();
return E_INVALIDARG;
}
Unlock();
if (TAPIIsBadWritePtr( plRegister, sizeof(long) ) )
{
LOG((TL_ERROR, "RegisterCallNotifications - invalid plRegister"));
return E_POINTER;
}
try
{
pCAddress = dynamic_cast<CAddress *>(pAddress);
}
catch(...)
{
hr = E_POINTER;
}
if ( ( NULL == pCAddress ) || !SUCCEEDED(hr) )
{
LOG((TL_ERROR, "RegisterCallNotifications - bad address"));
return E_POINTER;
}
//
// determine the privileges
//
if (fOwner)
{
dwPrivs |= LINECALLPRIVILEGE_OWNER;
}
if (fMonitor)
{
dwPrivs |= LINECALLPRIVILEGE_MONITOR;
}
if ( 0 == dwPrivs )
{
LOG((TL_ERROR, "RegisterCallNotifications - fMonitor and/or fOwner must be true"));
return E_INVALIDARG;
}
if (! (pCAddress->GetMediaMode(
lMediaTypes,
&dwMediaModes
) ) )
{
LOG((TL_ERROR, "RegisterCallNotifications - bad mediamodes"));
return E_INVALIDARG;
}
Lock();
pRegisterItem = (REGISTERITEM *)ClientAlloc( sizeof(REGISTERITEM) );
if ( NULL == pRegisterItem )
{
LOG((TL_ERROR, "RegisterCallNotifications - Alloc registrationarray failed"));
Unlock();
return E_OUTOFMEMORY;
}
hr = pCAddress->AddCallNotification(
dwPrivs,
dwMediaModes,
lCallbackInstance,
&pRegister
);
if (!SUCCEEDED(hr))
{
LOG((TL_ERROR, "RegisterCallNotifications - AddCallNotification failed"));
ClientFree( pRegisterItem );
Unlock();
return hr;
}
pRegisterItem->dwType = RA_ADDRESS;
pRegisterItem->pInterface = (PVOID)pCAddress;
pRegisterItem->pRegister = pRegister;
try
{
m_RegisterItemPtrList.push_back( (PVOID)pRegisterItem );
}
catch(...)
{
hr = E_OUTOFMEMORY;
LOG((TL_ERROR, "RegisterCallNotifications- failed - because of alloc failure"));
ClientFree( pRegisterItem );
}
#if DBG
if (m_dwEventFilterMask == 0)
{
LOG((TL_WARN, "RegisterCallNotifications - no Event Mask set !!!"));
}
#endif
Unlock();
//
// return registration cookie
//
if( S_OK == hr )
{
//
// create a 32-bit handle for the RegisterItem pointer
//
DWORD dwCookie = CreateHandleTableEntry((ULONG_PTR)pRegisterItem);
if (0 == dwCookie)
{
hr = E_OUTOFMEMORY;
LOG((TL_ERROR, "RegisterCallNotifications - failed to create a handle for REGISTERITEM object %p", pRegisterItem));
}
else
{
LOG((TL_INFO,
"RegisterCallNotifications - Mapped handle %lx (to be returned as cookie) to REGISTERITEM object %p",
dwCookie, pRegisterItem ));
// register the cookie with the address object, so address can remove it if
// the address is deallocated before the call to CTAPI::UnregisterNotifications
pCAddress->RegisterNotificationCookie(dwCookie);
*plRegister = dwCookie;
}
}
LOG((TL_TRACE, "RegisterCallNotifications - return %lx", hr));
return hr;
}
STDMETHODIMP
CTAPI::UnregisterNotifications(
long ulRegister
)
{
DWORD dwType;
HRESULT hr = S_OK;
REGISTERITEM * pRegisterItem = NULL;
LOG((TL_TRACE, "UnregisterNotifications - enter. Cookie %lx", ulRegister));
Lock();
if (!( m_dwFlags & TAPIFLAG_INITIALIZED ))
{
LOG((TL_ERROR, "UnregNot - tapi object must be initialized first" ));
Unlock();
return E_INVALIDARG;
}
//
// convert cookie to registration object pointer
//
pRegisterItem = (REGISTERITEM*) GetHandleTableEntry(ulRegister);
//
// remove cookie from the table
//
DeleteHandleTableEntry(ulRegister);
Unlock();
if ( NULL != pRegisterItem )
{
LOG((TL_INFO, "UnregisterNotifications - Matched cookie %lx to REGISTERITEM object %p", ulRegister, pRegisterItem ));
if (IsBadReadPtr( pRegisterItem, sizeof(REGISTERITEM) ) )
{
LOG((TL_ERROR, "UnregNot - invalid pRegisterItem returned from the handle table search"));
return E_POINTER;
}
}
else
{
LOG((TL_WARN, "UnregisterNotifications - invalid lRegister"));
return E_INVALIDARG;
}
dwType = pRegisterItem->dwType;
//
// switch on the type of notification
//
switch ( dwType )
{
case RA_ADDRESS:
CAddress * pCAddress;
ITAddress * pAddress;
pCAddress = (CAddress *) (pRegisterItem->pInterface);
//
// try to get the address
//
try
{
hr = pCAddress->QueryInterface(
IID_ITAddress,
(void **)&pAddress
);
}
catch(...)
{
hr = E_POINTER;
}
if ( !SUCCEEDED(hr) )
{
LOG((TL_ERROR, "Invalid interface in unregisternotifications"));
return hr;
}
//
// tell the address
//
pCAddress->RemoveCallNotification( pRegisterItem->pRegister );
//
// tell the address to remove a cookie from its list
//
pCAddress->RemoveNotificationCookie(ulRegister);
pAddress->Release();
Lock();
//
// remove array from our list
//
m_RegisterItemPtrList.remove( pRegisterItem );
Unlock();
//
// free structure
//
ClientFree( pRegisterItem );
break;
case RA_CALLHUB:
break;
}
LOG((TL_TRACE, "UnregisterNotifications - exit - success"));
return S_OK;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP
CTAPI::get_CallHubs(
VARIANT * pVariant
)
{
LOG((TL_TRACE, "get_CallHubs enter"));
LOG((TL_TRACE, " pVariant ------->%p", pVariant));
HRESULT hr;
IDispatch * pDisp;
Lock();
if (!( m_dwFlags & TAPIFLAG_INITIALIZED ) )
{
LOG((TL_ERROR, "get_CallHubs - tapi object must be initialized first" ));
Unlock();
return E_INVALIDARG;
}
Unlock();
if ( TAPIIsBadWritePtr( pVariant, sizeof(VARIANT) ) )
{
LOG((TL_ERROR, "get_CallHubs - bad pointer"));
return E_POINTER;
}
CComObject< CTapiCollection< ITCallHub > > * p;
CComObject< CTapiCollection< ITCallHub > >::CreateInstance( &p );
if (NULL == p)
{
LOG((TL_ERROR, "get_CallHubs - could not create collection" ));
return E_OUTOFMEMORY;
}
Lock();
//
// initialize
//
hr = p->Initialize( m_CallHubArray );
Unlock();
if (S_OK != hr)
{
LOG((TL_ERROR, "get_CallHubs - 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_CallHubs - 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_CallHubss exit - return %lx", hr ));
return hr;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// EnumerateCallHubs
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP
CTAPI::EnumerateCallHubs(
IEnumCallHub ** ppEnumCallHub
)
{
HRESULT hr = S_OK;
CComObject< CTapiEnum<IEnumCallHub, ITCallHub, &IID_IEnumCallHub> > * pEnum;
LOG((TL_TRACE, "EnumerateCallHubs enter"));
Lock();
if (!( m_dwFlags & TAPIFLAG_INITIALIZED ))
{
LOG((TL_ERROR, "EnumerateCallHubs - tapi object must be initialized first" ));
Unlock();
return E_INVALIDARG;
}
Unlock();
if ( TAPIIsBadWritePtr( ppEnumCallHub, sizeof( IEnumCallHub *) ) )
{
LOG((TL_ERROR, "EnumerateCallHubs - bad pointer"));
return E_POINTER;
}
//
// create the object
//
hr = CComObject< CTapiEnum<IEnumCallHub, ITCallHub, &IID_IEnumCallHub> >::CreateInstance( &pEnum );
if (S_OK != hr)
{
LOG((TL_ERROR, "EnumerateCallHubs - could not create enum - return %lx", hr));
return hr;
}
//
// initialize
//
Lock();
hr = pEnum->Initialize( m_CallHubArray );
Unlock();
if (S_OK != hr)
{
pEnum->Release();
LOG((TL_ERROR, "EnumerateCallHubs - could not initialize enum - return %lx", hr));
return hr;
}
*ppEnumCallHub = pEnum;
LOG((TL_TRACE, "EnumerateCallHubs exit - return %lx", hr));
return hr;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// CTAPI::EnumConnectionPoints
//
// Standard IConnectionPoint method
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
HRESULT
__stdcall
CTAPI::EnumConnectionPoints(
IEnumConnectionPoints **ppEnum
)
{
HRESULT hr;
LOG((TL_TRACE, "EnumConnectionPoints enter"));
hr = E_NOTIMPL;
LOG((TL_TRACE, "EnumConnectionPointer exit - return %lx", hr));
return hr;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// FindConnectionPoint
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HRESULT
__stdcall
CTAPI::FindConnectionPoint(
REFIID riid,
IConnectionPoint **ppCP
)
{
LOG((TL_TRACE, "FindConnectionPoint enter"));
#if DBG
{
WCHAR guidName[100];
StringFromGUID2(riid, (LPOLESTR)&guidName, 100);
LOG((TL_INFO, "FindConnectionPoint - RIID : %S", guidName));
}
#endif
Lock();
if (!( m_dwFlags & TAPIFLAG_INITIALIZED ))
{
LOG((TL_ERROR, "FindConnectionPoint - tapi object must be initialized first" ));
Unlock();
return TAPI_E_NOT_INITIALIZED;
}
Unlock();
if ( TAPIIsBadWritePtr( ppCP, sizeof(IConnectionPoint *) ) )
{
LOG((TL_ERROR, "FindConnectionPoint - bad pointer"));
return E_POINTER;
}
//
// is this the right interface?
//
if ( (IID_ITTAPIEventNotification != riid ) && (DIID_ITTAPIDispatchEventNotification != riid ) )
{
* ppCP = NULL;
LOG((TL_ERROR, "FindConnectionPoint - do not support this riid"));
return CONNECT_E_NOCONNECTION;
}
//
// if it's the right interface, create a new connection point
// and return it
//
Lock();
*ppCP = m_pCP;
(*ppCP)->AddRef();
Unlock();
//
// success
//
LOG((TL_TRACE, "FindConnectionPoint - Success"));
return S_OK;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// CreateAllAddressesOnAllLines
// This is called when the first TAPI object is created.
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HRESULT
CTAPI::CreateAllAddressesOnAllLines(
void
)
{
DWORD dwCount;
LOG((TL_TRACE, "CreateAllAddressesOnAllLines enter"));
Lock();
// go through all line devs
for (dwCount = 0; dwCount < m_dwLineDevs; dwCount++)
{
CreateAddressesOnSingleLine( dwCount, FALSE );
}
Unlock();
return S_OK;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// CreateAddressesOnSingleLine
//
// assumed called in lock!
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HRESULT
CTAPI::CreateAddressesOnSingleLine( DWORD dwDeviceID, BOOL bFireEvent )
{
DWORD dwRealAddresses = 0, dwAddress;
DWORD dwAPIVersion;
HRESULT hr;
LPLINEDEVCAPS pDevCaps = NULL;
LPLINEADDRESSCAPS pAddressCaps = NULL;
LOG((TL_TRACE, "CreateAddressesOnSingleLine: entered."));
hr = LineNegotiateAPIVersion(
(HLINEAPP)m_dwLineInitDataHandle,
dwDeviceID,
&dwAPIVersion
);
if (S_OK != hr)
{
LOG((TL_WARN, "CreateAddressesOnSingleLine: LineNegotiateAPIVersion failed on device %d", dwDeviceID));
return hr;
}
LOG((TL_INFO, "CreateAddressesOnSingleLine: LineNegotiateAPIVersion returned version %lx", dwAPIVersion));
hr = LineGetDevCapsWithAlloc(
(HLINEAPP)m_dwLineInitDataHandle,
dwDeviceID,
dwAPIVersion,
&pDevCaps
);
if (S_OK != hr)
{
LOG((TL_WARN, "CreateAddressesOnSingleLine: LineGetDevCaps failed for device %d", dwDeviceID));
if ( NULL != pDevCaps )
{
ClientFree( pDevCaps );
}
return hr;
}
if (pDevCaps->dwNumAddresses == 0)
{
LOG((TL_WARN, "CreateAddressesOnSingleLine: Device %d has no addressess - will assume 1 address", dwDeviceID));
pDevCaps->dwNumAddresses = 1;
}
LPVARSTRING pVarString;
DWORD dwProviderID;
//
// get the permanent provider ID for this line.
//
hr = LineGetID(
NULL,
dwDeviceID,
NULL,
LINECALLSELECT_DEVICEID,
&pVarString,
L"tapi/providerid"
);
if (S_OK != hr)
{
if (NULL != pVarString)
{
ClientFree( pVarString);
}
if ( NULL != pDevCaps )
{
ClientFree( pDevCaps );
}
LOG((TL_ERROR, "CreateAddressesOnSingleLine: get_ServiceProviderName - LineGetID returned %lx", hr ));
return hr;
}
//
// get the id DWORD at the end of the structure
//
dwProviderID = *((LPDWORD) (((LPBYTE) pVarString) + pVarString->dwStringOffset));
ClientFree( pVarString );
// go through all the addresses on each line, and
// create an address object.
for (dwAddress = 0; dwAddress < pDevCaps->dwNumAddresses; dwAddress++)
{
CComObject<CAddress> * pAddress;
ITAddress * pITAddress;
try
{
hr = CComObject<CAddress>::CreateInstance( &pAddress );
}
catch(...)
{
LOG((TL_ERROR, "CreateAddressesOnSingleLine: CreateInstance - Address - threw"));
continue;
}
if ( !SUCCEEDED(hr) || (NULL == pAddress) )
{
LOG((TL_ERROR, "CreateAddressesOnSingleLine: CreateInstance - Address - failed - %lx", hr));
continue;
}
//
// initialize the address
// if there are no phone devices,
// give NULL for the hPhoneApp, so the address
// doesn't think that there may be a phone device
//
hr = pAddress->Initialize(
this,
(HLINEAPP)m_dwLineInitDataHandle,
#ifdef USE_PHONEMSP
(m_dwPhoneDevs)?((HPHONEAPP)m_dwPhoneInitDataHandle):NULL,
#endif USE_PHONEMSP
dwAPIVersion,
dwDeviceID,
dwAddress,
dwProviderID,
pDevCaps,
m_dwEventFilterMask
);
if (S_OK != hr)
{
LOG((TL_ERROR, "CreateAddressesOnSingleLine: failed for device %d, address %d", dwDeviceID, dwAddress));
delete pAddress;
continue;
}
//
// add to list
//
pITAddress = dynamic_cast<ITAddress *>(pAddress);
m_AddressArray.Add( pITAddress );
pAddress->Release();
if ( bFireEvent )
{
CTapiObjectEvent::FireEvent(
this,
TE_ADDRESSCREATE,
pAddress,
0,
NULL
);
}
}
if ( NULL != pDevCaps )
{
ClientFree( pDevCaps );
}
LOG((TL_INFO, "CreateAddressesOnSingleLine: completed."));
return S_OK;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// CreateAllPhones
// This is called when the first TAPI object is created.
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HRESULT
CTAPI::CreateAllPhones(
void
)
{
DWORD dwCount;
LOG((TL_TRACE, "CreateAllPhones enter"));
Lock();
// go through all phone devs
for (dwCount = 0; dwCount < m_dwPhoneDevs; dwCount++)
{
CreatePhone( dwCount, FALSE );
}
Unlock();
return S_OK;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// CreatePhone
//
// assumed called in lock!
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HRESULT
CTAPI::CreatePhone( DWORD dwDeviceID, BOOL bFireEvent )
{
DWORD dwAPIVersion;
HRESULT hr;
hr = PhoneNegotiateAPIVersion(
(HPHONEAPP)m_dwPhoneInitDataHandle,
dwDeviceID,
&dwAPIVersion
);
if (S_OK != hr)
{
LOG((TL_WARN, "CreatePhone - phoneNegotiateAPIVersion failed on device %d", dwDeviceID));
return hr;
}
LOG((TL_INFO, "CreatePhone - phoneNegotiateAPIVersion returned version %lx", dwAPIVersion));
// create a phone object.
CComObject<CPhone> * pPhone;
ITPhone * pITPhone;
__try
{
hr = CComObject<CPhone>::CreateInstance( &pPhone );
}
__except( (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH )
{
LOG((TL_ERROR, "CreatePhone - CreateInstancefailed - because of alloc failure"));
return hr;
}
if ( !SUCCEEDED(hr) || (NULL == pPhone) )
{
LOG((TL_ERROR, "CreatePhone - CreateInstance failed - %lx", hr));
return hr;
}
//
// initialize the phone
//
hr = pPhone->Initialize(
this,
(HLINEAPP)m_dwPhoneInitDataHandle,
dwAPIVersion,
dwDeviceID
);
if ( FAILED(hr) )
{
LOG((TL_ERROR, "CreatePhone failed for device %d", dwDeviceID));
delete pPhone;
return hr;
}
//
// add to list
//
pITPhone = dynamic_cast<ITPhone *>(pPhone);
m_PhoneArray.Add( pITPhone );
pPhone->Release();
if ( bFireEvent )
{
CTapiObjectEvent::FireEvent(this,
TE_PHONECREATE,
NULL,
0,
pITPhone
);
}
return S_OK;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// Shutdown
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
HRESULT
STDMETHODCALLTYPE
CTAPI::Shutdown()
{
PtrList::iterator iter, end;
int iCount;
DWORD dwSignalled;
int tapiObjectArraySize=0;
CTAPI *pTapi;
LOG((TL_TRACE, "Shutdown[%p] - enter", this));
LOG((TL_TRACE, "Shutdown - enter"));
CoWaitForMultipleHandles (0,
INFINITE,
1,
&ghTapiInitShutdownSerializeMutex,
&dwSignalled
);
Lock();
if ( (!( m_dwFlags & TAPIFLAG_INITIALIZED )) &&
(!( m_dwFlags & TAPIFLAG_REINIT)))
{
LOG((TL_WARN, "Shutdown - already shutdown - return S_FALSE"));
Unlock();
ReleaseMutex( ghTapiInitShutdownSerializeMutex );
return S_FALSE;
}
m_dwFlags &= ~TAPIFLAG_INITIALIZED;
m_dwFlags &= ~TAPIFLAG_REINIT;
pTapi = this;
//
// close all the phones
//
for(iCount = 0; iCount < m_PhoneArray.GetSize(); iCount++)
{
CPhone *pCPhone = NULL;
try
{
pCPhone = dynamic_cast<CPhone *>(m_PhoneArray[iCount]);
}
catch(...)
{
LOG((TL_ERROR, "Shutdown - phone array contains a bad phone pointer"));
pCPhone = NULL;
}
if (NULL != pCPhone)
{
pCPhone->ForceClose();
}
}
EnterCriticalSection( &gcsTapiObjectArray );
m_sTAPIObjectArray.Remove ( pTapi );
tapiObjectArraySize = m_sTAPIObjectArray.GetSize();
LeaveCriticalSection ( &gcsTapiObjectArray );
m_AgentHandlerArray.Shutdown();
gpLineHashTable->Flush(this);
gpCallHashTable->Flush(this);
gpCallHubHashTable->Flush(this);
gpPhoneHashTable->Flush(this);
//
// tell each address in the array that it is time to toss all
// the cookies
//
int nAddressArraySize = m_AddressArray.GetSize();
for (int i = 0; i < nAddressArraySize; i++)
{
//
// we need a pointer to CAddress to unregister cookies
//
CAddress *pAddress = NULL;
//
// in case address array contains a pointer to nonreadable memory,
// do dynamic cast inside try/catch
//
try
{
pAddress = dynamic_cast<CAddress*>(m_AddressArray[i]);
}
catch(...)
{
LOG((TL_ERROR, "Shutdown - address array contains a bad address pointer"));
pAddress = NULL;
}
//
// attempt to unregister address' notifications
//
if (NULL != pAddress)
{
//
// unregister all notification cookies
//
pAddress->UnregisterAllCookies();
//
// notify address that tapi is being shutdown, so it can do
// whatever clean up is necessary
//
pAddress->AddressOnTapiShutdown();
}
else
{
//
// we have an address that is not an address. debug!
//
LOG((TL_ERROR,
"Shutdown - address array contains a bad address pointer."));
_ASSERTE(FALSE);
}
}
m_AddressArray.Shutdown();
m_PhoneArray.Shutdown();
m_CallHubArray.Shutdown();
Unlock();
NewShutdown();
Lock();
if ( NULL != m_pCP )
{
m_pCP->Release();
m_pCP = NULL;
}
iter = m_RegisterItemPtrList.begin();
end = m_RegisterItemPtrList.end();
while (iter != end)
{
ClientFree( *iter );
iter ++;
}
m_RegisterItemPtrList.clear();
Unlock();
if ( 0 == tapiObjectArraySize )
{
FinalTapiCleanup();
EnterCriticalSection( &gcsGlobalInterfaceTable );
ReleaseGIT();
LeaveCriticalSection( &gcsGlobalInterfaceTable );
//
// no longer need handle table.
//
ShutdownAndDeallocateHandleTable();
}
ReleaseMutex( ghTapiInitShutdownSerializeMutex );
LOG((TL_TRACE, "Shutdown - exit"));
return S_OK;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// finalrelease of tapi object
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
void
CTAPI::FinalRelease()
{
LOG((TL_TRACE, "FinalRelease - enter"));
Lock();
FreeAllCaches();
Unlock();
LOG((TL_TRACE, "FinalRelease - exit"));
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// VerifyAndGetArrayBounds
//
// Helper function for variant/safearrays
//
// Array
// IN Variant that contains a safearray
//
// ppsa
// OUT safearray returned here
//
// pllBound
// OUT array lower bound returned here
//
// pluBound
// OUT array upper boudn returned here
//
// RETURNS
//
// verifies that Array contains an array, and returns the array, upper
// and lower bounds.
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HRESULT
VerifyAndGetArrayBounds(
VARIANT Array,
SAFEARRAY ** ppsa,
long * pllBound,
long * pluBound
)
{
UINT uDims;
HRESULT hr = S_OK;
//
// see if the variant & safearray are valid
//
try
{
if (!(V_ISARRAY(&Array)))
{
if ( VT_NULL ==Array.vt )
{
//
// null is usually valid
//
*ppsa = NULL;
LOG((TL_INFO, "Returning NULL array"));
return S_FALSE;
}
LOG((TL_ERROR, "Array - not an array"));
return E_INVALIDARG;
}
if ( NULL == Array.parray )
{
//
// null is usually valide
//
*ppsa = NULL;
LOG((TL_INFO, "Returning NULL array"));
return S_FALSE;
}
*ppsa = V_ARRAY(&Array);
uDims = SafeArrayGetDim( *ppsa );
}
catch(...)
{
hr = E_POINTER;
}
if (!SUCCEEDED(hr))
{
LOG((TL_ERROR, "Array - invalid array"));
return hr;
}
//
// verify array
//
if (1 != uDims)
{
if (0 == uDims)
{
LOG((TL_ERROR, "Array - has 0 dim"));
return E_INVALIDARG;
}
else
{
LOG((TL_WARN, "Array - has > 1 dim - will only use 1"));
}
}
//
// Get array bounds
//
SafeArrayGetUBound(
*ppsa,
1,
pluBound
);
SafeArrayGetLBound(
*ppsa,
1,
pllBound
);
return S_OK;
}
BOOL QueueCallbackEvent(CTAPI * pTapi, TAPI_EVENT te, IDispatch * pEvent);
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
HRESULT
CTAPI::Event(
TAPI_EVENT te,
IDispatch * pEvent
)
{
HRESULT hr = S_OK;
DWORD dwEventFilterMask;
LOG((TL_TRACE, "Event[%p] - enter. Event[0x%x]", this, te));
Lock();
dwEventFilterMask = m_dwEventFilterMask;
Unlock();
if( (te != TE_ADDRESS) &&
(te != TE_CALLHUB) &&
(te != TE_CALLINFOCHANGE) &&
(te != TE_CALLMEDIA) &&
(te != TE_CALLNOTIFICATION) &&
(te != TE_CALLSTATE) &&
(te != TE_FILETERMINAL) &&
(te != TE_PRIVATE) &&
(te != TE_QOSEVENT) &&
(te != TE_TAPIOBJECT) &&
(te != TE_ADDRESSDEVSPECIFIC) &&
(te != TE_PHONEDEVSPECIFIC) )
{
if( (te & dwEventFilterMask) == 0)
{
//
// Don't fire the event
//
hr = S_FALSE;
LOG((TL_INFO, "Event - This Event not Enabled %x", te));
return hr;
}
}
//
// It's an event from the event filtering mechanism
// TE_ADDRESS, TE_CALLHUB, TE_CALLINFOCHANGE, TE_CALLMEDIA,
// TE_CALLNOTIFICATION, TE_CALLSTATE, TE_FILETERMINAL,
// TE_PRIVATE, TE_QOSEVENT, TE_TAPIOBJECT
//
AddRef();
pEvent->AddRef();
if(QueueCallbackEvent(this, te, pEvent) == TRUE)
{
LOG((TL_INFO, "Event queued"));
}
else
{
Release();
pEvent->Release();
LOG((TL_INFO, "Event queuing Failed"));
}
LOG((TL_TRACE, "Event - exit"));
return hr;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
HRESULT
CTAPI::EventFire(
TAPI_EVENT te,
IDispatch * pEvent
)
{
ITTAPIEventNotification * pCallback = NULL;
IDispatch * pDispatch = NULL;
HRESULT hr = S_OK;
CTAPIConnectionPoint * pCP;
LOG((TL_TRACE, "EventFire - enter"));
Lock();
if( NULL != m_pCP )
{
m_pCP->AddRef();
}
pCP = m_pCP;
Unlock();
if ( NULL != pCP )
{
pDispatch = (IDispatch *)pCP->GrabEventCallback();
if ( NULL != pDispatch )
{
hr = pDispatch->QueryInterface(IID_ITTAPIEventNotification,
(void **)&pCallback
);
if (SUCCEEDED(hr) )
{
if ( NULL != pCallback )
{
LOG((TL_TRACE, "EventFire - fire on ITTAPIEventNotification"));
pCallback->Event( te, pEvent );
pCallback->Release();
}
#if DBG
else
{
LOG((TL_WARN, "EventFire - can't fire event on ITTAPIEventNotification - no callback"));
}
#endif
}
else
{
CComVariant varResult;
CComVariant* pvars = new CComVariant[2];
LOG((TL_TRACE, "EventFire - fire on IDispatch"));
VariantClear(&varResult);
pvars[1] = te;
pvars[0] = pEvent;
DISPPARAMS disp = { pvars, NULL, 2, 0 };
pDispatch->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL);
delete[] pvars;
hr = varResult.scode;
}
pDispatch->Release();
}
#if DBG
else
{
LOG((TL_WARN, "Event - can't fire event on IDispatch - no callback"));
}
#endif
}
#if DBG
else
{
LOG((TL_WARN, "Event - can't fire event - no m_pCP"));
}
#endif
if(NULL != pCP)
{
pCP->Release();
}
pEvent->Release();
LOG((TL_TRACE, "EventFire - exit"));
return S_OK;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// AddCallHub
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
void
CTAPI::AddCallHub( CCallHub * pCallHub )
{
ITCallHub * pITCallHub;
Lock();
pITCallHub = dynamic_cast<ITCallHub *>(pCallHub);
m_CallHubArray.Add( pITCallHub );
Unlock();
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// RemoveCallHub
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
void
CTAPI::RemoveCallHub( CCallHub * pCallHub )
{
ITCallHub * pITCallHub;
Lock();
pITCallHub = dynamic_cast<ITCallHub *>(pCallHub);
m_CallHubArray.Remove( pITCallHub );
Unlock();
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP
CTAPI::get_PrivateTAPIObjects(VARIANT*)
{
LOG((TL_TRACE, "get_PrivateTAPIObjects - enter"));
LOG((TL_ERROR, "get_PrivateTAPIObjects - exit E_NOTIMPL"));
return E_NOTIMPL;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// former EnumeratePrivateTAPIObjects
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP
CTAPI::EnumeratePrivateTAPIObjects(IEnumUnknown**)
{
LOG((TL_TRACE, "EnumeratePrivateTAPIObjects - enter"));
LOG((TL_ERROR, "EnumeratePrivateTAPIObjects - return E_NOTIMPL"));
return E_NOTIMPL;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// RegisterRequestRecipient
//
// simply call LineRegisterRequestRecipient - registers as assisted
// telephony application
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP
CTAPI::RegisterRequestRecipient(
long lRegistrationInstance,
long lRequestMode,
#ifdef NEWREQUEST
long lAddressTypes,
#endif
VARIANT_BOOL fEnable
)
{
HRESULT hr;
LOG((TL_TRACE, "RegisterRequestRecipient - enter"));
Lock();
if (!( m_dwFlags & TAPIFLAG_INITIALIZED ))
{
LOG((TL_ERROR, "RegisterRequestRecipient - tapi object must be initialized first" ));
Unlock();
return E_INVALIDARG;
}
Unlock();
hr = LineRegisterRequestRecipient(
(HLINEAPP)m_dwLineInitDataHandle,
lRegistrationInstance,
lRequestMode,
#ifdef NEWREQUEST
lAddressTypes,
#endif
fEnable?TRUE : FALSE
);
return hr;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// SetAssistedTelephonyPriority
//
// set the app priority for assisted telephony
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP
CTAPI::SetAssistedTelephonyPriority(
BSTR pAppFilename,
VARIANT_BOOL fPriority
)
{
HRESULT hr;
LOG((TL_TRACE, "SetAssistedTelephonyPriority - enter"));
hr = LineSetAppPriority(
pAppFilename,
0,
LINEREQUESTMODE_MAKECALL,
fPriority?1:0
);
LOG((TL_TRACE, "SetAssistedTelephonyPriority - exit - return %lx", hr));
return hr;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// SetApplicationPriority
//
// sets the app priority for incoming calls and handoff.
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP
CTAPI::SetApplicationPriority(
BSTR pAppFilename,
long lMediaType,
VARIANT_BOOL fPriority
)
{
HRESULT hr;
LOG((TL_TRACE, "SetApplicationPriority - enter"));
hr = LineSetAppPriority(
pAppFilename,
lMediaType,
0,
fPriority?1:0
);
LOG((TL_TRACE, "SetApplicationPriority - exit - return %lx", hr));
return hr;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// put_EventFilter
//
// sets the Event filter mask
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP
CTAPI::put_EventFilter(long lFilterMask)
{
HRESULT hr = S_OK;
DWORD dwOldFilterMask;
ULONG64 ulEventMasks;
DWORD dwLineDevStateSubMasks;
DWORD dwAddrStateSubMasks;
LOG((TL_TRACE, "put_EventFilter - enter"));
if (~ALL_EVENT_FILTER_MASK & lFilterMask)
{
LOG((TL_ERROR, "put_EventFilter - Unknown Event type in mask %x", lFilterMask ));
hr = E_INVALIDARG;
}
else
{
Lock();
//
// Event Filtering, we should pass the mask
// to all addresses
//
HRESULT hr = E_FAIL;
hr = SetEventFilterToAddresses( lFilterMask );
if( FAILED(hr) )
{
Unlock();
LOG((TL_ERROR, "put_EventFilter - exit"
"CopyEventFilterMaskToAddresses failed. Returns 0x%08x", hr));
return hr;
}
//
// Set the event filter
//
dwOldFilterMask = m_dwEventFilterMask;
m_dwEventFilterMask = lFilterMask;
Unlock();
// Convert lFilterMask to server side 64 bit masks
// we alway should receive:
// TE_CALLSTATE,
// TE_CALLNOTIFICATION,
// TE_PHONEEVENT
// TE_CALLHUB
// TE_CALLINFOCHANGE
// TE_TAPIOBJECT
// events because these events are used internally
// by Tapi3 objets
ulEventMasks = EM_LINE_CALLSTATE // TE_CALLSTATE
| EM_LINE_APPNEWCALL // TE_CALLNOTIFICATION
| EM_PHONE_CLOSE // TE_PHONEEVENT
| EM_PHONE_STATE // TE_PHONEEVENT
| EM_PHONE_BUTTONMODE // TE_PHONEEVENT
| EM_PHONE_BUTTONSTATE // TE_PHONEVENT
| EM_LINE_APPNEWCALLHUB // TE_CALLHUB
| EM_LINE_CALLHUBCLOSE // TE_CALLHUB
| EM_LINE_CALLINFO // TE_CALLINFOCHANGE
| EM_LINE_CREATE // TE_TAPIOBJECT
| EM_LINE_REMOVE // TE_TAPIOBJECT
| EM_LINE_CLOSE // TE_TAPIOBJECT
| EM_PHONE_CREATE // TE_TAPIOBJECT
| EM_PHONE_REMOVE // TE_TAPIOBJECT
;
dwLineDevStateSubMasks = LINEDEVSTATE_REINIT // TE_TAPIOBJECT
| LINEDEVSTATE_TRANSLATECHANGE; // TE_TAPIOBJECT
dwAddrStateSubMasks = 0;
if (lFilterMask & TE_ADDRESS)
{
// AE_STATE
dwLineDevStateSubMasks |=
LINEDEVSTATE_CONNECTED |
LINEDEVSTATE_INSERVICE |
LINEDEVSTATE_OUTOFSERVICE |
LINEDEVSTATE_MAINTENANCE |
LINEDEVSTATE_REMOVED |
LINEDEVSTATE_DISCONNECTED |
LINEDEVSTATE_LOCK;
// AE_MSGWAITON, AAE_MSGWAITOFF
dwLineDevStateSubMasks |=
LINEDEVSTATE_MSGWAITON |
LINEDEVSTATE_MSGWAITOFF ;
// AE_CAPSCHANGE
dwAddrStateSubMasks |=
LINEADDRESSSTATE_CAPSCHANGE;
dwLineDevStateSubMasks |=
LINEDEVSTATE_CAPSCHANGE;
dwLineDevStateSubMasks |=
LINEDEVSTATE_RINGING | // AE_RINGING
LINEDEVSTATE_CONFIGCHANGE; // AE_CONFIGCHANGE
dwAddrStateSubMasks |=
LINEADDRESSSTATE_FORWARD; // AE_FORWARD
// AE_NEWTERMINAL : ignore private MSP events
// AE_REMOVETERMINAL : ignore private MSP events
}
if (lFilterMask & TE_CALLMEDIA)
{
// Skil media event
}
if (lFilterMask & TE_PRIVATE)
{
// skip MSP private event
}
if (lFilterMask & TE_REQUEST)
{
// LINE_REQUEST is not masked by the server
}
if (lFilterMask & TE_AGENT)
{
ulEventMasks |= EM_LINE_AGENTSTATUSEX | EM_LINE_AGENTSTATUS;
}
if (lFilterMask & TE_AGENTSESSION)
{
ulEventMasks |= EM_LINE_AGENTSESSIONSTATUS;
}
if (lFilterMask & TE_QOSEVENT)
{
ulEventMasks |= EM_LINE_QOSINFO;
}
if (lFilterMask & TE_AGENTHANDLER)
{
// TAPI 3 client side only?
}
if (lFilterMask & TE_ACDGROUP)
{
ulEventMasks |= EM_LINE_GROUPSTATUS;
}
if (lFilterMask & TE_QUEUE)
{
ulEventMasks |= EM_LINE_QUEUESTATUS;
}
if (lFilterMask & TE_DIGITEVENT)
{
// LINE_MONITORDIGITS not controled by event filtering
}
if (lFilterMask & TE_GENERATEEVENT)
{
// LINE_GENERATE not controled by event filtering
}
if (lFilterMask & TE_TONEEVENT)
{
// LINE_MONITORTONE not controled by event filtering
}
if (lFilterMask & TE_GATHERDIGITS)
{
// LINE_GATHERDIGITS not controled by event filtering
}
if (lFilterMask & TE_ADDRESSDEVSPECIFIC)
{
ulEventMasks |= EM_LINE_DEVSPECIFICEX | EM_LINE_DEVSPECIFIC;
}
if (lFilterMask & TE_PHONEDEVSPECIFIC)
{
ulEventMasks |= EM_PHONE_DEVSPECIFIC;
}
hr = tapiSetEventFilterMasks (
TAPIOBJ_NULL,
NULL,
ulEventMasks
);
if (hr == 0)
{
hr = tapiSetEventFilterSubMasks (
TAPIOBJ_NULL,
NULL,
EM_LINE_LINEDEVSTATE,
dwLineDevStateSubMasks
);
}
if (hr == 0)
{
hr = tapiSetEventFilterSubMasks (
TAPIOBJ_NULL,
NULL,
EM_LINE_ADDRESSSTATE,
dwAddrStateSubMasks
);
}
if (hr != 0)
{
hr = mapTAPIErrorCode(hr);
}
LOG((TL_INFO, "put_EventFilter - mask changed %x to %x", dwOldFilterMask, lFilterMask ));
}
LOG((TL_TRACE,hr, "put_EventFilter - exit "));
return hr;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// get_EventFilter
//
// gets the Event filter mask
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP
CTAPI::get_EventFilter(long * plFilterMask)
{
HRESULT hr = S_OK;
LOG((TL_TRACE, "get_EventFilter - enter"));
if ( TAPIIsBadWritePtr( plFilterMask, sizeof(long) ) )
{
LOG((TL_ERROR, "get_EventFilter - bad plFilterMask pointer"));
hr = E_POINTER;
}
else
{
Lock();
*plFilterMask = m_dwEventFilterMask;
Unlock();
}
LOG((TL_TRACE, hr, "get_EventFilter - exit "));
return hr;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Interface : ITTAPI2
// Method : get_Phones
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HRESULT
CTAPI::get_Phones(
VARIANT * pPhones
)
{
HRESULT hr;
IDispatch * pDisp;
LOG((TL_TRACE, "get_Phones enter"));
Lock();
if (!( m_dwFlags & TAPIFLAG_INITIALIZED ) )
{
LOG((TL_ERROR, "get_Phones - tapi object must be initialized first" ));
Unlock();
return TAPI_E_NOT_INITIALIZED;
}
Unlock();
if ( TAPIIsBadWritePtr( pPhones, sizeof( VARIANT ) ) )
{
LOG((TL_ERROR, "get_Phones - bad pointer"));
return E_POINTER;
}
CComObject< CTapiCollection< ITPhone > > * p;
CComObject< CTapiCollection< ITPhone > >::CreateInstance( &p );
if (NULL == p)
{
LOG((TL_ERROR, "get_Phones - could not create collection" ));
return E_OUTOFMEMORY;
}
// get the IDispatch interface
hr = p->_InternalQueryInterface( IID_IDispatch, (void **) &pDisp );
if (S_OK != hr)
{
LOG((TL_ERROR, "get_Phones - could not get IDispatch interface" ));
delete p;
return hr;
}
Lock();
// initialize
hr = p->Initialize( m_PhoneArray );
Unlock();
if (S_OK != hr)
{
LOG((TL_ERROR, "get_Phones - could not initialize collection" ));
pDisp->Release();
return hr;
}
// put it in the variant
VariantInit(pPhones);
pPhones->vt = VT_DISPATCH;
pPhones->pdispVal = pDisp;
LOG((TL_TRACE, "get_Phones - exit - return %lx", hr ));
return hr;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Interface : ITTAPI2
// Method : EnumeratePhones
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HRESULT
CTAPI::EnumeratePhones(
IEnumPhone ** ppEnumPhone
)
{
HRESULT hr;
LOG((TL_TRACE, "EnumeratePhones - enter"));
LOG((TL_TRACE, " ppEnumPhone----->%p", ppEnumPhone ));
Lock();
if (!( m_dwFlags & TAPIFLAG_INITIALIZED ) )
{
LOG((TL_ERROR, "EnumeratePhones - tapi object must be initialized first" ));
Unlock();
return TAPI_E_NOT_INITIALIZED;
}
Unlock();
if ( TAPIIsBadWritePtr( ppEnumPhone, sizeof( IEnumPhone * ) ) )
{
LOG((TL_ERROR, "EnumeratePhones - bad pointer"));
return E_POINTER;
}
//
// create the enumerator
//
CComObject< CTapiEnum< IEnumPhone, ITPhone, &IID_IEnumPhone > > * p;
hr = CComObject< CTapiEnum< IEnumPhone, ITPhone, &IID_IEnumPhone > >
::CreateInstance( &p );
if (S_OK != hr)
{
LOG((TL_ERROR, "EnumeratePhones - could not create enum" ));
return hr;
}
Lock();
// initialize it with our phone list, initialize adds a reference to p
p->Initialize( m_PhoneArray );
Unlock();
//
// return it
//
*ppEnumPhone = p;
LOG((TL_TRACE, "EnumeratePhones - exit - return %lx", hr ));
return hr;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
// Interface : ITTAPI2
// Method : CreateEmptyCollectionObject
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP
CTAPI::CreateEmptyCollectionObject(
ITCollection2 ** ppCollection
)
{
HRESULT hr;
LOG((TL_TRACE, "CreateEmptyCollectionObject enter"));
if ( TAPIIsBadWritePtr( ppCollection, sizeof( ITCollection2 * ) ) )
{
LOG((TL_ERROR, "CreateEmptyCollectionObject - bad pointer"));
return E_POINTER;
}
// Initialize the return value in case we fail
*ppCollection = NULL;
CComObject< CTapiCollection< IDispatch > > * p;
hr = CComObject< CTapiCollection< IDispatch > >::CreateInstance( &p );
if ( S_OK != hr )
{
LOG((TL_ERROR, "CreateEmptyCollectionObject - could not create CTapiCollection" ));
return E_OUTOFMEMORY;
}
// get the ITCollection2 interface
hr = p->QueryInterface( IID_ITCollection2, (void **) ppCollection );
if ( FAILED(hr) )
{
LOG((TL_ERROR, "CreateEmptyCollectionObject - could not get ITCollection2 interface" ));
delete p;
return hr;
}
LOG((TL_TRACE, "CreateEmptyCollectionObject - exit - return %lx", hr ));
return hr;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// DoLineCreate
//
// handles line_create message. basically, creates a new
// address object
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
void
CTAPI::DoLineCreate( DWORD dwDeviceID )
{
HRESULT hr;
Lock();
CreateAddressesOnSingleLine( dwDeviceID, TRUE );
Unlock();
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// DoLineRemove( DWORD dwDeviceID )
//
// tapisrv has sent a LINE_REMOVE message. find the corresponding
// address object(s), remove them from our list, and send a
// message to the app
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
void
CTAPI::DoLineRemove( DWORD dwDeviceID )
{
HRESULT hr;
ITAddress * pAddress;
CAddress * pCAddress;
int iCount;
#if DBG
BOOL bFound = FALSE;
#endif
LOG((TL_TRACE, "DoLineRemove - enter - dwDeviceID %d", dwDeviceID));
Lock();
//
// go through the addresses
//
for(iCount = 0; iCount < m_AddressArray.GetSize(); iCount++)
{
pAddress = m_AddressArray[iCount];
pCAddress = dynamic_cast<CAddress *>(pAddress);
if (pCAddress != NULL)
{
//
// does the device ID match?
//
if ( dwDeviceID == pCAddress->GetDeviceID() )
{
LOG((TL_INFO, "DoLineRemove - found matching address - %p", pAddress));
//
// make sure the address is in the correct state
//
pCAddress->OutOfService(LINEDEVSTATE_REMOVED);
//
// fire event
//
CTapiObjectEvent::FireEvent(
this,
TE_ADDRESSREMOVE,
pAddress,
0,
NULL
);
//
// remove from our list
//
LOG((TL_INFO, "DoLineRemove - removing address %p", pAddress));
m_AddressArray.RemoveAt(iCount);
iCount--;
#if DBG
bFound = TRUE;
#endif
}
}
}
#if DBG
if ( !bFound )
{
LOG((TL_WARN, "Receive LINE_REMOVE but couldn't find address object"));
}
#endif
LOG((TL_TRACE, "DoLineRemove - exiting"));
Unlock();
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// DoPhoneCreate
//
// handles PHONE_CREATE message. basically, creates a new
// phone object
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
void
CTAPI::DoPhoneCreate( DWORD dwDeviceID )
{
HRESULT hr;
Lock();
CreatePhone( dwDeviceID, TRUE );
Unlock();
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// DoPhoneRemove( DWORD dwDeviceID )
//
// tapisrv has sent a PHONE_REMOVE message. find the corresponding
// phone object(s), remove them from our list, and send a
// message to the app
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
void
CTAPI::DoPhoneRemove( DWORD dwDeviceID )
{
HRESULT hr;
ITPhone * pPhone;
CPhone * pCPhone;
int iPhoneCount;
int iAddressCount;
#if DBG
BOOL bFound;
#endif
LOG((TL_TRACE, "DoPhoneRemove - enter - dwDeviceID %d", dwDeviceID));
Lock();
//
// go through the phones
//
for(iPhoneCount = 0; iPhoneCount < m_PhoneArray.GetSize(); iPhoneCount++)
{
pPhone = m_PhoneArray[iPhoneCount];
pCPhone = dynamic_cast<CPhone *>(pPhone);
if (NULL == pCPhone)
{
//
// something went terribly wrong
//
LOG((TL_ERROR, "DoPhoneRemove - failed to cast ptr %p to a phone object", pPhone));
_ASSERTE(FALSE);
continue;
}
//
// does the device ID match?
//
if ( dwDeviceID == pCPhone->GetDeviceID() )
{
LOG((TL_INFO, "DoPhoneRemove - found matching phone - %p", pPhone));
//
// fire event
//
CTapiObjectEvent::FireEvent(this,
TE_PHONEREMOVE,
NULL,
0,
pPhone
);
//
// remove from our list
//
LOG((TL_INFO, "DoPhoneRemove - removing phone %p", pPhone));
m_PhoneArray.RemoveAt(iPhoneCount);
iPhoneCount--;
#if DBG
bFound = TRUE;
#endif
}
}
#if DBG
if ( !bFound )
{
LOG((TL_WARN, "Receive PHONE_REMOVE but couldn't find phone object"));
}
#endif
LOG((TL_TRACE, "DoPhoneRemove - exiting"));
Unlock();
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
BOOL
CTAPI::FindTapiObject( CTAPI * pTapi )
{
PtrList::iterator iter, end;
BOOL bFound = FALSE;
int iReturn = -1;
EnterCriticalSection( &gcsTapiObjectArray );
//
// go through the list
//
iReturn = m_sTAPIObjectArray.Find( pTapi );
if (iReturn != -1)
{
pTapi->AddRef();
bFound = TRUE;
}
LeaveCriticalSection ( &gcsTapiObjectArray );
return bFound;
}
////////////////////////////////////////////////////////////////////////////
//
// GetTapiObjectFromAsyncEventMSG
//
// this method attempts to get tapi object pointer from PASYNCEVENTMSG
//
// it returns NULL on failure or addref'ed tapi object on success
//
////////////////////////////////////////////////////////////////////////////
CTAPI *GetTapiObjectFromAsyncEventMSG(PASYNCEVENTMSG pParams)
{
LOG((TL_TRACE, "GetTapiObjectFromAsyncEventMSG - entered"));
//
// get pInitData from the structure we have
//
PT3INIT_DATA pInitData = (PT3INIT_DATA) GetHandleTableEntry(pParams->InitContext);
if (IsBadReadPtr(pInitData, sizeof(T3INIT_DATA)))
{
LOG((TL_WARN, "GetTapiObjectFromAsyncEventMSG - could not recover pInitData"));
return NULL;
}
//
// get tapi object from pInitData
//
CTAPI *pTapi = pInitData->pTAPI;
//
// is it any good?
//
if (IsBadReadPtr(pTapi, sizeof(CTAPI)))
{
LOG((TL_WARN,
"GetTapiObjectFromAsyncEventMSG - tapi pointer [%p] does not point to readable memory",
pTapi));
return NULL;
}
//
// double check that this is a known tapi object...
//
if (!CTAPI::FindTapiObject(pTapi))
{
//
// the object is not in the list of tapi objects
//
LOG((TL_WARN,
"GetTapiObjectFromAsyncEventMSG - CTAPI::FindTapiObject did not find the tapi object [%p]",
pTapi));
return NULL;
}
LOG((TL_TRACE, "GetTapiObjectFromAsyncEventMSG - exit. pTapi %p", pTapi));
return pTapi;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
void
HandleLineCreate( PASYNCEVENTMSG pParams )
{
LOG((TL_TRACE, "HandleLineCreate - enter"));
//
// get tapi object
//
CTAPI *pTapi = GetTapiObjectFromAsyncEventMSG(pParams);
if (NULL == pTapi)
{
LOG((TL_WARN,
"HandleLineCreate - tapi object not present [%p]",
pTapi));
return;
}
//
// we have tapi object, do what we have to do.
//
pTapi->DoLineCreate( pParams->Param1 );
//
// GetTapiObjectFromAsyncEventMSG returned a addref'ed tapi object. release
//
pTapi->Release();
pTapi = NULL;
LOG((TL_TRACE, "HandleLineCreate - exit"));
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
void
HandleLineRemove( PASYNCEVENTMSG pParams )
{
LOG((TL_TRACE, "HandleLineRemove - enter"));
//
// get tapi object
//
CTAPI *pTapi = GetTapiObjectFromAsyncEventMSG(pParams);
if (NULL == pTapi)
{
LOG((TL_WARN,
"HandleLineRemove - tapi object not present [%p]",
pTapi));
return;
}
//
// we have tapi object, do what we have to do.
//
pTapi->DoLineRemove( pParams->Param1 );
//
// GetTapiObjectFromAsyncEventMSG returned a addref'ed tapi object. release
//
pTapi->Release();
pTapi = NULL;
LOG((TL_TRACE, "HandleLineRemove - exit"));
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
void
HandlePhoneCreate( PASYNCEVENTMSG pParams )
{
LOG((TL_TRACE, "HandlePhoneCreate - enter"));
//
// get tapi object
//
CTAPI *pTapi = GetTapiObjectFromAsyncEventMSG(pParams);
if (NULL == pTapi)
{
LOG((TL_WARN,
"HandlePhoneCreate - tapi object not present [%p]",
pTapi));
return;
}
//
// we have tapi object, do what we have to do.
//
pTapi->DoPhoneCreate( pParams->Param1 );
//
// GetTapiObjectFromAsyncEventMSG returned a addref'ed tapi object. release
//
pTapi->Release();
pTapi = NULL;
LOG((TL_TRACE, "HandlePhoneCreate - exit"));
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
void
HandlePhoneRemove( PASYNCEVENTMSG pParams )
{
LOG((TL_TRACE, "HandlePhoneRemove - enter"));
//
// get tapi object
//
CTAPI *pTapi = GetTapiObjectFromAsyncEventMSG(pParams);
if (NULL == pTapi)
{
LOG((TL_WARN,
"HandlePhoneRemove - tapi object not present [%p]",
pTapi));
return;
}
//
// we have tapi object, do what we have to do.
//
pTapi->DoPhoneRemove(pParams->Param1);
//
// GetTapiObjectFromAsyncEventMSG returned a addref'ed tapi object. release
//
pTapi->Release();
pTapi = NULL;
LOG((TL_TRACE, "HandlePhoneRemove - exit"));
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
HRESULT
CTapiObjectEvent::FireEvent(
CTAPI * pTapi,
TAPIOBJECT_EVENT Event,
ITAddress * pAddress,
long lCallbackInstance,
ITPhone * pPhone
)
{
HRESULT hr = S_OK;
CComObject<CTapiObjectEvent> * p;
IDispatch * pDisp;
//
// Check the event filter mask
// This event is not filtered by TapiSrv because is
// related with TE_TAPIOBJECT, a specific TAPI3 event.
//
DWORD dwEventFilterMask = Event;
long nTapiEventFilter = 0;
pTapi->get_EventFilter( &nTapiEventFilter );
STATICLOG((TL_INFO, " TapiObjectEventMask ---> %ld", dwEventFilterMask ));
if( !( nTapiEventFilter & TE_TAPIOBJECT))
{
STATICLOG((TL_WARN, "FireEvent - filtering out this event [%lx]", Event));
return S_OK;
}
//
// create event
//
hr = CComObject<CTapiObjectEvent>::CreateInstance( &p );
if ( !SUCCEEDED(hr) )
{
STATICLOG((TL_ERROR, "Could not create TapiObjectEvent object - %lx", hr));
return hr;
}
//
// initialize
//
p->m_Event = Event;
p->m_pTapi = dynamic_cast<ITTAPI *>(pTapi);
p->m_pTapi->AddRef();
p->m_pAddress = pAddress;
p->m_lCallbackInstance = lCallbackInstance;
p->m_pPhone = pPhone;
if ( NULL != pAddress )
{
pAddress->AddRef();
}
if ( NULL != pPhone )
{
pPhone->AddRef();
}
#if DBG
p->m_pDebug = (PWSTR) ClientAlloc( 1 );
#endif
//
// get idisp interface
//
hr = p->QueryInterface(
IID_IDispatch,
(void **)&pDisp
);
if ( !SUCCEEDED(hr) )
{
STATICLOG((TL_ERROR, "Could not get disp interface of TapiObjectEvent object %lx", hr));
delete p;
return hr;
}
//
// fire event
//
pTapi->Event(
TE_TAPIOBJECT,
pDisp
);
//
// release stuff
//
pDisp->Release();
return S_OK;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
void
CTapiObjectEvent::FinalRelease(void)
{
m_pTapi->Release();
if ( NULL != m_pAddress )
{
m_pAddress->Release();
}
if ( NULL != m_pPhone )
{
m_pPhone->Release();
}
#if DBG
ClientFree( m_pDebug );
#endif
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP
CTapiObjectEvent::get_TAPIObject( ITTAPI ** ppTapi )
{
if ( TAPIIsBadWritePtr( ppTapi, sizeof( ITTAPI *) ) )
{
return E_POINTER;
}
*ppTapi = m_pTapi;
(*ppTapi)->AddRef();
return S_OK;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP
CTapiObjectEvent::get_Event( TAPIOBJECT_EVENT * pEvent )
{
if ( TAPIIsBadWritePtr( pEvent, sizeof( TAPIOBJECT_EVENT ) ) )
{
return E_POINTER;
}
*pEvent = m_Event;
return S_OK;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP
CTapiObjectEvent::get_Address( ITAddress ** ppAddress )
{
if ( TAPIIsBadWritePtr( ppAddress, sizeof( ITAddress *) ) )
{
return E_POINTER;
}
if ((m_Event != TE_ADDRESSCREATE) && (m_Event != TE_ADDRESSREMOVE) &&
(m_Event != TE_ADDRESSCLOSE))
{
return TAPI_E_WRONGEVENT;
}
*ppAddress = m_pAddress;
if ( NULL != m_pAddress )
{
m_pAddress->AddRef();
}
return S_OK;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP
CTapiObjectEvent::get_CallbackInstance( long * plCallbackInstance )
{
if ( TAPIIsBadWritePtr( plCallbackInstance, sizeof( long ) ) )
{
return E_POINTER;
}
*plCallbackInstance = m_lCallbackInstance;
return S_OK;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_Phone
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP
CTapiObjectEvent::get_Phone(
ITPhone ** ppPhone
)
{
if ( TAPIIsBadWritePtr( ppPhone , sizeof(ITPhone *) ) )
{
return E_POINTER;
}
if ((m_Event != TE_PHONECREATE) && (m_Event != TE_PHONEREMOVE))
{
return TAPI_E_WRONGEVENT;
}
*ppPhone = m_pPhone;
if ( NULL != m_pPhone )
{
m_pPhone->AddRef();
}
return S_OK;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// HandleReinit
//
// we got a reinit message, so go through all the tapi objects, and
// fire the event
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void
CTAPI::HandleReinit()
{
LOG((TL_TRACE, "HandleReinit - enter"));
//
// Fire the event
//
CTapiObjectEvent::FireEvent(
this,
TE_REINIT,
NULL,
0,
NULL
);
Lock();
m_dwFlags |= TAPIFLAG_REINIT;
Unlock();
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
HRESULT
CTAPI::GetBuffer(
DWORD dwType,
UINT_PTR pObject,
LPVOID * ppBuffer
)
{
switch (dwType)
{
case BUFFERTYPE_ADDRCAP:
return m_pAddressCapCache->GetBuffer(
pObject,
ppBuffer
);
break;
case BUFFERTYPE_LINEDEVCAP:
return m_pLineCapCache->GetBuffer(
pObject,
ppBuffer
);
break;
case BUFFERTYPE_PHONECAP:
return m_pPhoneCapCache->GetBuffer(
pObject,
ppBuffer
);
break;
default:
return E_FAIL;
}
return E_UNEXPECTED;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
HRESULT
CTAPI::SetBuffer(
DWORD dwType,
UINT_PTR pObject,
LPVOID pBuffer
)
{
switch (dwType)
{
case BUFFERTYPE_ADDRCAP:
return m_pAddressCapCache->SetBuffer(
pObject,
pBuffer
);
break;
case BUFFERTYPE_LINEDEVCAP:
return m_pLineCapCache->SetBuffer(
pObject,
pBuffer
);
break;
case BUFFERTYPE_PHONECAP:
return m_pPhoneCapCache->SetBuffer(
pObject,
pBuffer
);
break;
default:
return E_FAIL;
}
return E_UNEXPECTED;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
HRESULT
CTAPI::InvalidateBuffer(
DWORD dwType,
UINT_PTR pObject
)
{
switch (dwType)
{
case BUFFERTYPE_ADDRCAP:
return m_pAddressCapCache->InvalidateBuffer(
pObject
);
break;
case BUFFERTYPE_LINEDEVCAP:
return m_pLineCapCache->InvalidateBuffer(
pObject
);
break;
case BUFFERTYPE_PHONECAP:
return m_pPhoneCapCache->InvalidateBuffer(
pObject
);
break;
default:
return E_FAIL;
}
return E_UNEXPECTED;
}
BOOL
CTAPI::FindRegistration( PVOID pRegistration )
{
PtrList::iterator iter, end;
Lock();
iter = m_RegisterItemPtrList.begin();
end = m_RegisterItemPtrList.end();
for ( ; iter != end; iter++ )
{
REGISTERITEM * pItem;
pItem = (REGISTERITEM *)(*iter);
if ( pRegistration == pItem->pRegister )
{
Unlock();
return TRUE;
}
}
Unlock();
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// IDispatch implementation
//
typedef IDispatchImpl<ITapi2Vtbl<CTAPI>, &IID_ITTAPI2, &LIBID_TAPI3Lib> TapiType;
typedef IDispatchImpl<ICallCenterVtbl<CTAPI>, &IID_ITTAPICallCenter, &LIBID_TAPI3Lib> CallCenterType;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// CTAPI::GetIDsOfNames
//
// Overide if IDispatch method
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CTAPI::GetIDsOfNames(REFIID riid,
LPOLESTR* rgszNames,
UINT cNames,
LCID lcid,
DISPID* rgdispid
)
{
HRESULT hr = DISP_E_UNKNOWNNAME;
// See if the requsted method belongs to the default interface
hr = TapiType::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
if (SUCCEEDED(hr))
{
LOG((TL_INFO, "GetIDsOfNames - found %S on ITTAPI", *rgszNames));
rgdispid[0] |= IDISPTAPI;
return hr;
}
// If not, then try the Call Center interface
hr = CallCenterType::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
if (SUCCEEDED(hr))
{
LOG((TL_TRACE, "GetIDsOfNames - found %S on ITTAPICallCenter", *rgszNames));
Lock();
if (!( m_dwFlags & TAPIFLAG_CALLCENTER_INITIALIZED ) )
{
LOG((TL_INFO, "GetIDsOfNames - Call Center not initialized" ));
UpdateAgentHandlerArray();
m_dwFlags |= TAPIFLAG_CALLCENTER_INITIALIZED;
LOG((TL_INFO, "GetIDsOfNames - Call Center initialized" ));
}
Unlock();
rgdispid[0] |= IDISPTAPICALLCENTER;
return hr;
}
LOG((TL_INFO, "GetIDsOfNames - Didn't find %S on our iterfaces", *rgszNames));
return hr;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// CTAPI::Invoke
//
// Overide if IDispatch method
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CTAPI::Invoke(DISPID dispidMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS* pdispparams,
VARIANT* pvarResult,
EXCEPINFO* pexcepinfo,
UINT* puArgErr
)
{
HRESULT hr = DISP_E_MEMBERNOTFOUND;
DWORD dwInterface = (dispidMember & INTERFACEMASK);
LOG((TL_TRACE, "Invoke - dispidMember %X", dispidMember));
// Call invoke for the required interface
switch (dwInterface)
{
case IDISPTAPI:
{
hr = TapiType::Invoke(dispidMember,
riid,
lcid,
wFlags,
pdispparams,
pvarResult,
pexcepinfo,
puArgErr
);
break;
}
case IDISPTAPICALLCENTER:
{
hr = CallCenterType::Invoke(dispidMember,
riid,
lcid,
wFlags,
pdispparams,
pvarResult,
pexcepinfo,
puArgErr
);
break;
}
} // end switch (dwInterface)
LOG((TL_TRACE, hr, "Invoke - exit" ));
return hr;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// CTAPI::SetEventFilterToAddresses
//
// Copy the event filter down to all addresses
// It's called by put_EventFilter() method
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
HRESULT CTAPI::SetEventFilterToAddresses(
DWORD dwEventFilterMask
)
{
LOG((TL_TRACE, "CopyEventFilterMaskToAddresses enter"));
CAddress* pAddress = NULL;
HRESULT hr = S_OK;
//
// Enumerate the addresses
//
for ( int iAddress = 0; iAddress < m_AddressArray.GetSize(); iAddress++ )
{
pAddress = dynamic_cast<CAddress *>(m_AddressArray[iAddress]);
if( pAddress != NULL )
{
hr = pAddress->SetEventFilterMask(
dwEventFilterMask
);
if( FAILED(hr) )
{
break;
}
}
}
LOG((TL_TRACE, "CopyEventFilterMaskToAddresses exit 0x%08x", hr));
return hr;
}
///////////////////////////////////////////////////////////////////////////////
//
// CTAPI::IsValidTapiObject
//
// a helper static function that checks if it was passed a valid tapi object
//
// if the object is valid, the function addrefs it and returns TRUE
// if the object is not valid, the function returns true
//
// static
BOOL CTAPI::IsValidTapiObject(CTAPI *pTapiObject)
{
STATICLOG((TL_TRACE, "CTAPI::IsValidTapiObject enter[%p]", pTapiObject));
//
// before we go into trouble of checking tapi object array see if the ptr
// is readable at all
//
if ( IsBadReadPtr(pTapiObject, sizeof(CTAPI) ) )
{
STATICLOG((TL_WARN, "CTAPI::IsValidTapiObject - object not readabe"));
return FALSE;
}
//
// see if this object is in the array of tapi objects
//
EnterCriticalSection( &gcsTapiObjectArray );
if (-1 == m_sTAPIObjectArray.Find(pTapiObject) )
{
LeaveCriticalSection ( &gcsTapiObjectArray );
STATICLOG((TL_WARN, "CTAPI::IsValidTapiObject - object not in the array"));
return FALSE;
}
//
// the object is in the array, so it must be valid, addref it
//
try
{
//
// inside try, in case something else went bad
//
pTapiObject->AddRef();
}
catch(...)
{
//
// the object is in the array, but we had problems addrefing.
// something's not kosher.
//
STATICLOG((TL_ERROR,
"CTAPI::IsValidTapiObject - object in in the array but addref threw"));
LeaveCriticalSection ( &gcsTapiObjectArray );
_ASSERTE(FALSE);
return FALSE;
}
LeaveCriticalSection ( &gcsTapiObjectArray );
STATICLOG((TL_TRACE, "CTAPI::IsValidTapiObject -- finish. the object is valid"));
return TRUE;
}