///////////////////////////////////////////////////////////////////////////////////////// // // 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 // ///////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// // TapiModule.CPP #include "stdafx.h" #include "TapiDialer.h" #include "TapiModule.h" #include "AVTapi.h" #include "AVGenNtfy.h" #include "ThreadRend.h" CTapiModule::CTapiModule() { m_pAVTapi = NULL; m_pAVGenNot = NULL; m_hWndParent = NULL; m_lInit = 0; m_lNumThreads = 0; m_hEventThread = NULL; m_hEventThreadWakeUp = NULL; } CTapiModule::~CTapiModule() { EMPTY_LIST( m_lstThreadIDs ); } void CTapiModule::Init( _ATL_OBJMAP_ENTRY* p, HINSTANCE h ) { // Initialize the common controls INITCOMMONCONTROLSEX ccs = { sizeof(INITCOMMONCONTROLSEX), ICC_WIN95_CLASSES }; InitCommonControlsEx( &ccs ); // Initialize my home grown atomic operators AtomicInit(); CComModule::Init( p, h ); } void CTapiModule::Term() { RELEASE_UNK( m_pAVTapi ); RELEASE_UNK( m_pAVGenNot ); // Release atomic operations AtomicTerm(); CComModule::Term(); } bool CTapiModule::StartupThreads() { if ( AtomicSeizeToken(m_lInit) ) { ATLTRACE(_T(".enter.CTapiModule::StartupThreads().\n") ); m_hEventThread = CreateEvent( NULL, FALSE, FALSE, NULL ); m_hEventThreadWakeUp = CreateEvent( NULL, FALSE, FALSE, NULL); DWORD dwID; HANDLE hThread = CreateThread( NULL, 0, ThreadRendezvousProc, (void *) NULL, NULL, &dwID ); if ( hThread ) CloseHandle( hThread ); if ( m_hEventThread && m_hEventThreadWakeUp ) return true; } // Clear out handles and exit CLOSEHANDLE( m_hEventThread ); CLOSEHANDLE( m_hEventThreadWakeUp ); return false; } void CTapiModule::ShutdownThreads() { ATLTRACE(_T(".enter.CTapiModule::ShutdownThreads().\n")); if ( AtomicReleaseToken(m_lInit) ) { BOOL bReset = ResetEvent( m_hEventThread ); while ( m_lNumThreads ) { ATLTRACE(_T(".1.CTapiModule::ShutdownThreads() -- thread count = %ld\n"), m_lNumThreads ); SetEvent( m_hEventThreadWakeUp ); if ( WaitForSingleObject(m_hEventThread, 5000) == WAIT_TIMEOUT ) { ATLTRACE(_T(".error.CTapiModule::ShutdownThreads() -- timed out waiting for threads.\n") ); KillThreads(); break; } } Sleep(0); CLOSEHANDLE( m_hEventThread ); CLOSEHANDLE( m_hEventThreadWakeUp ); ATLTRACE(_T(".1.CTapiModule::ShutdownThreads() -- SUCCESSFUL shutdown.\n") ); } } HRESULT CTapiModule::get_AVGenNot( IAVGeneralNotification **pp ) { HRESULT hr = E_FAIL; Lock(); if ( m_pAVGenNot ) hr = (dynamic_cast<IUnknown *> (m_pAVGenNot))->QueryInterface(IID_IAVGeneralNotification, (void **) pp ); Unlock(); return hr; } void CTapiModule::SetAVGenNot( CAVGeneralNotification *p ) { Lock(); RELEASE_UNK( m_pAVGenNot ); if ( p ) { m_pAVGenNot = p; (dynamic_cast<IUnknown *> (m_pAVGenNot))->AddRef(); } Unlock(); } void CTapiModule::SetAVTapi( CAVTapi *p ) { Lock(); RELEASE_UNK( m_pAVTapi ); if ( p ) { m_pAVTapi = p; (dynamic_cast<IUnknown *> (m_pAVTapi))->AddRef(); } Unlock(); } HRESULT CTapiModule::get_AVTapi( IAVTapi **pp ) { HRESULT hr = E_FAIL; Lock(); if ( m_pAVTapi ) hr = (dynamic_cast<IUnknown *> (m_pAVTapi))->QueryInterface(IID_IAVTapi, (void **) pp ); Unlock(); return hr; } HRESULT CTapiModule::GetAVTapi( CAVTapi **pp ) { HRESULT hr = E_FAIL; Lock(); if ( m_pAVTapi ) { *pp = m_pAVTapi; (dynamic_cast<IUnknown *> (m_pAVTapi))->AddRef(); hr = S_OK; } Unlock(); return hr; } int CTapiModule::DoMessageBox( UINT nIDS, UINT nType, bool bUseActiveWnd ) { TCHAR szText[255]; LoadString( GetResourceInstance(), nIDS, szText, ARRAYSIZE(szText) ); return DoMessageBox( szText, nType, bUseActiveWnd ); } int CTapiModule::DoMessageBox( const TCHAR *pszText, UINT nType, bool bUseActiveWnd ) { TCHAR szTitle[50]; LoadString( GetResourceInstance(), IDS_PROJNAME, szTitle, ARRAYSIZE(szTitle) ); return ::MessageBox( (bUseActiveWnd) ? GetActiveWindow() : GetParentWnd(), pszText, szTitle, nType ); } DWORD CTapiModule::GuessAddressType( LPCTSTR pszText ) { DWORD dwRet = LINEADDRESSTYPE_DOMAINNAME; int nLen = _tcslen( pszText ); if ( pszText && nLen ) { if ( IsPhoneNumber(nLen, pszText) ) dwRet = LINEADDRESSTYPE_PHONENUMBER; else if ( IsMachineName(nLen, pszText) ) dwRet = LINEADDRESSTYPE_DOMAINNAME; else if ( IsIPAddress(nLen, pszText) ) dwRet = LINEADDRESSTYPE_IPADDRESS; else if ( IsEmailAddress(nLen, pszText) ) dwRet = LINEADDRESSTYPE_EMAILNAME; } // ATLTRACE(".1.CTapiModule::GuessAddressType() returning %lx.\n", dwRet); return dwRet; } bool CTapiModule::IsMachineName( int nLen, LPCTSTR pszText ) { // Double backslash is all it takes TCHAR szText[50]; LoadString( _Module.GetResourceInstance(), IDS_STR_MACHINENAME_PARTS, szText, ARRAYSIZE(szText) ); return (bool) ((nLen > 2) && !_tcsncmp(pszText, szText, 2)); } bool CTapiModule::IsIPAddress( int nLen, LPCTSTR pszText ) { // All numbers and .'s TCHAR szText[50]; LoadString( _Module.GetResourceInstance(), IDS_STR_TCPIP_PARTS, szText, ARRAYSIZE(szText) ); return (bool) (_tcsspn(pszText, szText) == nLen); } bool CTapiModule::IsEmailAddress( int nLen, LPCTSTR pszText ) { TCHAR szText[50]; LoadString( _Module.GetResourceInstance(), IDS_STR_EMAIL_PARTS, szText, ARRAYSIZE(szText) ); return (bool) (_tcscspn(pszText, szText) < nLen); } bool CTapiModule::IsPhoneNumber( int nLen, LPCTSTR pszText ) { _ASSERT( pszText ); TCHAR szText[50]; LoadString( _Module.GetResourceInstance(), IDS_STR_PHONE_PARTS, szText, ARRAYSIZE(szText) ); if ( (pszText[0] == _T('x')) || (pszText[0] == _T('X')) ) return (bool) (_tcsspn((LPCTSTR) (pszText + 1), szText) == (nLen - 1) ); return (bool) (_tcsspn(pszText, szText) == nLen); } void CTapiModule::AddThread( HANDLE hThread ) { m_critThreadIDs.Lock(); m_lstThreadIDs.push_back( hThread ); ::InterlockedIncrement( &m_lNumThreads ); m_critThreadIDs.Unlock(); } void CTapiModule::RemoveThread( HANDLE hThread ) { m_critThreadIDs.Lock(); THREADIDLIST::iterator i, iEnd = m_lstThreadIDs.end(); for ( i = m_lstThreadIDs.begin(); i != iEnd; i++ ) { if ( *i == hThread ) { m_lstThreadIDs.erase( i ); ::InterlockedDecrement( &m_lNumThreads ); CloseHandle( hThread ); break; } } m_critThreadIDs.Unlock(); } void CTapiModule::KillThreads() { m_critThreadIDs.Lock(); THREADIDLIST::iterator i, iEnd = m_lstThreadIDs.end(); for ( i = m_lstThreadIDs.begin(); i != iEnd; i++ ) { ATLTRACE( _T(".error.CTapiModule::KillThreads() -- killing thread %d!!!!!!!\n"), *i ); TerminateThread( *i, -1 ); CloseHandle( *i ); } EMPTY_LIST( m_lstThreadIDs ); m_critThreadIDs.Unlock(); }