|
|
/*++
Copyright (c) 1997-1999 Microsoft Corporation
Module Name:
Address.h
Abstract:
Declaration of the CAddress Author:
mquinton - 06/12/97
Notes:
Revision History:
--*/
#ifndef __ADDRESS_H_
#define __ADDRESS_H_
#include "resource.h" // main symbols
#ifdef USE_PHONEMSP
#include "terminal.h"
#endif USE_PHONEMSP
#include "ObjectSafeImpl.h"
#include <mspenum.h> // for CSafeComEnum
class CAddress; class CTerminal; class CTAPI;
extern CHashTable * gpLineHashTable; extern CHashTable * gpHandleHashTable; extern void RemoveHandleFromHashTable(ULONG_PTR Handle);
// address flag defines
#define ADDRESSFLAG_MSP 0x00000001
#define ADDRESSFLAG_WAVEOUTDEVICE 0x00000002
#define ADDRESSFLAG_WAVEINDEVICE 0x00000004
#define ADDRESSFLAG_PHONEDEVICE 0x00000008
#define ADDRESSFLAG_DATAMODEM 0x00000010
#define ADDRESSFLAG_PRIVATEOBJECTS 0x00000020
#define ADDRESSFLAG_CALLHUB 0x00000100
#define ADDRESSFLAG_CALLHUBTRACKING 0x00000200
#define ADDRESSFLAG_WAVEFULLDUPLEX 0x00000400
#define ADDRESSFLAG_NOCALLHUB 0x00010000
#define ADDRESSFLAG_DEVSTATECHANGE 0x00020000
#define ADDRESSFLAG_ADDRESSSTATECHANGE 0x00040000
#define ADDRESSFLAG_DEVCAPSCHANGE 0x00080000
#define ADDRESSFLAG_ADDRESSCAPSCHANGE 0x00100000
#define ADDRESSFLAG_AMREL (ADDRESSFLAG_MSP | ADDRESSFLAG_WAVEINDEVICE | ADDRESSFLAG_WAVEOUTDEVICE | ADDRESSFLAG_WAVEFULLDUPLEX)
#define CALLHUBSUPPORT_FULL 1
#define CALLHUBSUPPORT_NONE 3
#define CALLHUBSUPPORT_UNKNOWN 4
// Status message defines, set by LineSetStatusMessages( )
#define ALL_LINEDEVSTATE_MESSAGES (LINEDEVSTATE_OTHER | \
LINEDEVSTATE_RINGING | \ LINEDEVSTATE_CONNECTED | \ LINEDEVSTATE_DISCONNECTED | \ LINEDEVSTATE_MSGWAITON | \ LINEDEVSTATE_MSGWAITOFF | \ LINEDEVSTATE_INSERVICE | \ LINEDEVSTATE_OUTOFSERVICE | \ LINEDEVSTATE_MAINTENANCE | \ LINEDEVSTATE_OPEN | \ LINEDEVSTATE_CLOSE | \ LINEDEVSTATE_NUMCALLS | \ LINEDEVSTATE_NUMCOMPLETIONS | \ LINEDEVSTATE_TERMINALS | \ LINEDEVSTATE_ROAMMODE | \ LINEDEVSTATE_BATTERY | \ LINEDEVSTATE_SIGNAL | \ LINEDEVSTATE_DEVSPECIFIC | \ LINEDEVSTATE_REINIT | \ LINEDEVSTATE_LOCK | \ LINEDEVSTATE_CAPSCHANGE | \ LINEDEVSTATE_CONFIGCHANGE | \ LINEDEVSTATE_TRANSLATECHANGE | \ LINEDEVSTATE_COMPLCANCEL | \ LINEDEVSTATE_REMOVED)
#define ALL_LINEADDRESSSTATE_MESSAGES (LINEADDRESSSTATE_OTHER | \
LINEADDRESSSTATE_DEVSPECIFIC | \ LINEADDRESSSTATE_INUSEZERO | \ LINEADDRESSSTATE_INUSEONE | \ LINEADDRESSSTATE_INUSEMANY | \ LINEADDRESSSTATE_NUMCALLS | \ LINEADDRESSSTATE_FORWARD | \ LINEADDRESSSTATE_TERMINALS | \ LINEADDRESSSTATE_CAPSCHANGE)
/////////////////////////////////////////////////////////////////
// Intermediate classes used for DISPID encoding
template <class T> class ITAddress2Vtbl : public ITAddress2 { };
template <class T> class ITAddressCapabilitiesVtbl : public ITAddressCapabilities { }; template <class T> class ITMediaSupportVtbl : public ITMediaSupport { }; template <class T> class ITAddressTranslationVtbl : public ITAddressTranslation { }; template <class T> class ITLegacyAddressMediaControl2Vtbl : public ITLegacyAddressMediaControl2 { };
/////////////////////////////////////////////////////////////////////////////
// CEventMasks
class CEventMasks { public: CEventMasks() { m_dwTapiObjectMask = EM_NOSUBEVENTS; m_dwAddressMask = EM_NOSUBEVENTS; m_dwCallNotificationMask = EM_NOSUBEVENTS; m_dwCallStateMask = EM_NOSUBEVENTS; m_dwCallMediaMask = EM_NOSUBEVENTS; m_dwCallHubMask = EM_NOSUBEVENTS; m_dwCallInfoChangeMask = EM_NOSUBEVENTS; m_dwQOSEventMask = EM_NOSUBEVENTS; m_dwFileTerminalMask = EM_NOSUBEVENTS; m_dwPrivateMask = EM_NOSUBEVENTS; m_dwAddressDevSpecificMask = EM_NOSUBEVENTS; m_dwPhoneDevSpecificMask = EM_NOSUBEVENTS; }
~CEventMasks() { }
DECLARE_TRACELOG_CLASS(CEventMasks)
private: //
// Event masks
// Some event come from MSP:
// TE_ADDRESS, TE_CALLMEDIA, TE_FILETERMINAL
//
DWORD m_dwTapiObjectMask; // TE_TAPIOBJECT
DWORD m_dwAddressMask; // TE_ADDRESS MSP
DWORD m_dwCallNotificationMask; // TE_CALLNOTIFICATION
DWORD m_dwCallStateMask; // TE_CALLSTATE
DWORD m_dwCallMediaMask; // TE_CALLMEDIA MSP
DWORD m_dwCallHubMask; // TE_CALLHUB
DWORD m_dwCallInfoChangeMask; // TE_CALLINFOCHANGE
DWORD m_dwQOSEventMask; // TE_QOSEVENT
DWORD m_dwFileTerminalMask; // TE_FILETERMINAL MSP
DWORD m_dwPrivateMask; // TE_PRIVATE MSP
DWORD m_dwAddressDevSpecificMask; // TE_ADDRESSDEVSPECIFIC
DWORD m_dwPhoneDevSpecificMask; // TE_PHONEDEVSPECIFIC
public: // Constants
static const DWORD EM_ALLSUBEVENTS = 0x0FFFFFFF; static const DWORD EM_NOSUBEVENTS = 0x00000000;
static const DWORD EM_ALLEVENTS = (DWORD)(-1);
public: // Public methods
HRESULT SetSubEventFlag( DWORD dwEvent, // The event
DWORD dwFlag, // The flag that should be setted
BOOL bEnable );
HRESULT GetSubEventFlag( DWORD dwEvent, // The event
DWORD dwFlag, // The flag that should be setted
BOOL* pEnable );
DWORD GetSubEventMask( TAPI_EVENT TapiEvent );
BOOL IsSubEventValid( TAPI_EVENT TapiEvent, DWORD dwSubEvent, BOOL bAcceptAllSubEvents, BOOL bCallLevel );
HRESULT CopyEventMasks( CEventMasks* pEventMasks );
HRESULT SetTapiSrvAddressEventMask( IN HLINE hLine );
HRESULT SetTapiSrvCallEventMask( IN HCALL hCall );
private: ULONG64 GetTapiSrvEventMask( IN BOOL bCallLevel); DWORD GetTapiSrvLineStateMask(); DWORD GetTapiSrvAddrStateMask(); }; /////////////////////////////////////////////////////////////////////////////
// CAddress
class CAddress : public CTAPIComObjectRoot<CAddress>, public IDispatchImpl<ITAddress2Vtbl<CAddress>, &IID_ITAddress2, &LIBID_TAPI3Lib>, public IDispatchImpl<ITAddressCapabilitiesVtbl<CAddress>, &IID_ITAddressCapabilities, &LIBID_TAPI3Lib>, public IDispatchImpl<ITMediaSupportVtbl<CAddress>, &IID_ITMediaSupport, &LIBID_TAPI3Lib>, public IDispatchImpl<ITAddressTranslationVtbl<CAddress>, &IID_ITAddressTranslation, &LIBID_TAPI3Lib>, public IDispatchImpl<ITLegacyAddressMediaControl2Vtbl<CAddress>, &IID_ITLegacyAddressMediaControl2, &LIBID_TAPI3Lib>, public CObjectSafeImpl { public: CAddress() : m_pTAPI(NULL), m_hLineApp(NULL), m_hLine(NULL), #ifdef USE_PHONEMSP
m_hPhoneApp(NULL), #endif USE_PHONEMSP
m_dwAPIVersion(0), m_dwDeviceID(0), m_dwAddressID(0), m_dwMediaModesSupported(0), m_szAddress(NULL), m_szAddressName(NULL), m_szProviderName(NULL), m_pMSPAggAddress(NULL), m_pPrivate(NULL), m_hMSPEvent(NULL), m_hWaitEvent(NULL), m_MSPContext(0), m_dwAddressFlags(0), m_fEnableCallHubTrackingOnLineOpen(TRUE), m_bTapiSignaledShutdown(FALSE)
{ LOG((TL_TRACE, "CAddress[%p] - enter", this)); LOG((TL_TRACE, "CAddress - exit")); }
~CAddress() { LOG((TL_TRACE, "~CAddress[%p] - enter", this)); LOG((TL_TRACE, "~CAddress - exit")); }
DECLARE_DEBUG_ADDREF_RELEASE(CAddress) DECLARE_QI() DECLARE_MARSHALQI(CAddress) DECLARE_TRACELOG_CLASS(CAddress)
BEGIN_COM_MAP(CAddress) // COM_INTERFACE_ENTRY_FUNC(IID_IDispatch, 0, IDispatchQI)
COM_INTERFACE_ENTRY2(IDispatch, ITAddress2) COM_INTERFACE_ENTRY(ITAddress) COM_INTERFACE_ENTRY(ITAddress2) COM_INTERFACE_ENTRY(ITMediaSupport) COM_INTERFACE_ENTRY(ITAddressCapabilities) COM_INTERFACE_ENTRY(ITAddressTranslation) COM_INTERFACE_ENTRY(ITLegacyAddressMediaControl) COM_INTERFACE_ENTRY(ITLegacyAddressMediaControl2) COM_INTERFACE_ENTRY(IObjectSafety) COM_INTERFACE_ENTRY_AGGREGATE_BLIND(m_pMSPAggAddress) COM_INTERFACE_ENTRY_FUNC(IID_IMarshal, 0, IMarshalQI) COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pFTM) COM_INTERFACE_ENTRY_AGGREGATE_BLIND(m_pPrivate) END_COM_MAP()
void FinalRelease(); private:
// tapi info
ITTAPI * m_pTAPI; HLINEAPP m_hLineApp; HLINE m_hLine; #ifdef USE_PHONEMSP
HPHONEAPP m_hPhoneApp; #endif USE_PHONEMSP
// caps/info that we keep around
// because it is used often
DWORD m_dwAPIVersion; DWORD m_dwDeviceID; DWORD m_dwAddressID; DWORD m_dwMediaModesSupported; DWORD m_dwProviderID; PWSTR m_szAddress; PWSTR m_szAddressName; PWSTR m_szProviderName;
// m_dwAddressFlags keeps some info about the address
// see ADDRESSFLAG_ constants above
DWORD m_dwAddressFlags;
// tapi structures - using caching scheme
// so these can be NULL
LPLINEADDRESSCAPS m_pAddressCaps; LPLINEDEVCAPS m_pDevCaps; // current address state
ADDRESS_STATE m_AddressState;
// msp for this address
IUnknown * m_pMSPAggAddress;
// event for msp to signal on event
HANDLE m_hMSPEvent;
HANDLE m_hWaitEvent; // Create a context handle for MSP Callback
ULONG_PTR m_MSPContext;
// IUnk for the private object
IUnknown * m_pPrivate;
// TAPI terminals owned by this address
TerminalArray m_TerminalArray; // calls currently on this address
CallInfoArrayNR m_CallArray;
// list of "addresslines"
PtrList m_AddressLinesPtrList;
// list of call notification cookies
LongList m_NotificationCookies;
// addressline used for callhubtracking
AddressLineStruct * m_pCallHubTrackingLine;
// if true, we will do LineSetCallHubTracking in FindOrOpenALine
// it is only false if the user has called SetCallHubTracking(FALSE)
// on this address
BOOL m_fEnableCallHubTrackingOnLineOpen;
//
// this flag, when set, signals that the tapi object has signaled shutdown
// it is currently used to synchronize creation of new calls and call
// cleanup performed on tapi shutdown
//
BOOL m_bTapiSignaledShutdown;
HRESULT UpdateAddressCaps(); HRESULT UpdateLineDevCaps(); ITMSPAddress * GetMSPAddress();
HRESULT GetPhoneArrayFromTapiAndPrune( PhoneArray *pPhoneArray, BOOL bPreferredOnly );
public: BOOL IsValidAddressLine(AddressLineStruct *pAddressLine, BOOL bAddref = FALSE); HRESULT MSPEvent(); #ifdef USE_PHONEMSP
HRESULT CreatePhoneDeviceMSP( IUnknown * pUnk, HLINE hLine, IUnknown ** ppMSPAggAddress ); #endif USE_PHONEMSP
HRESULT CreateStaticTerminalArray( TerminalArray& StaticTermArray ); HRESULT CreateDynamicTerminalClassesList( TerminalClassPtrList * pList ); HRESULT CreateMSPCall( MSP_HANDLE hCall, DWORD dwReserved, long lMediaType, IUnknown * pOuterUnk, IUnknown ** ppStreamControl ); DWORD GetDeviceID(){ return m_dwDeviceID; } DWORD GetAPIVersion(){ return m_dwAPIVersion; } DWORD GetAddressID(){ return m_dwAddressID; } HLINEAPP GetHLineApp(){ return m_hLineApp; } #ifdef USE_PHONEMSP
HPHONEAPP GetHPhoneApp(){ return m_hPhoneApp; } #endif USE_PHONEMSP
BOOL HasMSP(){ return (m_pMSPAggAddress?TRUE:FALSE); } BOOL HasWaveDevice(){ return m_dwAddressFlags & (ADDRESSFLAG_WAVEINDEVICE | ADDRESSFLAG_WAVEOUTDEVICE | ADDRESSFLAG_WAVEFULLDUPLEX); } BOOL HasFullDuplexWaveDevice(){ return m_dwAddressFlags & ADDRESSFLAG_WAVEFULLDUPLEX; } BOOL HasPhoneDevice(){ return m_dwAddressFlags & ADDRESSFLAG_PHONEDEVICE; } DWORD GetMediaModes(){ return m_dwMediaModesSupported; } PWSTR GetAddressName(){ return m_szAddressName; } BOOL IsSPCallHubTrackingAddress(){ return m_dwAddressFlags & ADDRESSFLAG_CALLHUBTRACKING; } BOOL IsSPCallHubAddress(){ return m_dwAddressFlags & ADDRESSFLAG_CALLHUB; } CTAPI * GetTapi(BOOL bAddRefTapi = FALSE); BOOL HasPrivateObjects(){return m_dwAddressFlags & ADDRESSFLAG_PRIVATEOBJECTS;} DWORD GetProviderID(){return m_dwProviderID;} BOOL GetMediaMode( long lMediaType, DWORD * pdwMediaMode ); HRESULT ShutdownMSPCall( IUnknown * pStreamControl ); HRESULT InitializeWaveDeviceIDs( HLINE hLine ); HRESULT AddNotificationLine( AddressLineStruct * pLine ) { HRESULT hr = S_OK;
Lock();
try { m_AddressLinesPtrList.push_back( (PVOID)pLine ); } catch(...) { LOG((TL_ERROR, "AddNotificationLine - failed to add to m_AddressLinesPtrList list - alloc failure" ));
hr = E_OUTOFMEMORY; }
Unlock();
return hr; }
HRESULT RegisterNotificationCookie(long lCookie);
HRESULT RemoveNotificationCookie(long lCookie);
void UnregisterAllCookies();
void AddressOnTapiShutdown();
void AddTerminal( ITTerminal * pTerminal ) { Lock(); m_TerminalArray.Add( pTerminal ); Unlock(); } HRESULT AddCallNotification( DWORD dwPrivs, DWORD dwMediaModes, long lInstance, PVOID * ppRegister );
HRESULT RemoveCallNotification( PVOID pRegister );
HRESULT SetCallHubTracking( BOOL bSet ); DWORD DoesThisAddressSupportCallHubs( CCall * pCall );
HRESULT FindOrOpenALine( DWORD dwMediaModes, AddressLineStruct ** ppAddressLine ); HRESULT MaybeCloseALine( AddressLineStruct ** ppAddressLine ); HRESULT InternalCreateCall( PWSTR pszDestAddress, long lAddressType, long lMediaType, CALL_PRIVILEGE cp, BOOL bNeedToNotify, HCALL hCall, BOOL bExpose, CCall ** ppCall );
HRESULT Initialize( ITTAPI * pTAPI, HLINEAPP hLineApp, #ifdef USE_PHONEMSP
HPHONEAPP hPhoneApp, #endif USE_PHONEMSP
DWORD dwAPIVersion, DWORD dwDeviceID, DWORD dwAddressID, DWORD dwProviderID, LPLINEDEVCAPS pDevCaps, DWORD dwEventFilterMask );
HRESULT AddCall( ITCallInfo * pCallInfo );
HRESULT RemoveCall( ITCallInfo * pCallInfo );
void InService( DWORD dwType ); void OutOfService( DWORD dwType ); void CapsChange( BOOL ); HRESULT SaveAddressName(LPLINEDEVCAPS); void SetAddrCapBuffer( LPVOID pBuf ); void SetLineDevCapBuffer( LPVOID pBuf ); HRESULT ReceiveTSPData( IUnknown * pCall, LPBYTE pBuffer, DWORD dwSize ); HRESULT HandleSendTSPData( MSP_EVENT_INFO * pEvent ); HRESULT HandleMSPAddressEvent( MSP_EVENT_INFO * pEvent ); HRESULT HandleMSPCallEvent( MSP_EVENT_INFO * pEvent );
HRESULT HandleMSPFileTerminalEvent( MSP_EVENT_INFO * pEvent); HRESULT HandleMSPTTSTerminalEvent( MSP_EVENT_INFO * pEvent); HRESULT HandleMSPASRTerminalEvent( MSP_EVENT_INFO * pEvent); HRESULT HandleMSPToneTerminalEvent( MSP_EVENT_INFO * pEvent);
HRESULT HandleMSPPrivateEvent( MSP_EVENT_INFO * pEvent ); HRESULT ReleaseEvent( MSP_EVENT_INFO * pEvent );
// ITMediaSupport methods
STDMETHOD(get_MediaTypes)(long * plMediaTypes); STDMETHOD(QueryMediaType)( long lMediaType, VARIANT_BOOL * pbSupport );
// ITAddress methods
STDMETHOD(get_State)(ADDRESS_STATE * pAddressState); STDMETHOD(get_AddressName)(BSTR * ppName); STDMETHOD(get_ServiceProviderName)(BSTR * ppName); STDMETHOD(get_TAPIObject)(ITTAPI ** ppTapiObject); STDMETHOD(CreateCall)( BSTR lpszDestAddress, long lAddressType, long lMediaType, ITBasicCallControl ** ppCall ); STDMETHOD(get_Calls)(VARIANT * pVariant); STDMETHOD(EnumerateCalls)(IEnumCall ** ppCallEnum); STDMETHOD(CreateForwardInfoObject)(ITForwardInformation ** ppForwardInfo); STDMETHOD(Forward)( ITForwardInformation * pForwardInfo, ITBasicCallControl * pCall ); STDMETHOD(get_CurrentForwardInfo)( ITForwardInformation ** ppForwardInfo ); STDMETHOD(get_DialableAddress)(BSTR * pDialableAddress); STDMETHOD(put_MessageWaiting)(VARIANT_BOOL fMessageWaiting); STDMETHOD(get_MessageWaiting)(VARIANT_BOOL * pfMessageWaiting); STDMETHOD(put_DoNotDisturb)(VARIANT_BOOL fDoNotDisturb); STDMETHOD(get_DoNotDisturb)(VARIANT_BOOL * pfDoNotDisturb); STDMETHOD(get_LineID)(long * plLineID); STDMETHOD(get_AddressID)(long * plAddressID);
// ITAddress2 methods
STDMETHOD(get_Phones)(VARIANT * pPhones); STDMETHOD(EnumeratePhones)(IEnumPhone ** ppEnumPhone);
STDMETHOD(get_PreferredPhones)(VARIANT * pPhones); STDMETHOD(EnumeratePreferredPhones)(IEnumPhone ** ppEnumPhone);
STDMETHOD(GetPhoneFromTerminal)( ITTerminal * pTerminal, ITPhone ** ppPhone );
STDMETHOD(get_EventFilter)( TAPI_EVENT TapiEvent, long lSubEvent, VARIANT_BOOL* pEnable );
STDMETHOD(put_EventFilter)( TAPI_EVENT TapiEvent, long lSubEvent, VARIANT_BOOL bEnable );
STDMETHOD(DeviceSpecific)( IN ITCallInfo *pCall, IN BYTE *pParams, IN DWORD dwSize );
STDMETHOD(DeviceSpecificVariant)( IN ITCallInfo *pCall, IN VARIANT varDevSpecificByteArray );
STDMETHOD(NegotiateExtVersion)( IN long lLowVersion, IN long lHighVersion, IN long *plExtVersion );
// itaddresscapabilities
STDMETHOD(get_AddressCapability)(ADDRESS_CAPABILITY AddressCap, long * plCapability); STDMETHOD(get_AddressCapabilityString)(ADDRESS_CAPABILITY_STRING AddressCapString, BSTR * ppCapabilityString); STDMETHOD(get_CallTreatments)(VARIANT * pVariant ); STDMETHOD(EnumerateCallTreatments)(IEnumBstr ** ppEnumCallTreatment ); STDMETHOD(get_CompletionMessages)(VARIANT * pVariant ); STDMETHOD(EnumerateCompletionMessages)(IEnumBstr ** ppEnumCompletionMessage ); STDMETHOD(get_DeviceClasses)(VARIANT * pVariant ); STDMETHOD(EnumerateDeviceClasses)(IEnumBstr ** ppEnumDeviceClass );
// ITAddressTranslation
STDMETHOD(TranslateAddress)( BSTR pAddressToTranslate, long ulCard, long ulTranslateOptions, ITAddressTranslationInfo ** ppTranslated ); STDMETHOD(TranslateDialog)( TAPIHWND hwndOwner, BSTR pAddressIn ); STDMETHOD(EnumerateLocations)(IEnumLocation ** ppEnumLocation ); STDMETHOD(get_Locations)(VARIANT * pVariant); STDMETHOD(EnumerateCallingCards)(IEnumCallingCard ** ppEnumLocations ); STDMETHOD(get_CallingCards)(VARIANT * pVariant);
// ITLegacyAddressMediaControl
STDMETHOD(GetID)( BSTR pDeviceClass, DWORD * pdwSize, BYTE ** ppDeviceID );
STDMETHOD(GetDevConfig)( BSTR pDeviceClass, DWORD * pdwSize, BYTE ** ppDeviceConfig );
STDMETHOD(SetDevConfig)( BSTR pDeviceClass, DWORD dwSize, BYTE * pDeviceConfig );
// ITLegacyAddressMediaControl2
STDMETHOD(ConfigDialog)( HWND hwndOwner, BSTR pDeviceClass );
STDMETHOD(ConfigDialogEdit)( HWND hwndOwner, BSTR pDeviceClass, DWORD dwSizeIn, BYTE * pDeviceConfigIn, DWORD * pdwSizeOut, BYTE ** ppDeviceConfigOut );
// IDispatch Methods
STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid ); STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr );
STDMETHOD_(ULONG, InternalAddRef)() { DWORD dwR;
dwR = InterlockedIncrement(&m_dwRef);;
#if DBG
LogDebugAddRef(m_dwRef); #endif
return dwR; }
STDMETHOD_(ULONG, InternalRelease)() { DWORD dwR; PtrList::iterator iter, end; AddressLineStruct * pLine; T3LINE * pt3Line;
LOG((TL_INFO, "InternalRelease - m_dwRef %d",m_dwRef )); Lock(); gpLineHashTable->Lock(); gpHandleHashTable->Lock(); dwR = InterlockedDecrement(&m_dwRef);
// if ref count is 0 (means we entered function with 1) then we final release
if (0 == dwR) { // remove from the hash table, so any more messages
// from tapisrv are ignored
//
//
// release addresslines
//
LOG((TL_TRACE, "InternalRelease - final" ));
iter = m_AddressLinesPtrList.begin(); end = m_AddressLinesPtrList.end();
LOG((TL_INFO, "InternalRelease - m_AddressLinesPtrList size %d ", m_AddressLinesPtrList.size() ));
for ( ; iter != end; iter++ ) { pLine = (AddressLineStruct *)(*iter);
pt3Line = &(pLine->t3Line);
if(FAILED(gpLineHashTable->Remove( (ULONG_PTR)(pt3Line->hLine) ) )) { LOG((TL_INFO, "InternalRelease - pLineHashTable->Remove failed" )); } }
gpLineHashTable->Unlock();
// remove from the handle hash table, so any more messages
// from msp are ignored
//
RemoveHandleFromHashTable(m_MSPContext); // unregister all the cookies, so CTAPI::UnregisterNotifications
// does nothing if called later
UnregisterAllCookies();
gpHandleHashTable->Unlock();
// ExternalFinalRelease();
dwR = m_dwRef = 0;
Unlock(); LOG((TL_INFO, "InternalRelease - final OK dwR %d",dwR )); } else { gpLineHashTable->Unlock(); gpHandleHashTable->Unlock(); Unlock(); LOG((TL_INFO, "InternalRelease - not final dwR %d",dwR )); }
#if DBG
LogDebugRelease( dwR ); #endif
return dwR; }
//
// (implementing method from CObjectSafeImpl)
// check the aggregated objects to see if they support the interface requested.
// if they do, return the non-delegating IUnknown of the first object that
// supports the interface.
//
// it needs to be released by the caller.
//
HRESULT QIOnAggregates(REFIID riid, IUnknown **ppNonDelegatingUnknown);
public: //
// Event filtering methods
//
HRESULT SetEventFilterMask( IN DWORD dwEventFilterMask );
// Get subevents mask
/*DWORD GetSubEventsMask(
IN int nEvent );*/
// Get subevents mask
DWORD GetSubEventsMask( IN TAPI_EVENT TapiEvent );
private: //
// Helper methods for event filtering
//
HRESULT SetSubEventFlag( TAPI_EVENT TapiEvent, DWORD dwSubEvent, BOOL bEnable );
HRESULT GetSubEventFlag( TAPI_EVENT TapiEvent, DWORD dwSubEvent, BOOL* pEnable );
HRESULT SetSubEventFlagToCalls( TAPI_EVENT TapiEvent, DWORD dwFlag, BOOL bEnable );
public: CEventMasks m_EventMasks; // Event filtering masks
HRESULT GetEventMasks( OUT CEventMasks* pEventMasks );
};
////////////////////////////////////////////////////////////////////////
// CAddressTypeCollection
//
////////////////////////////////////////////////////////////////////////
class CAddressTypeCollection : public CTAPIComObjectRoot<CAddressTypeCollection>, public CComDualImpl<ITCollection, &IID_ITCollection, &LIBID_TAPI3Lib>, public CObjectSafeImpl { public:
DECLARE_MARSHALQI(CAddressTypeCollection) DECLARE_TRACELOG_CLASS(CAddressTypeCollection)
BEGIN_COM_MAP(CAddressTypeCollection) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(ITCollection) COM_INTERFACE_ENTRY(IObjectSafety) COM_INTERFACE_ENTRY_FUNC(IID_IMarshal, 0, IMarshalQI) COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pFTM) END_COM_MAP()
private:
DWORD m_dwSize; CComVariant * m_Var; public:
// initialize
HRESULT STDMETHODCALLTYPE Initialize( PDWORD pdwAddressTypes, DWORD dwElements ) { DWORD dw; HRESULT hr = S_OK;
LOG((TL_TRACE, "Initialize - enter"));
// create variant array
m_dwSize = dwElements;
m_Var = new CComVariant[m_dwSize];
if (NULL == m_Var) { LOG((TL_ERROR, "Could not alloc for CComVariant array")); hr = E_OUTOFMEMORY; } else { for (dw = 0; dw < m_dwSize; dw++) { // create a variant and add it to the collection
CComVariant& var = m_Var[dw];
var.vt = VT_I4; var.lVal = pdwAddressTypes[dw]; } } LOG((TL_TRACE, "Initialize - exit")); return hr; } STDMETHOD(get_Count)( long* retval ) { HRESULT hr = S_OK;
LOG((TL_TRACE, "get_Count - enter"));
try { *retval = m_dwSize; } catch(...) { hr = E_INVALIDARG; }
LOG((TL_TRACE, "get_Count - exit")); return hr; }
STDMETHOD(get_Item)( long Index, VARIANT* retval ) { HRESULT hr = S_OK;
LOG((TL_TRACE, "get_Item - enter")); if (retval == NULL) { return E_POINTER; }
try { VariantInit(retval); } catch(...) { hr = E_INVALIDARG; }
if (S_OK != hr) { return hr; }
retval->vt = VT_I4; retval->lVal = 0;
// use 1-based index, VB like
if ((Index < 1) || (Index > m_dwSize)) { return E_INVALIDARG; }
VariantCopy(retval, &m_Var[Index-1]);
LOG((TL_TRACE, "get_Item - exit"));
return S_OK; }
HRESULT STDMETHODCALLTYPE get__NewEnum( IUnknown** retval ) { HRESULT hr = S_OK;
LOG((TL_TRACE, "get__NumEnum - enter")); if (NULL == retval) { return E_POINTER; }
*retval = NULL;
typedef CComObject<CSafeComEnum<IEnumVARIANT, &IID_IEnumVARIANT, VARIANT, _Copy<VARIANT> > > enumvar;
enumvar* p = new enumvar;
if (NULL == p) { LOG((TL_ERROR, "Could not alloc for enumvar")); hr = E_OUTOFMEMORY; } else { hr = p->Init(&m_Var[0], &m_Var[m_dwSize], NULL, AtlFlagCopy);
if (SUCCEEDED(hr)) { hr = p->QueryInterface(IID_IEnumVARIANT, (void**)retval); }
if (FAILED(hr)) { delete p; } }
LOG((TL_TRACE, "get__NewEnum - exit")); return hr; }
void FinalRelease() { LOG((TL_TRACE, "FinalRelease()")); } };
////////////////////////////////////////////////////////////////////////
// CTerminalClassCollection
//
////////////////////////////////////////////////////////////////////////
class CTerminalClassCollection : public CTAPIComObjectRoot<CTerminalClassCollection>, public CComDualImpl<ITCollection, &IID_ITCollection, &LIBID_TAPI3Lib>, public CObjectSafeImpl { public:
DECLARE_MARSHALQI(CTerminalClassCollection) DECLARE_TRACELOG_CLASS(CTerminalClassCollection)
BEGIN_COM_MAP(CTerminalClassCollection) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(ITCollection) COM_INTERFACE_ENTRY(IObjectSafety) COM_INTERFACE_ENTRY_FUNC(IID_IMarshal, 0, IMarshalQI) COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pFTM) END_COM_MAP()
private:
DWORD m_dwSize; CComVariant * m_Var; public:
// initialize
HRESULT STDMETHODCALLTYPE Initialize( TerminalClassPtrList classlist ) { TerminalClassPtrList::iterator i; HRESULT hr = S_OK; DWORD dw = 0;
LOG((TL_TRACE, "Initialize - enter"));
// create variant array
m_dwSize = classlist.size();
m_Var = new CComVariant[m_dwSize]; if (NULL == m_Var) { LOG((TL_ERROR, "Could not alloc for CComVariant array")); hr = E_OUTOFMEMORY; } else { for (i = classlist.begin(); i != classlist.end(); i++) { // create a variant and add it to the collection
CComVariant& var = m_Var[dw];
var.vt = VT_BSTR; var.bstrVal = *i; dw++; } }
LOG((TL_TRACE, "Initialize - exit")); return hr; } STDMETHOD(get_Count)( long* retval ) { HRESULT hr = S_OK;
LOG((TL_TRACE, "get_Count - enter"));
try { *retval = m_dwSize; } catch(...) { hr = E_INVALIDARG; }
LOG((TL_TRACE, "get_Count - exit")); return hr; }
STDMETHOD(get_Item)( long Index, VARIANT* retval ) { HRESULT hr = S_OK;
LOG((TL_TRACE, "get_Item - enter")); if (retval == NULL) { return E_POINTER; }
try { VariantInit(retval); } catch(...) { hr = E_INVALIDARG; }
if (S_OK != hr) { return hr; }
retval->vt = VT_BSTR; retval->bstrVal = NULL;
// use 1-based index, VB like
if ((Index < 1) || (Index > m_dwSize)) { return E_INVALIDARG; }
VariantCopy(retval, &m_Var[Index-1]);
LOG((TL_TRACE, "get_Item - exit"));
return S_OK; }
HRESULT STDMETHODCALLTYPE get__NewEnum( IUnknown** retval ) { HRESULT hr;
LOG((TL_TRACE, "get__NumEnum - enter")); if (NULL == retval) { return E_POINTER; }
*retval = NULL;
typedef CComObject<CSafeComEnum<IEnumVARIANT, &IID_IEnumVARIANT, VARIANT, _Copy<VARIANT> > > enumvar;
enumvar* p = new enumvar;
if ( NULL == m_Var ) { LOG((TL_ERROR, "Internal variant is NULL")); hr = E_FAIL; } else if ( NULL == p ) { LOG((TL_ERROR, "Could not alloc for enumvar")); hr = E_OUTOFMEMORY; } else { hr = p->Init(&m_Var[0], &m_Var[m_dwSize], NULL, AtlFlagCopy);
if (SUCCEEDED(hr)) { hr = p->QueryInterface(IID_IEnumVARIANT, (void**)retval); }
if (FAILED(hr)) { delete p; } }
LOG((TL_TRACE, "get__NewEnum - exit")); return hr; }
void FinalRelease() { LOG((TL_INFO, "FinalRelease()")); }
};
class CAddressEvent : public CTAPIComObjectRoot<CAddressEvent>, public CComDualImpl<ITAddressEvent, &IID_ITAddressEvent, &LIBID_TAPI3Lib>, public CObjectSafeImpl { public:
DECLARE_MARSHALQI(CAddressEvent) DECLARE_TRACELOG_CLASS(CAddressEvent)
BEGIN_COM_MAP(CAddressEvent) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(ITAddressEvent) COM_INTERFACE_ENTRY(IObjectSafety) COM_INTERFACE_ENTRY_FUNC(IID_IMarshal, 0, IMarshalQI) COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pFTM) END_COM_MAP()
static HRESULT FireEvent( CAddress * pAddress, ADDRESS_EVENT Event, ITTerminal * pTerminal ); void FinalRelease(); protected: ITAddress * m_pAddress; ADDRESS_EVENT m_Event; ITTerminal * m_pTerminal;
#if DBG
PWSTR m_pDebug; #endif
public: //
// itaddressstateevent
//
STDMETHOD(get_Address)( ITAddress ** ppAddress ); STDMETHOD(get_Event)( ADDRESS_EVENT * pEvent ); STDMETHOD(get_Terminal)( ITTerminal ** ppTerminal ); };
class CAddressDevSpecificEvent : public CTAPIComObjectRoot<CAddressDevSpecificEvent, CComMultiThreadModelNoCS>, public CComDualImpl<ITAddressDeviceSpecificEvent, &IID_ITAddressDeviceSpecificEvent, &LIBID_TAPI3Lib>, public CObjectSafeImpl { public:
DECLARE_MARSHALQI(CAddressDevSpecificEvent) DECLARE_TRACELOG_CLASS(CAddressDevSpecificEvent)
BEGIN_COM_MAP(CAddressDevSpecificEvent) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(ITAddressDeviceSpecificEvent) COM_INTERFACE_ENTRY(IObjectSafety) COM_INTERFACE_ENTRY_FUNC(IID_IMarshal, 0, IMarshalQI) COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pFTM) END_COM_MAP()
static HRESULT FireEvent( CAddress * pAddress, CCall * pCall, long lParam1, long lParam2, long lParam3 ); ~CAddressDevSpecificEvent();
protected:
CAddressDevSpecificEvent();
//
// properties
//
ITAddress *m_pAddress; ITCallInfo *m_pCall;
long m_l1; long m_l2; long m_l3;
#if DBG
PWSTR m_pDebug; #endif
public:
STDMETHOD(get_Address)( ITAddress ** ppAddress ); STDMETHOD(get_Call) ( ITCallInfo ** ppCall ); STDMETHOD(get_lParam1)( long *plParam1 ); STDMETHOD(get_lParam2)( long *plParam2 ); STDMETHOD(get_lParam3)( long *plParam3 ); };
#define NUMFORWARDTYPES 18
typedef struct { DWORD dwForwardType; BSTR bstrDestination; BSTR bstrCaller; DWORD dwCallerAddressType; DWORD dwDestAddressType; } MYFORWARDSTRUCT;
class CForwardInfo : public CTAPIComObjectRoot<CForwardInfo>, public CComDualImpl<ITForwardInformation2, &IID_ITForwardInformation2, &LIBID_TAPI3Lib>, public CObjectSafeImpl { public:
DECLARE_MARSHALQI(CForwardInfo) DECLARE_TRACELOG_CLASS(CForwardInfo)
BEGIN_COM_MAP(CForwardInfo) COM_INTERFACE_ENTRY2(IDispatch, ITForwardInformation2) COM_INTERFACE_ENTRY(ITForwardInformation) COM_INTERFACE_ENTRY(ITForwardInformation2) COM_INTERFACE_ENTRY(IObjectSafety) COM_INTERFACE_ENTRY_FUNC(IID_IMarshal, 0, IMarshalQI) COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pFTM) END_COM_MAP()
HRESULT Initialize(); HRESULT CreateForwardList( LINEFORWARDLIST ** ppForwardList ); void FinalRelease(); protected:
MYFORWARDSTRUCT m_ForwardStructs[NUMFORWARDTYPES]; long m_lNumRings; public:
STDMETHOD(put_NumRingsNoAnswer)(long lNumRings); STDMETHOD(get_NumRingsNoAnswer)(long * plNumRings); STDMETHOD(SetForwardType)( long ForwardType, BSTR pDestAddress, BSTR pCallerAddress ); STDMETHOD(get_ForwardTypeDestination)( long ForwardType, BSTR * ppDestAddress ); STDMETHOD(get_ForwardTypeCaller)( long Forwardtype, BSTR * ppCallerAddress ); STDMETHOD(GetForwardType)( long ForwardType, BSTR * ppDestinationAddress, BSTR * ppCallerAddress ); STDMETHOD(Clear)(); STDMETHOD(SetForwardType2)( long ForwardType, BSTR pDestAddress, long DestAddressType, BSTR pCallerAddress, long CallerAddressType ); STDMETHOD(GetForwardType2)( long ForwardType, BSTR * ppDestinationAddress, long * pDestAddressType, BSTR * ppCallerAddress, long * pCallerAddressType ); STDMETHOD(get_ForwardTypeDestinationAddressType)( long ForwardType, long * pDestAddressType ); STDMETHOD(get_ForwardTypeCallerAddressType)( long Forwardtype, long * pCallerAddressType ); };
#define FORWARDMODENEEDSCALLER(__dwMode__) \
( ( LINEFORWARDMODE_UNCONDSPECIFIC | LINEFORWARDMODE_BUSYSPECIFIC | \ LINEFORWARDMODE_NOANSWSPECIFIC | LINEFORWARDMODE_BUSYNASPECIFIC ) & \ (__dwMode__) )
////////////////////////////////////////////////////////////////////////
// CAddressTranslationInfo
//
////////////////////////////////////////////////////////////////////////
class CAddressTranslationInfo : public CTAPIComObjectRoot<CAddressTranslationInfo>, public CComDualImpl<ITAddressTranslationInfo, &IID_ITAddressTranslationInfo, &LIBID_TAPI3Lib>, public CObjectSafeImpl { public:
CAddressTranslationInfo() : m_szDialableString(NULL), m_szDisplayableString(NULL), m_dwCurrentCountryCode(0), m_dwDestinationCountryCode(0), m_dwTranslationResults(0) {}
DECLARE_MARSHALQI(CAddressTranslationInfo) DECLARE_TRACELOG_CLASS(CAddressTranslationInfo)
BEGIN_COM_MAP(CAddressTranslationInfo) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(ITAddressTranslationInfo) COM_INTERFACE_ENTRY(IObjectSafety) COM_INTERFACE_ENTRY_FUNC(IID_IMarshal, 0, IMarshalQI) COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pFTM) END_COM_MAP()
HRESULT Initialize( PWSTR pszDialableString, PWSTR pszDisplayableString, DWORD dwCurrentCountry, DWORD dwDestCountry, DWORD dwTranslateResults ); void FinalRelease(); private: DWORD m_dwCurrentCountryCode; DWORD m_dwDestinationCountryCode; DWORD m_dwTranslationResults; PWSTR m_szDialableString; PWSTR m_szDisplayableString; public:
STDMETHOD(get_DialableString)(BSTR * ppDialableString ); STDMETHOD(get_DisplayableString)(BSTR * ppDisplayableString ); STDMETHOD(get_CurrentCountryCode)(long * CountryCode ); STDMETHOD(get_DestinationCountryCode)(long * CountryCode ); STDMETHOD(get_TranslationResults)(long * Results ); };
////////////////////////////////////////////////////////////////////////
// CLocationInfo
//
////////////////////////////////////////////////////////////////////////
class CLocationInfo: public CTAPIComObjectRoot<CLocationInfo>, public CComDualImpl<ITLocationInfo, &IID_ITLocationInfo, &LIBID_TAPI3Lib>, public CObjectSafeImpl { public:
DECLARE_MARSHALQI(CLocationInfo) DECLARE_TRACELOG_CLASS(CLocationInfo)
BEGIN_COM_MAP(CLocationInfo) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(ITLocationInfo) COM_INTERFACE_ENTRY(IObjectSafety) COM_INTERFACE_ENTRY_FUNC(IID_IMarshal, 0, IMarshalQI) COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pFTM) END_COM_MAP()
HRESULT Initialize( PWSTR pszLocationName, PWSTR pszCityCode, PWSTR pszLocalAccessCode, PWSTR pszLongDistanceAccessCode, PWSTR pszTollPrefixList, PWSTR pszCancelCallWaitingCode , DWORD dwPermanentLocationID, DWORD dwCountryCode, DWORD dwPreferredCardID, DWORD dwCountryID, DWORD dwOptions );
void FinalRelease(); private:
DWORD m_dwPermanentLocationID; DWORD m_dwCountryCode; DWORD m_dwCountryID; DWORD m_dwOptions; DWORD m_dwPreferredCardID; PWSTR m_szLocationName; PWSTR m_szCityCode; PWSTR m_szLocalAccessCode; PWSTR m_szLongDistanceAccessCode; PWSTR m_szTollPrefixList; PWSTR m_szCancelCallWaitingCode; public:
// ITLocationInfo
STDMETHOD(get_PermanentLocationID)(long * ulLocationID ); STDMETHOD(get_CountryCode)(long * ulCountryCode); STDMETHOD(get_CountryID)(long * ulCountryID); STDMETHOD(get_Options)(long * Options); STDMETHOD(get_PreferredCardID)( long * ulCardID);
STDMETHOD(get_LocationName)(BSTR * ppLocationName ); STDMETHOD(get_CityCode)(BSTR * ppCode ); STDMETHOD(get_LocalAccessCode)(BSTR * ppCode ); STDMETHOD(get_LongDistanceAccessCode)(BSTR * ppCode ); STDMETHOD(get_TollPrefixList)(BSTR * ppTollList); STDMETHOD(get_CancelCallWaitingCode)(BSTR * ppCode ); };
////////////////////////////////////////////////////////////////////////
// CCallingCard
//
////////////////////////////////////////////////////////////////////////
class CCallingCard: public CTAPIComObjectRoot<CCallingCard>, public CComDualImpl<ITCallingCard, &IID_ITCallingCard, &LIBID_TAPI3Lib>, public CObjectSafeImpl
{ public:
DECLARE_MARSHALQI(CCallingCard) DECLARE_TRACELOG_CLASS(CCallingCard)
BEGIN_COM_MAP(CCallingCard) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(ITCallingCard) COM_INTERFACE_ENTRY(IObjectSafety) COM_INTERFACE_ENTRY_FUNC(IID_IMarshal, 0, IMarshalQI) COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pFTM) END_COM_MAP()
HRESULT Initialize( PWSTR pszCardName, PWSTR pszSameAreaDialingRule, PWSTR pszLongDistanceDialingRule, PWSTR pszInternationalDialingRule, DWORD dwPermanentCardID, DWORD dwNumberOfDigits, DWORD dwOptions ); void FinalRelease(); private:
DWORD m_dwPermanentCardID; DWORD m_dwNumberOfDigits; DWORD m_dwOptions; PWSTR m_szCardName; PWSTR m_szSameAreaDialingRule; PWSTR m_szLongDistanceDialingRule; PWSTR m_szInternationalDialingRule; public:
// ITCallingCard
STDMETHOD(get_PermanentCardID)(long * ulCardID); STDMETHOD(get_NumberOfDigits)(long * ulDigits); STDMETHOD(get_Options)(long * ulOptions);
STDMETHOD(get_CardName)(BSTR * ppCardName ); STDMETHOD(get_SameAreaDialingRule)(BSTR * ppRule ); STDMETHOD(get_LongDistanceDialingRule)(BSTR * ppRule ); STDMETHOD(get_InternationalDialingRule)(BSTR * ppRule ); };
/////////////////////////////////////////////////////////////////////////////
// _CopyBSTR is used in creating BSTR enumerators.
/////////////////////////////////////////////////////////////////////////////
class _CopyBSTR { public: static void copy(BSTR *p1, BSTR *p2) { (*p1) = SysAllocString(*p2); } static void init(BSTR* p) {*p = NULL;} static void destroy(BSTR* p) { SysFreeString(*p);} };
#endif //__ADDRESS_H_
|