|
|
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
phone.cpp
Abstract:
Implementation of phone object for TAPI 3.1
Notes:
optional-notes
Revision History:
--*/
#include "stdafx.h"
#define TIMER_KEEP_ALIVE 0x0FFFFFFF
/////////////////////////////////////////////////////////////////////////////
// IDispatch implementation
//
typedef IDispatchImpl<ITPhoneVtbl<CPhone>, &IID_ITPhone, &LIBID_TAPI3Lib> PhoneType;
typedef IDispatchImpl<ITAutomatedPhoneControlVtbl<CPhone>, &IID_ITAutomatedPhoneControl, &LIBID_TAPI3Lib> AutomatedPhoneControlType;
extern HRESULT mapTAPIErrorCode(long lErrorCode);
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// CPhone::GetIDsOfNames
//
// Overidden IDispatch method
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::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 = PhoneType::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid); if (SUCCEEDED(hr)) { LOG((TL_INFO, "GetIDsOfNames - found %S on ITPhone", *rgszNames)); rgdispid[0] |= IDISPPHONE; return hr; }
// If not, then try the ITAutomatedPhoneControl interface
hr = AutomatedPhoneControlType::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid); if (SUCCEEDED(hr)) { LOG((TL_INFO, "GetIDsOfNames - found %S on ITAutomatedPhoneControl", *rgszNames)); rgdispid[0] |= IDISPAPC; return hr; }
LOG((TL_INFO, "GetIDsOfNames - Didn't find %S on our iterfaces", *rgszNames)); return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// CPhone::Invoke
//
// Overide if IDispatch method
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::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 IDISPPHONE: { hr = PhoneType::Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr ); break; } case IDISPAPC: { hr = AutomatedPhoneControlType::Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr ); break; }
} // end switch (dwInterface)
LOG((TL_TRACE, hr, "Invoke - exit" )); return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// CPhone::InternalAddRef
//
// Overidden IDispatch method
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP_(ULONG) CPhone::InternalAddRef() { DWORD dwR;
dwR = InterlockedIncrement(&m_dwRef);
LOG((TL_INFO, "InternalAddRef - dwR %d",dwR ));
#if DBG
LogDebugAddRef(m_dwRef); #endif
return dwR; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// CPhone::InternalRelease
//
// Overidden IDispatch method
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP_(ULONG) CPhone::InternalRelease() { DWORD dwR; PtrList::iterator iter, end; T3LINE * pt3Line;
LOG((TL_INFO, "InternalRelease - m_dwRef %d",m_dwRef )); Lock(); gpPhoneHashTable->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
//
if (m_hPhone) { if(FAILED(gpPhoneHashTable->Remove( (ULONG_PTR)(m_hPhone) ) )) { LOG((TL_INFO, "InternalRelease - pLineHashTable->Remove failed" )); } }
gpPhoneHashTable->Unlock();
dwR = m_dwRef = 0;
Unlock(); LOG((TL_INFO, "InternalRelease - final OK dwR %d",dwR )); } else { gpPhoneHashTable->Unlock(); Unlock(); LOG((TL_INFO, "InternalRelease - not final dwR %d",dwR )); }
#if DBG
LogDebugRelease( dwR ); #endif
return dwR; }
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
// ITPhone methods
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Open
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::Open( PHONE_PRIVILEGE Privilege ) { DWORD dwPrivilege; T3PHONE t3Phone; HRESULT hr;
LOG((TL_TRACE, "Open - enter" ));
Lock();
//
// We cannot be opened multiple time simultaneously
// return TAPI_E_INUSE if someone else has us open
//
if (m_hPhone) { LOG((TL_TRACE, "Open - phone in use" )); Unlock(); return TAPI_E_INUSE; }
switch(Privilege) { case PP_OWNER: dwPrivilege = PHONEPRIVILEGE_OWNER; break; case PP_MONITOR: dwPrivilege = PHONEPRIVILEGE_MONITOR; break; default: { LOG((TL_TRACE, "Open - invalid privilege" )); Unlock(); return TAPI_E_INVALPRIVILEGE; } break; }
t3Phone.hPhone = NULL; t3Phone.pPhone = this;
hr = PhoneOpen(m_hPhoneApp, m_dwDeviceID, &t3Phone, m_dwAPIVersion, dwPrivilege);
if ( SUCCEEDED(hr) ) { hr = PhoneSetStatusMessages(&t3Phone, PHONESTATE_CAPSCHANGE | PHONESTATE_HANDSETHOOKSWITCH | PHONESTATE_HEADSETHOOKSWITCH | PHONESTATE_LAMP | PHONESTATE_RINGMODE | PHONESTATE_RINGVOLUME | PHONESTATE_SPEAKERHOOKSWITCH | PHONESTATE_DISPLAY, PHONEBUTTONMODE_CALL | PHONEBUTTONMODE_DISPLAY | PHONEBUTTONMODE_DUMMY | PHONEBUTTONMODE_FEATURE | PHONEBUTTONMODE_KEYPAD | PHONEBUTTONMODE_LOCAL, PHONEBUTTONSTATE_UP | PHONEBUTTONSTATE_DOWN | PHONEBUTTONSTATE_UNKNOWN | PHONEBUTTONSTATE_UNAVAIL);
if ( SUCCEEDED(hr) ) { m_hPhone = t3Phone.hPhone;
m_dwPrivilege = dwPrivilege; } else { PhoneClose(t3Phone.hPhone); } }
//
// Defaults for phone automation settings
//
m_fPhoneHandlingEnabled = FALSE; m_dwAutoEndOfNumberTimeout = APC_DEFAULT_AEONT; m_fAutoDialtone = TRUE; m_fAutoStopTonesOnOnHook = TRUE; m_fAutoStopRingOnOffHook = TRUE; m_fAutoKeypadTones = TRUE; m_dwAutoKeypadTonesMinimumDuration = APC_DEFAULT_AKTMD; m_fAutoVolumeControl = TRUE; m_dwAutoVolumeControlStep = APC_DEFAULT_VCS; m_dwAutoVolumeControlRepeatDelay = APC_DEFAULT_VCRD; m_dwAutoVolumeControlRepeatPeriod = APC_DEFAULT_VCRP;
Unlock();
if ( FAILED(hr) ) { LOG((TL_TRACE, "Open - PhoneOpen returned failure - " "exit 0x%08x", hr )); return hr; }
LOG((TL_TRACE, "Open - exit S_OK"));
return S_OK; }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Close
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::Close() { HRESULT hr;
LOG((TL_TRACE, "Close - enter" ));
Lock();
if ( m_hPhone == NULL ) { LOG((TL_WARN, "Close - phone not open - return S_OK")); Unlock();
return S_OK; }
if (m_dwPrivilege == PHONEPRIVILEGE_OWNER) { //
// Turn off automatic phone handling
//
m_fPhoneHandlingEnabled = FALSE;
//
// Stop any ringers or tones
//
if (m_fRinger == TRUE) { StopRinger(); }
if (m_Tone != PT_SILENCE) { StopTone(); }
CloseWaveDevice();
//
// Unselect any calls
//
if (m_pCall != NULL) { InternalUnselectCall(m_pCall); } } //
// Finally, actually close the phone
//
hr = PhoneClose(m_hPhone);
m_hPhone = NULL; Unlock();
LOG((TL_TRACE, "Close - exit - return %lx", hr)); return hr; }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_Addresses
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::get_Addresses( VARIANT *pAddresses ) { IEnumAddress * pEnum; ITAddress * pAddress; AddressArray aAddresses; HRESULT hr; IDispatch * pDisp;
LOG((TL_TRACE, "get_Addresses - enter" ));
if ( TAPIIsBadWritePtr( pAddresses, sizeof (VARIANT) ) ) { LOG((TL_ERROR, "get_Addresses - bad pointer")); return E_POINTER; }
Lock();
//
// get the addresses from tapi
//
hr = m_pTAPI->EnumerateAddresses( &pEnum );
if ( FAILED(hr) ) { LOG((TL_ERROR, "get_Addresses - could not enumerate addresses from tapi - return %lx", hr)); Unlock();
return hr; }
//
// choose only addresses that this phone is on
//
while ( S_OK == pEnum->Next( 1, &pAddress, NULL ) ) { if (IsPhoneOnAddress( pAddress )) { if ( !aAddresses.Add( pAddress ) ) { LOG((TL_ERROR, "get_Addresses - could add address to array")); } }
pAddress->Release(); }
pEnum->Release();
Unlock();
//
// create the collection
//
CComObject< CTapiCollection< ITAddress > > * p; hr = CComObject< CTapiCollection< ITAddress > >::CreateInstance( &p ); if ( S_OK != hr ) // CreateInstance deletes object on S_FALSE
{ LOG((TL_ERROR, "get_Addresses - could not create collection" )); return E_OUTOFMEMORY; }
//
// get the IDispatch interface
//
hr = p->_InternalQueryInterface( IID_IDispatch, (void **) &pDisp );
if ( FAILED(hr) ) { LOG((TL_ERROR, "get_Addresses - could not get IDispatch interface" )); delete p; return hr; } hr = p->Initialize( aAddresses );
aAddresses.Shutdown();
if ( FAILED(hr) ) { LOG((TL_ERROR, "get_Addresses - could not initialize collection" )); pDisp->Release(); return hr; }
//
// put it in the variant
//
VariantInit(pAddresses); pAddresses->vt = VT_DISPATCH; pAddresses->pdispVal = pDisp;
LOG((TL_TRACE, "get_Addresses - exit - return %lx", hr)); return hr; }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// EnumerateAddresses
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::EnumerateAddresses( IEnumAddress ** ppEnumAddress ) { IEnumAddress * pEnumAddress; ITAddress * pAddress; AddressArray aAddresses; HRESULT hr;
LOG((TL_TRACE, "EnumerateAddresses - enter" ));
if ( TAPIIsBadWritePtr( ppEnumAddress, sizeof (IEnumAddress *) ) ) { LOG((TL_ERROR, "EnumerateAddresses - bad pointer")); return E_POINTER; }
Lock();
//
// get the addresses from tapi
//
hr = m_pTAPI->EnumerateAddresses( &pEnumAddress );
if ( FAILED(hr) ) { LOG((TL_ERROR, "EnumerateAddresses - could not enumerate addresses from tapi - return %lx", hr)); Unlock();
return hr; }
//
// choose only addresses that this phone is on
//
while ( S_OK == pEnumAddress->Next( 1, &pAddress, NULL ) ) { if (IsPhoneOnAddress( pAddress )) { if ( !aAddresses.Add( pAddress ) ) { LOG((TL_ERROR, "EnumerateAddresses - could add address to array")); } }
pAddress->Release(); }
pEnumAddress->Release();
Unlock();
//
// create the enum
//
CComObject< CTapiEnum<IEnumAddress, ITAddress, &IID_IEnumAddress> > * pEnum; hr = CComObject< CTapiEnum<IEnumAddress, ITAddress, &IID_IEnumAddress> >::CreateInstance( &pEnum );
if ( S_OK != hr ) // CreateInstance deletes object on S_FALSE
{ LOG((TL_ERROR, "EnumerateAddresses - could not create enum - return %lx", hr));
return hr; }
//
// initialize
//
hr = pEnum->Initialize( aAddresses );
aAddresses.Shutdown();
if ( FAILED(hr) ) { pEnum->Release(); LOG((TL_ERROR, "EnumerateAddresses - could not initialize enum - return %lx", hr));
return hr; }
*ppEnumAddress = pEnum;
LOG((TL_TRACE, "EnumerateAddresses - exit - return %lx", hr)); return hr; }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_PreferredAddresses
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::get_PreferredAddresses( VARIANT *pAddresses ) { IEnumAddress * pEnum; ITAddress * pAddress; AddressArray aAddresses; HRESULT hr; IDispatch * pDisp;
LOG((TL_TRACE, "get_PreferredAddresses - enter" ));
if ( TAPIIsBadWritePtr( pAddresses, sizeof (VARIANT) ) ) { LOG((TL_ERROR, "get_PreferredAddresses - bad pointer")); return E_POINTER; }
Lock();
//
// get the addresses from tapi
//
hr = m_pTAPI->EnumerateAddresses( &pEnum );
if ( FAILED(hr) ) { LOG((TL_ERROR, "get_PreferredAddresses - could not enumerate addresses from tapi - return %lx", hr)); Unlock();
return hr; }
//
// choose only addresses that this phone is on
//
while ( S_OK == pEnum->Next( 1, &pAddress, NULL ) ) { if (IsPhoneOnPreferredAddress( pAddress )) { if ( !aAddresses.Add( pAddress ) ) { LOG((TL_ERROR, "get_PreferredAddresses - could add address to array")); } }
pAddress->Release(); }
pEnum->Release();
Unlock();
//
// create the collection
//
CComObject< CTapiCollection< ITAddress > > * p; hr = CComObject< CTapiCollection< ITAddress > >::CreateInstance( &p ); if ( S_OK != hr ) // CreateInstance deletes object on S_FALSE
{ LOG((TL_ERROR, "get_PreferredAddresses - could not create collection" )); return E_OUTOFMEMORY; }
//
// get the IDispatch interface
//
hr = p->_InternalQueryInterface( IID_IDispatch, (void **) &pDisp );
if ( FAILED(hr) ) { LOG((TL_ERROR, "get_PreferredAddresses - could not get IDispatch interface" )); delete p; return hr; } hr = p->Initialize( aAddresses );
aAddresses.Shutdown();
if ( FAILED(hr) ) { LOG((TL_ERROR, "get_PreferredAddresses - could not initialize collection" )); pDisp->Release(); return hr; }
//
// put it in the variant
//
VariantInit(pAddresses); pAddresses->vt = VT_DISPATCH; pAddresses->pdispVal = pDisp;
LOG((TL_TRACE, "get_PreferredAddresses - exit - return %lx", hr)); return hr; }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// EnumeratePreferredAddresses
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::EnumeratePreferredAddresses( IEnumAddress ** ppEnumAddress ) { IEnumAddress * pEnumAddress; ITAddress * pAddress; AddressArray aAddresses; HRESULT hr;
LOG((TL_TRACE, "EnumeratePreferredAddresses - enter" ));
if ( TAPIIsBadWritePtr( ppEnumAddress, sizeof (IEnumAddress *) ) ) { LOG((TL_ERROR, "EnumeratePreferredAddresses - bad pointer")); return E_POINTER; }
Lock();
//
// get the addresses from tapi
//
hr = m_pTAPI->EnumerateAddresses( &pEnumAddress );
if ( FAILED(hr) ) { LOG((TL_ERROR, "EnumeratePreferredAddresses - could not enumerate addresses from tapi - return %lx", hr)); Unlock();
return hr; }
//
// choose only addresses that this phone is on
//
while ( S_OK == pEnumAddress->Next( 1, &pAddress, NULL ) ) { if (IsPhoneOnPreferredAddress( pAddress )) { if ( !aAddresses.Add( pAddress ) ) { LOG((TL_ERROR, "EnumeratePreferredAddresses - could add address to array")); } }
pAddress->Release(); }
pEnumAddress->Release();
Unlock();
//
// create the enum
//
CComObject< CTapiEnum<IEnumAddress, ITAddress, &IID_IEnumAddress> > * pEnum; hr = CComObject< CTapiEnum<IEnumAddress, ITAddress, &IID_IEnumAddress> >::CreateInstance( &pEnum );
if ( S_OK != hr ) // CreateInstance deletes object on S_FALSE
{ LOG((TL_ERROR, "EnumeratePreferredAddresses - could not create enum - return %lx", hr));
return hr; }
//
// initialize
//
hr = pEnum->Initialize( aAddresses );
aAddresses.Shutdown();
if ( FAILED(hr) ) { pEnum->Release(); LOG((TL_ERROR, "EnumeratePreferredAddresses - could not initialize enum - return %lx", hr));
return hr; }
*ppEnumAddress = pEnum;
LOG((TL_TRACE, "EnumeratePreferredAddresses - exit - return %lx", hr)); return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_PhoneCapsLong
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::get_PhoneCapsLong( PHONECAPS_LONG pclCap, long * plCapability ) { HRESULT hr = S_OK;
if ( TAPIIsBadWritePtr( plCapability, sizeof(long) ) ) { LOG((TL_ERROR, "get_PhoneCapsLong - bad pointer"));
return E_POINTER; }
LOG((TL_TRACE, "get_PhoneCapsLong - enter" ));
Lock(); //
// Update the cache
//
hr = UpdatePhoneCaps();
if ( FAILED(hr) ) { LOG((TL_ERROR, "get_PhoneCapsLong - could not get phonecaps"));
Unlock(); return hr; }
switch (pclCap) { case PCL_HOOKSWITCHES: *plCapability = m_pPhoneCaps->dwHookSwitchDevs; break; case PCL_HANDSETHOOKSWITCHMODES: *plCapability = m_pPhoneCaps->dwHandsetHookSwitchModes; break; case PCL_HEADSETHOOKSWITCHMODES: *plCapability = m_pPhoneCaps->dwHeadsetHookSwitchModes; break; case PCL_SPEAKERPHONEHOOKSWITCHMODES: *plCapability = m_pPhoneCaps->dwSpeakerHookSwitchModes; break;
case PCL_DISPLAYNUMROWS: *plCapability = m_pPhoneCaps->dwDisplayNumRows; break;
case PCL_DISPLAYNUMCOLUMNS: *plCapability = m_pPhoneCaps->dwDisplayNumColumns; break;
case PCL_NUMRINGMODES: *plCapability = m_pPhoneCaps->dwNumRingModes; break;
case PCL_NUMBUTTONLAMPS: *plCapability = m_pPhoneCaps->dwNumButtonLamps; break;
case PCL_GENERICPHONE: if( m_dwAPIVersion >= TAPI_VERSION2_0 ) { *plCapability = (m_pPhoneCaps->dwPhoneFeatures & PHONEFEATURE_GENERICPHONE) ? 1:0; } else { *plCapability = 0; } break;
default: LOG((TL_ERROR, "get_PhoneCapsLong - bad pclCap"));
Unlock(); return E_INVALIDARG; }
Unlock();
LOG((TL_TRACE, "get_PhoneCapsLong - exit - return %lx", hr)); return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_PhoneCapsString
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::get_PhoneCapsString( PHONECAPS_STRING pcsCap, BSTR * ppCapability ) { HRESULT hr;
if ( TAPIIsBadWritePtr( ppCapability, sizeof(BSTR) ) ) { LOG((TL_ERROR, "get_PhoneCapsString - bad pointer"));
return E_POINTER; }
LOG((TL_TRACE, "get_PhoneCapsString - enter" ));
Lock(); //
// Update the cache
//
hr = UpdatePhoneCaps();
if ( FAILED(hr) ) { LOG((TL_ERROR, "get_PhoneCapsString - could not get phonecaps - %lx", hr));
Unlock(); return hr; }
DWORD dwSize; DWORD dwOffset;
//
// Get the size and offset of the string in the phone caps
//
switch (pcsCap) { case PCS_PHONENAME: dwSize = m_pPhoneCaps->dwPhoneNameSize; dwOffset = m_pPhoneCaps->dwPhoneNameOffset; break; case PCS_PHONEINFO: dwSize = m_pPhoneCaps->dwPhoneInfoSize; dwOffset = m_pPhoneCaps->dwPhoneInfoOffset; break; case PCS_PROVIDERINFO: dwSize = m_pPhoneCaps->dwProviderInfoSize; dwOffset = m_pPhoneCaps->dwProviderInfoOffset; break;
default: LOG((TL_ERROR, "get_PhoneCapsString - bad pcsCap"));
Unlock(); return E_INVALIDARG; }
//
// Allocate the BSTR
//
if ( dwSize != 0 ) { *ppCapability = SysAllocString( (LPWSTR)(((LPBYTE)(m_pPhoneCaps)) + dwOffset) );
if ( NULL == *ppCapability ) { LOG((TL_ERROR, "get_PhoneCapsString - SysAllocString failed - E_OUTOFMEMORY")); Unlock(); return E_OUTOFMEMORY; } }
Unlock();
LOG((TL_TRACE, "get_PhoneCapsString - exit - return S_OK")); return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_Terminals
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::get_Terminals( ITAddress * pAddress, VARIANT * pTerminals ) { IEnumTerminal * pEnumTerminal; ITTerminal * pTerminal; ITStaticAudioTerminal * pStaticAudioTerminal; TerminalArray aTerminals; HRESULT hr; IDispatch * pDisp; ITTerminalSupport * pTerminalSupport; LONG lMediaType; TERMINAL_DIRECTION nDir;
LOG((TL_TRACE, "get_Terminals - enter" ));
if ( IsBadReadPtr( pAddress, sizeof (ITAddress) ) ) { LOG((TL_ERROR, "get_Terminals - bad pointer")); return E_POINTER; }
if ( TAPIIsBadWritePtr( pTerminals, sizeof (VARIANT) ) ) { LOG((TL_ERROR, "get_Terminals - bad pointer")); return E_POINTER; }
Lock();
//
// Get the ITTerminalSupport interface
//
hr = pAddress->QueryInterface(IID_ITTerminalSupport, (void **) &pTerminalSupport);
if ( SUCCEEDED(hr) ) { //
// Get all the terminals on this address
//
hr = pTerminalSupport->EnumerateStaticTerminals( &pEnumTerminal );
if ( SUCCEEDED(hr) ) { while ( S_OK == pEnumTerminal->Next( 1, &pTerminal, NULL ) ) { hr = pTerminal->get_MediaType(&lMediaType);
if ( SUCCEEDED(hr) ) { hr = pTerminal->get_Direction(&nDir);
if ( SUCCEEDED(hr) ) { //
// we only care about audio terminals
//
if (lMediaType == TAPIMEDIATYPE_AUDIO) { //
// we only care about terminals which implement ITStaticAudioTerminal
// because we need to get the wave ID
//
hr = pTerminal->QueryInterface(IID_ITStaticAudioTerminal, (void **) &pStaticAudioTerminal);
if ( SUCCEEDED(hr) ) { LONG lWaveId;
hr = pStaticAudioTerminal->get_WaveId(&lWaveId);
if ( SUCCEEDED(hr) ) { LOG((TL_INFO, "get_Terminals - got terminal wave id %d", lWaveId));
if (IsPhoneUsingWaveID( lWaveId, nDir )) { if ( !aTerminals.Add( pTerminal ) ) { LOG((TL_ERROR, "get_Terminals - could add terminal to array")); } } } pStaticAudioTerminal->Release(); } } } else { LOG((TL_WARN, "get_Terminals - could not get terminal direction - %lx", hr)); } } else { LOG((TL_WARN, "get_Terminals - could not get terminal media type - %lx", hr)); }
pTerminal->Release(); } pEnumTerminal->Release(); } pTerminalSupport->Release(); }
Unlock();
//
// create the collection
//
CComObject< CTapiCollection< ITTerminal > > * p; hr = CComObject< CTapiCollection< ITTerminal > >::CreateInstance( &p ); if ( S_OK != hr ) // CreateInstance deletes object on S_FALSE
{ LOG((TL_ERROR, "get_Terminals - could not create collection" )); return E_OUTOFMEMORY; }
//
// get the IDispatch interface
//
hr = p->_InternalQueryInterface( IID_IDispatch, (void **) &pDisp );
if ( FAILED(hr) ) { LOG((TL_ERROR, "get_Terminals - could not get IDispatch interface" )); delete p; return hr; } //
// initialize
//
hr = p->Initialize( aTerminals );
aTerminals.Shutdown();
if ( FAILED(hr) ) { LOG((TL_ERROR, "get_Terminals - could not initialize collection" )); pDisp->Release(); return hr; }
//
// put it in the variant
//
VariantInit(pTerminals); pTerminals->vt = VT_DISPATCH; pTerminals->pdispVal = pDisp;
LOG((TL_TRACE, "get_Terminals - exit - return %lx", hr)); return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// EnumerateTerminals
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::EnumerateTerminals( ITAddress * pAddress, IEnumTerminal ** ppEnumTerminal ) { IEnumTerminal * pEnumTerminal; ITTerminal * pTerminal; ITStaticAudioTerminal * pStaticAudioTerminal; TerminalArray aTerminals; HRESULT hr; ITTerminalSupport * pTerminalSupport; LONG lMediaType; TERMINAL_DIRECTION nDir;
LOG((TL_TRACE, "EnumerateTerminals - enter" ));
if ( IsBadReadPtr( pAddress, sizeof (ITAddress) ) ) { LOG((TL_ERROR, "get_Terminals - bad pointer")); return E_POINTER; }
if ( TAPIIsBadWritePtr( ppEnumTerminal, sizeof (IEnumTerminal *) ) ) { LOG((TL_ERROR, "EnumerateTerminals - bad pointer")); return E_POINTER; }
Lock();
//
// Get the ITTerminalSupport interface
//
hr = pAddress->QueryInterface(IID_ITTerminalSupport, (void **) &pTerminalSupport);
if ( SUCCEEDED(hr) ) { //
// Get all the terminals on this address
//
hr = pTerminalSupport->EnumerateStaticTerminals( &pEnumTerminal );
if ( SUCCEEDED(hr) ) { while ( S_OK == pEnumTerminal->Next( 1, &pTerminal, NULL ) ) { hr = pTerminal->get_MediaType(&lMediaType);
if ( SUCCEEDED(hr) ) { hr = pTerminal->get_Direction(&nDir);
if ( SUCCEEDED(hr) ) { //
// we only care about audio terminals
//
if (lMediaType == TAPIMEDIATYPE_AUDIO) { //
// we only care about terminals which implement ITStaticAudioTerminal
// because we need to get the wave ID
//
hr = pTerminal->QueryInterface(IID_ITStaticAudioTerminal, (void **) &pStaticAudioTerminal);
if ( SUCCEEDED(hr) ) { LONG lWaveId;
hr = pStaticAudioTerminal->get_WaveId(&lWaveId);
if ( SUCCEEDED(hr) ) { LOG((TL_INFO, "get_Terminals - got terminal wave id %d", lWaveId));
if (IsPhoneUsingWaveID( lWaveId, nDir )) { if ( !aTerminals.Add( pTerminal ) ) { LOG((TL_ERROR, "get_Terminals - could add terminal to array")); } } } pStaticAudioTerminal->Release(); } } } else { LOG((TL_WARN, "get_Terminals - could not get terminal direction - %lx", hr)); } } else { LOG((TL_WARN, "get_Terminals - could not get terminal media type - %lx", hr)); }
pTerminal->Release(); } pEnumTerminal->Release(); } pTerminalSupport->Release(); }
Unlock();
//
// create the enum
//
CComObject< CTapiEnum<IEnumTerminal, ITTerminal, &IID_IEnumTerminal> > * pEnum; hr = CComObject< CTapiEnum<IEnumTerminal, ITTerminal, &IID_IEnumTerminal> >::CreateInstance( &pEnum );
if ( S_OK != hr ) // CreateInstance deletes object on S_FALSE
{ LOG((TL_ERROR, "EnumerateTerminals - could not create enum - return %lx", hr));
return hr; }
//
// initialize
//
hr = pEnum->Initialize( aTerminals );
aTerminals.Shutdown();
if ( FAILED(hr) ) { pEnum->Release(); LOG((TL_ERROR, "EnumerateTerminals - could not initialize enum - return %lx", hr));
return hr; }
*ppEnumTerminal = pEnum;
LOG((TL_TRACE, "EnumerateTerminals - exit - return %lx", hr )); return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_ButtonMode
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::get_ButtonMode( long lButtonID, PHONE_BUTTON_MODE * pButtonMode ) { HRESULT hr = S_OK; DWORD dwNumButtons; LPPHONEBUTTONINFO pButtonInfo;
LOG((TL_TRACE, "get_ButtonMode - enter" ));
if ( TAPIIsBadWritePtr( pButtonMode, sizeof(PHONE_BUTTON_MODE) ) ) { LOG((TL_ERROR, "get_ButtonMode - bad pointer"));
return E_POINTER; }
Lock();
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "get_ButtonMode - phone not open")); Unlock();
return TAPI_E_PHONENOTOPEN; }
//
// Get the ButtonInfo buffer
//
hr = PhoneGetButtonInfo( m_hPhone, lButtonID, &pButtonInfo );
Unlock();
if ( SUCCEEDED(hr) ) { switch ( pButtonInfo->dwButtonMode ) { case PHONEBUTTONMODE_CALL: *pButtonMode = PBM_CALL; break;
case PHONEBUTTONMODE_DISPLAY: *pButtonMode = PBM_DISPLAY; break; case PHONEBUTTONMODE_DUMMY: *pButtonMode = PBM_DUMMY; break;
case PHONEBUTTONMODE_FEATURE: *pButtonMode = PBM_FEATURE; break;
case PHONEBUTTONMODE_KEYPAD: *pButtonMode = PBM_KEYPAD; break;
case PHONEBUTTONMODE_LOCAL: *pButtonMode = PBM_LOCAL; break;
default: LOG((TL_ERROR, "get_ButtonMode - bad button mode"));
hr = E_FAIL; }
//
// Free the ButtonInfo buffer
//
ClientFree( pButtonInfo ); }
LOG((TL_TRACE, "get_ButtonMode - exit - return %lx", hr)); return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// put_ButtonMode
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::put_ButtonMode( long lButtonID, PHONE_BUTTON_MODE ButtonMode ) { HRESULT hr;
LOG((TL_TRACE, "put_ButtonMode - enter" ));
Lock();
//
// Make sure the phone is open with owner privilege.
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "put_ButtonMode - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
if ( m_dwPrivilege != PHONEPRIVILEGE_OWNER ) { LOG((TL_ERROR, "put_ButtonMode - wrong phone privilege - " "exit TAPI_E_NOTOWNER"));
Unlock();
return TAPI_E_NOTOWNER; } //
// get info for this button
//
PHONEBUTTONINFO *pButtonInfo = NULL;
hr = PhoneGetButtonInfo(m_hPhone, lButtonID, &pButtonInfo);
if ( FAILED(hr) ) { LOG((TL_ERROR, "put_ButtonMode - failed to get button info"));
Unlock(); return hr; }
//
// make sure the memory we got back is writeable
//
if (TAPIIsBadWritePtr(pButtonInfo, sizeof(PHONEBUTTONINFO))) { LOG((TL_ERROR, "put_ButtonMode - PhoneGetButtonInfo returned a bad memory block"));
Unlock(); return E_UNEXPECTED; }
//
// set the appropriate button mode in the structure that we have. leave everything else unchanged
//
switch (ButtonMode) { case PBM_DUMMY: pButtonInfo->dwButtonMode = PHONEBUTTONMODE_DUMMY; break;
case PBM_CALL: pButtonInfo->dwButtonMode = PHONEBUTTONMODE_CALL; break;
case PBM_FEATURE: pButtonInfo->dwButtonMode = PHONEBUTTONMODE_FEATURE; break;
case PBM_KEYPAD: pButtonInfo->dwButtonMode = PHONEBUTTONMODE_KEYPAD; break;
case PBM_LOCAL: pButtonInfo->dwButtonMode = PHONEBUTTONMODE_LOCAL; break;
case PBM_DISPLAY: pButtonInfo->dwButtonMode = PHONEBUTTONMODE_DISPLAY; break;
default: LOG((TL_ERROR, "put_ButtonMode - bad ButtonMode"));
Unlock();
ClientFree(pButtonInfo); pButtonInfo = NULL;
return E_INVALIDARG; }
//
// set the new button mode
//
hr = PhoneSetButtonInfo(m_hPhone, lButtonID, pButtonInfo);
Unlock(); //
// free memory returned to us by PhoneGetButtonInfo
//
ClientFree(pButtonInfo); pButtonInfo = NULL;
LOG((TL_TRACE, "put_ButtonMode - put_ButtonMode - return %lx", hr )); return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// put_ButtonText
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::put_ButtonText( long lButtonID, BSTR bstrButtonText ) { HRESULT hr;
LOG((TL_TRACE, "put_ButtonText - enter" ));
if ( IsBadStringPtrW(bstrButtonText, -1) ) { LOG((TL_ERROR, "put_ButtonText - invalid parameter", "exit E_POINTER"));
return E_POINTER; }
Lock();
//
// Make sure the phone is open with owner privilege.
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "put_ButtonText - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
if ( m_dwPrivilege != PHONEPRIVILEGE_OWNER ) { LOG((TL_ERROR, "put_ButtonText - wrong phone privilege - " "exit TAPI_E_NOTOWNER"));
Unlock();
return TAPI_E_NOTOWNER; }
//
// get info for this button
//
PHONEBUTTONINFO *pButtonInfo = NULL;
hr = PhoneGetButtonInfo(m_hPhone, lButtonID, &pButtonInfo);
if ( FAILED(hr) ) { LOG((TL_ERROR, "put_ButtonText - failed to get button info"));
Unlock(); return hr; }
//
// make sure the memory we got back is writeable
//
if ( TAPIIsBadWritePtr(pButtonInfo, sizeof(PHONEBUTTONINFO)) ) { LOG((TL_ERROR, "put_ButtonText - PhoneGetButtonInfo returned a bad memory block"));
Unlock(); return E_UNEXPECTED; } DWORD dwButtonTextLength = SysStringByteLen(bstrButtonText);
//
// add the string to the structure we have. if the new string fits in
// place of the old string, put it in there. otherwise, allocate a bigger
// structure and append the new string at the end
//
if ( dwButtonTextLength <= pButtonInfo->dwButtonTextSize ) { CopyMemory((BYTE*)pButtonInfo + pButtonInfo->dwButtonTextOffset, bstrButtonText, dwButtonTextLength); pButtonInfo->dwButtonTextSize = dwButtonTextLength; } else { //
// create the new structure that will have everything the old one does + the new string
//
DWORD dwBiggerStructureSize = pButtonInfo->dwTotalSize + dwButtonTextLength;
//
// allocate the new, bigger structure
//
PHONEBUTTONINFO *pBiggerButtonInfo = (PHONEBUTTONINFO *)ClientAlloc(dwBiggerStructureSize);
if ( NULL == pBiggerButtonInfo ) { LOG((TL_ERROR, "put_ButtonText - failed to allocate memory for the new structure"));
ClientFree(pButtonInfo);
Unlock();
return E_OUTOFMEMORY; }
//
// copy the old data into the bigger structure
//
CopyMemory(pBiggerButtonInfo, pButtonInfo, pButtonInfo->dwTotalSize);
//
// append the new structure with the new string (the new text starts after the old data)
//
//
// set the offset and size for the text in the new structure
//
pBiggerButtonInfo->dwButtonTextOffset = pButtonInfo->dwTotalSize; pBiggerButtonInfo->dwButtonTextSize = dwButtonTextLength;
//
// copy the text to the end of the new structure
//
CopyMemory((BYTE*)pBiggerButtonInfo + pBiggerButtonInfo->dwButtonTextOffset, bstrButtonText, dwButtonTextLength);
//
// set the size of the new structure
//
pBiggerButtonInfo->dwTotalSize = dwBiggerStructureSize;
//
// free memory allocated by the old structure
//
ClientFree(pButtonInfo);
//
// pButtonInfo will now point to the new structure
//
pButtonInfo = pBiggerButtonInfo; pBiggerButtonInfo = NULL; } //
// set the new button text
//
hr = PhoneSetButtonInfo(m_hPhone, lButtonID, pButtonInfo);
Unlock();
//
// free memory returned to us by PhoneGetButtonInfo
//
ClientFree(pButtonInfo); pButtonInfo = NULL;
LOG((TL_TRACE, "put_ButtonText - exit - return %lx", hr ));
return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_PhoneCapsBuffer
//
// returns the requested buffer from phone capapabilities array --
// the scriptable version
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::get_PhoneCapsBuffer( IN PHONECAPS_BUFFER pcbCaps, OUT VARIANT *pVarBuffer ) { LOG((TL_TRACE, "get_PhoneCapsBuffer[%p] - enter", this ));
//
// check arguments
//
if ( TAPIIsBadWritePtr( pVarBuffer, sizeof(VARIANT) ) ) { LOG((TL_ERROR, "get_PhoneCapsBuffer - bad pointer"));
return E_POINTER; }
//
// get the buffer
//
DWORD dwBufferSize = 0;
BYTE *pBuffer = NULL;
HRESULT hr = GetPhoneCapsBuffer(pcbCaps, &dwBufferSize, &pBuffer);
if (FAILED(hr)) { LOG((TL_ERROR, "get_PhoneCapsBuffer - failed to get phone caps buffer"));
return hr; }
VariantInit(pVarBuffer);
//
// fill the variant with the data buffer
//
hr = FillVariantFromBuffer(dwBufferSize, pBuffer, pVarBuffer); //
// no longer need the buffer -- we hope that now have all the data in the variant
//
CoTaskMemFree(pBuffer);
if (FAILED(hr)) { LOG((TL_ERROR, "get_PhoneCapsBuffer - failed to copy phone caps buffer to a variant"));
return hr; } LOG((TL_TRACE, "get_PhoneCapsBuffer - exit - return S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// GetPhoneCapsBuffer
//
// returns the requested buffer from phone capapabilities array
//
// on success, the caller must call CoTaskMemFree to free the buffer that is
// returned by this method
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::GetPhoneCapsBuffer( IN PHONECAPS_BUFFER pcbCaps, OUT DWORD *pdwSize, OUT BYTE **ppPhoneCapsBuffer ) { LOG((TL_TRACE, "GetPhoneCapsBuffer - enter" ));
//
// check arguments
//
if ( TAPIIsBadWritePtr( ppPhoneCapsBuffer, sizeof(BYTE*) ) ) { LOG((TL_ERROR, "GetPhoneCapsBuffer - bad pointer"));
return E_POINTER; } *ppPhoneCapsBuffer = NULL;
if ( TAPIIsBadWritePtr( pdwSize, sizeof(DWORD) ) ) { LOG((TL_ERROR, "GetPhoneCapsBuffer - bad pointer"));
return E_POINTER; }
*pdwSize = 0;
Lock();
//
// update phone capabilities cache
//
HRESULT hr = UpdatePhoneCaps();
if ( FAILED(hr) ) { LOG((TL_ERROR, "GetPhoneCapsBuffer - could not get phonecaps"));
Unlock(); return hr; }
switch (pcbCaps) {
case PCB_DEVSPECIFICBUFFER: { //
// allocate the buffer for device-specific caps
//
*pdwSize = m_pPhoneCaps->dwDevSpecificSize;
*ppPhoneCapsBuffer = static_cast<BYTE*>(CoTaskMemAlloc(*pdwSize));
if (NULL == *ppPhoneCapsBuffer) { LOG((TL_ERROR, "GetPhoneCapsBuffer - could not allocate memory for the output buffer"));
Unlock(); return E_OUTOFMEMORY; }
//
// copy data to the buffer to be returned to the caller
//
CopyMemory( *ppPhoneCapsBuffer, (BYTE*)m_pPhoneCaps + m_pPhoneCaps->dwDevSpecificOffset, *pdwSize);
break; } default: Unlock();
LOG((TL_ERROR, "GetPhoneCapsBuffer - unknown capability type %x", pcbCaps));
return E_INVALIDARG;
break; }
Unlock();
LOG((TL_TRACE, "GetPhoneCapsBuffer - exit - return S_OK")); return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_Display
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::get_Display( BSTR *pbstrDisplay ) { HRESULT hr; LONG lResult; LPVARSTRING pVarString = NULL;
LOG((TL_TRACE, "get_Display - enter" ));
//
// check arguments
//
if ( TAPIIsBadWritePtr( pbstrDisplay, sizeof(BSTR) ) ) { LOG((TL_ERROR, "get_Display - bad pointer"));
return E_POINTER; }
Lock();
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "get_Display - phone not open"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
hr = PhoneGetDisplay(m_hPhone, &pVarString);
Unlock();
if (FAILED(hr)) { LOG((TL_ERROR, "get_Display - failed to get display. hr = %lx", hr));
if (NULL != pVarString) { ClientFree(pVarString); }
return hr; } //
// succeeded. extract display information and place it in the the output bstr
//
hr = S_OK;
switch (pVarString->dwStringFormat) { case STRINGFORMAT_ASCII: { int nWCHARSNeeded = MultiByteToWideChar(CP_ACP, 0, (char*)((BYTE*)pVarString + pVarString->dwStringOffset), pVarString->dwStringSize, NULL, 0);
if (0 == nWCHARSNeeded) { LOG((TL_ERROR, "get_Display - failed to get the size of the buffer needed for the display. LastError = %lx", GetLastError()));
hr = E_FAIL;
break; } //
// allocate the buffer required for conversion
//
LPWSTR lpWideCharStr = (LPWSTR)ClientAlloc(sizeof(WCHAR) * nWCHARSNeeded);
if (NULL == lpWideCharStr) { LOG((TL_ERROR, "get_Display - failed to allocate memory for lpWideCharStr" ));
hr = E_OUTOFMEMORY;
break; }
//
// perform conversion
//
int nResult = MultiByteToWideChar(CP_ACP, 0, (char*)((BYTE*)pVarString + pVarString->dwStringOffset), pVarString->dwStringSize, lpWideCharStr, nWCHARSNeeded);
if (0 == nResult) { LOG((TL_ERROR, "get_Display - failed to convert string to wchar. last error %lx", GetLastError()));
ClientFree(lpWideCharStr);
hr = E_FAIL;
break; }
//
// allocate bstr and initialize it with the converted string
//
*pbstrDisplay = SysAllocString(lpWideCharStr); //
// no longer need the wchar string -- we hope the data is in bstr
//
ClientFree(lpWideCharStr);
if (NULL == *pbstrDisplay) { LOG((TL_ERROR, "get_Display - failed to allocate memory for bstr"));
hr = E_OUTOFMEMORY;
break; } }
break; case STRINGFORMAT_BINARY:
//
// allocate bstr and copy data as is
//
*pbstrDisplay = SysAllocStringByteLen(NULL, pVarString->dwStringSize);
if (NULL == *pbstrDisplay) { LOG((TL_ERROR, "get_Display - failed to allocate memory for bstr"));
hr = E_OUTOFMEMORY;
break; }
CopyMemory(*pbstrDisplay, ((BYTE*)pVarString + pVarString->dwStringOffset), pVarString->dwStringSize);
break;
case STRINGFORMAT_DBCS:
LOG((TL_ERROR, "get_Display - unsupported string format"));
hr = E_FAIL;
break;
case STRINGFORMAT_UNICODE: { WCHAR *pwcDisplay = (WCHAR*)((BYTE*)pVarString + pVarString->dwStringOffset);
*pbstrDisplay = SysAllocString(pwcDisplay);
if (NULL == *pbstrDisplay) { LOG((TL_ERROR, "get_Display - failed to allocate memory for bstr"));
hr = E_OUTOFMEMORY;
break; } }
break; default:
ClientFree(pVarString); pVarString = NULL;
LOG((TL_ERROR, "get_Display - tapisrv returned unrecognized string type %lx", pVarString->dwStringFormat));
hr = E_FAIL;
break; }
ClientFree(pVarString); pVarString = NULL;
LOG((TL_TRACE, "get_Display - exit - return %lx", hr)); return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// SetDisplay
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::SetDisplay( long lRow, long lColumn, BSTR bstrDisplay ) { HRESULT hr;
LOG((TL_TRACE, "SetDisplay - enter" ));
if (bstrDisplay == NULL) { LOG((TL_ERROR, "SetDisplay - invalid parameter", "exit E_POINTER"));
return E_POINTER; }
Lock();
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "SetDisplay - phone not open"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
//
// pass the text to tapisrv
//
hr = PhoneSetDisplay( m_hPhone, lRow, lColumn, (char*)bstrDisplay, SysStringByteLen(bstrDisplay));
Unlock();
LOG((TL_TRACE, "SetDisplay - exit - return %lx", hr)); return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_ButtonFunction
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::get_ButtonFunction( long lButtonID, PHONE_BUTTON_FUNCTION * pButtonFunction ) { HRESULT hr = S_OK; DWORD dwNumButtons; LPPHONEBUTTONINFO pButtonInfo;
LOG((TL_TRACE, "get_ButtonFunction - enter" ));
if ( TAPIIsBadWritePtr( pButtonFunction, sizeof(PHONE_BUTTON_FUNCTION) ) ) { LOG((TL_ERROR, "get_ButtonFunction - bad pointer"));
return E_POINTER; }
Lock();
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "get_ButtonFunction - phone not open")); Unlock();
return TAPI_E_PHONENOTOPEN; }
//
// get the ButtonInfo buffer
//
hr = PhoneGetButtonInfo( m_hPhone, lButtonID, &pButtonInfo );
if ( SUCCEEDED(hr) ) { switch ( pButtonInfo->dwButtonFunction ) { case PHONEBUTTONFUNCTION_ABBREVDIAL: *pButtonFunction = PBF_ABBREVDIAL; break;
case PHONEBUTTONFUNCTION_BUSY: *pButtonFunction = PBF_BUSY; break;
case PHONEBUTTONFUNCTION_BRIDGEDAPP: *pButtonFunction = PBF_BRIDGEDAPP; break;
case PHONEBUTTONFUNCTION_CALLAPP: *pButtonFunction = PBF_CALLAPP; break;
case PHONEBUTTONFUNCTION_CALLID: *pButtonFunction = PBF_CALLID; break;
case PHONEBUTTONFUNCTION_CAMPON: *pButtonFunction = PBF_CAMPON; break;
case PHONEBUTTONFUNCTION_COVER: *pButtonFunction = PBF_COVER; break;
case PHONEBUTTONFUNCTION_CONFERENCE: *pButtonFunction = PBF_CONFERENCE; break;
case PHONEBUTTONFUNCTION_CONNECT: *pButtonFunction = PBF_CONNECT; break;
case PHONEBUTTONFUNCTION_DATAOFF: *pButtonFunction = PBF_DATAOFF; break;
case PHONEBUTTONFUNCTION_DATAON: *pButtonFunction = PBF_DATAON; break;
case PHONEBUTTONFUNCTION_DATETIME: *pButtonFunction = PBF_DATETIME; break;
case PHONEBUTTONFUNCTION_DIRECTORY: *pButtonFunction = PBF_DIRECTORY; break;
case PHONEBUTTONFUNCTION_DISCONNECT: *pButtonFunction = PBF_DISCONNECT; break;
case PHONEBUTTONFUNCTION_DONOTDISTURB: *pButtonFunction = PBF_DONOTDISTURB; break;
case PHONEBUTTONFUNCTION_DROP: *pButtonFunction = PBF_DROP; break;
case PHONEBUTTONFUNCTION_FLASH: *pButtonFunction = PBF_FLASH; break;
case PHONEBUTTONFUNCTION_FORWARD: *pButtonFunction = PBF_FORWARD; break;
case PHONEBUTTONFUNCTION_HOLD: *pButtonFunction = PBF_HOLD; break;
case PHONEBUTTONFUNCTION_INTERCOM: *pButtonFunction = PBF_INTERCOM; break;
case PHONEBUTTONFUNCTION_LASTNUM: *pButtonFunction = PBF_LASTNUM; break;
case PHONEBUTTONFUNCTION_MSGINDICATOR: *pButtonFunction = PBF_MSGINDICATOR; break;
case PHONEBUTTONFUNCTION_MSGWAITOFF: *pButtonFunction = PBF_MSGWAITOFF; break;
case PHONEBUTTONFUNCTION_MSGWAITON: *pButtonFunction = PBF_MSGWAITON; break;
case PHONEBUTTONFUNCTION_MUTE: *pButtonFunction = PBF_MUTE; break;
case PHONEBUTTONFUNCTION_NIGHTSRV: *pButtonFunction = PBF_NIGHTSRV; break;
case PHONEBUTTONFUNCTION_NONE: *pButtonFunction = PBF_NONE; break;
case PHONEBUTTONFUNCTION_PARK: *pButtonFunction = PBF_PARK; break;
case PHONEBUTTONFUNCTION_PICKUP: *pButtonFunction = PBF_PICKUP; break;
case PHONEBUTTONFUNCTION_QUEUECALL: *pButtonFunction = PBF_QUEUECALL; break;
case PHONEBUTTONFUNCTION_RECALL: *pButtonFunction = PBF_RECALL; break;
case PHONEBUTTONFUNCTION_REDIRECT: *pButtonFunction = PBF_REDIRECT; break;
case PHONEBUTTONFUNCTION_REJECT: *pButtonFunction = PBF_REJECT; break;
case PHONEBUTTONFUNCTION_REPDIAL: *pButtonFunction = PBF_REPDIAL; break;
case PHONEBUTTONFUNCTION_RINGAGAIN: *pButtonFunction = PBF_RINGAGAIN; break;
case PHONEBUTTONFUNCTION_SAVEREPEAT: *pButtonFunction = PBF_SAVEREPEAT; break;
case PHONEBUTTONFUNCTION_SELECTRING: *pButtonFunction = PBF_SELECTRING; break;
case PHONEBUTTONFUNCTION_SETREPDIAL: *pButtonFunction = PBF_SETREPDIAL; break;
case PHONEBUTTONFUNCTION_SENDCALLS: *pButtonFunction = PBF_SENDCALLS; break;
case PHONEBUTTONFUNCTION_SPEAKEROFF: *pButtonFunction = PBF_SPEAKEROFF; break;
case PHONEBUTTONFUNCTION_SPEAKERON: *pButtonFunction = PBF_SPEAKERON; break;
case PHONEBUTTONFUNCTION_STATIONSPEED: *pButtonFunction = PBF_STATIONSPEED; break;
case PHONEBUTTONFUNCTION_SYSTEMSPEED: *pButtonFunction = PBF_SYSTEMSPEED; break;
case PHONEBUTTONFUNCTION_TRANSFER: *pButtonFunction = PBF_TRANSFER; break;
case PHONEBUTTONFUNCTION_UNKNOWN: *pButtonFunction = PBF_UNKNOWN; break;
case PHONEBUTTONFUNCTION_VOLUMEDOWN: *pButtonFunction = PBF_VOLUMEDOWN; break;
case PHONEBUTTONFUNCTION_VOLUMEUP: *pButtonFunction = PBF_VOLUMEUP; break;
case PHONEBUTTONFUNCTION_SEND: *pButtonFunction = PBF_SEND; break;
default: LOG((TL_ERROR, "get_ButtonFunction - bad button function"));
hr = E_FAIL; }
//
// Free the ButtonInfo buffer
//
ClientFree( pButtonInfo ); }
Unlock();
LOG((TL_TRACE, "get_ButtonFunction - exit - return %lx", hr)); return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// put_ButtonFunction
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::put_ButtonFunction( IN long lButtonID, IN PHONE_BUTTON_FUNCTION ButtonFunction ) { HRESULT hr;
LOG((TL_TRACE, "put_ButtonFunction - enter" ));
Lock();
//
// Make sure the phone is open with owner privilege.
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "put_ButtonFunction - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
if ( m_dwPrivilege != PHONEPRIVILEGE_OWNER ) { LOG((TL_ERROR, "put_ButtonFunction - wrong phone privilege - " "exit TAPI_E_NOTOWNER"));
Unlock();
return TAPI_E_NOTOWNER; }
//
// get info for this button
//
PHONEBUTTONINFO *pButtonInfo = NULL;
hr = PhoneGetButtonInfo(m_hPhone, lButtonID, &pButtonInfo);
if ( FAILED(hr) ) { LOG((TL_ERROR, "put_ButtonFunction - failed to get button info - %lx", hr));
Unlock(); return hr; }
//
// make sure the memory we got back is writeable
//
if (TAPIIsBadWritePtr(pButtonInfo, sizeof(PHONEBUTTONINFO))) { LOG((TL_ERROR, "put_ButtonFunction - PhoneGetButtonInfo returned a bad memory block"));
Unlock(); return E_UNEXPECTED; } //
// translate PHONE_BUTTON_FUNCTION to a DWORD value understood by tapisrv
//
DWORD dwButtonFunction = 0;
switch ( ButtonFunction ) { case PBF_ABBREVDIAL: dwButtonFunction = PHONEBUTTONFUNCTION_ABBREVDIAL; break;
case PBF_BUSY: dwButtonFunction = PHONEBUTTONFUNCTION_BUSY; break;
case PBF_BRIDGEDAPP: dwButtonFunction = PHONEBUTTONFUNCTION_BRIDGEDAPP; break;
case PBF_CALLAPP: dwButtonFunction = PHONEBUTTONFUNCTION_CALLAPP; break;
case PBF_CALLID: dwButtonFunction = PHONEBUTTONFUNCTION_CALLID; break;
case PBF_CAMPON: dwButtonFunction = PHONEBUTTONFUNCTION_CAMPON; break;
case PBF_COVER: dwButtonFunction = PHONEBUTTONFUNCTION_COVER; break;
case PBF_CONFERENCE: dwButtonFunction = PHONEBUTTONFUNCTION_CONFERENCE; break;
case PBF_CONNECT: dwButtonFunction = PHONEBUTTONFUNCTION_CONNECT; break;
case PBF_DATAOFF: dwButtonFunction = PHONEBUTTONFUNCTION_DATAOFF; break;
case PBF_DATAON: dwButtonFunction = PHONEBUTTONFUNCTION_DATAON; break;
case PBF_DATETIME: dwButtonFunction = PHONEBUTTONFUNCTION_DATETIME; break;
case PBF_DIRECTORY: dwButtonFunction = PHONEBUTTONFUNCTION_DIRECTORY; break;
case PBF_DISCONNECT: dwButtonFunction = PHONEBUTTONFUNCTION_DISCONNECT; break;
case PBF_DONOTDISTURB: dwButtonFunction = PHONEBUTTONFUNCTION_DONOTDISTURB; break;
case PBF_DROP: dwButtonFunction = PHONEBUTTONFUNCTION_DROP; break;
case PBF_FLASH: dwButtonFunction = PHONEBUTTONFUNCTION_FLASH; break;
case PBF_FORWARD: dwButtonFunction = PHONEBUTTONFUNCTION_FORWARD; break;
case PBF_HOLD: dwButtonFunction = PHONEBUTTONFUNCTION_HOLD; break;
case PBF_INTERCOM: dwButtonFunction = PHONEBUTTONFUNCTION_INTERCOM; break;
case PBF_LASTNUM: dwButtonFunction = PHONEBUTTONFUNCTION_LASTNUM; break;
case PBF_MSGINDICATOR: dwButtonFunction = PHONEBUTTONFUNCTION_MSGINDICATOR; break;
case PBF_MSGWAITOFF: dwButtonFunction = PHONEBUTTONFUNCTION_MSGWAITOFF; break;
case PBF_MSGWAITON: dwButtonFunction = PHONEBUTTONFUNCTION_MSGWAITON; break;
case PBF_MUTE: dwButtonFunction = PHONEBUTTONFUNCTION_MUTE; break;
case PBF_NIGHTSRV: dwButtonFunction = PHONEBUTTONFUNCTION_NIGHTSRV; break;
case PBF_NONE: dwButtonFunction = PHONEBUTTONFUNCTION_NONE; break;
case PBF_PARK: dwButtonFunction = PHONEBUTTONFUNCTION_PARK; break;
case PBF_PICKUP: dwButtonFunction = PHONEBUTTONFUNCTION_PICKUP; break;
case PBF_QUEUECALL: dwButtonFunction = PHONEBUTTONFUNCTION_QUEUECALL; break;
case PBF_RECALL: dwButtonFunction = PHONEBUTTONFUNCTION_RECALL; break;
case PBF_REDIRECT: dwButtonFunction = PHONEBUTTONFUNCTION_REDIRECT; break;
case PBF_REJECT: dwButtonFunction = PHONEBUTTONFUNCTION_REJECT; break;
case PBF_REPDIAL: dwButtonFunction = PHONEBUTTONFUNCTION_REPDIAL; break;
case PBF_RINGAGAIN: dwButtonFunction = PHONEBUTTONFUNCTION_RINGAGAIN; break;
case PBF_SAVEREPEAT: dwButtonFunction = PHONEBUTTONFUNCTION_SAVEREPEAT; break;
case PBF_SELECTRING: dwButtonFunction = PHONEBUTTONFUNCTION_SELECTRING; break;
case PBF_SETREPDIAL: dwButtonFunction = PHONEBUTTONFUNCTION_SETREPDIAL; break;
case PBF_SENDCALLS: dwButtonFunction = PHONEBUTTONFUNCTION_SENDCALLS; break;
case PBF_SPEAKEROFF: dwButtonFunction = PHONEBUTTONFUNCTION_SPEAKEROFF; break;
case PBF_SPEAKERON: dwButtonFunction = PHONEBUTTONFUNCTION_SPEAKERON; break;
case PBF_STATIONSPEED: dwButtonFunction = PHONEBUTTONFUNCTION_STATIONSPEED; break;
case PBF_SYSTEMSPEED: dwButtonFunction = PHONEBUTTONFUNCTION_SYSTEMSPEED; break;
case PBF_TRANSFER: dwButtonFunction = PHONEBUTTONFUNCTION_TRANSFER; break;
case PBF_UNKNOWN: dwButtonFunction = PHONEBUTTONFUNCTION_UNKNOWN; break;
case PBF_VOLUMEDOWN: dwButtonFunction = PHONEBUTTONFUNCTION_VOLUMEDOWN; break;
case PBF_VOLUMEUP: dwButtonFunction = PHONEBUTTONFUNCTION_VOLUMEUP; break;
case PBF_SEND: dwButtonFunction = PHONEBUTTONFUNCTION_SEND; break;
default: LOG((TL_ERROR, "put_ButtonFunction - bad ButtonFunction"));
Unlock(); ClientFree(pButtonInfo); pButtonInfo = NULL;
return E_INVALIDARG; }
//
// put the value into the structure to be passed to tapisrv
//
pButtonInfo->dwButtonFunction = dwButtonFunction;
//
// set the new button function
//
hr = PhoneSetButtonInfo(m_hPhone, lButtonID, pButtonInfo);
Unlock();
//
// free memory returned to us by PhoneGetButtonInfo
//
ClientFree(pButtonInfo); pButtonInfo = NULL;
LOG((TL_TRACE, "put_ButtonFunction - exit - return %lx", hr ));
return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_ButtonText
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::get_ButtonText( long lButtonID, BSTR * ppButtonText ) { LPPHONEBUTTONINFO pButtonInfo; HRESULT hr;
LOG((TL_TRACE, "get_ButtonText - enter" ));
if ( TAPIIsBadWritePtr( ppButtonText, sizeof(BSTR) ) ) { LOG((TL_ERROR, "get_ButtonText - bad pointer"));
return E_POINTER; }
Lock();
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "get_ButtonText - phone not open")); Unlock();
return TAPI_E_PHONENOTOPEN; }
//
// Get the ButtonInfo buffer
//
hr = PhoneGetButtonInfo( m_hPhone, lButtonID, &pButtonInfo );
if ( SUCCEEDED(hr) ) { if ( pButtonInfo->dwButtonTextSize != 0 ) { //
// Allocate the BSTR
//
*ppButtonText = SysAllocString( (LPWSTR)(((LPBYTE)(pButtonInfo)) + pButtonInfo->dwButtonTextOffset) );
if ( NULL == *ppButtonText ) { LOG((TL_ERROR, "get_ButtonText - SysAllocString Failed")); hr = E_OUTOFMEMORY; } } else { LOG((TL_ERROR, "get_ButtonText - button has no text"));
hr = E_FAIL; }
//
// Free the ButtonInfo buffer
//
ClientFree( pButtonInfo ); }
Unlock();
LOG((TL_TRACE, "get_ButtonText - exit - return %lx", hr)); return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_ButtonState
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::get_ButtonState( long lButtonID, PHONE_BUTTON_STATE * pButtonState ) { LPPHONEBUTTONINFO pButtonInfo; HRESULT hr;
LOG((TL_TRACE, "get_ButtonState - enter" ));
if ( TAPIIsBadWritePtr( pButtonState, sizeof(PHONE_BUTTON_STATE) ) ) { LOG((TL_ERROR, "get_ButtonState - bad pointer"));
return E_POINTER; }
Lock();
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "get_ButtonState - phone not open")); Unlock();
return TAPI_E_PHONENOTOPEN; }
//
// Get the ButtonInfo buffer
//
hr = PhoneGetButtonInfo( m_hPhone, lButtonID, &pButtonInfo );
if (FAILED(hr)) { LOG((TL_ERROR, "get_ButtonState - failed to get get button info")); Unlock();
return hr; }
switch (pButtonInfo->dwButtonState) { case PHONEBUTTONSTATE_UP: *pButtonState = PBS_UP; break; case PHONEBUTTONSTATE_DOWN: *pButtonState = PBS_DOWN; break; case PHONEBUTTONSTATE_UNKNOWN: *pButtonState = PBS_UNKNOWN; break; case PHONEBUTTONSTATE_UNAVAIL: *pButtonState = PBS_UNAVAIL; break; default: LOG((TL_ERROR, "get_ButtonState - bad button state"));
hr = E_FAIL; }
//
// Free the ButtonInfo buffer
//
ClientFree( pButtonInfo );
Unlock();
LOG((TL_TRACE, "get_ButtonState - exit - return %lx", hr)); return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_LampMode
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::get_LampMode( long lLampID, PHONE_LAMP_MODE* pLampMode ) { LOG((TL_TRACE, "get_LampMode - enter" ));
if ( TAPIIsBadWritePtr( pLampMode, sizeof(PHONE_LAMP_MODE) ) ) { LOG((TL_ERROR, "get_LampMode - bad pointer"));
return E_POINTER; }
Lock();
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "get_LampMode - phone not open")); Unlock();
return TAPI_E_PHONENOTOPEN; }
//
// get lamp mode from tapisrv
//
DWORD dwLampMode = 0;
HRESULT hr = PhoneGetLamp(m_hPhone, lLampID, &dwLampMode);
Unlock();
if (FAILED(hr)) { LOG((TL_ERROR, "get_LampMode - failed to get lamp mode - %lx", hr));
return hr; }
//
// map the value returned by tapisrv to tapi3.x value
//
switch (dwLampMode) { case PHONELAMPMODE_DUMMY: *pLampMode = LM_DUMMY; break;
case PHONELAMPMODE_BROKENFLUTTER: *pLampMode = LM_BROKENFLUTTER; break;
case PHONELAMPMODE_FLASH: *pLampMode = LM_FLASH; break;
case PHONELAMPMODE_FLUTTER: *pLampMode = LM_FLUTTER; break;
case PHONELAMPMODE_OFF: *pLampMode = LM_OFF; break;
case PHONELAMPMODE_STEADY: *pLampMode = LM_STEADY; break;
case PHONELAMPMODE_UNKNOWN: *pLampMode = LM_UNKNOWN; break;
case PHONELAMPMODE_WINK : *pLampMode = LM_WINK; break;
default: LOG((TL_ERROR, "get_LampMode - bad lamp mode received from tapisrv"));
return E_FAIL; }
LOG((TL_TRACE, "get_LampMode - exit - return S_OK")); return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// put_LampMode
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::put_LampMode( long lLampID, PHONE_LAMP_MODE enLampMode ) {
LOG((TL_TRACE, "put_LampMode - enter" ));
Lock();
//
// Make sure the phone is open with owner privilege.
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "put_LampMode - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
if ( m_dwPrivilege != PHONEPRIVILEGE_OWNER ) { LOG((TL_ERROR, "put_LampMode - wrong phone privilege - " "exit TAPI_E_NOTOWNER"));
Unlock();
return TAPI_E_NOTOWNER; }
//
// map PHONE_LAMP_MODE to the dword value understood by tapisrv
//
DWORD dwLampMode = 0;
switch (enLampMode) { case LM_DUMMY: dwLampMode = PHONELAMPMODE_DUMMY; break;
case LM_BROKENFLUTTER: dwLampMode = PHONELAMPMODE_BROKENFLUTTER; break;
case LM_FLASH: dwLampMode = PHONELAMPMODE_FLASH; break;
case LM_FLUTTER: dwLampMode = PHONELAMPMODE_FLUTTER; break;
case LM_OFF: dwLampMode = PHONELAMPMODE_OFF; break;
case LM_STEADY: dwLampMode = PHONELAMPMODE_STEADY; break;
case LM_UNKNOWN: dwLampMode = PHONELAMPMODE_UNKNOWN; break;
case LM_WINK: dwLampMode = PHONELAMPMODE_WINK; break;
default: LOG((TL_ERROR, "put_LampMode - unknown lamp mode"));
Unlock();
return E_INVALIDARG; }
//
// make a call to tapisrv to set lamp mode
//
HRESULT hr = PhoneSetLamp(m_hPhone, lLampID, dwLampMode);
Unlock();
LOG((TL_TRACE, "put_LampMode - exit - return %lx", hr ));
return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_HookSwitchState
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::get_HookSwitchState( PHONE_HOOK_SWITCH_DEVICE HookSwitchDevice, PHONE_HOOK_SWITCH_STATE * pHookSwitchState ) { HRESULT hr; LPPHONESTATUS pPhoneStatus; DWORD dwHookSwitchMode;
LOG((TL_TRACE, "get_HookSwitchState - enter" ));
if ( 0 == HookSwitchDevice ) { LOG((TL_ERROR, "get_HookSwitchState - invalid hookswitch")); return E_INVALIDARG; }
if ( TAPIIsBadWritePtr( pHookSwitchState, sizeof(PHONE_HOOK_SWITCH_STATE) ) ) { LOG((TL_ERROR, "get_HookSwitchState - bad pointer"));
return E_POINTER; }
Lock();
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "get_HookSwitchState - phone not open")); Unlock(); return TAPI_E_PHONENOTOPEN; }
//
// Update the phone caps cache
//
hr = UpdatePhoneCaps();
if ( FAILED(hr) ) { LOG((TL_ERROR, "get_HookSwitchState - could not get phonecaps - %lx", hr));
Unlock(); return hr; }
if ( !(m_pPhoneCaps->dwHookSwitchDevs & HookSwitchDevice) ) { LOG((TL_ERROR, "get_HookSwitchState - invalid hookswitch")); Unlock(); return TAPI_E_RESOURCEUNAVAIL; }
//
// Get the PhoneStatus buffer
//
hr = PhoneGetStatusWithAlloc(m_hPhone, &pPhoneStatus);
if ( SUCCEEDED(hr) ) { //
// get the proper hookswitch mode from the phone status struct
//
switch (HookSwitchDevice) { case PHSD_HANDSET: dwHookSwitchMode = pPhoneStatus->dwHandsetHookSwitchMode; break; case PHSD_SPEAKERPHONE: dwHookSwitchMode = pPhoneStatus->dwSpeakerHookSwitchMode; break; case PHSD_HEADSET: dwHookSwitchMode = pPhoneStatus->dwHeadsetHookSwitchMode; break; default: LOG((TL_ERROR, "get_HookSwitchState - bad HookSwitchDevice"));
hr = E_INVALIDARG; } }
if ( pPhoneStatus != NULL ) { //
// Free the PhoneStatusBuffer
//
ClientFree( pPhoneStatus ); }
if ( SUCCEEDED(hr) ) { //
// translate the hookswitch mode to a tapi3 value
//
switch (dwHookSwitchMode) { case PHONEHOOKSWITCHMODE_ONHOOK: *pHookSwitchState = PHSS_ONHOOK; break; case PHONEHOOKSWITCHMODE_MIC: *pHookSwitchState = PHSS_OFFHOOK_MIC_ONLY; break; case PHONEHOOKSWITCHMODE_SPEAKER: *pHookSwitchState = PHSS_OFFHOOK_SPEAKER_ONLY; break; case PHONEHOOKSWITCHMODE_MICSPEAKER: *pHookSwitchState = PHSS_OFFHOOK; break;
default: LOG((TL_ERROR, "get_HookSwitchState - bad dwHookSwitchMode"));
hr = E_FAIL; } }
Unlock();
LOG((TL_TRACE, "get_HookSwitchState - exit - return %lx", hr)); return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// put_HookSwitchState
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::put_HookSwitchState( PHONE_HOOK_SWITCH_DEVICE HookSwitchDevice, PHONE_HOOK_SWITCH_STATE HookSwitchState ) { DWORD dwHookSwitchMode; HRESULT hr;
LOG((TL_TRACE, "put_HookSwitchState - enter" ));
if ( 0 == HookSwitchDevice ) { LOG((TL_ERROR, "put_HookSwitchState - invalid hookswitch")); return E_INVALIDARG; }
Lock();
//
// Make sure the phone is open with owner privilege.
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "put_HookSwitchState - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
if ( m_dwPrivilege != PHONEPRIVILEGE_OWNER ) { LOG((TL_ERROR, "put_HookSwitchState - wrong phone privilege - " "exit TAPI_E_NOTOWNER"));
Unlock();
return TAPI_E_NOTOWNER; }
//
// Update the phone caps cache
//
hr = UpdatePhoneCaps();
if ( FAILED(hr) ) { LOG((TL_ERROR, "put_HookSwitchState - could not get phonecaps - %lx", hr));
Unlock(); return hr; }
if ( !(m_pPhoneCaps->dwHookSwitchDevs & HookSwitchDevice) ) { LOG((TL_ERROR, "put_HookSwitchState - invalid hookswitch")); Unlock(); return TAPI_E_RESOURCEUNAVAIL; }
//
// Translate the hookswithstate from tapi3 to tapi2 values
//
switch (HookSwitchState) { case PHSS_ONHOOK: dwHookSwitchMode = PHONEHOOKSWITCHMODE_ONHOOK; break;
case PHSS_OFFHOOK_MIC_ONLY: dwHookSwitchMode = PHONEHOOKSWITCHMODE_MIC; break;
case PHSS_OFFHOOK_SPEAKER_ONLY: dwHookSwitchMode = PHONEHOOKSWITCHMODE_SPEAKER; break;
case PHSS_OFFHOOK: dwHookSwitchMode = PHONEHOOKSWITCHMODE_MICSPEAKER; break;
default: LOG((TL_ERROR, "put_HookSwitchState - bad HookSwitchMode")); Unlock();
return E_INVALIDARG; } //
// Set the proper hookswitch
//
switch (HookSwitchDevice) { case PHSD_HANDSET: hr = PhoneSetHookSwitch(m_hPhone, PHONEHOOKSWITCHDEV_HANDSET, dwHookSwitchMode); break;
case PHSD_SPEAKERPHONE: hr = PhoneSetHookSwitch(m_hPhone, PHONEHOOKSWITCHDEV_SPEAKER, dwHookSwitchMode); break;
case PHSD_HEADSET: hr = PhoneSetHookSwitch(m_hPhone, PHONEHOOKSWITCHDEV_HEADSET, dwHookSwitchMode); break;
default: LOG((TL_ERROR, "put_HookSwitchState - bad HookSwitchDevice"));
hr = E_INVALIDARG; }
Unlock();
LOG((TL_TRACE, "put_HookSwitchState - exit - return %lx", hr)); return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// put_RingMode
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::put_RingMode( long lRingMode ) { HRESULT hr; DWORD dwDummy; DWORD dwVolume;
LOG((TL_TRACE, "put_RingMode - enter" ));
Lock();
//
// Make sure the phone is open with owner privilege.
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "put_RingMode - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
if ( m_dwPrivilege != PHONEPRIVILEGE_OWNER ) { LOG((TL_ERROR, "put_RingMode - wrong phone privilege - " "exit TAPI_E_NOTOWNER"));
Unlock();
return TAPI_E_NOTOWNER; }
hr = PhoneGetRing(m_hPhone, &dwDummy, &dwVolume);
if ( FAILED(hr) ) { LOG((TL_ERROR, "put_RingMode - PhoneGetRing failed")); Unlock(); return hr; } hr = PhoneSetRing(m_hPhone, lRingMode, dwVolume );
Unlock();
LOG((TL_TRACE, "put_RingMode - exit - return %lx", hr)); return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_RingMode
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::get_RingMode( long * plRingMode ) { HRESULT hr; DWORD dwDummy;
LOG((TL_TRACE, "get_RingMode - enter" ));
if ( TAPIIsBadWritePtr( plRingMode, sizeof(long) ) ) { LOG((TL_ERROR, "get_RingMode - bad pointer"));
return E_POINTER; }
Lock();
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "get_RingMode - phone not open")); Unlock(); return TAPI_E_PHONENOTOPEN; } hr = PhoneGetRing(m_hPhone, (LPDWORD)plRingMode, &dwDummy);
Unlock();
LOG((TL_TRACE, "get_RingMode - exit - return %lx", hr)); return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// put_RingVolume
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::put_RingVolume( long lRingVolume ) { HRESULT hr; DWORD dwDummy; DWORD dwMode;
LOG((TL_TRACE, "put_RingVolume - enter" ));
Lock();
//
// Make sure the phone is open with owner privilege.
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "put_RingVolume - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
if ( m_dwPrivilege != PHONEPRIVILEGE_OWNER ) { LOG((TL_ERROR, "put_RingVolume - wrong phone privilege - " "exit TAPI_E_NOTOWNER"));
Unlock();
return TAPI_E_NOTOWNER; }
hr = PhoneGetRing(m_hPhone, &dwMode, &dwDummy);
if ( FAILED(hr) ) { LOG((TL_ERROR, "put_RingVolume - PhoneGetRing failed")); Unlock(); return hr; } hr = PhoneSetRing(m_hPhone, dwMode, lRingVolume );
Unlock();
LOG((TL_TRACE, "put_RingVolume - exit" )); return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_RingVolume
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::get_RingVolume( long * plRingVolume ) { HRESULT hr; DWORD dwDummy;
LOG((TL_TRACE, "get_RingVolume - enter" ));
if ( TAPIIsBadWritePtr( plRingVolume, sizeof(long) ) ) { LOG((TL_ERROR, "get_RingVolume - bad pointer"));
return E_POINTER; }
Lock();
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "get_RingVolume - phone not open")); Unlock(); return TAPI_E_PHONENOTOPEN; } hr = PhoneGetRing(m_hPhone, &dwDummy, (LPDWORD)plRingVolume );
Unlock();
LOG((TL_TRACE, "get_RingVolume - exit - return %lx", hr)); return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_Privilege
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhone::get_Privilege( PHONE_PRIVILEGE * pPrivilege ) { HRESULT hr = S_OK;
LOG((TL_TRACE, "get_Privilege - enter" ));
if ( TAPIIsBadWritePtr( pPrivilege, sizeof(PHONE_PRIVILEGE) ) ) { LOG((TL_ERROR, "get_Privilege - bad pointer"));
return E_POINTER; }
Lock();
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "get_Privilege - phone not open")); Unlock(); return TAPI_E_PHONENOTOPEN; }
switch(m_dwPrivilege) { case PHONEPRIVILEGE_OWNER: *pPrivilege = PP_OWNER; break; case PHONEPRIVILEGE_MONITOR: *pPrivilege = PP_MONITOR; break; default: _ASSERTE(FALSE); hr = E_UNEXPECTED; break; }
Unlock();
LOG((TL_TRACE, "get_Privilege - exit - return %lx", hr)); return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Initialize
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HRESULT CPhone::Initialize( ITTAPI * pTAPI, HPHONEAPP hPhoneApp, DWORD dwAPIVersion, DWORD dwDeviceID ) { LPVARSTRING pVarString = NULL; LONG lResult; T3PHONE t3Phone; HRESULT hr;
LOG((TL_TRACE, "Initialize - enter" )); LOG((TL_INFO, " hPhoneApp --------->%lx", hPhoneApp )); LOG((TL_INFO, " dwAPIVersion ------>%lx", dwAPIVersion )); LOG((TL_INFO, " dwDeviceID -------->%lx", dwDeviceID ));
Lock(); //
// save relevant info
//
m_pTAPI = NULL; m_dwDeviceID = dwDeviceID; m_hPhoneApp = hPhoneApp; m_dwAPIVersion = dwAPIVersion; m_pPhoneCaps = NULL; m_hPhone = NULL; m_pdwLineDeviceIDs = NULL; m_dwNumLineDeviceIDs = 0;
try { InitializeCriticalSection( &m_csAutomatedPhoneState ); } catch(...) { LOG((TL_ERROR, "Initialize - out of memory" )); Unlock(); return E_OUTOFMEMORY; }
try { InitializeCriticalSection( &m_csToneTimer ); } catch(...) { LOG((TL_ERROR, "Initialize - out of memory" ));
DeleteCriticalSection( &m_csAutomatedPhoneState ); Unlock(); return E_OUTOFMEMORY; }
try { InitializeCriticalSection( &m_csRingTimer ); } catch(...) { LOG((TL_ERROR, "Initialize - out of memory" ));
DeleteCriticalSection( &m_csAutomatedPhoneState ); DeleteCriticalSection( &m_csToneTimer );
Unlock(); return E_OUTOFMEMORY; }
//
// allocate a buffer for the numbers gathered
//
m_wszNumbersGathered = (LPWSTR)ClientAlloc( (APC_MAX_NUMBERS_GATHERED + 1) * sizeof( WCHAR ) );
if (m_wszNumbersGathered == NULL) { LOG((TL_ERROR, "Initialize - out of memory" ));
DeleteCriticalSection( &m_csAutomatedPhoneState ); DeleteCriticalSection( &m_csToneTimer ); DeleteCriticalSection( &m_csRingTimer );
Unlock(); return E_OUTOFMEMORY; }
//
// get line device ids associated with this phone
// we need to open the phone device to do this
//
t3Phone.hPhone = NULL; t3Phone.pPhone = this;
hr = PhoneOpen(m_hPhoneApp, m_dwDeviceID, &t3Phone, m_dwAPIVersion, PHONEPRIVILEGE_MONITOR);
if ( SUCCEEDED(hr) ) { hr = PhoneGetID( t3Phone.hPhone, &pVarString, L"tapi/line" );
PhoneClose(t3Phone.hPhone);
if ( SUCCEEDED(hr) ) { m_pdwLineDeviceIDs = (DWORD *)ClientAlloc( pVarString->dwUsedSize );
if (m_pdwLineDeviceIDs == NULL) { LOG((TL_ERROR, "Initialize - out of memory" )); ClientFree( pVarString );
ClientFree( m_wszNumbersGathered ); m_wszNumbersGathered = NULL;
DeleteCriticalSection( &m_csAutomatedPhoneState ); DeleteCriticalSection( &m_csToneTimer ); DeleteCriticalSection( &m_csRingTimer );
Unlock(); return E_OUTOFMEMORY; }
CopyMemory( m_pdwLineDeviceIDs, ((LPBYTE)pVarString)+pVarString->dwStringOffset, pVarString->dwStringSize );
m_dwNumLineDeviceIDs = pVarString->dwStringSize / sizeof(DWORD);
LOG((TL_INFO, " dwNumLineDeviceIDs -->%lx", m_dwNumLineDeviceIDs )); } if ( NULL != pVarString ) { ClientFree( pVarString ); } } else { LOG((TL_ERROR, "Initialize - PhoneOpen failed %lx", hr ));
ClientFree( m_wszNumbersGathered ); m_wszNumbersGathered = NULL;
DeleteCriticalSection( &m_csAutomatedPhoneState ); DeleteCriticalSection( &m_csToneTimer ); DeleteCriticalSection( &m_csRingTimer );
Unlock(); return hr; }
m_hTimerQueue = CreateTimerQueue();
if (m_hTimerQueue == NULL) { LOG((TL_ERROR, "Initialize - CreateTimerQueue failed %lx", hr ));
ClientFree( m_wszNumbersGathered ); m_wszNumbersGathered = NULL;
if (m_pdwLineDeviceIDs != NULL) { ClientFree( m_pdwLineDeviceIDs ); m_pdwLineDeviceIDs = NULL; }
DeleteCriticalSection( &m_csAutomatedPhoneState ); DeleteCriticalSection( &m_csToneTimer ); DeleteCriticalSection( &m_csRingTimer );
Unlock(); return E_OUTOFMEMORY; }
m_hTimerEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (m_hTimerEvent == NULL) { LOG((TL_ERROR, "Initialize - CreateEvent failed %lx", hr ));
ClientFree( m_wszNumbersGathered ); m_wszNumbersGathered = NULL;
if (m_pdwLineDeviceIDs != NULL) { ClientFree( m_pdwLineDeviceIDs ); m_pdwLineDeviceIDs = NULL; }
DeleteCriticalSection( &m_csAutomatedPhoneState ); DeleteCriticalSection( &m_csToneTimer ); DeleteCriticalSection( &m_csRingTimer ); DeleteTimerQueue( m_hTimerQueue ); m_hTimerQueue = NULL;
Unlock(); return E_OUTOFMEMORY; } AddRef(); //
// Save a pointer to TAPI
//
m_pTAPI = pTAPI; m_pTAPI->AddRef();
m_fInitialized = TRUE;
Unlock();
LOG((TL_TRACE, S_OK, "Initialize - exit"));
return S_OK; }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// FinalRelease
// Clean up anything in the phone object.
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void CPhone::FinalRelease() { LOG((TL_TRACE, "FinalRelease enter, this %p", this ));
Lock();
if (m_fInitialized == TRUE) { //
// Deallocate the phone caps cache
//
InvalidatePhoneCaps();
//
// Close the phone if it is open
//
if ( m_hPhone != NULL ) { if (m_dwPrivilege == PHONEPRIVILEGE_OWNER) { if (m_fRinger == TRUE) { StopRinger(); }
if (m_Tone != PT_SILENCE) { StopTone(); }
CloseWaveDevice(); }
PhoneClose(m_hPhone); }
//
// Delete timers
//
if (m_hTimerQueue != NULL) { DeleteTimerQueue(m_hTimerQueue); m_hTimerQueue = NULL; }
if (m_hTimerEvent != NULL) { CloseHandle( m_hTimerEvent ); m_hTimerEvent = NULL; }
//
// Deallocate memory
//
if (m_wszNumbersGathered != NULL) { ClientFree( m_wszNumbersGathered ); m_wszNumbersGathered = NULL; }
if (m_pdwLineDeviceIDs != NULL) { ClientFree( m_pdwLineDeviceIDs ); m_pdwLineDeviceIDs = NULL; }
DeleteCriticalSection( &m_csAutomatedPhoneState ); DeleteCriticalSection( &m_csToneTimer ); DeleteCriticalSection( &m_csRingTimer );
if ( m_pCall != NULL ) { m_pCall->Release(); m_pCall = NULL; }
//
// Release our refernece to the Tapi object
//
if (m_pTAPI != NULL) { m_pTAPI->Release(); m_pTAPI = NULL; } }
Unlock();
LOG((TL_TRACE, "FinalRelease - exit, this %p", this )); }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// SetPhoneCapsBuffer
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void CPhone::SetPhoneCapBuffer( LPVOID pBuf ) { Lock();
//
// This allow the phone caps cache to notify us that our phone
// caps buffer has changed (or more likely it will pass us NULL
// to say out buffer has been destroyed)
//
m_pPhoneCaps = (LPPHONECAPS)pBuf; Unlock(); }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// UpdatePhoneCaps
//
// must be called in lock
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HRESULT CPhone::UpdatePhoneCaps() { HRESULT hr = S_OK;
//
// Only do something if we don't have a current phone caps buffer
//
if ( NULL == m_pPhoneCaps ) { LPPHONECAPS pTemp; CTAPI * pCTapi;
pCTapi = GetTapi(); if( NULL == pCTapi ) { LOG((TL_ERROR, "UpdatePhoneCaps - dynamic cast operation failed"));
_ASSERTE(FALSE);
hr = E_UNEXPECTED; } else { //
// Get a new buffer from the cache
//
hr = pCTapi->GetBuffer( BUFFERTYPE_PHONECAP, (UINT_PTR)this, (LPVOID*)&m_pPhoneCaps ); }
if ( FAILED(hr) ) { LOG((TL_ERROR, "UpdatePhoneCaps - GetBuffer failed - %lx", hr)); m_pPhoneCaps = NULL;
return hr; }
pTemp = m_pPhoneCaps; //
// Get the phone caps from tapi2
//
hr = PhoneGetDevCaps( m_hPhoneApp, m_dwDeviceID, m_dwAPIVersion, &m_pPhoneCaps );
if ( FAILED(hr) ) { LOG((TL_ERROR, "UpdatePhoneCaps - PhoneGetDevCaps failed - %lx", hr));
//
// Invalidate our buffer which is no good
//
InvalidatePhoneCaps();
return hr; }
//
// PhoneGetDevsCaps may have reallocated our buffer. If so, tell the tapiobject
// cache mechanism what our new buffer is.
//
if ( m_pPhoneCaps != pTemp ) { pCTapi->SetBuffer( BUFFERTYPE_PHONECAP, (UINT_PTR)this, (LPVOID)m_pPhoneCaps ); } }
return S_OK; }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// InvalidatePhoneCaps
//
// must be called in lock
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HRESULT CPhone::InvalidatePhoneCaps() { HRESULT hr = S_OK;
if ( NULL != m_pPhoneCaps ) { CTAPI * pCTapi;
pCTapi = GetTapi(); if( NULL == pCTapi ) { LOG((TL_ERROR, "InvalidatePhoneCaps - dynamic cast operation failed"));
_ASSERTE(FALSE);
hr = E_UNEXPECTED; } else { pCTapi->InvalidateBuffer( BUFFERTYPE_PHONECAP, (UINT_PTR)this ); } m_pPhoneCaps = NULL; }
return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// IsPhoneOnAddress
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
BOOL CPhone::IsPhoneOnAddress(ITAddress *pAddress) { BOOL bResult = FALSE; HRESULT hr; ITTerminalSupport * pTerminalSupport; ITMediaSupport * pMediaSupport; LONG lMediaType;
Lock();
//
// Update phone caps cache
//
hr = UpdatePhoneCaps();
if ( FAILED(hr) ) { Unlock();
LOG((TL_ERROR, "IsPhoneOnAddress - UpdatePhoneCaps failed %lx", hr )); return FALSE; }
if ( (m_dwAPIVersion >= TAPI_VERSION2_0) && (m_pPhoneCaps->dwPhoneFeatures & PHONEFEATURE_GENERICPHONE) ) { //
// We are a generic phone, therefore we
// are on any address that has a MSP and audio media types.
//
//
// get the terminal support interface
//
hr = pAddress->QueryInterface( IID_ITTerminalSupport, (void **)&pTerminalSupport );
if ( FAILED(hr) ) { Unlock();
LOG((TL_ERROR, "IsPhoneOnAddress - QueryInterface IID_ITTerminalSupport failed %lx", hr )); return FALSE; }
pTerminalSupport->Release();
//
// get the media support interface
//
hr = pAddress->QueryInterface( IID_ITMediaSupport, (void **)&pMediaSupport );
if ( FAILED(hr) ) { Unlock();
LOG((TL_ERROR, "IsPhoneOnAddress - QueryInterface IID_ITMediaSupport failed %lx", hr )); return FALSE; }
//
// get the mediatype
//
hr = pMediaSupport->get_MediaTypes(&lMediaType);
pMediaSupport->Release();
if ( FAILED(hr) ) { Unlock();
LOG((TL_ERROR, "IsPhoneOnAddress - get_MediaTypes failed %lx", hr )); return FALSE; }
//
// make sure address supports audio
//
if (lMediaType & (LINEMEDIAMODE_INTERACTIVEVOICE | LINEMEDIAMODE_AUTOMATEDVOICE)) { bResult = TRUE; } }
//
// If we haven't already decided that we support this address
// check to see if this a preferred address.
//
if ( bResult == FALSE ) { bResult = IsPhoneOnPreferredAddress(pAddress); }
Unlock();
return bResult; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// IsPhoneOnPreferredAddress
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
BOOL CPhone::IsPhoneOnPreferredAddress(ITAddress *pAddress) { BOOL bResult = FALSE; HRESULT hr; CAddress * pCAddress;
Lock();
if ( m_dwNumLineDeviceIDs > 0 ) { //
// Check out list of line device IDs to see if we are
// preferred on this address
//
pCAddress = dynamic_cast<CAddress *>(pAddress);
if (NULL == pCAddress) { Unlock();
LOG((TL_ERROR, "IsPhoneOnPreferredAddress - dynamic cast failed" )); return FALSE; }
for (int i = 0; i < m_dwNumLineDeviceIDs; i++ ) { if ( m_pdwLineDeviceIDs[i] == pCAddress->GetDeviceID() ) { //
// Yes, we matched this device ID to one in our list
//
bResult = TRUE; break; } } }
Unlock();
return bResult; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// IsPhoneUsingWaveID
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
BOOL CPhone::IsPhoneUsingWaveID(DWORD dwWaveID, TERMINAL_DIRECTION nDir) { T3PHONE t3Phone; BOOL bResult = FALSE; HRESULT hr; LPVARSTRING pVarString = NULL; DWORD dwPhoneWaveID;
//
// get wave device ids associated with this phone
// we need to open the phone device to do this
// Must use monitor privilege, because owner privilege open will
// fail if anyone happens to have the phone open as owner.
//
t3Phone.hPhone = NULL; t3Phone.pPhone = this;
Lock();
hr = PhoneOpen(m_hPhoneApp, m_dwDeviceID, &t3Phone, m_dwAPIVersion, PHONEPRIVILEGE_MONITOR);
if ( SUCCEEDED(hr) ) { switch(nDir) { case TD_CAPTURE: { hr = PhoneGetID( t3Phone.hPhone, &pVarString, L"wave/in" );
if ( SUCCEEDED(hr) ) { if (pVarString->dwStringSize == sizeof(DWORD)) { CopyMemory( &dwPhoneWaveID, ((LPBYTE)pVarString)+pVarString->dwStringOffset, pVarString->dwStringSize );
if ( dwWaveID == dwPhoneWaveID ) { LOG((TL_INFO, "IsPhoneUsingWaveID - matched phone wave capture id %d", dwPhoneWaveID )); bResult = TRUE; } } } break; }
case TD_RENDER: { hr = PhoneGetID( t3Phone.hPhone, &pVarString, L"wave/out" );
if ( SUCCEEDED(hr) ) { if (pVarString->dwStringSize == sizeof(DWORD)) { CopyMemory( &dwPhoneWaveID, ((LPBYTE)pVarString)+pVarString->dwStringOffset, pVarString->dwStringSize );
if ( dwWaveID == dwPhoneWaveID ) { LOG((TL_INFO, "IsPhoneUsingWaveID - matched phone wave render id %d", dwPhoneWaveID )); bResult = TRUE; } } } break; } }
if ( NULL != pVarString ) { ClientFree( pVarString ); }
PhoneClose(t3Phone.hPhone); } else { LOG((TL_ERROR, "IsPhoneUsingWaveID - PhoneOpen failed %lx", hr )); }
Unlock();
return bResult; }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// GetTapi
//
// private method to get the tapi object
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
CTAPI * CPhone::GetTapi() { CTAPI * p = NULL;
Lock(); if( m_pTAPI != NULL ) { p = dynamic_cast<CTAPI *>(m_pTAPI); }
Unlock();
return p; }
//
// handle dev specific message
//
void HandlePhoneDevSpecificMessage( PASYNCEVENTMSG pParams ) {
LOG((TL_INFO, "HandlePhoneDevSpecificMessage - enter"));
//
// find the phone corresponding to this event
//
CPhone *pPhone = NULL;
if (!FindPhoneObject((HPHONE)pParams->hDevice, &pPhone)) { LOG((TL_WARN, "HandlePhoneDevSpecificMessage - FindPhoneObject failed to find matching phone.")); return; }
//
// fire event
//
CPhoneDevSpecificEvent::FireEvent( pPhone, pParams->Param1, pParams->Param2, pParams->Param3 );
//
// undo findphoneobject's addref
//
pPhone->Release(); pPhone = NULL;
LOG((TL_INFO, "HandlePhoneDevSpecificMessage - exit. ")); }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// HandlePhoneButtonMessage
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
HRESULT HandlePhoneButtonMessage( PASYNCEVENTMSG pParams ) { LOG((TL_TRACE, "HandlePhoneButtonMessage - enter")); CPhone * pCPhone;
if (!FindPhoneObject((HPHONE)pParams->hDevice, &pCPhone)) { LOG((TL_TRACE, "HandlePhoneButtonMessage - bad phone handle")); return E_FAIL; }
switch ( pParams->Param3 ) { case PHONEBUTTONSTATE_DOWN:
//
// Automation event hook
//
pCPhone->Automation_ButtonDown( pParams->Param1 );
CPhoneEvent::FireEvent( pCPhone, PE_BUTTON, PBS_DOWN, (PHONE_HOOK_SWITCH_STATE)0, (PHONE_HOOK_SWITCH_DEVICE)0, 0, pParams->Param1, NULL, NULL ); break;
case PHONEBUTTONSTATE_UNAVAIL: CPhoneEvent::FireEvent( pCPhone, PE_BUTTON, PBS_UNAVAIL, (PHONE_HOOK_SWITCH_STATE)0, (PHONE_HOOK_SWITCH_DEVICE)0, 0, pParams->Param1, NULL, NULL ); break;
case PHONEBUTTONSTATE_UNKNOWN: CPhoneEvent::FireEvent( pCPhone, PE_BUTTON, PBS_UNKNOWN, (PHONE_HOOK_SWITCH_STATE)0, (PHONE_HOOK_SWITCH_DEVICE)0, 0, pParams->Param1, NULL, NULL ); break;
case PHONEBUTTONSTATE_UP:
//
// Automation event hook
//
pCPhone->Automation_ButtonUp( pParams->Param1 );
CPhoneEvent::FireEvent( pCPhone, PE_BUTTON, PBS_UP, (PHONE_HOOK_SWITCH_STATE)0, (PHONE_HOOK_SWITCH_DEVICE)0, 0, pParams->Param1, NULL, NULL ); break;
}
pCPhone->Release();
LOG((TL_TRACE, "HandlePhoneButtonMessage - exit"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// HandlePhoneStateMessage
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
HRESULT HandlePhoneStateMessage( PASYNCEVENTMSG pParams ) { LOG((TL_TRACE, "HandlePhoneStateMessage - enter"));
CPhone * pCPhone; PHONE_HOOK_SWITCH_STATE HookSwitchState;
if (!FindPhoneObject((HPHONE)pParams->hDevice, &pCPhone)) { LOG((TL_TRACE, "HandlePhoneStateMessage - bad phone handle")); return E_FAIL; }
switch( pParams->Param1 ) // PhoneState
{ case PHONESTATE_CAPSCHANGE:
pCPhone->Lock();
//
// Phone caps have changed, so invalidate out cache
//
pCPhone->InvalidatePhoneCaps();
pCPhone->Unlock();
CPhoneEvent::FireEvent( pCPhone, PE_CAPSCHANGE, (PHONE_BUTTON_STATE)0, (PHONE_HOOK_SWITCH_STATE)0, (PHONE_HOOK_SWITCH_DEVICE)0, 0, 0, NULL, NULL ); break;
case PHONESTATE_HANDSETHOOKSWITCH:
if ( pParams->Param2 == PHONEHOOKSWITCHMODE_ONHOOK ) { //
// Automation event hook
//
pCPhone->Automation_OnHook( PHSD_HANDSET ); } else { //
// Automation event hook
//
pCPhone->Automation_OffHook( PHSD_HANDSET ); }
switch (pParams->Param2) { case PHONEHOOKSWITCHMODE_ONHOOK: HookSwitchState = PHSS_ONHOOK; break; case PHONEHOOKSWITCHMODE_MIC: HookSwitchState = PHSS_OFFHOOK_MIC_ONLY; break; case PHONEHOOKSWITCHMODE_SPEAKER: HookSwitchState = PHSS_OFFHOOK_SPEAKER_ONLY; break; case PHONEHOOKSWITCHMODE_MICSPEAKER: HookSwitchState = PHSS_OFFHOOK; break;
default: LOG((TL_ERROR, "HandlePhoneStateMessage - bad HookSwitchMode")); pCPhone->Release(); return E_FAIL; }
CPhoneEvent::FireEvent( pCPhone, PE_HOOKSWITCH, (PHONE_BUTTON_STATE)0, HookSwitchState, PHSD_HANDSET, 0, 0, NULL, NULL ); break;
case PHONESTATE_HEADSETHOOKSWITCH:
if ( pParams->Param2 == PHONEHOOKSWITCHMODE_ONHOOK ) { //
// Automation event hook
//
pCPhone->Automation_OnHook( PHSD_HEADSET ); } else { //
// Automation event hook
//
pCPhone->Automation_OffHook( PHSD_HEADSET ); }
switch (pParams->Param2) { case PHONEHOOKSWITCHMODE_ONHOOK: HookSwitchState = PHSS_ONHOOK; break; case PHONEHOOKSWITCHMODE_MIC: HookSwitchState = PHSS_OFFHOOK_MIC_ONLY; break; case PHONEHOOKSWITCHMODE_SPEAKER: HookSwitchState = PHSS_OFFHOOK_SPEAKER_ONLY; break; case PHONEHOOKSWITCHMODE_MICSPEAKER: HookSwitchState = PHSS_OFFHOOK; break;
default: LOG((TL_ERROR, "HandlePhoneStateMessage - bad HookSwitchMode")); pCPhone->Release(); return E_FAIL; }
CPhoneEvent::FireEvent( pCPhone, PE_HOOKSWITCH, (PHONE_BUTTON_STATE)0, HookSwitchState, PHSD_HEADSET, 0, 0, NULL, NULL ); break;
case PHONESTATE_LAMP: CPhoneEvent::FireEvent( pCPhone, PE_LAMPMODE, (PHONE_BUTTON_STATE)0, (PHONE_HOOK_SWITCH_STATE)0, (PHONE_HOOK_SWITCH_DEVICE)0, 0, pParams->Param2, NULL, NULL ); break;
case PHONESTATE_RINGMODE: CPhoneEvent::FireEvent( pCPhone, PE_RINGMODE, (PHONE_BUTTON_STATE)0, (PHONE_HOOK_SWITCH_STATE)0, (PHONE_HOOK_SWITCH_DEVICE)0, pParams->Param2, 0, NULL, NULL ); break;
case PHONESTATE_RINGVOLUME: CPhoneEvent::FireEvent( pCPhone, PE_RINGVOLUME, (PHONE_BUTTON_STATE)0, (PHONE_HOOK_SWITCH_STATE)0, (PHONE_HOOK_SWITCH_DEVICE)0, 0, 0, NULL, NULL ); break;
case PHONESTATE_SPEAKERHOOKSWITCH:
if ( pParams->Param2 == PHONEHOOKSWITCHMODE_ONHOOK ) { //
// Automation event hook
//
pCPhone->Automation_OnHook( PHSD_SPEAKERPHONE ); } else { //
// Automation event hook
//
pCPhone->Automation_OffHook( PHSD_SPEAKERPHONE ); }
switch (pParams->Param2) { case PHONEHOOKSWITCHMODE_ONHOOK: HookSwitchState = PHSS_ONHOOK; break; case PHONEHOOKSWITCHMODE_MIC: HookSwitchState = PHSS_OFFHOOK_MIC_ONLY; break; case PHONEHOOKSWITCHMODE_SPEAKER: HookSwitchState = PHSS_OFFHOOK_SPEAKER_ONLY; break; case PHONEHOOKSWITCHMODE_MICSPEAKER: HookSwitchState = PHSS_OFFHOOK; break;
default: LOG((TL_ERROR, "HandlePhoneStateMessage - bad HookSwitchMode")); pCPhone->Release(); return E_FAIL; }
CPhoneEvent::FireEvent( pCPhone, PE_HOOKSWITCH, (PHONE_BUTTON_STATE)0, HookSwitchState, PHSD_SPEAKERPHONE, 0, 0, NULL, NULL ); break;
case PHONESTATE_DISPLAY: CPhoneEvent::FireEvent( pCPhone, PE_DISPLAY, (PHONE_BUTTON_STATE)0, (PHONE_HOOK_SWITCH_STATE)0, (PHONE_HOOK_SWITCH_DEVICE)0, 0, 0, NULL, NULL ); break;
default: LOG((TL_INFO, "HandlePhoneStateMessage - PHONE_STATE %lx event not handled", pParams->Param1)); }
pCPhone->Release();
LOG((TL_TRACE, "HandlePhoneStateMessage - exit"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// HandlePhoneCloseMessage
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
HRESULT HandlePhoneCloseMessage( PASYNCEVENTMSG pParams ) { LOG((TL_TRACE, "HandlePhoneCloseMessage - enter"));
CPhone * pCPhone;
if (!FindPhoneObject((HPHONE)pParams->hDevice, &pCPhone)) { LOG((TL_TRACE, "HandlePhoneCloseMessage - bad phone handle")); return E_FAIL; }
pCPhone->ForceClose();
pCPhone->Release();
LOG((TL_TRACE, "HandlePhoneCloseMessage - exit"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// ForceClose
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
void CPhone::ForceClose() { Lock();
//
// If phone isn't open then get out of here
//
if ( m_hPhone == NULL ) { Unlock();
return; }
Unlock();
//
// Close the phone
//
Close();
//
// Fire a PE_CLOSE event
//
CPhoneEvent::FireEvent( this, PE_CLOSE, (PHONE_BUTTON_STATE)0, (PHONE_HOOK_SWITCH_STATE)0, (PHONE_HOOK_SWITCH_DEVICE)0, 0, 0, NULL, NULL ); }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// ITAutomatedPhoneControl implementation
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// Automation_CallState
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
void CPhone::Automation_CallState( ITCallInfo * pCall, CALL_STATE cs, CALL_STATE_EVENT_CAUSE cause ) { LOG((TL_TRACE, "Automation_CallState - enter"));
EnterCriticalSection(&m_csAutomatedPhoneState);
LOG((TL_INFO, "Automation_CallState - phone[%p]", this)); LOG((TL_INFO, "Automation_CallState - selected call [%p]", m_pCall)); LOG((TL_INFO, "Automation_CallState - current phone state [%d]", m_AutomatedPhoneState)); LOG((TL_INFO, "Automation_CallState - phone control enabled [%s]", m_fPhoneHandlingEnabled ? "TRUE" : "FALSE")); LOG((TL_INFO, "Automation_CallState - new call state [%d]", cs));
if (m_fPhoneHandlingEnabled) { if ( pCall == m_pCall ) { switch( cs ) {
case CS_IDLE: LOG((TL_INFO, "Automation_CallState - CS_IDLE")); break;
case CS_INPROGRESS: LOG((TL_INFO, "Automation_CallState - CS_INPROGRESS")); switch(m_AutomatedPhoneState) { case APS_ONHOOK_IDLE: case APS_ONHOOK_RINGING_IN: { StartRinger( 0, 0 );
m_AutomatedPhoneState = APS_ONHOOK_RINGING_OUT; } break; case APS_OFFHOOK_DIALTONE: case APS_OFFHOOK_WARNING: case APS_OFFHOOK_DIALING: case APS_OFFHOOK_DEAD_LINE: case APS_OFFHOOK_CALL_INIT: case APS_OFFHOOK_BUSY_TONE: { StartTone( PT_RINGBACK, 0);
m_AutomatedPhoneState = APS_OFFHOOK_RINGING_OUT; } break; } break;
case CS_CONNECTED: LOG((TL_INFO, "Automation_CallState - CS_CONNECTED")); switch(m_AutomatedPhoneState) { case APS_OFFHOOK_CALL_INIT: { m_AutomatedPhoneState = APS_OFFHOOK_CONNECTED; } break; case APS_OFFHOOK_RINGING_OUT: { // stop ringback
StopTone();
m_AutomatedPhoneState = APS_OFFHOOK_CONNECTED; } break; case APS_ONHOOK_RINGING_OUT: { m_AutomatedPhoneState = APS_ONHOOK_CONNECTED; } break; case APS_ONHOOK_IDLE: { StartRinger( 0, 0 );
m_AutomatedPhoneState = APS_ONHOOK_CONNECTED; } break; case APS_ONHOOK_RINGING_IN: { m_AutomatedPhoneState = APS_ONHOOK_CONNECTED; } break; case APS_OFFHOOK_DIALTONE: case APS_OFFHOOK_WARNING: case APS_OFFHOOK_DIALING: case APS_OFFHOOK_DEAD_LINE: case APS_OFFHOOK_BUSY_TONE: { // An app shouldn't do this to us, but stop the
// tone and move to the connected state
StopTone();
m_AutomatedPhoneState = APS_OFFHOOK_CONNECTED; } } break;
case CS_DISCONNECTED: LOG((TL_INFO, "Automation_CallState - CS_DISCONNECTED")); switch(m_AutomatedPhoneState) { case APS_ONHOOK_RINGING_IN: case APS_ONHOOK_RINGING_OUT: case APS_ONHOOK_CONNECTED: { //
// Stop the ringer
//
if (m_fRinger == TRUE) { StopRinger(); }
// unselect the call
InternalUnselectCall( pCall );
m_AutomatedPhoneState = APS_ONHOOK_IDLE; } break; case APS_ONHOOK_IDLE: { // unselect the call
InternalUnselectCall( pCall ); } break; case APS_OFFHOOK_DIALTONE: case APS_OFFHOOK_DIALING: case APS_OFFHOOK_RINGING_OUT: case APS_OFFHOOK_CALL_INIT: case APS_OFFHOOK_CONNECTED: { switch( cause ) { case CEC_DISCONNECT_BUSY: { // start busy tone
StartTone( PT_BUSY, 0 );
m_AutomatedPhoneState = APS_OFFHOOK_BUSY_TONE; } break; case CEC_DISCONNECT_NORMAL: { // stop any playing tone
StopTone();
m_AutomatedPhoneState = APS_OFFHOOK_DEAD_LINE; } break; default: { // start error tone
StartTone( PT_ERRORTONE, 0 );
m_AutomatedPhoneState = APS_OFFHOOK_WARNING; } }
// unselect the call
InternalUnselectCall( pCall ); } break; } break;
case CS_OFFERING: LOG((TL_INFO, "Automation_CallState - CS_OFFERING")); switch(m_AutomatedPhoneState) { case APS_ONHOOK_IDLE: case APS_ONHOOK_RINGING_OUT: { StartRinger( 0, 0 );
m_AutomatedPhoneState = APS_ONHOOK_RINGING_IN; } break; case APS_OFFHOOK_DIALTONE: case APS_OFFHOOK_WARNING: case APS_OFFHOOK_DIALING: case APS_OFFHOOK_DEAD_LINE: case APS_OFFHOOK_CALL_INIT: case APS_OFFHOOK_BUSY_TONE: { StopTone();
ITBasicCallControl * pCallBCC; ITCallInfo * pCall;
HRESULT hr;
pCall = m_pCall; pCall->AddRef();
hr = pCall->QueryInterface( IID_ITBasicCallControl, (void **) & pCallBCC );
if ( SUCCEEDED(hr) ) { LeaveCriticalSection(&m_csAutomatedPhoneState);
hr = pCallBCC->Answer();
pCallBCC->Release(); if ( FAILED(hr) ) { LOG((TL_ERROR, "Automation_CallState - Answer failed %08x", hr )); } else { CPhoneEvent::FireEvent( this, PE_ANSWER, (PHONE_BUTTON_STATE)0, (PHONE_HOOK_SWITCH_STATE)0, (PHONE_HOOK_SWITCH_DEVICE)0, 0, 0, NULL, pCall ); }
pCall->Release(); EnterCriticalSection(&m_csAutomatedPhoneState); }
m_AutomatedPhoneState = APS_OFFHOOK_CALL_INIT; } break; } break;
case CS_HOLD: LOG((TL_INFO, "Automation_CallState - CS_HOLD")); break;
case CS_QUEUED: LOG((TL_INFO, "Automation_CallState - CS_QUEUED")); break; } } } //m_fPhoneHandlingEnabled
LOG((TL_INFO, "Automation_CallState - new phone state [%d]", m_AutomatedPhoneState));
LeaveCriticalSection(&m_csAutomatedPhoneState);
LOG((TL_TRACE, "Automation_CallState - exit")); }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// Automation_EndOfNumberTimeout
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
void CPhone::Automation_EndOfNumberTimeout() { LOG((TL_TRACE, "Automation_EndOfNumberTimeout - enter"));
EnterCriticalSection(&m_csAutomatedPhoneState);
if (m_fPhoneHandlingEnabled && m_dwAutoEndOfNumberTimeout) { if (m_hAutoEndOfNumberTimer) // make sure the timer hasn't been cancelled
// while waiting for the critical section
{ switch (m_AutomatedPhoneState) { case APS_OFFHOOK_DIALING: { //
// We need to fire and event with the number we have
// collected
//
CPhoneEvent::FireEvent( this, PE_NUMBERGATHERED, (PHONE_BUTTON_STATE)0, (PHONE_HOOK_SWITCH_STATE)0, (PHONE_HOOK_SWITCH_DEVICE)0, 0, 0, m_wszNumbersGathered, NULL );
m_AutomatedPhoneState = APS_OFFHOOK_CALL_INIT; } break; } } } //m_fPhoneHandlingEnabled
LeaveCriticalSection(&m_csAutomatedPhoneState);
LOG((TL_TRACE, "Automation_EndOfNumberTimeout - exit")); }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// Automation_ButtonDown
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
void CPhone::Automation_ButtonDown( DWORD dwButtonId ) { PHONE_BUTTON_MODE ButtonMode; WCHAR wszNumber[11]; // enough to hold a big number in case dwButtonId is bad
HRESULT hr; BOOL fResult;
LOG((TL_TRACE, "Automation_ButtonDown - enter"));
EnterCriticalSection(&m_csAutomatedPhoneState);
if (m_fPhoneHandlingEnabled) { hr = get_ButtonMode((LONG)dwButtonId, &ButtonMode);
if ( SUCCEEDED(hr) ) { if (ButtonMode == PBM_KEYPAD) { switch (m_AutomatedPhoneState) { case APS_OFFHOOK_DIALTONE: { if (m_fAutoDialtone) { // Stop the dial tone
StopTone(); }
CPhoneEvent::FireEvent( this, PE_DIALING, (PHONE_BUTTON_STATE)0, (PHONE_HOOK_SWITCH_STATE)0, (PHONE_HOOK_SWITCH_DEVICE)0, 0, 0, NULL, NULL ); m_AutomatedPhoneState = APS_OFFHOOK_DIALING; } // Fall Thru
case APS_OFFHOOK_DIALING: { // Kill auto end of number timer
if (m_hAutoEndOfNumberTimer) { DeleteTimerQueueTimer(m_hTimerQueue, m_hAutoEndOfNumberTimer, m_hTimerEvent // non-blocking
);
m_hAutoEndOfNumberTimer = NULL; }
if ( dwButtonId <= 10 ) // digit key
{ //
// We have a dialed digit. Append it to the phone
// number we have so far.
//
if ( dwButtonId == 10) // star
{ wsprintfW(wszNumber, L"*"); } else // regular digit
{ wsprintfW(wszNumber, L"%d", dwButtonId); }
if ( (lstrlenW(m_wszNumbersGathered) + lstrlenW(wszNumber)) < APC_MAX_NUMBERS_GATHERED ) { lstrcatW(m_wszNumbersGathered, wszNumber); } LOG((TL_INFO, "Automation_ButtonDown - '%s'", wszNumber)); } else if ( dwButtonId == 11 ) // pound key
{ LOG((TL_INFO, "Automation_ButtonDown - '#'"));
// Kill auto end of number timer
if (m_hAutoEndOfNumberTimer) { DeleteTimerQueueTimer(m_hTimerQueue, m_hAutoEndOfNumberTimer, m_hTimerEvent // non-blocking
);
m_hAutoEndOfNumberTimer = NULL; }
//
// We have dialed a #. Send a number gathered event
//
CPhoneEvent::FireEvent( this, PE_NUMBERGATHERED, (PHONE_BUTTON_STATE)0, (PHONE_HOOK_SWITCH_STATE)0, (PHONE_HOOK_SWITCH_DEVICE)0, 0, 0, m_wszNumbersGathered, NULL );
m_AutomatedPhoneState = APS_OFFHOOK_CALL_INIT; } } // Fall Thru
case APS_OFFHOOK_WARNING: case APS_OFFHOOK_DEAD_LINE: case APS_OFFHOOK_CALL_INIT: case APS_OFFHOOK_CONNECTED: case APS_OFFHOOK_BUSY_TONE: case APS_OFFHOOK_RINGING_OUT: { if (m_fAutoKeypadTones) { // Kill DTMF timer
if (m_hDTMFTimer) { DeleteTimerQueueTimer(m_hTimerQueue, m_hDTMFTimer, INVALID_HANDLE_VALUE // blocking
);
m_hDTMFTimer = NULL; }
// Stop the old DTMF tone
if (m_DTMF != PT_SILENCE) { m_WavePlayer.StopTone( (long) m_DTMF); }
// Play the DTMF tone
m_WavePlayer.StartTone( (long) dwButtonId ); m_DTMF = (PHONE_TONE) dwButtonId; m_dwDTMFStart = GetTickCount(); } } break; } } else if ( ButtonMode == PBM_FEATURE ) { PHONE_BUTTON_FUNCTION ButtonFunction;
hr = get_ButtonFunction((LONG)dwButtonId, &ButtonFunction);
if ( SUCCEEDED(hr) ) { switch (ButtonFunction) { case PBF_VOLUMEUP: { DWORD dwVolume;
LOG((TL_INFO, "Automation_ButtonDown - VOLUMEUP")); if (m_fAutoVolumeControl) { // Kill volume timer
if (m_hVolumeTimer) { DeleteTimerQueueTimer(m_hTimerQueue, m_hVolumeTimer, INVALID_HANDLE_VALUE // blocking
);
m_hVolumeTimer = NULL; }
hr = m_WavePlayer.GetVolume( &dwVolume );
if ( SUCCEEDED(hr) ) { dwVolume += m_dwAutoVolumeControlStep;
if (dwVolume > 0xFFFF) dwVolume = 0xFFFF;
hr = m_WavePlayer.SetVolume( dwVolume );
if ( SUCCEEDED(hr) ) { LOG((TL_INFO, "Automation_ButtonDown - Volume: %d", dwVolume));
m_fVolumeUp = TRUE;
fResult = CreateTimerQueueTimer(&m_hVolumeTimer, m_hTimerQueue, &CPhone::VolumeTimerCallback, (PVOID)this, max(m_dwAutoVolumeControlRepeatDelay,m_dwAutoVolumeControlRepeatPeriod), m_dwAutoVolumeControlRepeatPeriod, WT_EXECUTEINIOTHREAD );
if (fResult == FALSE) { // CreateTimerQueueTimer failed, not much to do but log the error
LOG((TL_ERROR, "Automation_ButtonDown - CreateTimerQueueTimer failed - %lx", GetLastError())); } } } } } break;
case PBF_VOLUMEDOWN: { DWORD dwVolume;
LOG((TL_INFO, "Automation_ButtonDown - VOLUMEDOWN"));
if (m_fAutoVolumeControl) { // Kill volume timer
if (m_hVolumeTimer) { DeleteTimerQueueTimer(m_hTimerQueue, m_hVolumeTimer, INVALID_HANDLE_VALUE // blocking
);
m_hVolumeTimer = NULL; }
hr = m_WavePlayer.GetVolume( &dwVolume ); if ( SUCCEEDED(hr) ) { dwVolume -= m_dwAutoVolumeControlStep;
if (dwVolume > 0xFFFF) dwVolume = 0x0000;
hr = m_WavePlayer.SetVolume( dwVolume );
if ( SUCCEEDED(hr) ) { LOG((TL_INFO, "Automation_ButtonDown - Volume: %d", dwVolume));
m_fVolumeUp = FALSE;
fResult = CreateTimerQueueTimer(&m_hVolumeTimer, m_hTimerQueue, &CPhone::VolumeTimerCallback, (PVOID)this, max(m_dwAutoVolumeControlRepeatDelay,m_dwAutoVolumeControlRepeatPeriod), m_dwAutoVolumeControlRepeatPeriod, WT_EXECUTEINIOTHREAD );
if (fResult == FALSE) { // CreateTimerQueueTimer failed, not much to do but log the error
LOG((TL_ERROR, "Automation_ButtonDown - CreateTimerQueueTimer failed - %lx", GetLastError())); } } } } } break;
case PBF_SEND: { LOG((TL_INFO, "Automation_ButtonDown - PBF_SEND"));
switch (m_AutomatedPhoneState) { case APS_OFFHOOK_DIALING: { // Kill auto end of number timer
if (m_hAutoEndOfNumberTimer) { DeleteTimerQueueTimer(m_hTimerQueue, m_hAutoEndOfNumberTimer, m_hTimerEvent // non-blocking
);
m_hAutoEndOfNumberTimer = NULL; }
//
// We have pressed send. Send a number gathered event.
//
CPhoneEvent::FireEvent( this, PE_NUMBERGATHERED, (PHONE_BUTTON_STATE)0, (PHONE_HOOK_SWITCH_STATE)0, (PHONE_HOOK_SWITCH_DEVICE)0, 0, 0, m_wszNumbersGathered, NULL );
m_AutomatedPhoneState = APS_OFFHOOK_CALL_INIT; } break; } // switch (m_AutomatedPhoneState)
} break; } // switch (ButtonFunction)
} } } } //m_fPhoneHandlingEnabled
LeaveCriticalSection(&m_csAutomatedPhoneState);
LOG((TL_TRACE, "Automation_ButtonDown - exit")); }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
void CPhone::Automation_ButtonUp( DWORD dwButtonId ) { PHONE_BUTTON_MODE ButtonMode; HRESULT hr; BOOL fResult;
LOG((TL_TRACE, "Automation_ButtonUp - enter"));
EnterCriticalSection(&m_csAutomatedPhoneState);
if (m_fPhoneHandlingEnabled) { hr = get_ButtonMode((LONG)dwButtonId, &ButtonMode);
if ( SUCCEEDED(hr) ) { if ( ButtonMode == PBM_KEYPAD ) { switch (m_AutomatedPhoneState) { case APS_OFFHOOK_DIALING: { if ( dwButtonId <= 10 ) // digit key
{ if (m_dwAutoEndOfNumberTimeout) { fResult = CreateTimerQueueTimer(&m_hAutoEndOfNumberTimer, m_hTimerQueue, &CPhone::AutoEndOfNumberTimerCallback, (PVOID)this, m_dwAutoEndOfNumberTimeout, 0, WT_EXECUTEINIOTHREAD );
if (fResult == FALSE) { // CreateTimerQueueTimer failed, not much to do but log the error
LOG((TL_ERROR, "Automation_ButtonUp - CreateTimerQueueTimer failed - %lx", GetLastError())); } } } } // Fall Thru
case APS_OFFHOOK_CONNECTED: case APS_OFFHOOK_CALL_INIT: case APS_OFFHOOK_DEAD_LINE: case APS_OFFHOOK_DIALTONE: case APS_OFFHOOK_WARNING: case APS_OFFHOOK_BUSY_TONE: case APS_OFFHOOK_RINGING_OUT: { if (m_fAutoKeypadTones) { if ((PHONE_TONE)dwButtonId == m_DTMF) { DWORD dwElapsed = GetTickCount() - m_dwDTMFStart;
if ( dwElapsed > m_dwAutoKeypadTonesMinimumDuration ) { // Stop the DTMF tone
m_WavePlayer.StopTone( (long) m_DTMF); m_DTMF = PT_SILENCE; } else { // Limit the DTMF tone
fResult = CreateTimerQueueTimer(&m_hDTMFTimer, m_hTimerQueue, &CPhone::DTMFTimerCallback, (PVOID)this, m_dwAutoKeypadTonesMinimumDuration - dwElapsed, 0, WT_EXECUTEINIOTHREAD );
if (fResult == FALSE) { // CreateTimerQueueTimer failed, not much to do but log the error
LOG((TL_ERROR, "Automation_ButtonUp - CreateTimerQueueTimer failed - %lx", GetLastError())); } } } } } break; } } else if ( ButtonMode == PBM_FEATURE ) { PHONE_BUTTON_FUNCTION ButtonFunction;
hr = get_ButtonFunction((LONG)dwButtonId, &ButtonFunction);
if ( SUCCEEDED(hr) ) { switch (ButtonFunction) { case PBF_VOLUMEUP: { DWORD dwVolume;
LOG((TL_INFO, "Automation_ButtonUp - VOLUMEUP")); if (m_fAutoVolumeControl) { // Kill volume timer
if (m_hVolumeTimer) { DeleteTimerQueueTimer(m_hTimerQueue, m_hVolumeTimer, INVALID_HANDLE_VALUE // blocking
);
m_hVolumeTimer = NULL; } } } break;
case PBF_VOLUMEDOWN: { DWORD dwVolume;
LOG((TL_INFO, "Automation_ButtonUp - VOLUMEDOWN"));
if (m_fAutoVolumeControl) { // Kill volume timer
if (m_hVolumeTimer) { DeleteTimerQueueTimer(m_hTimerQueue, m_hVolumeTimer, INVALID_HANDLE_VALUE // blocking
);
m_hVolumeTimer = NULL; } } } break; } } } } } //m_fPhoneHandlingEnabled
LeaveCriticalSection(&m_csAutomatedPhoneState);
LOG((TL_TRACE, "Automation_ButtonUp - exit")); }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
void CPhone::Automation_OnHook( PHONE_HOOK_SWITCH_DEVICE phsd ) { LOG((TL_TRACE, "Automation_OnHook - enter"));
EnterCriticalSection(&m_csAutomatedPhoneState);
if (m_fPhoneHandlingEnabled) { if (m_dwOffHookCount > 0) m_dwOffHookCount--;
if (m_dwOffHookCount == 0) { switch (m_AutomatedPhoneState) { case APS_ONHOOK_IDLE: case APS_ONHOOK_RINGING_IN: case APS_ONHOOK_CONNECTED: case APS_ONHOOK_RINGING_OUT: { //
// Something is wrong!! Most likely this phone was offhook on startup, but told
// us it was onhook. Lets clean up the best we can
//
LOG((TL_WARN, "Automation_OnHook - Phone is already in onhook state!" ));
if (m_fAutoStopTonesOnOnHook) { // Kill DTMF timer
if (m_hDTMFTimer) { DeleteTimerQueueTimer(m_hTimerQueue, m_hDTMFTimer, INVALID_HANDLE_VALUE // blocking
);
m_hDTMFTimer = NULL; }
// Stop any DTMF that may be playing
if (m_DTMF != PT_SILENCE) { // Stop the DTMF tone
m_WavePlayer.StopTone( (long) m_DTMF ); m_DTMF = PT_SILENCE; }
// Stop any tone that may be playing
StopTone(); }
m_AutomatedPhoneState = APS_ONHOOK_IDLE; } break;
case APS_OFFHOOK_DIALTONE: case APS_OFFHOOK_WARNING: case APS_OFFHOOK_DEAD_LINE: case APS_OFFHOOK_DIALING: case APS_OFFHOOK_CONNECTED: case APS_OFFHOOK_CALL_INIT: case APS_OFFHOOK_BUSY_TONE: case APS_OFFHOOK_RINGING_OUT: { if (m_fAutoStopTonesOnOnHook) { // Kill DTMF timer
if (m_hDTMFTimer) { DeleteTimerQueueTimer(m_hTimerQueue, m_hDTMFTimer, INVALID_HANDLE_VALUE // blocking
);
m_hDTMFTimer = NULL; }
// Stop any DTMF that may be playing
if (m_DTMF != PT_SILENCE) { // Stop the DTMF tone
m_WavePlayer.StopTone( (long) m_DTMF ); m_DTMF = PT_SILENCE; }
// Stop any tone that may be playing
StopTone(); }
// Kill automated end of number timer
if (m_hAutoEndOfNumberTimer) { DeleteTimerQueueTimer(m_hTimerQueue, m_hAutoEndOfNumberTimer, m_hTimerEvent // non-blocking
);
m_hAutoEndOfNumberTimer = NULL; }
if (m_pCall) { CALL_STATE cs; HRESULT hr;
hr = m_pCall->get_CallState( &cs );
if ( SUCCEEDED(hr) ) { if ( cs != CS_DISCONNECTED ) { ITBasicCallControl * pCallBCC; ITCallInfo * pCall;
pCall = m_pCall; pCall->AddRef();
hr = pCall->QueryInterface( IID_ITBasicCallControl, (void **) & pCallBCC );
if ( SUCCEEDED(hr) ) { LeaveCriticalSection(&m_csAutomatedPhoneState);
hr = pCallBCC->Disconnect( DC_NORMAL );
pCallBCC->Release(); if ( FAILED(hr) ) { LOG((TL_ERROR, "Automation_OnHook - Disconnect failed %08x", hr )); } else { CPhoneEvent::FireEvent( this, PE_DISCONNECT, (PHONE_BUTTON_STATE)0, (PHONE_HOOK_SWITCH_STATE)0, (PHONE_HOOK_SWITCH_DEVICE)0, 0, 0, NULL, pCall ); }
pCall->Release(); EnterCriticalSection(&m_csAutomatedPhoneState); } } else { // If we are already disconnected we can unselect the call, otherwise
// the CS_DISCONNECT event will do it for us.
InternalUnselectCall( m_pCall ); } } }
m_AutomatedPhoneState = APS_ONHOOK_IDLE; } break; } } } //m_fPhoneHandlingEnabled
LeaveCriticalSection(&m_csAutomatedPhoneState);
LOG((TL_TRACE, "Automation_OnHook - exit")); }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
void CPhone::Automation_OffHook( PHONE_HOOK_SWITCH_DEVICE phsd ) { LOG((TL_TRACE, "Automation_OffHook - enter"));
EnterCriticalSection(&m_csAutomatedPhoneState);
if (m_fPhoneHandlingEnabled) { m_dwOffHookCount++;
// We just went offhook
if (m_dwOffHookCount == 1) { switch (m_AutomatedPhoneState) { case APS_ONHOOK_IDLE: { if (m_fAutoStopRingOnOffHook) { // Stop incoming ring
StopRinger(); } if (m_fAutoDialtone) { // Start the dialtone
StartTone( PT_NORMALDIALTONE, 0 ); }
// Clear the numbers gathered
lstrcpyW(m_wszNumbersGathered, L"");
m_AutomatedPhoneState = APS_OFFHOOK_DIALTONE; } break;
case APS_ONHOOK_RINGING_IN: { if (m_fAutoStopRingOnOffHook) { // Stop incoming ring
StopRinger(); }
if (m_pCall) { CALL_STATE cs; HRESULT hr;
hr = m_pCall->get_CallState( &cs );
if ( SUCCEEDED(hr) ) { if ( cs == CS_OFFERING ) { ITBasicCallControl * pCallBCC; ITCallInfo * pCall;
pCall = m_pCall; pCall->AddRef();
hr = pCall->QueryInterface( IID_ITBasicCallControl, (void **) & pCallBCC );
if ( SUCCEEDED(hr) ) { LeaveCriticalSection(&m_csAutomatedPhoneState);
hr = pCallBCC->Answer();
pCallBCC->Release();
if ( FAILED(hr) ) { LOG((TL_ERROR, "Automation_OffHook - Answer failed %08x", hr )); } else { CPhoneEvent::FireEvent( this, PE_ANSWER, (PHONE_BUTTON_STATE)0, (PHONE_HOOK_SWITCH_STATE)0, (PHONE_HOOK_SWITCH_DEVICE)0, 0, 0, NULL, pCall ); } pCall->Release();
EnterCriticalSection(&m_csAutomatedPhoneState); } } } }
m_AutomatedPhoneState = APS_OFFHOOK_CALL_INIT; } break;
case APS_ONHOOK_RINGING_OUT: { if (m_fAutoStopRingOnOffHook) { // Stop incoming ring
StopRinger(); }
if (m_pCall) { CALL_STATE cs; HRESULT hr;
hr = m_pCall->get_CallState( &cs );
if ( SUCCEEDED(hr) ) { switch( cs ) { case CS_INPROGRESS: { StartTone( PT_RINGBACK, 0 );
m_AutomatedPhoneState = APS_OFFHOOK_RINGING_OUT; } break;
case CS_CONNECTED: { m_AutomatedPhoneState = APS_OFFHOOK_CONNECTED; } break; } } } } break; case APS_ONHOOK_CONNECTED: { if (m_fAutoStopRingOnOffHook) { // Stop incoming ring
StopRinger(); }
m_AutomatedPhoneState = APS_OFFHOOK_CONNECTED; } break; } } } //m_fPhoneHandlingEnabled
LeaveCriticalSection(&m_csAutomatedPhoneState);
LOG((TL_TRACE, "Automation_OffHook - exit")); }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
VOID CALLBACK CPhone::ToneTimerCallback( PVOID lpParameter, BOOLEAN TimerOrWaitFired ) { CPhone * pCPhone = (CPhone *)(lpParameter);
STATICLOG((TL_TRACE, "ToneTimerCallback - enter"));
BOOL Stopped = TRUE;
if (pCPhone != NULL) { if (TryEnterCriticalSection( &pCPhone->m_csToneTimer )) { if (pCPhone->m_WavePlayer.PlayingTone( (long) pCPhone->m_Tone )) { //
// Tone was on
//
pCPhone->m_WavePlayer.StopTone( (long) pCPhone->m_Tone );
if (pCPhone->m_dwTonePeriodOn > 0) { //
// Tone is periodic
//
if (pCPhone->m_dwToneDuration > 0) { //
// Tone is periodic with limited duration
//
if ( pCPhone->m_dwToneDuration > pCPhone->m_dwTonePeriodOn ) { pCPhone->m_dwToneDuration -= pCPhone->m_dwTonePeriodOn;
if ( pCPhone->m_dwTonePeriodOff < pCPhone->m_dwToneDuration ) { //
// Remaining duration is greater than the period
//
ChangeTimerQueueTimer( pCPhone->m_hTimerQueue, pCPhone->m_hToneTimer, pCPhone->m_dwTonePeriodOff, TIMER_KEEP_ALIVE );
Stopped = FALSE; } else { //
// Remaining duration is less than the period
//
ChangeTimerQueueTimer( pCPhone->m_hTimerQueue, pCPhone->m_hToneTimer, pCPhone->m_dwToneDuration, 0 );
Stopped = FALSE; } } } else { //
// Tone is periodic with infinite duration
//
ChangeTimerQueueTimer( pCPhone->m_hTimerQueue, pCPhone->m_hToneTimer, pCPhone->m_dwTonePeriodOff, TIMER_KEEP_ALIVE );
Stopped = FALSE; } } } else { //
// Tone was off
//
if (pCPhone->m_dwTonePeriodOff > 0) { //
// Tone is periodic
//
if (pCPhone->m_dwToneDuration > 0) { //
// Tone is periodic with limited duration
//
if ( pCPhone->m_dwToneDuration > pCPhone->m_dwTonePeriodOff ) { pCPhone->m_dwToneDuration -= pCPhone->m_dwTonePeriodOff;
if ( pCPhone->m_dwTonePeriodOn < pCPhone->m_dwToneDuration ) { //
// Remaining duration is greater than the period
//
pCPhone->m_WavePlayer.StartTone( (long) pCPhone->m_Tone );
ChangeTimerQueueTimer( pCPhone->m_hTimerQueue, pCPhone->m_hToneTimer, pCPhone->m_dwTonePeriodOn, TIMER_KEEP_ALIVE );
Stopped = FALSE; } else { //
// Remaining duration is less than the period
//
pCPhone->m_WavePlayer.StartTone( (long) pCPhone->m_Tone );
ChangeTimerQueueTimer( pCPhone->m_hTimerQueue, pCPhone->m_hToneTimer, pCPhone->m_dwToneDuration, 0 );
Stopped = FALSE; } } } else { //
// Tone is periodic with infinite duration
//
pCPhone->m_WavePlayer.StartTone( (long) pCPhone->m_Tone );
ChangeTimerQueueTimer( pCPhone->m_hTimerQueue, pCPhone->m_hToneTimer, pCPhone->m_dwTonePeriodOn, TIMER_KEEP_ALIVE );
Stopped = FALSE; } } }
if (Stopped) pCPhone->m_Tone = PT_SILENCE;
LeaveCriticalSection( &pCPhone->m_csToneTimer ); } }
STATICLOG((TL_TRACE, "ToneTimerCallback - exit")); }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
VOID CALLBACK CPhone::DTMFTimerCallback( PVOID lpParameter, BOOLEAN TimerOrWaitFired ) { CPhone * pCPhone = (CPhone *)(lpParameter);
STATICLOG((TL_TRACE, "DTMFTimerCallback - enter"));
if (pCPhone != NULL) { pCPhone->m_WavePlayer.StopTone( (long) pCPhone->m_DTMF ); pCPhone->m_DTMF = PT_SILENCE; }
STATICLOG((TL_TRACE, "DTMFTimerCallback - exit")); }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
VOID CALLBACK CPhone::RingTimerCallback( PVOID lpParameter, BOOLEAN TimerOrWaitFired ) { HRESULT hr; DWORD dwDummy; DWORD dwVolume; CPhone * pCPhone = (CPhone *)(lpParameter);
STATICLOG((TL_TRACE, "RingTimerCallback - enter"));
BOOL Stopped = TRUE;
if (pCPhone != NULL) { if ( TryEnterCriticalSection( &pCPhone->m_csRingTimer )) { if ( pCPhone->m_fUseWaveForRinger ) { //
// Using wave player for ring
//
if ( pCPhone->m_dwRingDuration > 0 ) { //
// Ring has a limited duration
//
if ( pCPhone->m_dwRingDuration > pCPhone->m_dwRingPeriod ) { pCPhone->m_dwRingDuration -= pCPhone->m_dwRingPeriod;
if ( pCPhone->m_dwRingPeriod < pCPhone->m_dwRingDuration ) { //
// Remaining duration is greater than period
//
hr = pCPhone->m_WavePlayer.StartRing();
Stopped = FALSE; } else { //
// Remaining duration is less than period
//
ChangeTimerQueueTimer( pCPhone->m_hTimerQueue, pCPhone->m_hRingTimer, pCPhone->m_dwRingDuration, 0 );
hr = pCPhone->m_WavePlayer.StartRing();
Stopped = FALSE; } } } else { //
// Ring has an infinite duration
//
hr = pCPhone->m_WavePlayer.StartRing();
Stopped = FALSE; }
//
// Stop the ring if needed
//
if (Stopped) { hr = pCPhone->m_WavePlayer.StopRing(); } } else { //
// Using phone's ringer, duration must have elapsed because
// this is not periodic
//
hr = PhoneGetRing(pCPhone->m_hPhone, &dwDummy, &dwVolume);
if ( FAILED(hr) ) { STATICLOG((TL_TRACE, "RingTimerCallback - PhoneGetRing failed - %lx", hr));
LeaveCriticalSection( &pCPhone->m_csRingTimer );
return; }
hr = PhoneSetRing(pCPhone->m_hPhone, 0, dwVolume ); }
if (Stopped) { pCPhone->m_fRinger = FALSE; }
LeaveCriticalSection( &pCPhone->m_csRingTimer ); } }
STATICLOG((TL_TRACE, "RingTimerCallback - exit")); }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
VOID CALLBACK CPhone::VolumeTimerCallback( PVOID lpParameter, BOOLEAN TimerOrWaitFired ) { HRESULT hr; DWORD dwVolume; CPhone * pCPhone = (CPhone *)(lpParameter);
STATICLOG((TL_TRACE, "VolumeTimerCallback - enter"));
if (pCPhone != NULL) { hr = pCPhone->m_WavePlayer.GetVolume( &dwVolume ); if ( SUCCEEDED(hr) ) { if (pCPhone->m_fVolumeUp) { dwVolume += pCPhone->m_dwAutoVolumeControlStep;
if (dwVolume > 0xFFFF) { dwVolume = 0xFFFF; } } else { dwVolume -= pCPhone->m_dwAutoVolumeControlStep;
if (dwVolume > 0xFFFF) { dwVolume = 0x0000; } }
hr = pCPhone->m_WavePlayer.SetVolume( dwVolume );
if ( SUCCEEDED(hr) ) { STATICLOG((TL_INFO, "VolumeTimerCallback - Volume: %lx", dwVolume)); } else { STATICLOG((TL_INFO, "VolumeTimerCallback - SetVolume failed - %lx", hr)); } } else { STATICLOG((TL_INFO, "VolumeTimerCallback - GetVolume failed - %lx", hr)); } }
STATICLOG((TL_TRACE, "VolumeTimerCallback - exit")); }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
VOID CALLBACK CPhone::AutoEndOfNumberTimerCallback( PVOID lpParameter, BOOLEAN TimerOrWaitFired ) { HRESULT hr; CPhone * pCPhone = (CPhone *)(lpParameter);
STATICLOG((TL_TRACE, "AutoEndOfNumberTimerCallback - enter"));
if (pCPhone != NULL) { pCPhone->Automation_EndOfNumberTimeout(); }
STATICLOG((TL_TRACE, "AutoEndOfNumberTimerCallback - exit")); }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// GetPhoneWaveRenderID
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
HRESULT CPhone::GetPhoneWaveRenderID(DWORD * pdwWaveID) { T3PHONE t3Phone; HRESULT hr; LPVARSTRING pVarString = NULL; DWORD dwPhoneWaveID;
//
// get wave device ids associated with this phone
// we need to open the phone device to do this
// Must use monitor privilege, because owner privilege open will
// fail if anyone happens to have the phone open as owner.
//
t3Phone.hPhone = NULL; t3Phone.pPhone = this;
Lock();
hr = PhoneOpen(m_hPhoneApp, m_dwDeviceID, &t3Phone, m_dwAPIVersion, PHONEPRIVILEGE_MONITOR );
if ( SUCCEEDED(hr) ) { hr = PhoneGetID( t3Phone.hPhone, &pVarString, L"wave/out" );
if ( SUCCEEDED(hr) ) { if (pVarString->dwStringSize == sizeof(DWORD)) { CopyMemory( pdwWaveID, ((LPBYTE)pVarString)+pVarString->dwStringOffset, pVarString->dwStringSize );
LOG((TL_INFO, "GetPhoneWaveRenderID - got phone wave " "render id %d", *pdwWaveID )); } } else { LOG((TL_ERROR, "GetPhoneRenderWaveID - PhoneGetID failed %08x", hr )); }
if ( NULL != pVarString ) { ClientFree( pVarString ); }
PhoneClose(t3Phone.hPhone); } else { LOG((TL_ERROR, "GetPhoneRenderWaveID - PhoneOpen failed %08x", hr )); }
Unlock();
return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
void CPhone::OpenWaveDevice( ) { HRESULT hr;
LOG((TL_TRACE, "OpenWaveDevice - enter" ));
if (!m_WavePlayer.IsInitialized()) { hr = m_WavePlayer.Initialize();
if ( FAILED(hr) ) { LOG((TL_ERROR, "OpenWaveDevice - Initialize failed %08x", hr ));
return; } }
if (!m_WavePlayer.IsInUse()) { if (m_fUseWaveForRinger) { hr = m_WavePlayer.OpenWaveDeviceForRing( WAVE_MAPPER );
if ( FAILED(hr) ) { LOG((TL_ERROR, "OpenWaveDevice - OpenWaveDeviceForRing failed %08x", hr )); } }
long lWaveId;
hr = GetPhoneWaveRenderID( (DWORD *) & lWaveId ); if ( FAILED(hr) ) { LOG((TL_ERROR, "OpenWaveDevice - GetPhoneWaveRenderID failed %08x", hr ));
return; }
hr = m_WavePlayer.OpenWaveDeviceForTone( lWaveId );
if ( FAILED(hr) ) { LOG((TL_ERROR, "OpenWaveDevice - OpenWaveDeviceForTone failed %08x", hr )); }
hr = m_WavePlayer.OpenMixerDevice( lWaveId );
if ( FAILED(hr) ) { LOG((TL_ERROR, "OpenWaveDevice - OpenMixerDevice failed %08x", hr )); } }
LOG((TL_TRACE, "OpenWaveDevice - exit" )); }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
void CPhone::CloseWaveDevice( ) { LOG((TL_TRACE, "CloseWaveDevice - enter" ));
if (m_WavePlayer.IsInUse()) { if (m_fUseWaveForRinger) { m_WavePlayer.CloseWaveDeviceForRing(); }
m_WavePlayer.CloseWaveDeviceForTone();
m_WavePlayer.CloseMixerDevice(); }
LOG((TL_TRACE, "CloseWaveDevice - exit" )); }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// ITAutomatedPhoneControlQI
// Don't give out the ITAutomatedPhoneControl interface
// if the application does not have the phone open.
// Also, open the wave devices if owner.
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
HRESULT WINAPI CPhone::ITAutomatedPhoneControlQI(void* pv, REFIID riid, LPVOID* ppv, DWORD_PTR dw) { STATICLOG((TL_TRACE,"AutomatedPhoneControlQI - enter"));
*ppv = NULL;
CPhone * pPhone = ((CPhone *)pv);
pPhone->Lock();
if (pPhone->m_hPhone == NULL) { STATICLOG((TL_WARN,"The application does not have this phone open")); STATICLOG((TL_WARN,"so it cannot access the AutomatedPhoneControl interface"));
pPhone->Unlock();
return TAPI_E_PHONENOTOPEN; } if (pPhone->m_dwPrivilege != PHONEPRIVILEGE_OWNER) { STATICLOG((TL_WARN,"The application does not have owner privilege")); STATICLOG((TL_WARN,"so it cannot access the AutomatedPhoneControl interface"));
pPhone->Unlock();
return TAPI_E_NOTOWNER; }
HRESULT hr = pPhone->UpdatePhoneCaps();
if ( FAILED(hr) ) { STATICLOG((TL_ERROR,"UpdatePhoneCaps failed 0x%lx", hr));
pPhone->Unlock();
return hr; }
if ( ( pPhone->GetAPIVersion() < TAPI_VERSION2_0 ) || !(pPhone->m_pPhoneCaps->dwPhoneFeatures & PHONEFEATURE_GENERICPHONE) ) { STATICLOG((TL_TRACE,"The phone does not have PCL_GENERICPHONE capability")); STATICLOG((TL_TRACE,"so it cannot access the AutomatedPhoneControl interface"));
pPhone->Unlock();
return E_NOINTERFACE; }
if ( pPhone->m_pPhoneCaps->dwNumRingModes == 0) { //
// The hardware doesn't have a ringer, so use the wave
// device as a ringer
//
pPhone->m_fUseWaveForRinger = TRUE; } else { //
// Use the hardware ringer
//
pPhone->m_fUseWaveForRinger = FALSE; }
pPhone->OpenWaveDevice();
pPhone->Unlock();
//
// S_FALSE tells atl to continue querying for the interface
//
STATICLOG((TL_TRACE, "AutomatedPhoneControlQI - exit"));
return S_FALSE; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::StartTone( IN PHONE_TONE Tone, IN long lDuration ) { HRESULT hr; BOOL fResult;
LOG((TL_TRACE, "StartTone - enter"));
//
// Check arguments.
//
if ( ( Tone < PT_KEYPADZERO) || ( Tone > PT_SILENCE ) ) { LOG((TL_ERROR, "StartTone - " "invalid tone type - exit E_INVALIDARG"));
return E_INVALIDARG; } if ( lDuration < 0 ) { LOG((TL_ERROR, "StartTone - " "negative argument - exit E_INVALIDARG"));
return E_INVALIDARG; }
Lock();
//
// Make sure the phone is open with owner privilege.
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "StartTone - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
if ( m_dwPrivilege != PHONEPRIVILEGE_OWNER ) { LOG((TL_ERROR, "StartTone - wrong phone privilege - " "exit TAPI_E_NOTOWNER"));
Unlock();
return TAPI_E_NOTOWNER; } //
// Kill the tone timer
//
if (m_hToneTimer) { EnterCriticalSection( &m_csToneTimer );
DeleteTimerQueueTimer(m_hTimerQueue, m_hToneTimer, INVALID_HANDLE_VALUE // blocking
);
m_hToneTimer = NULL;
LeaveCriticalSection( &m_csToneTimer ); }
//
// Stop the old tone if there was one
//
if (m_Tone != PT_SILENCE) { m_WavePlayer.StopTone( (long) m_Tone ); m_Tone = PT_SILENCE; }
//
// Start the new tone if needed
//
if ( Tone != PT_SILENCE ) { //
// Set duration and period
//
m_dwToneDuration = lDuration;
switch ( Tone ) { case PT_BUSY: m_dwTonePeriodOn = 500; m_dwTonePeriodOff = 500; break;
case PT_RINGBACK: m_dwTonePeriodOn = 2000; m_dwTonePeriodOff = 4000; break;
case PT_ERRORTONE: m_dwTonePeriodOn = 100; m_dwTonePeriodOff = 100; break;
default: // not periodic
m_dwTonePeriodOn = 0; m_dwTonePeriodOff = 0; break; }
hr = m_WavePlayer.StartTone( (long) Tone );
if ( SUCCEEDED(hr) ) { if ( (m_dwTonePeriodOn > 0) && ((m_dwTonePeriodOn < m_dwToneDuration) || (m_dwToneDuration == 0)) ) { //
// Tone is periodic and duration is greater than the period
//
fResult = CreateTimerQueueTimer(&m_hToneTimer, m_hTimerQueue, &CPhone::ToneTimerCallback, (PVOID)this, m_dwTonePeriodOn, TIMER_KEEP_ALIVE, WT_EXECUTEINIOTHREAD );
if (fResult == FALSE) { // CreateTimerQueueTimer failed, lets stop the tone and bail out
LOG((TL_ERROR, "StartTone - CreateTimerQueueTimer failed - %lx", GetLastError()));
hr = HRESULT_FROM_WIN32(GetLastError());
m_WavePlayer.StopTone( (long) Tone ); } } else if (m_dwToneDuration > 0) { //
// Tone is not periodic, or duration is less than the period
//
fResult = CreateTimerQueueTimer(&m_hToneTimer, m_hTimerQueue, &CPhone::ToneTimerCallback, (PVOID)this, m_dwToneDuration, 0, WT_EXECUTEINIOTHREAD );
if (fResult == FALSE) { // CreateTimerQueueTimer failed, lets stop the tone and bail out
LOG((TL_ERROR, "StartTone - CreateTimerQueueTimer failed - %lx", GetLastError()));
hr = HRESULT_FROM_WIN32(GetLastError());
m_WavePlayer.StopTone( (long) Tone ); } } } if ( FAILED(hr) ) { LOG((TL_ERROR, "StartTone - exit 0x%08x", hr)); Unlock();
return hr; }
m_Tone = Tone; }
Unlock();
LOG((TL_TRACE, "StartTone - exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::StopTone() { HRESULT hr = S_OK;
LOG((TL_TRACE, "StopTone - enter"));
Lock();
//
// Make sure the phone is open with owner privilege.
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "StopTone - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
if ( m_dwPrivilege != PHONEPRIVILEGE_OWNER ) { LOG((TL_ERROR, "StopTone - wrong phone privilege - " "exit TAPI_E_NOTOWNER"));
Unlock();
return TAPI_E_NOTOWNER; }
//
// Kill the tone timer
//
if (m_hToneTimer) { EnterCriticalSection( &m_csToneTimer );
DeleteTimerQueueTimer(m_hTimerQueue, m_hToneTimer, INVALID_HANDLE_VALUE // blocking
);
m_hToneTimer = NULL;
LeaveCriticalSection( &m_csToneTimer ); }
//
// Stop the old tone if there was one
//
if (m_Tone != PT_SILENCE) { hr = m_WavePlayer.StopTone( (long) m_Tone ); m_Tone = PT_SILENCE; }
Unlock();
LOG((TL_ERROR, "StopTone - exit - return %lx", hr));
return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::get_Tone( OUT PHONE_TONE * pTone ) { LOG((TL_TRACE, "get_Tone - " "enter"));
if ( TAPIIsBadWritePtr( pTone, sizeof( PHONE_TONE ) ) ) { LOG((TL_ERROR, "get_Tone - " "bad parameter - exit E_POINTER"));
return E_POINTER; }
Lock();
//
// Make sure the phone is open
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "get_Tone - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
*pTone = m_Tone;
Unlock();
LOG((TL_TRACE, "get_Tone - " "exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::StartRinger( IN long lRingMode, IN long lDuration ) { HRESULT hr; DWORD dwDummy; DWORD dwVolume; BOOL fResult;
LOG((TL_TRACE, "StartRinger - enter")); if ( lDuration < 0 ) { LOG((TL_ERROR, "StartRinger - " "negative argument - exit E_INVALIDARG"));
return E_INVALIDARG; }
Lock();
//
// Make sure the phone is open with owner privilege.
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "StartRinger - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
if ( m_dwPrivilege != PHONEPRIVILEGE_OWNER ) { LOG((TL_ERROR, "StartRinger - wrong phone privilege - " "exit TAPI_E_NOTOWNER"));
Unlock();
return TAPI_E_NOTOWNER; }
//
// Kill ring timer
//
if (m_hRingTimer) { EnterCriticalSection( &m_csRingTimer );
DeleteTimerQueueTimer(m_hTimerQueue, m_hRingTimer, INVALID_HANDLE_VALUE // blocking
);
m_hRingTimer = NULL;
LeaveCriticalSection( &m_csRingTimer ); }
//
// Start ring and set duration and period
//
m_dwRingDuration = lDuration;
if (lRingMode == 0) { if (m_fUseWaveForRinger) { m_dwRingPeriod = 4000;
hr = m_WavePlayer.StartRing(); } else { m_dwRingPeriod = 0;
hr = put_RingMode(1); } } else { m_dwRingPeriod = 0;
hr = put_RingMode(lRingMode); }
if ( FAILED(hr) ) { LOG((TL_ERROR, "StartRinger - exit 0x%08x", hr)); Unlock();
return hr; }
if ( (m_dwRingPeriod > 0) && ((m_dwRingPeriod < m_dwRingDuration) || (m_dwRingDuration == 0)) ) { //
// Ring is periodic (wave generated) and duration is greater than the period
//
fResult = CreateTimerQueueTimer(&m_hRingTimer, m_hTimerQueue, &CPhone::RingTimerCallback, (PVOID)this, m_dwRingPeriod, m_dwRingPeriod, WT_EXECUTEINIOTHREAD );
if (fResult == FALSE) { // CreateTimerQueueTimer failed, lets stop the ring and bail out
LOG((TL_ERROR, "StartRinger - CreateTimerQueueTimer failed - %lx", GetLastError()));
hr = HRESULT_FROM_WIN32(GetLastError()); } } else if (m_dwRingDuration > 0) { //
// Ring is not periodic (ringer generated), or duration is less than period
//
fResult = CreateTimerQueueTimer(&m_hRingTimer, m_hTimerQueue, &CPhone::RingTimerCallback, (PVOID)this, m_dwRingDuration, 0, WT_EXECUTEINIOTHREAD );
if (fResult == FALSE) { // CreateTimerQueueTimer failed, lets stop the ring and bail out
LOG((TL_ERROR, "StartRinger - CreateTimerQueueTimer failed - %lx", GetLastError()));
hr = HRESULT_FROM_WIN32(GetLastError()); } }
if ( FAILED(hr) ) { if (m_fUseWaveForRinger) { m_WavePlayer.StopRing(); } else { put_RingMode(0); }
LOG((TL_ERROR, "StartRinger - exit 0x%08x", hr)); Unlock();
return hr; }
m_fRinger = TRUE;
Unlock();
LOG((TL_TRACE, "StartRinger - exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::StopRinger() { HRESULT hr; DWORD dwDummy; DWORD dwVolume;
LOG((TL_TRACE, "StopRinger - enter"));
Lock();
//
// Make sure the phone is open with owner privilege.
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "StopRinger - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
if ( m_dwPrivilege != PHONEPRIVILEGE_OWNER ) { LOG((TL_ERROR, "StopRinger - wrong phone privilege - " "exit TAPI_E_NOTOWNER"));
Unlock();
return TAPI_E_NOTOWNER; }
//
// Kill ring timer
//
if (m_hRingTimer) { EnterCriticalSection( &m_csRingTimer );
DeleteTimerQueueTimer(m_hTimerQueue, m_hRingTimer, INVALID_HANDLE_VALUE // blocking
);
m_hRingTimer = NULL;
LeaveCriticalSection( &m_csRingTimer ); }
if (m_fUseWaveForRinger) { hr = m_WavePlayer.StopRing(); } else { hr = put_RingMode( 0 ); }
if ( FAILED(hr) ) { LOG((TL_ERROR, "StopRinger - exit 0x%08x", hr));
Unlock(); return hr; }
m_fRinger = FALSE;
Unlock();
LOG((TL_TRACE, "StopRinger - exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::get_Ringer( OUT VARIANT_BOOL * pfRinging ) { LOG((TL_TRACE, "get_Ringer - " "enter"));
if ( TAPIIsBadWritePtr( pfRinging, sizeof( VARIANT_BOOL ) ) ) { LOG((TL_ERROR, "get_Ringer - " "bad parameter - exit E_POINTER"));
return E_POINTER; }
Lock();
//
// Make sure the phone is open
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "get_Ringer - phone not open")); Unlock(); return TAPI_E_PHONENOTOPEN; }
//
// Translate from BOOL to VARIANT_BOOL.
//
*pfRinging = m_fRinger ? VARIANT_TRUE : VARIANT_FALSE;
Unlock();
LOG((TL_TRACE, "get_Ringer - " "exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::put_PhoneHandlingEnabled( IN VARIANT_BOOL fEnabled ) { LOG((TL_TRACE, "put_PhoneHandlingEnabled - " "enter"));
//
// Translate from VARIANT_BOOL to BOOL. If someone mistakenly
// passes in TRUE instead of VARIANT_TRUE, we are still ok.
//
Lock();
//
// Make sure the phone is open with owner privilege.
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "put_PhoneHandlingEnabled - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
if ( m_dwPrivilege != PHONEPRIVILEGE_OWNER ) { LOG((TL_ERROR, "put_PhoneHandlingEnabled - wrong phone privilege - " "exit TAPI_E_NOTOWNER"));
Unlock();
return TAPI_E_NOTOWNER; }
//
// Make sure there is no call selected on the phone
//
if ( m_pCall != NULL ) { LOG((TL_ERROR, "put_PhoneHandlingEnabled - a call is " "selected - exit TAPI_E_INUSE"));
Unlock(); return TAPI_E_INUSE; }
EnterCriticalSection(&m_csAutomatedPhoneState); m_fPhoneHandlingEnabled = fEnabled ? TRUE : FALSE;
if (m_fPhoneHandlingEnabled) { HRESULT hr; DWORD dwHookSwitchDevs;
m_dwOffHookCount = 0;
hr = PhoneGetHookSwitch(m_hPhone, &dwHookSwitchDevs); if ( SUCCEEDED(hr) ) { if (dwHookSwitchDevs & PHONEHOOKSWITCHDEV_HANDSET) m_dwOffHookCount++; if (dwHookSwitchDevs & PHONEHOOKSWITCHDEV_SPEAKER) m_dwOffHookCount++; if (dwHookSwitchDevs & PHONEHOOKSWITCHDEV_HEADSET) m_dwOffHookCount++;
if (m_dwOffHookCount > 0) { // phone is off hook
m_AutomatedPhoneState = APS_OFFHOOK_DEAD_LINE; } else { // phone is on hook
m_AutomatedPhoneState = APS_ONHOOK_IDLE; } } else { LOG((TL_ERROR, "put_PhoneHandlingEnabled - PhoneGetHookSwitch failed - %lx", hr)); } }
LeaveCriticalSection(&m_csAutomatedPhoneState);
Unlock();
LOG((TL_TRACE, "put_PhoneHandlingEnabled - " "exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::get_PhoneHandlingEnabled( OUT VARIANT_BOOL * pfEnabled ) { LOG((TL_TRACE, "get_PhoneHandlingEnabled - " "enter"));
if ( TAPIIsBadWritePtr( pfEnabled, sizeof( VARIANT_BOOL ) ) ) { LOG((TL_ERROR, "get_PhoneHandlingEnabled - " "bad parameter - exit E_POINTER"));
return E_POINTER; }
//
// Translate from BOOL to VARIANT_BOOL.
//
Lock();
//
// Make sure the phone is open
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "get_PhoneHandlingEnabled - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
EnterCriticalSection(&m_csAutomatedPhoneState);
*pfEnabled = m_fPhoneHandlingEnabled ? VARIANT_TRUE : VARIANT_FALSE;
LeaveCriticalSection(&m_csAutomatedPhoneState);
Unlock();
LOG((TL_TRACE, "get_PhoneHandlingEnabled - " "exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::put_AutoEndOfNumberTimeout( IN long lTimeout ) { LOG((TL_TRACE, "put_AutoEndOfNumberTimeout - " "enter"));
if ( lTimeout < 0 ) { LOG((TL_ERROR, "put_AutoEndOfNumberTimeout - " "negative argument - exit E_INVALIDARG"));
return E_INVALIDARG; }
Lock();
//
// Make sure the phone is open with owner privilege
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "put_AutoEndOfNumberTimeout - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
if ( m_dwPrivilege != PHONEPRIVILEGE_OWNER ) { LOG((TL_ERROR, "put_AutoEndOfNumberTimeout - wrong phone privilege - " "exit TAPI_E_NOTOWNER"));
Unlock();
return TAPI_E_NOTOWNER; }
EnterCriticalSection(&m_csAutomatedPhoneState);
m_dwAutoEndOfNumberTimeout = lTimeout;
LeaveCriticalSection(&m_csAutomatedPhoneState);
Unlock();
LOG((TL_TRACE, "put_AutoEndOfNumberTimeout - " "exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::get_AutoEndOfNumberTimeout( OUT long * plTimeout ) { LOG((TL_TRACE, "get_AutoEndOfNumberTimeout - " "enter"));
if ( TAPIIsBadWritePtr( plTimeout, sizeof( long ) ) ) { LOG((TL_ERROR, "get_AutoEndOfNumberTimeout - " "bad parameter - exit E_POINTER"));
return E_POINTER; }
Lock();
//
// Make sure the phone is open
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "get_AutoEndOfNumberTimeout - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
EnterCriticalSection(&m_csAutomatedPhoneState);
*plTimeout = m_dwAutoEndOfNumberTimeout;
LeaveCriticalSection(&m_csAutomatedPhoneState);
Unlock();
LOG((TL_TRACE, "get_AutoEndOfNumberTimeout - " "exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::put_AutoDialtone( IN VARIANT_BOOL fEnabled ) { LOG((TL_TRACE, "put_AutoDialtone - " "enter"));
//
// Translate from VARIANT_BOOL to BOOL. If someone mistakenly
// passes in TRUE instead of VARIANT_TRUE, we are still ok.
//
Lock();
//
// Make sure the phone is open with owner privilege
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "put_AutoDialtone - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
if ( m_dwPrivilege != PHONEPRIVILEGE_OWNER ) { LOG((TL_ERROR, "put_AutoDialtone - wrong phone privilege - " "exit TAPI_E_NOTOWNER"));
Unlock();
return TAPI_E_NOTOWNER; }
EnterCriticalSection(&m_csAutomatedPhoneState);
m_fAutoDialtone = fEnabled ? TRUE : FALSE;
LeaveCriticalSection(&m_csAutomatedPhoneState);
Unlock();
LOG((TL_TRACE, "put_AutoDialtone - " "exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::get_AutoDialtone( OUT VARIANT_BOOL * pfEnabled ) { LOG((TL_TRACE, "get_AutoDialtone - " "enter"));
if ( TAPIIsBadWritePtr( pfEnabled, sizeof( VARIANT_BOOL ) ) ) { LOG((TL_ERROR, "get_AutoDialtone - " "bad parameter - exit E_POINTER"));
return E_POINTER; }
//
// Translate from BOOL to VARIANT_BOOL.
//
Lock();
//
// Make sure the phone is open
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "get_AutoDialtone - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
EnterCriticalSection(&m_csAutomatedPhoneState);
*pfEnabled = m_fAutoDialtone ? VARIANT_TRUE : VARIANT_FALSE;
LeaveCriticalSection(&m_csAutomatedPhoneState);
Unlock();
LOG((TL_TRACE, "get_AutoDialtone - " "exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::put_AutoStopTonesOnOnHook( IN VARIANT_BOOL fEnabled ) { LOG((TL_TRACE, "put_AutoStopTonesOnOnHook - " "enter"));
//
// Translate from VARIANT_BOOL to BOOL. If someone mistakenly
// passes in TRUE instead of VARIANT_TRUE, we are still ok.
//
Lock();
//
// Make sure the phone is open with owner privilege
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "put_AutoStopTonesOnOnHook - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
if ( m_dwPrivilege != PHONEPRIVILEGE_OWNER ) { LOG((TL_ERROR, "put_AutoStopTonesOnOnHook - wrong phone privilege - " "exit TAPI_E_NOTOWNER"));
Unlock();
return TAPI_E_NOTOWNER; }
EnterCriticalSection(&m_csAutomatedPhoneState);
m_fAutoStopTonesOnOnHook = fEnabled ? TRUE : FALSE;
LeaveCriticalSection(&m_csAutomatedPhoneState);
Unlock();
LOG((TL_TRACE, "put_AutoStopTonesOnOnHook - " "exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::get_AutoStopTonesOnOnHook( OUT VARIANT_BOOL * pfEnabled ) { LOG((TL_TRACE, "get_AutoStopTonesOnOnHook - " "enter"));
if ( TAPIIsBadWritePtr( pfEnabled, sizeof( VARIANT_BOOL ) ) ) { LOG((TL_ERROR, "get_AutoStopTonesOnOnHook - " "bad parameter - exit E_POINTER"));
return E_POINTER; }
//
// Translate from BOOL to VARIANT_BOOL.
//
Lock();
//
// Make sure the phone is open
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "get_AutoDialtone - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
EnterCriticalSection(&m_csAutomatedPhoneState);
*pfEnabled = m_fAutoStopTonesOnOnHook ? VARIANT_TRUE : VARIANT_FALSE;
LeaveCriticalSection(&m_csAutomatedPhoneState);
Unlock();
LOG((TL_TRACE, "get_AutoStopTonesOnOnHook - " "exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::put_AutoStopRingOnOffHook( IN VARIANT_BOOL fEnabled ) { LOG((TL_TRACE, "put_AutoStopRingOnOffHook - " "enter"));
//
// Translate from VARIANT_BOOL to BOOL. If someone mistakenly
// passes in TRUE instead of VARIANT_TRUE, we are still ok.
//
Lock();
//
// Make sure the phone is open with owner privilege
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "put_AutoStopRingOnOffHook - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
if ( m_dwPrivilege != PHONEPRIVILEGE_OWNER ) { LOG((TL_ERROR, "put_AutoStopRingOnOffHook - wrong phone privilege - " "exit TAPI_E_NOTOWNER"));
Unlock();
return TAPI_E_NOTOWNER; }
EnterCriticalSection(&m_csAutomatedPhoneState);
m_fAutoStopRingOnOffHook = fEnabled ? TRUE : FALSE;
LeaveCriticalSection(&m_csAutomatedPhoneState);
Unlock();
LOG((TL_TRACE, "put_AutoStopRingOnOffHook - " "exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::get_AutoStopRingOnOffHook( OUT VARIANT_BOOL * pfEnabled ) { LOG((TL_TRACE, "get_AutoStopRingOnOffHook - " "enter"));
if ( TAPIIsBadWritePtr( pfEnabled, sizeof( VARIANT_BOOL ) ) ) { LOG((TL_ERROR, "get_AutoStopRingOnOffHook - " "bad parameter - exit E_POINTER"));
return E_POINTER; }
//
// Translate from BOOL to VARIANT_BOOL.
//
Lock();
//
// Make sure the phone is open
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "get_AutoStopRingOnOffHook - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
EnterCriticalSection(&m_csAutomatedPhoneState);
*pfEnabled = m_fAutoStopRingOnOffHook ? VARIANT_TRUE : VARIANT_FALSE;
LeaveCriticalSection(&m_csAutomatedPhoneState);
Unlock();
LOG((TL_TRACE, "get_AutoStopRingOnOffHook - " "exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::put_AutoKeypadTones( IN VARIANT_BOOL fEnabled ) { LOG((TL_TRACE, "put_AutoKeypadTones - " "enter"));
//
// Translate from VARIANT_BOOL to BOOL. If someone mistakenly
// passes in TRUE instead of VARIANT_TRUE, we are still ok.
//
Lock();
//
// Make sure the phone is open with owner privilege
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "put_AutoKeypadTones - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
if ( m_dwPrivilege != PHONEPRIVILEGE_OWNER ) { LOG((TL_ERROR, "put_AutoKeypadTones - wrong phone privilege - " "exit TAPI_E_NOTOWNER"));
Unlock();
return TAPI_E_NOTOWNER; }
EnterCriticalSection(&m_csAutomatedPhoneState);
m_fAutoKeypadTones = fEnabled ? TRUE : FALSE;
LeaveCriticalSection(&m_csAutomatedPhoneState);
Unlock();
LOG((TL_TRACE, "put_AutoKeypadTones - " "exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::get_AutoKeypadTones ( OUT VARIANT_BOOL * pfEnabled ) { LOG((TL_TRACE, "get_AutoKeypadTones - " "enter"));
if ( TAPIIsBadWritePtr( pfEnabled, sizeof( VARIANT_BOOL ) ) ) { LOG((TL_ERROR, "get_AutoKeypadTones - " "bad parameter - exit E_POINTER"));
return E_POINTER; }
//
// Translate from BOOL to VARIANT_BOOL.
//
Lock();
//
// Make sure the phone is open
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "get_AutoKeypadTones - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
EnterCriticalSection(&m_csAutomatedPhoneState);
*pfEnabled = m_fAutoKeypadTones ? VARIANT_TRUE : VARIANT_FALSE;
LeaveCriticalSection(&m_csAutomatedPhoneState);
Unlock();
LOG((TL_TRACE, "get_AutoKeypadTones - " "exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::put_AutoKeypadTonesMinimumDuration( IN long lDuration ) { LOG((TL_TRACE, "put_AutoKeypadTonesMinimumDuration - " "enter"));
if ( lDuration < 0 ) { LOG((TL_ERROR, "put_AutoKeypadTonesMinimumDuration - " "negative argument - exit E_INVALIDARG"));
return E_INVALIDARG; }
Lock();
//
// Make sure the phone is open with owner privilege
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "put_AutoKeypadTonesMinimumDuration - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
if ( m_dwPrivilege != PHONEPRIVILEGE_OWNER ) { LOG((TL_ERROR, "put_AutoKeypadTonesMinimumDuration - wrong phone privilege - " "exit TAPI_E_NOTOWNER"));
Unlock();
return TAPI_E_NOTOWNER; }
EnterCriticalSection(&m_csAutomatedPhoneState);
m_dwAutoKeypadTonesMinimumDuration = lDuration;
LeaveCriticalSection(&m_csAutomatedPhoneState);
Unlock();
LOG((TL_TRACE, "put_AutoKeypadTonesMinimumDuration - " "exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::get_AutoKeypadTonesMinimumDuration( OUT long * plDuration ) { LOG((TL_TRACE, "get_AutoKeypadTonesMinimumDuration - " "enter"));
if ( TAPIIsBadWritePtr( plDuration, sizeof(long) ) ) { LOG((TL_ERROR, "get_AutoKeypadTonesMinimumDuration - " "bad parameter - exit E_POINTER"));
return E_POINTER; }
Lock();
//
// Make sure the phone is open
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "get_AutoKeypadTonesMinimumDuration - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
EnterCriticalSection(&m_csAutomatedPhoneState);
*plDuration = m_dwAutoKeypadTonesMinimumDuration;
LeaveCriticalSection(&m_csAutomatedPhoneState);
Unlock();
LOG((TL_TRACE, "get_AutoKeypadTonesMinimumDuration - " "exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::put_AutoVolumeControl( IN VARIANT_BOOL fEnabled ) { LOG((TL_TRACE, "put_AutoVolumeControl - " "enter"));
//
// Translate from VARIANT_BOOL to BOOL. If someone mistakenly
// passes in TRUE instead of VARIANT_TRUE, we are still ok.
//
Lock();
//
// Make sure the phone is open with owner privilege
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "put_AutoVolumeControl - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
if ( m_dwPrivilege != PHONEPRIVILEGE_OWNER ) { LOG((TL_ERROR, "put_AutoVolumeControl - wrong phone privilege - " "exit TAPI_E_NOTOWNER"));
Unlock();
return TAPI_E_NOTOWNER; }
EnterCriticalSection(&m_csAutomatedPhoneState);
m_fAutoVolumeControl = fEnabled ? TRUE : FALSE;
LeaveCriticalSection(&m_csAutomatedPhoneState);
Unlock();
LOG((TL_TRACE, "put_AutoVolumeControl - " "exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::get_AutoVolumeControl ( OUT VARIANT_BOOL * pfEnabled ) { LOG((TL_TRACE, "get_AutoVolumeControl - " "enter"));
if ( TAPIIsBadWritePtr( pfEnabled, sizeof( VARIANT_BOOL ) ) ) { LOG((TL_ERROR, "get_AutoVolumeControl - " "bad parameter - exit E_POINTER"));
return E_POINTER; }
//
// Translate from BOOL to VARIANT_BOOL.
//
Lock();
//
// Make sure the phone is open
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "get_AutoVolumeControl - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
EnterCriticalSection(&m_csAutomatedPhoneState);
*pfEnabled = m_fAutoVolumeControl ? VARIANT_TRUE : VARIANT_FALSE;
LeaveCriticalSection(&m_csAutomatedPhoneState);
Unlock();
LOG((TL_TRACE, "get_AutoVolumeControl - " "exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::put_AutoVolumeControlStep( IN long lStepSize ) { LOG((TL_TRACE, "put_AutoVolumeControlStep - " "enter"));
if ( (lStepSize < 0) || (lStepSize > 0xFFFF) ) { LOG((TL_ERROR, "put_AutoVolumeControlStep - " "invalid argument - exit E_INVALIDARG"));
return E_INVALIDARG; }
Lock();
//
// Make sure the phone is open with owner privilege
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "put_AutoVolumeControlStep - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
if ( m_dwPrivilege != PHONEPRIVILEGE_OWNER ) { LOG((TL_ERROR, "put_AutoVolumeControlStep - wrong phone privilege - " "exit TAPI_E_NOTOWNER"));
Unlock();
return TAPI_E_NOTOWNER; }
EnterCriticalSection(&m_csAutomatedPhoneState);
m_dwAutoVolumeControlStep = lStepSize;
LeaveCriticalSection(&m_csAutomatedPhoneState);
Unlock();
LOG((TL_TRACE, "put_AutoVolumeControlStep - " "exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::get_AutoVolumeControlStep( OUT long * plStepSize ) { LOG((TL_TRACE, "get_AutoVolumeControlStep - " "enter"));
if ( TAPIIsBadWritePtr( plStepSize, sizeof(long) ) ) { LOG((TL_ERROR, "get_AutoVolumeControlStep - " "bad parameter - exit E_POINTER"));
return E_POINTER; }
Lock();
//
// Make sure the phone is open
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "get_AutoVolumeControlStep - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
EnterCriticalSection(&m_csAutomatedPhoneState);
*plStepSize = m_dwAutoVolumeControlStep;
LeaveCriticalSection(&m_csAutomatedPhoneState);
Unlock();
LOG((TL_TRACE, "get_AutoVolumeControlStep - " "exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::put_AutoVolumeControlRepeatDelay( IN long lDelay ) { LOG((TL_TRACE, "put_AutoVolumeControlRepeatDelay - " "enter"));
if ( lDelay < 0 ) { LOG((TL_ERROR, "put_AutoVolumeControlRepeatDelay - " "invalid argument - exit E_INVALIDARG"));
return E_INVALIDARG; }
Lock();
//
// Make sure the phone is open with owner privilege
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "put_AutoVolumeControlRepeatDelay - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
if ( m_dwPrivilege != PHONEPRIVILEGE_OWNER ) { LOG((TL_ERROR, "put_AutoVolumeControlRepeatDelay - wrong phone privilege - " "exit TAPI_E_NOTOWNER"));
Unlock();
return TAPI_E_NOTOWNER; }
EnterCriticalSection(&m_csAutomatedPhoneState);
m_dwAutoVolumeControlRepeatDelay = lDelay;
LeaveCriticalSection(&m_csAutomatedPhoneState);
Unlock();
LOG((TL_TRACE, "put_AutoVolumeControlRepeatDelay - " "exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::get_AutoVolumeControlRepeatDelay( OUT long * plDelay ) { LOG((TL_TRACE, "get_AutoVolumeControlRepeatDelay - " "enter"));
if ( TAPIIsBadWritePtr( plDelay, sizeof(long) ) ) { LOG((TL_ERROR, "get_AutoVolumeControlRepeatDelay - " "bad parameter - exit E_POINTER"));
return E_POINTER; }
Lock();
//
// Make sure the phone is open
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "get_AutoVolumeControlRepeatDelay - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
EnterCriticalSection(&m_csAutomatedPhoneState);
*plDelay = m_dwAutoVolumeControlRepeatDelay;
LeaveCriticalSection(&m_csAutomatedPhoneState);
Unlock();
LOG((TL_TRACE, "get_AutoVolumeControlRepeatDelay - " "exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::put_AutoVolumeControlRepeatPeriod( IN long lPeriod ) { LOG((TL_TRACE, "put_AutoVolumeControlRepeatPeriod - " "enter"));
if ( lPeriod < 0 ) { LOG((TL_ERROR, "put_AutoVolumeControlRepeatPeriod - " "invalid argument - exit E_INVALIDARG"));
return E_INVALIDARG; }
Lock();
//
// Make sure the phone is open with owner privilege
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "put_AutoVolumeControlRepeatPeriod - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
if ( m_dwPrivilege != PHONEPRIVILEGE_OWNER ) { LOG((TL_ERROR, "put_AutoVolumeControlRepeatPeriod - wrong phone privilege - " "exit TAPI_E_NOTOWNER"));
Unlock();
return TAPI_E_NOTOWNER; }
EnterCriticalSection(&m_csAutomatedPhoneState);
m_dwAutoVolumeControlRepeatPeriod = lPeriod;
LeaveCriticalSection(&m_csAutomatedPhoneState);
Unlock();
LOG((TL_TRACE, "put_AutoVolumeControlRepeatPeriod - " "exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::get_AutoVolumeControlRepeatPeriod( OUT long * plPeriod ) { LOG((TL_TRACE, "get_AutoVolumeControlRepeatPeriod - " "enter"));
if ( TAPIIsBadWritePtr( plPeriod, sizeof(long) ) ) { LOG((TL_ERROR, "get_AutoVolumeControlRepeatPeriod - " "bad parameter - exit E_POINTER"));
return E_POINTER; }
Lock();
//
// Make sure the phone is open
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "get_AutoVolumeControlRepeatPeriod - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
EnterCriticalSection(&m_csAutomatedPhoneState);
*plPeriod = m_dwAutoVolumeControlRepeatPeriod;
LeaveCriticalSection(&m_csAutomatedPhoneState);
Unlock();
LOG((TL_TRACE, "get_AutoVolumeControlRepeatPeriod - " "exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
// UnselectAllPreviouslySelectedTerminals
//
// pCallBCC2 -- the call on which we started to select terminals
// pTerminal -- the last terminal we tried to select; it failed
// pEnum -- the enumerator that gave us the terminals we tried to select
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
void CPhone::UnselectAllPreviouslySelectedTerminals( IN ITBasicCallControl2 * pCall, IN ITTerminal * pTerminalThatFailed, IN IEnumTerminal * pEnum ) { HRESULT hr;
LOG((TL_TRACE, "UnselectAllPreviouslySelectedTerminals - " "enter"));
//
// Reset the enumerator. If this fails, stop -- we don't want to risk
// unselecting terminals that were selected independently of SelectCall().
//
hr = pEnum->Reset();
if ( FAILED(hr) ) { LOG((TL_WARN, "UnselectAllPreviouslySelectedTerminals - " "failed to reset enumerator %p - " "hr = 0x%08x. Not unselecting terminals.", pEnum, hr ));
return; }
ITTerminal * pTerminal; BOOL fDone = FALSE;
while ( S_OK == pEnum->Next( 1, & pTerminal, NULL ) ) { if ( pTerminal == pTerminalThatFailed ) { fDone = TRUE; } else { //
// Try to unselect the terminal. If it fails to unselect, there's
// nothing more we can do... just continue trying to unselect the
// rest of the terminals.
//
hr = pCall->UnselectTerminalOnCall( pTerminal );
if ( FAILED(hr) ) { LOG((TL_WARN, "UnselectAllPreviouslySelectedTerminals - " "cannot unselect terminal %p on ITBCC2 %p - " "hr = 0x%08x. Continuing...", pTerminal, pCall, hr )); } }
pTerminal->Release();
if ( fDone == TRUE ) { break; } }
LOG((TL_TRACE, "UnselectAllPreviouslySelectedTerminals - " "normal exit")); }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
HRESULT CPhone::SelectDefaultTerminalsOnCall( IN ITCallInfo * pCall ) { LOG((TL_TRACE, "SelectDefaultTerminalsOnCall - enter" ));
//
// Get the address for the call
//
HRESULT hr; ITAddress * pAddress;
hr = pCall->get_Address( & pAddress );
if ( FAILED(hr) ) { LOG((TL_ERROR, "SelectDefaultTerminalsOnCall - " "cannot get call's " "address - exit 0x%08x", hr ));
return hr; }
//
// Find the default terminals for this phone.
//
IEnumTerminal * pEnum;
hr = EnumerateTerminals( pAddress, & pEnum );
pAddress->Release();
if ( FAILED(hr) ) { LOG((TL_ERROR, "SelectDefaultTerminalsOnCall - " "cannot enum phone's " "terminals - exit 0x%08x", hr ));
return hr; }
//
// Get the terminal selection interface on the call.
//
ITBasicCallControl2 * pCallBCC2;
hr = pCall->QueryInterface( IID_ITBasicCallControl2, (void **) & pCallBCC2 );
if ( FAILED(hr) ) { LOG((TL_ERROR, "SelectDefaultTerminalsOnCall - " "cannot get call's " "ITBasicCallControl2 interface - " "exit 0x%08x", hr ));
pEnum->Release(); return hr; }
//
// Select each of the default terminals on the call.
//
ITTerminal * pTerminal;
while ( S_OK == pEnum->Next( 1, & pTerminal, NULL ) ) { //
// Select each terminal on the call.
// If one selection fails, unselect all the terminals
// that were successfully selected.
//
hr = pCallBCC2->SelectTerminalOnCall( pTerminal );
if ( FAILED(hr) ) { LOG((TL_ERROR, "SelectDefaultTerminalsOnCall - " "cannot select " "terminal %p on ITBCC2 %p - " "unselecting other terminals", pTerminal, pCallBCC2 ));
UnselectAllPreviouslySelectedTerminals(pCallBCC2, pTerminal, pEnum);
LOG((TL_ERROR, "SelectDefaultTerminalsOnCall - " "exit 0x%08x", hr ));
pTerminal->Release();
pEnum->Release(); pCallBCC2->Release();
return hr; }
pTerminal->Release(); }
pEnum->Release(); pCallBCC2->Release();
LOG((TL_TRACE, "SelectDefaultTerminalsOnCall - exit S_OK" ));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
HRESULT CPhone::UnselectDefaultTerminalsOnCall( IN ITCallInfo * pCall ) { LOG((TL_TRACE, "UnselectDefaultTerminalsOnCall - enter" ));
//
// Get the address for the call
//
HRESULT hr; ITAddress * pAddress;
hr = pCall->get_Address( & pAddress );
if ( FAILED(hr) ) { LOG((TL_ERROR, "UnselectDefaultTerminalsOnCall - " "cannot get call's " "address - exit 0x%08x", hr ));
return hr; }
//
// Find the default terminals for this phone.
//
IEnumTerminal * pEnum;
hr = EnumerateTerminals( pAddress, & pEnum );
pAddress->Release();
if ( FAILED(hr) ) { LOG((TL_ERROR, "UnselectDefaultTerminalsOnCall - " "cannot enum phone's " "terminals - exit 0x%08x", hr ));
return hr; }
//
// Get the terminal selection interface on the call.
//
ITBasicCallControl2 * pCallBCC2;
hr = pCall->QueryInterface( IID_ITBasicCallControl2, (void **) & pCallBCC2 );
if ( FAILED(hr) ) { LOG((TL_ERROR, "UnselectDefaultTerminalsOnCall - " "cannot get call's " "ITBasicCallControl2 interface - " "exit 0x%08x", hr ));
pEnum->Release(); return hr; }
//
// Unselect each of the default terminals on the call.
//
ITTerminal * pTerminal;
while ( S_OK == pEnum->Next( 1, & pTerminal, NULL ) ) { //
// Unselect each terminal on the call.
// If one unselection fails, keep on going
//
hr = pCallBCC2->UnselectTerminalOnCall( pTerminal );
if ( FAILED(hr) ) { LOG((TL_ERROR, "UnselectDefaultTerminalsOnCall - " "cannot unselect " "terminal %p on ITBCC2 %p", pTerminal, pCallBCC2 )); }
pTerminal->Release(); }
pEnum->Release(); pCallBCC2->Release();
LOG((TL_TRACE, "UnselectDefaultTerminalsOnCall - exit S_OK" ));
return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::SelectCall( IN ITCallInfo * pCall, IN VARIANT_BOOL fSelectDefaultTerminals ) { HRESULT hr; CALL_STATE cs; CALL_PRIVILEGE priv;
LOG((TL_TRACE, "SelectCall - enter"));
//
// check argument
//
if ( IsBadReadPtr( pCall, sizeof( ITCallInfo ) ) ) { LOG((TL_ERROR, "SelectCall - exit E_POINTER")); return E_POINTER; }
//
// Check if the app has owner privilege on this call.
//
hr = pCall->get_Privilege( & priv );
if ( FAILED(hr) ) { LOG((TL_ERROR, "SelectCall - cannot get call privilege - " "exit 0x%08x", hr ));
return hr; }
if ( priv != CP_OWNER ) { LOG((TL_ERROR, "SelectCall - wrong call privilege - " "exit TAPI_E_NOTOWNER"));
return TAPI_E_NOTOWNER; }
//
// check to make sure the call state isn't disconnected
//
hr = pCall->get_CallState( & cs );
if ( FAILED(hr) ) { LOG((TL_ERROR, "SelectCall - cannot get call state - " "exit 0x%08x", hr ));
return hr; }
if ( cs == CS_DISCONNECTED ) { LOG((TL_ERROR, "SelectCall - call is disconnected - " "exit TAPI_E_INVALCALLSTATE"));
return TAPI_E_INVALCALLSTATE; }
//
// check if another call already selected
//
Lock();
if ( m_pCall != NULL ) { LOG((TL_ERROR, "SelectCall - another call already " "selected - exit TAPI_E_INUSE"));
Unlock(); return TAPI_E_INUSE; }
//
// Make sure the phone is open with owner privilege.
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "SelectCall - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
if ( m_dwPrivilege != PHONEPRIVILEGE_OWNER ) { LOG((TL_ERROR, "SelectCall - wrong phone privilege - " "exit TAPI_E_NOTOWNER"));
Unlock();
return TAPI_E_NOTOWNER; }
m_fDefaultTerminalsSelected = FALSE;
//
// Perform default terminal selection if the invoker wants it.
//
if ( fSelectDefaultTerminals != VARIANT_FALSE ) { hr = SelectDefaultTerminalsOnCall( pCall );
if ( FAILED(hr) ) { LOG((TL_ERROR, "SelectCall - failed to select " "terminals - exit 0x%08x", hr ));
Unlock();
return hr; }
//
// Set this flag so that we know to unselect the terminals from the call when
// the call is unselected
//
m_fDefaultTerminalsSelected = TRUE; }
m_pCall = pCall; m_pCall->AddRef();
Unlock();
//
// Now that the call is selected, get the callstate
// so we can call Automation_CallState
//
hr = pCall->get_CallState( & cs );
if ( FAILED(hr) ) { LOG((TL_ERROR, "SelectCall - cannot get call state - " "exit 0x%08x", hr ));
return hr; }
Automation_CallState( pCall, cs, CEC_NONE );
LOG((TL_TRACE, "SelectCall - exit")); return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
HRESULT CPhone::InternalUnselectCall( IN ITCallInfo * pCall ) { HRESULT hr;
LOG((TL_TRACE, "InternalUnselectCall - enter"));
Lock();
if ( pCall != m_pCall ) { LOG((TL_ERROR, "InternalUnselectCall - call was not selected; " "exit TAPI_E_CALLNOTSELECTED"));
Unlock();
return TAPI_E_CALLNOTSELECTED; }
//
// Make sure the phone is open with owner privilege
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "InternalUnselectCall - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
if ( m_dwPrivilege != PHONEPRIVILEGE_OWNER ) { LOG((TL_ERROR, "InternalUnselectCall - wrong phone privilege - " "exit TAPI_E_NOTOWNER"));
Unlock();
return TAPI_E_NOTOWNER; }
//
// If we selected the default terminals on the call when the call was selected on this phone,
// then we need to unselect the default terminals from the call.
//
if ( m_fDefaultTerminalsSelected == TRUE ) { hr = UnselectDefaultTerminalsOnCall( pCall );
if ( FAILED(hr) ) { LOG((TL_ERROR, "InternalUnselectCall - UnselectDefaultTerminalsOnCall %p failed - %lx", pCall, hr ));
// If we fail here then maybe the app already unselected the terminals. In any case
// just continue...
} m_fDefaultTerminalsSelected = FALSE; }
//
// Release our reference to the call.
//
m_pCall->Release(); m_pCall = NULL;
LOG((TL_TRACE, "InternalUnselectCall - exit S_OK"));
Unlock(); return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::UnselectCall( IN ITCallInfo * pCall ) { HRESULT hr;
LOG((TL_TRACE, "UnselectCall - enter"));
//
// Check arguments.
//
if (IsBadReadPtr(pCall, sizeof( ITCallInfo ) ) ) { LOG((TL_ERROR, "UnselectCall - " "returning E_POINTER"));
return E_POINTER; }
hr = InternalUnselectCall( pCall );
if ( FAILED(hr) ) { LOG((TL_ERROR, "UnselectCall - " "InternalUnselectCall failed 0x%lx", hr));
return hr; }
EnterCriticalSection(&m_csAutomatedPhoneState);
if (m_fPhoneHandlingEnabled) { switch(m_AutomatedPhoneState) { case APS_ONHOOK_RINGING_IN: case APS_ONHOOK_RINGING_OUT: case APS_ONHOOK_CONNECTED: { //
// Stop the ringer
//
if (m_fRinger == TRUE) { StopRinger(); }
m_AutomatedPhoneState = APS_ONHOOK_IDLE; } break;
case APS_OFFHOOK_RINGING_OUT: case APS_OFFHOOK_CALL_INIT: case APS_OFFHOOK_CONNECTED: { //
// Stop any playing tone
//
if (m_Tone != PT_SILENCE) { StopTone(); }
m_AutomatedPhoneState = APS_OFFHOOK_DEAD_LINE; } break; } } //m_fPhoneHandlingEnabled
LeaveCriticalSection(&m_csAutomatedPhoneState);
LOG((TL_TRACE, "UnselectCall - exit S_OK"));
return S_OK; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::EnumerateSelectedCalls( OUT IEnumCall ** ppCallEnum ) { HRESULT hr = S_OK; LOG((TL_TRACE, "EnumerateSelectedCalls enter" )); LOG((TL_TRACE, " ppCallEnum----->%p", ppCallEnum ));
//
// Check arguments.
//
if (TAPIIsBadWritePtr(ppCallEnum, sizeof( IEnumCall * ) ) ) { LOG((TL_ERROR, "EnumerateSelectedCalls - " "returning E_POINTER"));
return E_POINTER; } //
// Create and initialize the enumerator.
//
CComObject< CTapiEnum< IEnumCall, ITCallInfo, &IID_IEnumCall > > * p; hr = CComObject< CTapiEnum< IEnumCall, ITCallInfo, &IID_IEnumCall > > ::CreateInstance( &p );
if ( hr != S_OK ) // CreateInstance deletes object on S_FALSE
{ LOG((TL_ERROR, "EnumerateSelectedCalls - " "could not create enum - " "exit 0x%08x", hr )); return hr; }
// Initialize adds a reference to p
hr = p->Initialize( );
if ( FAILED(hr) ) { delete p; LOG((TL_ERROR, "EnumerateSelectedCalls - " "could not init enum - " "exit 0x%08x", hr ));
return hr; }
//
// Add our single call to the enumerator, if we have one.
//
Lock();
//
// Make sure the phone is open
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "EnumerateSelectedCalls - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
p->Release();
return TAPI_E_PHONENOTOPEN; } if ( m_pCall != NULL ) { hr = p->Add( m_pCall ); } else { hr = S_OK; }
Unlock();
//
// Return the enum if we succeeded, else throw it away.
//
if ( SUCCEEDED(hr) ) { *ppCallEnum = p;
LOG((TL_TRACE, "EnumerateSelectedCalls exit - " "hr = 0x%08x", hr )); } else { p->Release(); LOG((TL_ERROR, "EnumerateSelectedCalls - " "could not add call to enum - " "exit 0x%08x", hr )); }
return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
STDMETHODIMP CPhone::get_SelectedCalls( OUT VARIANT * pVariant ) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_SelectedCalls enter" )); LOG((TL_TRACE, " pVariant----->%p", pVariant ));
//
// Check arguments.
//
if ( TAPIIsBadWritePtr(pVariant, sizeof( pVariant ) ) ) { LOG((TL_ERROR, "get_SelectedCalls - " "returning E_POINTER"));
return E_POINTER; }
//
// Create an array containing no calls or our single call. This
// type of array does not keep any COM refcounts. We will pass this
// array into the collection object initialization, and then we will
// shut down the array.
//
CTArray<ITCallInfo *> aCalls; BOOL fResult;
Lock();
//
// Make sure the phone is open
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "get_SelectedCalls - phone is not open - " "exit TAPI_E_PHONENOTOPEN"));
Unlock();
aCalls.Shutdown();
return TAPI_E_PHONENOTOPEN; } if ( m_pCall != NULL ) { fResult = aCalls.Add( m_pCall ); } else { fResult = TRUE; }
Unlock();
if ( fResult == FALSE ) { LOG((TL_ERROR, "get_SelectedCalls - " "could not add call to array; " "exit E_OUTOFMEMORY" )); return E_OUTOFMEMORY; } //
// Create and initialize the Collection.
//
CComObject< CTapiCollection< ITCallInfo > > * p;
hr = CComObject< CTapiCollection< ITCallInfo > > ::CreateInstance( &p );
if ( hr != S_OK ) // CreateInstance deleted object on S_FALSE
{ LOG((TL_ERROR, "get_SelectedCalls - " "could not create Collection - " "exit 0x%08x", hr )); aCalls.Shutdown();
return hr; }
//
// Get the collection object's IDispatch interface.
//
IDispatch * pDisp; hr = p->_InternalQueryInterface( IID_IDispatch, (void **) & pDisp );
if ( FAILED(hr) ) { LOG((TL_ERROR, "get_SelectedCalls - " "could not get IDispatch interface" )); delete p;
return hr; }
hr = p->Initialize( aCalls );
aCalls.Shutdown();
if ( FAILED(hr) ) { LOG((TL_ERROR, "get_SelectedCalls - " "could not init Collection - " "exit 0x%08x", hr ));
pDisp->Release(); return hr; }
//
// Put the collection object's IDispatch pointer into the variant.
//
VariantInit(pVariant); pVariant->vt = VT_DISPATCH; pVariant->pdispVal = pDisp;
LOG((TL_TRACE, "get_SelectedCalls exit - " "hr = 0x%08x", hr )); return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Class : CPhone
// Interface : ITPhone
// Method : DeviceSpecific
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HRESULT CPhone::DeviceSpecific( IN BYTE *pbDataArray, IN DWORD dwSize ) { LOG((TL_TRACE, "DeviceSpecific - enter"));
//
// check if arguments are any good
//
if ( NULL == pbDataArray ) { LOG((TL_ERROR, "DeviceSpecific - pbDataArray is NULL. E_INVALIDARG"));
return E_INVALIDARG; }
if ( 0 == dwSize ) { LOG((TL_ERROR, "DeviceSpecific - dwSize is 0. E_INVALIDARG"));
return E_INVALIDARG; }
//
// check if the buffer is valid
//
if ( IsBadReadPtr(pbDataArray, dwSize) ) { LOG((TL_ERROR, "DeviceSpecific - bad array passed in [%p] of size %ld", pbDataArray, dwSize));
return E_POINTER; }
//
// starting to access data members. lock.
//
Lock();
//
// see if the phone is open
//
if ( m_hPhone == NULL ) { LOG((TL_ERROR, "DeviceSpecific - phone not open. TAPI_E_PHONENOTOPEN"));
Unlock();
return TAPI_E_PHONENOTOPEN; }
//
// keep the phone handle
//
HPHONE hPhone = m_hPhone;
Unlock();
//
// make the tapisrv call. if hPhone becomes invalid, the call will simply
// fail. this is ok.
//
HRESULT hr = phoneDevSpecific(hPhone, pbDataArray, dwSize);
LOG((TL_TRACE, "DeviceSpecific - exit. hr = %lx", hr));
return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Class : CPhone
// Interface : ITPhone
// Method : DeviceSpecificVariant
//
// this is the scriptable version of DeviceSpecific
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HRESULT CPhone::DeviceSpecificVariant( IN VARIANT varDevSpecificByteArray ) { LOG((TL_TRACE, "DeviceSpecificVariant - enter"));
//
// extract buffer from the variant
//
DWORD dwByteArraySize = 0; BYTE *pBuffer = NULL;
HRESULT hr = E_FAIL; hr = MakeBufferFromVariant(varDevSpecificByteArray, &dwByteArraySize, &pBuffer);
if (FAILED(hr)) { LOG((TL_TRACE, "DeviceSpecificVariant - MakeBufferFromVariant failed. hr = %lx", hr));
return hr; }
//
// call the non-scriptable version and pass it the nonscriptable implementation
//
hr = DeviceSpecific(pBuffer, dwByteArraySize);
//
// success or failure, free the buffer allocated by MakeBufferFromVariant
//
ClientFree(pBuffer); pBuffer = NULL;
//
// log rc and exit
//
LOG((TL_TRACE, "DeviceSpecificVariant - exit. hr = %lx", hr));
return hr; }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Class : CPhone
// Interface : ITPhone
// Method : NegotiateExtVersion
//
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HRESULT CPhone::NegotiateExtVersion ( IN long lLowVersion, IN long lHighVersion, OUT long *plExtVersion ) { LOG((TL_TRACE, "NegotiateExtVersion - enter"));
//
// make sure the out parameter is writable
//
if (IsBadWritePtr(plExtVersion, sizeof(long)) ) { LOG((TL_ERROR, "NegotiateExtVersion - output arg [%p] not writeable", plExtVersion));
return E_POINTER; }
Lock();
//
// make a call to tapisrv
//
DWORD dwNegotiatedVersion = 0;
LONG lResult = phoneNegotiateExtVersion(m_hPhoneApp, m_dwDeviceID, m_dwAPIVersion, lLowVersion, lHighVersion, &dwNegotiatedVersion );
Unlock();
HRESULT hr = mapTAPIErrorCode(lResult);
//
// return the value on success
//
if ( SUCCEEDED(hr) ) { LOG((TL_TRACE, "NegotiateExtVersion - negotiated version %ld", dwNegotiatedVersion));
*plExtVersion = dwNegotiatedVersion; }
LOG((TL_TRACE, "NegotiateExtVersion - exit. hr = %lx", hr));
return hr; }
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
// ITPhoneEvent methods
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// FireEvent
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HRESULT CPhoneEvent::FireEvent( CPhone * pCPhone, PHONE_EVENT Event, PHONE_BUTTON_STATE ButtonState, PHONE_HOOK_SWITCH_STATE HookSwitchState, PHONE_HOOK_SWITCH_DEVICE HookSwitchDevice, DWORD dwRingMode, DWORD dwButtonLampId, PWSTR pNumber, ITCallInfo * pCallInfo ) { HRESULT hr = S_OK; CComObject<CPhoneEvent> * p; IDispatch * pDisp;
STATICLOG((TL_TRACE, "FireEvent enter" ));
//
// We have to filter Phoneevents because
// Tapisrv doesn't. Tapi3 receive always phone events
// and use them to keep alive the Phone object
//
CTAPI* pTapi = pCPhone->GetTapi(); if( pTapi == NULL ) { STATICLOG((TL_ERROR, "Tapi object is invalid - %lx", E_UNEXPECTED)); return E_UNEXPECTED; }
long nFilterMask = 0; pTapi->get_EventFilter( &nFilterMask ); if( (nFilterMask & TE_PHONEEVENT) == 0 ) { //
// The user didn't set the mask for TE_PHONEEVENT
// so we don't fire the event to the application
//
STATICLOG((TL_INFO, "The user didn't set the mask for TE_PHONEEVENT." " Don't fire the event to app - %lx", S_OK)); return S_OK; }
//
// create event
//
hr = CComObject<CPhoneEvent>::CreateInstance( &p );
if ( S_OK != hr ) // CreateInstance deletes object on S_FALSE
{ STATICLOG((TL_ERROR, "Could not create PhoneEvent object - %lx", hr)); return hr; }
//
// get idisp interface
//
hr = p->QueryInterface( IID_IDispatch, (void **)&pDisp );
if ( FAILED(hr) ) { STATICLOG((TL_ERROR, "Could not get disp interface of PhoneEvent object - %lx", hr)); delete p; return hr; }
//
// initialize
//
if (pNumber != NULL) { p->m_pNumber = SysAllocString( pNumber );
if (p->m_pNumber == NULL) { STATICLOG((TL_ERROR, "Out of memory allocating phone number")); pDisp->Release();
return E_OUTOFMEMORY; } } else { p->m_pNumber = NULL; }
p->m_Event = Event; p->m_pPhone = dynamic_cast<ITPhone *>(pCPhone); p->m_pPhone->AddRef(); p->m_ButtonState = ButtonState; p->m_HookSwitchState = HookSwitchState; p->m_HookSwitchDevice = HookSwitchDevice; p->m_dwRingMode = dwRingMode; p->m_dwButtonLampId = dwButtonLampId; p->m_pCallInfo = pCallInfo; if (p->m_pCallInfo != NULL) { p->m_pCallInfo->AddRef(); } #if DBG
p->m_pDebug = (PWSTR) ClientAlloc( 1 ); #endif
//
// get callback
//
//
// fire event
//
(pCPhone->GetTapi())->Event( TE_PHONEEVENT, pDisp );
//
// release stuff
//
pDisp->Release();
STATICLOG((TL_TRACE, "FireEvent exit - return S_OK" )); return S_OK; }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// finalrelease
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void CPhoneEvent::FinalRelease() { LOG((TL_INFO, "CPhoneEvent - FinalRelease")); m_pPhone->Release(); m_pPhone = NULL;
if (m_pCallInfo != NULL) { m_pCallInfo->Release(); m_pCallInfo = NULL; }
if (m_pNumber != NULL) { SysFreeString(m_pNumber); m_pNumber = NULL; }
#if DBG
ClientFree( m_pDebug ); m_pDebug = NULL; #endif
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_Phone
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhoneEvent::get_Phone( ITPhone ** ppPhone ) { if (TAPIIsBadWritePtr(ppPhone , sizeof(ITPhone *) ) ) { LOG((TL_ERROR, "get_Phone - bad pointer"));
return E_POINTER; }
*ppPhone = m_pPhone; (*ppPhone)->AddRef();
return S_OK; }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_Event
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhoneEvent::get_Event( PHONE_EVENT * pEvent ) { if (TAPIIsBadWritePtr(pEvent , sizeof(PHONE_EVENT) ) ) { LOG((TL_ERROR, "get_Event - bad pointer"));
return E_POINTER; }
*pEvent = m_Event;
return S_OK; }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_ButtonState
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhoneEvent::get_ButtonState( PHONE_BUTTON_STATE * pState ) { if (TAPIIsBadWritePtr(pState , sizeof(PHONE_BUTTON_STATE) ) ) { LOG((TL_ERROR, "get_ButtonState - bad pointer"));
return E_POINTER; }
if (m_Event != PE_BUTTON) { LOG((TL_ERROR, "get_ButtonState - wrong event"));
return TAPI_E_WRONGEVENT; }
*pState = m_ButtonState;
return S_OK; }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_HookSwitchState
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhoneEvent::get_HookSwitchState( PHONE_HOOK_SWITCH_STATE * pState ) { if (TAPIIsBadWritePtr(pState , sizeof(PHONE_HOOK_SWITCH_STATE) ) ) { LOG((TL_ERROR, "get_HookSwitchState - bad pointer"));
return E_POINTER; }
if (m_Event != PE_HOOKSWITCH) { LOG((TL_ERROR, "get_HookSwitchState - wrong event"));
return TAPI_E_WRONGEVENT; }
*pState = m_HookSwitchState;
return S_OK; }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_HookSwitchDevice
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhoneEvent::get_HookSwitchDevice( PHONE_HOOK_SWITCH_DEVICE * pDevice ) { if (TAPIIsBadWritePtr(pDevice , sizeof(PHONE_HOOK_SWITCH_DEVICE) ) ) { LOG((TL_ERROR, "get_HookSwitchDevice - bad pointer"));
return E_POINTER; }
if (m_Event != PE_HOOKSWITCH) { LOG((TL_ERROR, "get_HookSwitchDevice - wrong event"));
return TAPI_E_WRONGEVENT; }
*pDevice = m_HookSwitchDevice;
return S_OK; }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_RingMode
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhoneEvent::get_RingMode( long * plRingMode ) { if (TAPIIsBadWritePtr(plRingMode , sizeof(long) ) ) { LOG((TL_ERROR, "get_RingMode - bad pointer"));
return E_POINTER; }
if (m_Event != PE_RINGMODE) { LOG((TL_ERROR, "get_RingMode - wrong event"));
return TAPI_E_WRONGEVENT; }
*plRingMode = m_dwRingMode;
return S_OK; }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_ButtonLampId
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhoneEvent::get_ButtonLampId( long *plButtonLampId ) { if (TAPIIsBadWritePtr(plButtonLampId , sizeof(long) ) ) { LOG((TL_ERROR, "get_ButtonLampId - bad pointer"));
return E_POINTER; }
if ((m_Event != PE_LAMPMODE) && (m_Event != PE_BUTTON)) { LOG((TL_ERROR, "get_ButtonLampId - wrong event"));
return TAPI_E_WRONGEVENT; }
*plButtonLampId = m_dwButtonLampId;
return S_OK; }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_NumberGathered
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhoneEvent::get_NumberGathered( BSTR * ppNumber ) { if (TAPIIsBadWritePtr(ppNumber , sizeof(BSTR) ) ) { LOG((TL_ERROR, "get_NumberGathered - bad pointer"));
return E_POINTER; }
if (m_Event != PE_NUMBERGATHERED) { LOG((TL_ERROR, "get_NumberGathered - wrong event"));
return TAPI_E_WRONGEVENT; }
*ppNumber = SysAllocString(m_pNumber);
if (*ppNumber == NULL) { LOG((TL_ERROR, "get_NumberGathered - out of memory"));
return E_OUTOFMEMORY; }
return S_OK; }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_Call
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhoneEvent::get_Call( ITCallInfo ** ppCallInfo ) { if (TAPIIsBadWritePtr(ppCallInfo , sizeof(ITCallInfo *) ) ) { LOG((TL_ERROR, "get_Call - bad pointer"));
return E_POINTER; }
if ((m_Event != PE_ANSWER) && (m_Event != PE_DISCONNECT)) { LOG((TL_ERROR, "get_Call - wrong event"));
return TAPI_E_WRONGEVENT; }
if ( m_pCallInfo == NULL ) { LOG((TL_ERROR, "get_Call - NULL call pointer"));
return E_UNEXPECTED; }
*ppCallInfo = m_pCallInfo; (*ppCallInfo)->AddRef();
return S_OK; }
///////////////////////////////////////////////////////////////////////////////
//
// CPhoneDevSpecificEvent
//
// static
HRESULT CPhoneDevSpecificEvent::FireEvent( CPhone * pCPhone, long l1, long l2, long l3 ) { STATICLOG((TL_INFO, "CPhoneDevSpecificEvent::FireEvent - enter"));
//
// try to create the event
//
CComObject<CPhoneDevSpecificEvent> *pEventObject = NULL;
HRESULT hr = CComObject<CPhoneDevSpecificEvent>::CreateInstance(&pEventObject);
if ( FAILED(hr) ) { STATICLOG((TL_ERROR, "CPhoneDevSpecificEvent::FireEvent - failed to create CPhoneDevSpecificEvent. hr = %lx", hr));
return hr; }
//
// initialize the event with the data we received
//
//
// get ITPhone from CPhone we received
//
hr = pCPhone->_InternalQueryInterface(IID_ITPhone, (void**)(&(pEventObject->m_pPhone)) );
if (FAILED(hr)) { STATICLOG((TL_ERROR, "CPhoneDevSpecificEvent::FireEvent - failed to get ITPhone interface from phone. hr = %lx", hr));
delete pEventObject;
return hr; }
//
// keep the actual data
//
pEventObject->m_l1 = l1; pEventObject->m_l2 = l2; pEventObject->m_l3 = l3;
#if DBG
pEventObject->m_pDebug = (PWSTR) ClientAlloc( 1 ); #endif
//
// get event's idispatch interface
//
IDispatch *pDispatch = NULL;
hr = pEventObject->QueryInterface( IID_IDispatch, (void **)&pDispatch );
if ( FAILED(hr) ) { STATICLOG((TL_ERROR, "CPhoneDevSpecificEvent::FireEvent - Could not get disp interface of AddressEvent object %lx", hr));
//
// undo the QI we have performed earlier
//
pEventObject->m_pPhone->Release(); pEventObject->m_pPhone = NULL;
//
// delete the event object
//
delete pEventObject; return hr; }
//
// from this point on, we will be using events pDispatch
//
pEventObject = NULL;
//
// get callback
//
//
// fire event to tapi
//
hr = (pCPhone->GetTapi())->Event( TE_PHONEDEVSPECIFIC, pDispatch);
//
// succeeded or not, we no longer need a reference to the event object
//
pDispatch->Release(); pDispatch = NULL; STATICLOG((TL_INFO, "CPhoneDevSpecificEvent::FireEvent - exit. hr = %lx", hr));
return hr; }
CPhoneDevSpecificEvent::CPhoneDevSpecificEvent() :m_pPhone(NULL) { LOG((TL_INFO, "CPhoneDevSpecificEvent - enter"));
#if DBG
m_pDebug = NULL;
#endif
LOG((TL_INFO, "CPhoneDevSpecificEvent - exit")); }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// finalrelease
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void CPhoneDevSpecificEvent::FinalRelease() { LOG((TL_INFO, "FinalRelease - enter"));
if (NULL != m_pPhone) { m_pPhone->Release(); m_pPhone = NULL; } else { //
// we must have a phone -- if not, there is a bug in our code
//
_ASSERTE(FALSE); }
#if DBG
ClientFree( m_pDebug ); #endif
LOG((TL_INFO, "FinalRelease - exit"));
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_Phone
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhoneDevSpecificEvent::get_Phone( ITPhone ** ppPhone ) { LOG((TL_TRACE, "get_Phone - enter"));
//
// good out pointer?
//
if (TAPIIsBadWritePtr(ppPhone , sizeof(ITPhone *) ) ) { LOG((TL_ERROR, "get_Phone - bad pointer at [%p]", ppPhone));
return E_POINTER; }
//
// return addreff'd address
//
*ppPhone = m_pPhone; (*ppPhone)->AddRef();
LOG((TL_TRACE, "get_Phone- enter. phone[%p]", (*ppPhone) ));
return S_OK; }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_lParam1
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhoneDevSpecificEvent::get_lParam1( long *pl1 ) { LOG((TL_TRACE, "get_lParam1 - enter"));
//
// good out pointer?
//
if (TAPIIsBadWritePtr(pl1, sizeof(long) ) ) { LOG((TL_ERROR, "get_lParam1 - bad pointer at %p", pl1));
return E_POINTER; }
//
// log and return the value
//
*pl1 = m_l1;
LOG((TL_TRACE, "get_lParam1 - exit. p1[%ld]", *pl1));
return S_OK; }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_lParam2
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhoneDevSpecificEvent::get_lParam2( long *pl2 ) { LOG((TL_TRACE, "get_lParam2 - enter"));
//
// good out pointer?
//
if (TAPIIsBadWritePtr(pl2, sizeof(long) ) ) { LOG((TL_ERROR, "get_lParam2 - bad pointer at %p", pl2));
return E_POINTER; }
//
// log and return the value
//
*pl2 = m_l2;
LOG((TL_TRACE, "get_lParam2 - exit. p2[%ld]", *pl2));
return S_OK; }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// get_lParam3
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
STDMETHODIMP CPhoneDevSpecificEvent::get_lParam3( long *pl3 ) { LOG((TL_TRACE, "get_lParam3 - enter"));
//
// good out pointer?
//
if ( TAPIIsBadWritePtr(pl3, sizeof(long)) ) { LOG((TL_ERROR, "get_lParam3 - bad pointer at %p", pl3));
return E_POINTER; }
//
// log and return the value
//
*pl3 = m_l3;
LOG((TL_TRACE, "get_lParam3 - exit. p3[%ld]", *pl3));
return S_OK; }
|