/*++ Copyright (c) 1997 - 1999 Microsoft Corporation Module Name: terminal.cpp Abstract: Implementation of terminals object for TAPI 3.0, that are not handled by the terminal manager. currently there are these terminals: phone Audio in and Audio out terminal associated with a phone device. Each phone device can have up to 3 types of devices - handset, headset, and speakerphone. So, a single phone device can have 6 associated terminals! Author: mquinton - 4/17/97 Notes: optional-notes Revision History: --*/ #include "stdafx.h" HRESULT WaitForPhoneReply( DWORD dwID ); //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // CTerminal is the base terminal object that all other terminals are // derived from. It implements the ITTerminal methods. // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // ITTerminal methods // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // get_Name // Alloc and copy the name. The app is responsible for // freeing // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CTerminal::get_Name( BSTR * ppName ) { LOG((TL_TRACE, "get_Name - enter" )); if (TAPIIsBadWritePtr( ppName, sizeof (BSTR) ) ) { LOG((TL_ERROR, "getName - bad pointer")); return E_POINTER; } Lock(); *ppName = SysAllocString( m_pName ); Unlock(); if ( ( NULL == *ppName ) && ( NULL != m_pName ) ) { LOG((TL_ERROR, "get_Name - SysAllocString Failed" )); return E_OUTOFMEMORY; } LOG((TL_TRACE, "get_Name - exit - return S_OK" )); return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // get_State // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CTerminal::get_State( TERMINAL_STATE * pTerminalState ) { LOG((TL_TRACE, "get_State - enter" )); if (TAPIIsBadWritePtr( pTerminalState, sizeof(TERMINAL_STATE) ) ) { LOG((TL_ERROR, "get_State - bad pointer")); return E_POINTER; } Lock(); *pTerminalState = m_State; Unlock(); LOG((TL_TRACE, "get_State - exit - return SUCCESS" )); return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // get_TerminalType // By definition, TAPI terminals are static // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CTerminal::get_TerminalType( TERMINAL_TYPE * pType ) { LOG((TL_TRACE, "get_TerminalType - enter" )); if ( TAPIIsBadWritePtr( pType, sizeof( TERMINAL_TYPE ) ) ) { LOG((TL_ERROR, "get_TerminalType - bad pointer")); return E_POINTER; } Lock(); *pType = m_TerminalType; Unlock(); LOG((TL_TRACE, "get_TerminalType - exit - return S_OK" )); return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // get_TerminalClass // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CTerminal::get_TerminalClass( BSTR * pTerminalClass ) { HRESULT hr = S_OK; CLSID clsid; LPWSTR pClass = NULL; LOG((TL_TRACE, "get_TerminalClass - enter" )); if ( TAPIIsBadWritePtr( pTerminalClass, sizeof( BSTR ) ) ) { LOG((TL_ERROR, "get_TerminalClass - bad pointer")); return E_POINTER; } Lock(); hr = StringFromIID( m_Class, &pClass ); Unlock(); if (S_OK != hr) { return hr; } *pTerminalClass = SysAllocString( pClass ); if ( ( NULL == *pTerminalClass ) && ( NULL != pClass ) ) { LOG((TL_ERROR, "get_TerminalClass - SysAllocString Failed" )); return E_OUTOFMEMORY; } CoTaskMemFree( pClass ); LOG((TL_TRACE, "get_TerminalClass - exit - return SUCCESS" )); return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // get_MediaType // // returns the supported mediatype BSTR associated with this terminal. // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CTerminal::get_MediaType( long * plMediaType ) { if ( TAPIIsBadWritePtr( plMediaType, sizeof(long) ) ) { LOG((TL_ERROR, "get_MediaType - inval pointer")); return E_POINTER; } *plMediaType = m_lMediaType; return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // get_Direction // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CTerminal::get_Direction( TERMINAL_DIRECTION * pTerminalDirection ) { if (TAPIIsBadWritePtr( pTerminalDirection, sizeof( TERMINAL_DIRECTION ) ) ) { LOG((TL_ERROR, "get_Direction - bad pointer")); return E_POINTER; } Lock(); *pTerminalDirection = m_Direction; Unlock(); return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // GetTerminalNameFromPhoneCaps // // Creates a name for a phone device terminal based on the phone // caps // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ PWSTR GetTerminalNameFromPhoneCaps( LPPHONECAPS pPhoneCaps, DWORD dwHookSwitchDev, DWORD dwPhoneID ) { PWSTR pszName; PWSTR pszHookSwitchDevName = NULL; // // load the appropriate string to describe // the hookswitch device // switch (dwHookSwitchDev) { case PHONEHOOKSWITCHDEV_SPEAKER: { pszHookSwitchDevName = MyLoadString( IDS_SPEAKERTERMINAL ); break; } case PHONEHOOKSWITCHDEV_HANDSET: { pszHookSwitchDevName = MyLoadString( IDS_HANDSETTERMINAL ); break; } case PHONEHOOKSWITCHDEV_HEADSET: { pszHookSwitchDevName = MyLoadString( IDS_HEADSETTERMINAL ); break; } default: { return NULL; } } if ( NULL == pszHookSwitchDevName ) { return NULL; } // // if the sp supplies a name, use it // if ( 0 != pPhoneCaps->dwPhoneNameSize ) { pszName = (PWSTR) ClientAlloc( ( pPhoneCaps->dwPhoneNameSize + lstrlenW( pszHookSwitchDevName ) + 32 ) * sizeof(WCHAR) ); if (NULL == pszName) { ClientFree( pszHookSwitchDevName ); return NULL; } CopyMemory( pszName, ( ( (LPBYTE)pPhoneCaps ) + pPhoneCaps->dwPhoneNameOffset ), pPhoneCaps->dwPhoneNameSize ); } else { PWSTR pszTempName; // // else create a name // pszTempName = MyLoadString( IDS_PHONEDEVICE ); if ( NULL == pszTempName ) { ClientFree( pszHookSwitchDevName ); return NULL; } pszName = (PWSTR) ClientAlloc( (lstrlenW( pszTempName ) + lstrlenW( pszHookSwitchDevName ) + 32 ) * sizeof(WCHAR) ); if (NULL == pszName) { ClientFree( pszHookSwitchDevName ); ClientFree( pszTempName ); return NULL; } wsprintfW( pszName, L"%s %d", pszTempName, dwPhoneID ); ClientFree( pszTempName ); } // // put them together // lstrcatW( pszName, L" - " ); lstrcatW( pszName, pszHookSwitchDevName ); ClientFree( pszHookSwitchDevName ); return pszName; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // CTerminal::Create // // Static function to create an audio in terminal related to a phone // device. // // pAddress // Owning address // // dwPhoneID // tapi 2 phone device ID related to this terminal // // pPhoneCaps // PHONEDEVCAPS of the phone device // // dwHookSwitchDev // PHONEHOOKSWITCHDEV_ bit of this phone device // // ppTerminal // return the terminal here! // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CTerminal::Create( HPHONEAPP hPhoneApp, DWORD dwPhoneID, LPPHONECAPS pPhoneCaps, DWORD dwHookSwitchDev, TERMINAL_DIRECTION td, DWORD dwAPIVersion, ITTerminal ** ppTerminal ) { HRESULT hr = S_OK; CComObject< CTerminal > * p; // // create CTerminal // hr = CComObject< CTerminal >::CreateInstance( &p ); if (!SUCCEEDED(hr)) { LOG((TL_ERROR, "CreateInstance for Phone failed - %lx", hr)); return hr; } // // save stuff // p->m_dwHookSwitchDev = dwHookSwitchDev; p->m_dwPhoneID = dwPhoneID; p->m_hPhoneApp = hPhoneApp; p->m_Direction = td; p->m_dwAPIVersion = dwAPIVersion; // // class depends on which hookswitchdev this is // switch( dwHookSwitchDev ) { case PHONEHOOKSWITCHDEV_HANDSET: p->m_Class = CLSID_HandsetTerminal; break; case PHONEHOOKSWITCHDEV_HEADSET: p->m_Class = CLSID_HeadsetTerminal; break; case PHONEHOOKSWITCHDEV_SPEAKER: p->m_Class = CLSID_SpeakerphoneTerminal; break; default: break; } // // create a name // p->m_pName = GetTerminalNameFromPhoneCaps( pPhoneCaps, dwHookSwitchDev, dwPhoneID ); // // return the created terminal // p->AddRef(); *ppTerminal = p; #if DBG p->m_pDebug = (PWSTR) ClientAlloc( 1 ); #endif return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CTerminal::get_Gain(long *pVal) { HRESULT hr; ITPhoneMSPCallPrivate * pMSPCall; LOG((TL_TRACE, "get_Gain - Enter")); if ( TAPIIsBadWritePtr( pVal, sizeof(LONG) ) ) { LOG((TL_ERROR, "get_Gain - bad pointer")); return E_POINTER; } Lock(); if ( NULL == m_pMSPCall ) { Unlock(); return TAPI_E_NOTERMINALSELECTED; } pMSPCall = m_pMSPCall; pMSPCall->AddRef(); Unlock(); hr = pMSPCall->GetGain( pVal, m_dwHookSwitchDev ); pMSPCall->Release(); LOG((TL_TRACE, "get_Gain - Exit - return %lx", hr)); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CTerminal::put_Gain(long newVal) { HRESULT hr; ITPhoneMSPCallPrivate * pMSPCall; LOG((TL_TRACE, "put_Gain - Enter")); Lock(); if ( NULL == m_pMSPCall ) { Unlock(); return TAPI_E_NOTERMINALSELECTED; } pMSPCall = m_pMSPCall; pMSPCall->AddRef(); Unlock(); hr = pMSPCall->PutGain( newVal, m_dwHookSwitchDev ); pMSPCall->Release(); LOG((TL_TRACE, "put_Gain - Exit - return %lx", hr)); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CTerminal::get_Balance(long *pVal) { LOG((TL_TRACE, "get_Balance - Enter")); LOG((TL_TRACE, "get_Balance - Exit - return TAPI_E_NOTSUPPORTED")); // not suppported return TAPI_E_NOTSUPPORTED; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CTerminal::put_Balance(long newVal) { LOG((TL_TRACE, "put_Balance - Enter")); LOG((TL_TRACE, "put_Balance - Exit - return TAPI_E_NOTSUPPORTED")); // not supported return TAPI_E_NOTSUPPORTED; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CTerminal::get_Volume(long *pVal) { HRESULT hr; ITPhoneMSPCallPrivate * pMSPCall; LOG((TL_TRACE, "get_Volume - Enter")); if ( TAPIIsBadWritePtr( pVal, sizeof( long ) ) ) { LOG((TL_ERROR, "get_Volume - bad pointer")); return E_POINTER; } Lock(); if ( NULL == m_pMSPCall ) { Unlock(); return TAPI_E_NOTERMINALSELECTED; } pMSPCall = m_pMSPCall; pMSPCall->AddRef(); Unlock(); hr = pMSPCall->GetVolume( pVal, m_dwHookSwitchDev ); pMSPCall->Release(); LOG((TL_TRACE, "get_Volume - Exit - return %lx", hr)); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CTerminal::put_Volume(long newVal) { HRESULT hr; ITPhoneMSPCallPrivate * pMSPCall; LOG((TL_TRACE, "put_Volume - Enter")); Lock(); if ( NULL == m_pMSPCall ) { Unlock(); return TAPI_E_NOTERMINALSELECTED; } pMSPCall = m_pMSPCall; pMSPCall->AddRef(); Unlock(); hr = pMSPCall->PutVolume( newVal, m_dwHookSwitchDev ); pMSPCall->Release(); LOG((TL_TRACE, "put_Volume - Exit - return %lx", hr)); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CTerminal::GetHookSwitchDev(DWORD * pdwHookSwitchDev) { Lock(); *pdwHookSwitchDev = m_dwHookSwitchDev; Unlock(); return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CTerminal::GetPhoneID(DWORD * pdwPhoneID) { Lock(); *pdwPhoneID = m_dwPhoneID; Unlock(); return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CTerminal::GetHPhoneApp(HPHONEAPP * phPhoneApp) { Lock(); *phPhoneApp = m_hPhoneApp; Unlock(); return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CTerminal::GetAPIVersion(DWORD * pdwAPIVersion) { Lock(); *pdwAPIVersion = m_dwAPIVersion; Unlock(); return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CTerminal::SetMSPCall(ITPhoneMSPCallPrivate * pPhoneMSPCall) { Lock(); m_pMSPCall = pPhoneMSPCall; if ( NULL != m_pMSPCall ) { m_State = TS_INUSE; } else { m_State = TS_NOTINUSE; } Unlock(); return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= void CTerminal::FinalRelease() { if (NULL != m_pName) { ClientFree( m_pName ); } #if DBG if( m_pDebug != NULL ) { ClientFree( m_pDebug ); m_pDebug = NULL; } #endif } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // CreateTerminalName // // Creates a terminal name for // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ PWSTR CreateTerminalName( CAddress * pAddress, DWORD dwType, long lMediaType ) { PWSTR pName; WCHAR szTerminal[256]; WCHAR szMediaType[256]; DWORD dwSize; // // create the name // // first load the string "Terminal" // szTerminal[0] = L'\0'; szMediaType[0] = L'\0'; ::LoadStringW(_Module.GetResourceInstance(), IDS_TERMINAL, szTerminal, 256); dwSize = lstrlenW( szTerminal ) * sizeof (WCHAR); switch (dwType) { case 0: break; case 1: if ( LINEMEDIAMODE_DATAMODEM == lMediaType) { ::LoadStringW(_Module.GetResourceInstance(), IDS_DATAMODEM, szMediaType, 256); } else if ( LINEMEDIAMODE_G3FAX == lMediaType) { ::LoadStringW(_Module.GetResourceInstance(), IDS_G3FAX, szMediaType, 256); } dwSize += (lstrlenW( szMediaType ) * sizeof ( WCHAR )); break; default: break; } // // alloc enough memory for the name // dwSize += (lstrlenW( pAddress->GetAddressName() ) * sizeof(WCHAR)); dwSize += 32; pName = (PWSTR) ClientAlloc( dwSize ); if (NULL == pName) { return NULL; } // // terminal name should look like: // " (mediatype) Terminal" // lstrcpyW( pName, pAddress->GetAddressName() ); lstrcatW( pName, L" " ); if (dwType == 1) { lstrcatW( pName, szMediaType ); lstrcatW( pName, L" " ); } lstrcatW( pName, szTerminal ); return pName; }