You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
460 lines
18 KiB
460 lines
18 KiB
/////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 1997 Active Voice Corporation. All Rights Reserved.
|
|
//
|
|
// Active Agent(r) and Unified Communications(tm) are trademarks of Active Voice Corporation.
|
|
//
|
|
// Other brand and product names used herein are trademarks of their respective owners.
|
|
//
|
|
// The entire program and user interface including the structure, sequence, selection,
|
|
// and arrangement of the dialog, the exclusively "yes" and "no" choices represented
|
|
// by "1" and "2," and each dialog message are protected by copyrights registered in
|
|
// the United States and by international treaties.
|
|
//
|
|
// Protected by one or more of the following United States patents: 5,070,526, 5,488,650,
|
|
// 5,434,906, 5,581,604, 5,533,102, 5,568,540, 5,625,676, 5,651,054.
|
|
//
|
|
// Active Voice Corporation
|
|
// Seattle, Washington
|
|
// USA
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/////////////////////////////////////////////////////////
|
|
// ThreadDialing.cpp
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "TapiDialer.h"
|
|
#include "ThreadDial.h"
|
|
#include "AVTapi.h"
|
|
#include "AVTapiCall.h"
|
|
#include "ConfExp.h"
|
|
#include "ThreadPub.h"
|
|
|
|
CThreadDialingInfo::CThreadDialingInfo()
|
|
{
|
|
m_pITAddress = NULL;
|
|
|
|
m_bstrName = NULL;
|
|
m_bstrAddress = NULL;
|
|
m_bstrOriginalAddress = NULL;
|
|
m_bstrDisplayableAddress = NULL;
|
|
m_bstrUser1 = NULL;
|
|
m_bstrUser2 = NULL;
|
|
m_dwAddressType = 0;
|
|
|
|
m_bResolved = false;
|
|
m_nCallType = AV_VOICE_CALL;
|
|
m_lCallID = 0;
|
|
|
|
m_hMem = NULL;
|
|
}
|
|
|
|
CThreadDialingInfo::~CThreadDialingInfo()
|
|
{
|
|
SysFreeString( m_bstrName );
|
|
SysFreeString( m_bstrAddress );
|
|
SysFreeString( m_bstrOriginalAddress );
|
|
SysFreeString( m_bstrDisplayableAddress );
|
|
SysFreeString( m_bstrUser1 );
|
|
SysFreeString( m_bstrUser2 );
|
|
|
|
if ( m_hMem ) GlobalFree( m_hMem );
|
|
|
|
RELEASE( m_pITAddress );
|
|
}
|
|
|
|
HRESULT CThreadDialingInfo::set_ITAddress( ITAddress *pITAddress )
|
|
{
|
|
RELEASE( m_pITAddress );
|
|
if ( pITAddress )
|
|
return pITAddress->QueryInterface( IID_ITAddress, (void **) &m_pITAddress );
|
|
|
|
return E_POINTER;
|
|
}
|
|
|
|
HRESULT CThreadDialingInfo::TranslateAddress()
|
|
{
|
|
// Only valid for dialing POTS, with a valid string that doesn't start with "x"
|
|
if ( !m_pITAddress ||
|
|
(m_dwAddressType != LINEADDRESSTYPE_PHONENUMBER) ||
|
|
!m_bstrAddress ||
|
|
(SysStringLen(m_bstrAddress) == 0) )
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
ITAddressTranslation *pXlat;
|
|
CErrorInfo er( IDS_ER_TRANSLATE_ADDRESS, IDS_ER_CREATE_TAPI_OBJECT );
|
|
|
|
if ( SUCCEEDED(er.set_hr(m_pITAddress->QueryInterface(IID_ITAddressTranslation, (void **) &pXlat))) )
|
|
{
|
|
er.set_Details( IDS_ER_TRANSLATING_ADDRESS );
|
|
ITAddressTranslationInfo *pXlatInfo = NULL;
|
|
|
|
// Translate the address
|
|
int nTryCount = 0;
|
|
while ( SUCCEEDED(er.m_hr) && (nTryCount < 2) )
|
|
{
|
|
if ( SUCCEEDED(er.set_hr( pXlat->TranslateAddress( m_bstrAddress, 0, 0, &pXlatInfo) )) && pXlatInfo )
|
|
{
|
|
BSTR bstrTemp = NULL;
|
|
|
|
pXlatInfo->get_DialableString( &bstrTemp );
|
|
if ( bstrTemp && SysStringLen(bstrTemp) )
|
|
{
|
|
#ifdef _DEBUG
|
|
USES_CONVERSION;
|
|
ATLTRACE(_T(".1.CThreadDialingProc::TranslateAddress() -- from %s to %s.\n"), OLE2CT(m_bstrAddress), OLE2CT(bstrTemp) );
|
|
#endif
|
|
SysReAllocString( &m_bstrAddress, bstrTemp );
|
|
}
|
|
SysFreeString( bstrTemp );
|
|
bstrTemp = NULL;
|
|
|
|
// Displayable address as well
|
|
pXlatInfo->get_DisplayableString( &bstrTemp );
|
|
if ( bstrTemp && SysStringLen(bstrTemp) )
|
|
SysReAllocString( &m_bstrDisplayableAddress, bstrTemp );
|
|
SysFreeString( bstrTemp );
|
|
|
|
// Clean up
|
|
RELEASE( pXlatInfo );
|
|
break;
|
|
}
|
|
else if ( er.m_hr == TAPI_E_REGISTRY_SETTING_CORRUPT )
|
|
{
|
|
HWND hWndParent = NULL;
|
|
CComPtr<IAVTapi> pAVTapi;
|
|
if ( SUCCEEDED(_Module.get_AVTapi(&pAVTapi)) )
|
|
pAVTapi->get_hWndParent( &hWndParent );
|
|
|
|
// Show translate address dialog
|
|
pXlat->TranslateDialog( (TAPIHWND)hWndParent, m_bstrAddress );
|
|
er.set_hr( S_OK );
|
|
}
|
|
nTryCount++;
|
|
}
|
|
|
|
pXlat->Release();
|
|
}
|
|
|
|
return er.m_hr;
|
|
}
|
|
|
|
HRESULT CThreadDialingInfo::PutAllInfo( IAVTapiCall *pAVCall )
|
|
{
|
|
_ASSERT( pAVCall );
|
|
|
|
pAVCall->put_dwAddressType( m_dwAddressType );
|
|
pAVCall->put_bstrOriginalAddress( m_bstrOriginalAddress );
|
|
pAVCall->put_bstrDisplayableAddress( m_bstrDisplayableAddress );
|
|
pAVCall->put_bstrName( m_bstrName );
|
|
pAVCall->put_dwThreadID( GetCurrentThreadId() );
|
|
pAVCall->put_bstrUser( 0, m_bstrUser1 );
|
|
pAVCall->put_bstrUser( 1, m_bstrUser2 );
|
|
pAVCall->put_bResolved( m_bResolved );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
void CThreadDialingInfo::FixupAddress()
|
|
{
|
|
if ( m_dwAddressType == LINEADDRESSTYPE_DOMAINNAME )
|
|
{
|
|
if ( (SysStringLen(m_bstrAddress) > 2) && !wcsncmp(m_bstrAddress, L"\\\\", 2) )
|
|
{
|
|
BSTR bstrTemp = SysAllocString( &m_bstrAddress[2] );
|
|
|
|
//
|
|
// We have to verify the string allocation
|
|
//
|
|
|
|
if( IsBadStringPtr( bstrTemp, (UINT)-1) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
SysReAllocString( &m_bstrAddress, bstrTemp );
|
|
SysFreeString( bstrTemp );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
// ThreadDialingProc
|
|
//
|
|
DWORD WINAPI ThreadDialingProc( LPVOID lpInfo )
|
|
{
|
|
#define FETCH_STRING( _CMS_, _IDS_ ) \
|
|
if ( bSliders ) { \
|
|
if ( LoadString(_Module.GetResourceInstance(), _IDS_, szText, ARRAYSIZE(szText)) > 0 ) { \
|
|
if ( SUCCEEDED(SysReAllocString(&bstrText, T2COLE(szText))) ) \
|
|
pAVTapi->fire_SetCallState_CMS( lCallID, _CMS_, bstrText ); \
|
|
} \
|
|
}
|
|
|
|
ATLTRACE(_T(".enter.ThreadDialingProc().\n") );
|
|
|
|
HANDLE hThread = NULL;
|
|
BOOL bDup = DuplicateHandle( GetCurrentProcess(),
|
|
GetCurrentThread(),
|
|
GetCurrentProcess(),
|
|
&hThread,
|
|
THREAD_ALL_ACCESS,
|
|
TRUE,
|
|
0 );
|
|
|
|
|
|
_ASSERT( bDup );
|
|
_Module.AddThread( hThread );
|
|
|
|
// Data passed into thread
|
|
USES_CONVERSION;
|
|
_ASSERT( lpInfo );
|
|
CThreadDialingInfo *pInfo = (CThreadDialingInfo *) lpInfo;
|
|
long lCallID;
|
|
|
|
// Error info information
|
|
CErrorInfo er;
|
|
er.set_Operation( IDS_ER_PLACECALL );
|
|
er.set_Details( IDS_ER_COINITIALIZE );
|
|
HRESULT hr = er.set_hr( CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_SPEED_OVER_MEMORY) );
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
ATLTRACE(_T(".1.ThreadDialingProc() -- thread up and running.\n") );
|
|
|
|
|
|
CAVTapi *pAVTapi = NULL;
|
|
IConfRoom *pConfRoom = NULL;
|
|
IAVTapiCall *pAVCall = NULL;
|
|
bool bSliders = (bool) (pInfo->m_dwAddressType != LINEADDRESSTYPE_SDP);
|
|
|
|
if ( SUCCEEDED(hr = er.set_hr(_Module.GetAVTapi(&pAVTapi))) &&
|
|
SUCCEEDED(hr = er.set_hr(pAVTapi->get_ConfRoom(&pConfRoom))) )
|
|
{
|
|
TCHAR szText[255];
|
|
BSTR bstrText = NULL;
|
|
er.set_Details( IDS_ER_FIRE_NEW_CALL );
|
|
|
|
if ( bSliders )
|
|
{
|
|
if ( SUCCEEDED(hr = er.set_hr(pAVTapi->fire_NewCall(pInfo->m_pITAddress, pInfo->m_dwAddressType, pInfo->m_lCallID, NULL, pInfo->m_nCallType, &pAVCall))) )
|
|
{
|
|
// Retrieve call ID for convienence and set up called address info
|
|
pAVCall->get_lCallID( &lCallID );
|
|
pInfo->PutAllInfo( pAVCall );
|
|
|
|
// Set the caller ID for the call
|
|
pAVCall->ResolveAddress();
|
|
pAVCall->ForceCallerIDUpdate();
|
|
|
|
// Setting up media terminals
|
|
pAVTapi->fire_ClearCurrentActions( lCallID );
|
|
pAVTapi->fire_AddCurrentAction( lCallID, CM_ACTIONS_DISCONNECT, NULL );
|
|
FETCH_STRING( CM_STATES_DIALING, IDS_PLACECALL_FETCH_ADDRESS );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Joining a conference...
|
|
hr = er.set_hr(pAVTapi->CreateNewCall(pInfo->m_pITAddress, &pAVCall) );
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
pInfo->PutAllInfo( pAVCall );
|
|
pAVTapi->fire_ActionSelected( CC_ACTIONS_SHOWCONFROOM );
|
|
hr = pConfRoom->EnterConfRoom( pAVCall );
|
|
}
|
|
}
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
// Did we make the address okay (in the case of a conference )
|
|
if ( SUCCEEDED(hr) && SUCCEEDED(hr = pAVCall->CheckKillMe()) )
|
|
{
|
|
// Create the call and then dial
|
|
ITBasicCallControl *pITControl = NULL;
|
|
er.set_Details( IDS_ER_CREATE_CALL );
|
|
pInfo->FixupAddress();
|
|
|
|
// What kind of media types does the address support?
|
|
long lSupportedMediaModes = 0;
|
|
ITMediaSupport *pITMediaSupport;
|
|
if ( SUCCEEDED(pInfo->m_pITAddress->QueryInterface(IID_ITMediaSupport, (void **) &pITMediaSupport)) )
|
|
{
|
|
pITMediaSupport->get_MediaTypes( &lSupportedMediaModes );
|
|
pITMediaSupport->Release();
|
|
}
|
|
lSupportedMediaModes &= (TAPIMEDIATYPE_AUDIO | TAPIMEDIATYPE_VIDEO);
|
|
|
|
////////////////////////
|
|
// Create the call object
|
|
//
|
|
if ( SUCCEEDED(hr = er.set_hr(pInfo->m_pITAddress->
|
|
CreateCall( pInfo->m_bstrAddress,
|
|
pInfo->m_dwAddressType,
|
|
lSupportedMediaModes,
|
|
&pITControl))) )
|
|
{
|
|
// Set more call parameters
|
|
pAVCall->put_ITBasicCallControl( pITControl );
|
|
|
|
///////////////////////////////////
|
|
// Set caller/calling ID
|
|
// Set the terminals up for the call
|
|
//
|
|
ITCallInfo *pCallInfo;
|
|
if ( SUCCEEDED(pITControl->QueryInterface(IID_ITCallInfo, (void **) &pCallInfo)) )
|
|
{
|
|
// Set user user info if requested
|
|
if ( pInfo->m_hMem )
|
|
{
|
|
void *pbUU = GlobalLock( pInfo->m_hMem );
|
|
if ( pbUU )
|
|
{
|
|
pCallInfo->SetCallInfoBuffer( CIB_USERUSERINFO, GlobalSize(pInfo->m_hMem), (BYTE *) pbUU );
|
|
GlobalUnlock( pInfo->m_hMem );
|
|
}
|
|
}
|
|
|
|
|
|
// Identify who it is that's calling!
|
|
CComBSTR bstrName;
|
|
MyGetUserName( &bstrName );
|
|
|
|
if ( bstrName )
|
|
{
|
|
// Add the computer name to the end
|
|
BSTR bstrIP = NULL, bstrComputer = NULL;
|
|
GetIPAddress( &bstrIP, &bstrComputer );
|
|
if ( bstrComputer && SysStringLen(bstrComputer) )
|
|
{
|
|
bstrName.Append( _T("\n") );
|
|
bstrName.Append( bstrComputer );
|
|
}
|
|
SysFreeString( bstrIP );
|
|
SysFreeString( bstrComputer );
|
|
|
|
pCallInfo->put_CallInfoString( CIS_CALLINGPARTYID, bstrName );
|
|
}
|
|
|
|
// Identify who it is that we think we're calling
|
|
if ( pInfo->m_bstrName && (SysStringLen(pInfo->m_bstrName) > 0) )
|
|
pCallInfo->put_CallInfoString( CIS_CALLEDPARTYFRIENDLYNAME, pInfo->m_bstrName );
|
|
else
|
|
pCallInfo->put_CallInfoString( CIS_CALLEDPARTYFRIENDLYNAME, pInfo->m_bstrAddress );
|
|
|
|
///////////////////////////////////
|
|
// Setting up media terminals
|
|
//
|
|
pAVTapi->fire_ClearCurrentActions( lCallID );
|
|
pAVTapi->fire_AddCurrentAction( lCallID, CM_ACTIONS_DISCONNECT, NULL );
|
|
FETCH_STRING( CM_STATES_DIALING, IDS_PLACECALL_FETCH_ADDRESS );
|
|
|
|
// Don't create terminals for data calls
|
|
if ( pInfo->m_nCallType != AV_DATA_CALL )
|
|
{
|
|
er.set_Details( IDS_ER_CREATETERMINALS );
|
|
hr = er.set_hr( pAVTapi->CreateTerminalArray(pInfo->m_pITAddress, pAVCall, pCallInfo) );
|
|
}
|
|
|
|
pCallInfo->Release();
|
|
}
|
|
|
|
////////////////////////////////
|
|
// Do the dialing
|
|
//
|
|
if ( SUCCEEDED(hr) && SUCCEEDED(hr = pAVCall->CheckKillMe()) )
|
|
{
|
|
FETCH_STRING( CM_STATES_DIALING, IDS_PLACECALL_DIALING );
|
|
|
|
// Register the callback object and connect call
|
|
if ( SUCCEEDED(hr) && SUCCEEDED(hr = pAVCall->CheckKillMe()) )
|
|
{
|
|
er.set_Details( IDS_ER_CONNECT_CALL );
|
|
if ( bSliders && (pInfo->m_nCallType != AV_DATA_CALL) )
|
|
{
|
|
pAVTapi->ShowMedia( lCallID, NULL, FALSE );
|
|
pAVTapi->ShowMediaPreview( lCallID, NULL, FALSE );
|
|
}
|
|
|
|
hr = er.set_hr( pITControl->Connect(false) );
|
|
}
|
|
else if ( bSliders )
|
|
{
|
|
pConfRoom->Cancel();
|
|
}
|
|
}
|
|
else if ( bSliders )
|
|
{
|
|
pConfRoom->Cancel();
|
|
}
|
|
|
|
SAFE_DELETE( pInfo )
|
|
RELEASE( pAVCall );
|
|
pITControl->Release();
|
|
|
|
// Spin
|
|
if ( SUCCEEDED(hr) )
|
|
CAVTapiCall::WaitWithMessageLoop();
|
|
}
|
|
}
|
|
|
|
// Failed to make the call, update the call control window
|
|
if ( FAILED(hr) )
|
|
{
|
|
if ( bSliders )
|
|
{
|
|
pAVTapi->fire_ClearCurrentActions( lCallID );
|
|
pAVTapi->fire_AddCurrentAction( lCallID, CM_ACTIONS_CLOSE, NULL );
|
|
}
|
|
else
|
|
{
|
|
pConfRoom->Cancel();
|
|
}
|
|
|
|
// what was the problem?
|
|
switch ( hr )
|
|
{
|
|
case LINEERR_OPERATIONUNAVAIL:
|
|
FETCH_STRING( CM_STATES_UNAVAILABLE, IDS_PLACECALL_DISCONNECT_UNAVAIL );
|
|
hr = er.set_hr( S_OK );
|
|
break;
|
|
|
|
case LINEERR_INVALADDRESS:
|
|
FETCH_STRING( CM_STATES_UNAVAILABLE, IDS_PLACECALL_DISCONNECT_BADADDRESS);
|
|
hr = er.set_hr( S_OK );
|
|
break;
|
|
|
|
default:
|
|
if ( bSliders )
|
|
pAVTapi->fire_SetCallState_CMS( lCallID, CM_STATES_DISCONNECTED, NULL );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Release the string
|
|
SysFreeString( bstrText );
|
|
}
|
|
|
|
// Clean-up
|
|
RELEASE( pConfRoom );
|
|
if ( pAVTapi )
|
|
(dynamic_cast<IUnknown *> (pAVTapi))->Release();
|
|
|
|
CoUninitialize();
|
|
}
|
|
|
|
SAFE_DELETE( pInfo );
|
|
|
|
// Notify module of shutdown
|
|
_Module.RemoveThread( hThread );
|
|
SetEvent( _Module.m_hEventThread );
|
|
ATLTRACE(_T(".exit.ThreadDialingProc(0x%08lx).\n"), hr );
|
|
return hr;
|
|
}
|
|
|