/*++ Copyright (c) 1997-1999 Microsoft Corporation Module Name: address.cpp Abstract: Implementation of the Address object for TAPI 3.0. Author: mquinton - 4/17/97 Notes: optional-notes Revision History: --*/ #include "stdafx.h" #include "uuids.h" #include "TermEvnt.h" #include "tapievt.h" const CLSID CLSID_WAVEMSP = {0x4DDB6D36,0x3BC1,0x11d2,{0x86,0xF2,0x00,0x60,0x08,0xB0,0xE5,0xD2}}; extern HRESULT mapTAPIErrorCode(long lErrorCode); extern ULONG_PTR GenerateHandleAndAddToHashTable( ULONG_PTR Element); extern void RemoveHandleFromHashTable(ULONG_PTR dwHandle); extern CHashTable * gpHandleHashTable; extern CRetryQueue * gpRetryQueue; extern HANDLE ghAsyncRetryQueueEvent; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // WAITORTIMERCALLBACK // CAddress::MSPEventCallback( // PVOID pContext, // BOOLEAN b // ) // // this is the callback that gets called when an msp // sets it's message event // // queues a message to be handled in the callback thread // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= VOID NTAPI MSPEventCallback( VOID * pContext, BOOLEAN bFlag ) { CAddress * pAddress; HRESULT hr; gpHandleHashTable->Lock(); hr = gpHandleHashTable->Find( (ULONG_PTR)pContext, (ULONG_PTR *)&pAddress ); if ( SUCCEEDED(hr) ) { LOG((TL_INFO, "MSPEventCallback - Matched handle %p to Address object %p", pContext, pAddress )); ASYNCEVENTMSG msg; DWORD dwAddressHandle; pAddress->AddRef(); gpHandleHashTable->Unlock(); dwAddressHandle = CreateHandleTableEntry ((ULONG_PTR)pAddress); if (0 != dwAddressHandle) { ZeroMemory( &msg, sizeof(msg) ); msg.TotalSize = sizeof(msg); msg.Msg = PRIVATE_MSPEVENT; msg.Param1 = dwAddressHandle; // // try to queue the event // BOOL bQueueEventSuccess = gpRetryQueue->QueueEvent(&msg); if (bQueueEventSuccess) { SetEvent(ghAsyncRetryQueueEvent); } else { // // RetryQueue is either no longer accepting entries or // failed to allocate resources it needed. // // in any case, the event will not be processed. cleanup. // DeleteHandleTableEntry (dwAddressHandle); pAddress->Release(); pAddress = NULL; LOG((TL_ERROR, "MSPEventCallback - Couldn't enqueue event")); } } } else { LOG((TL_ERROR, "MSPEventCallback - Couldn't match handle %p to Address object ", pContext)); gpHandleHashTable->Unlock(); } } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // void HandlePrivateMSPEvent( PASYNCEVENTMSG pParams ) // // actually handles the msp event. this is called in the // asynceventsthread // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= void HandlePrivateMSPEvent( PASYNCEVENTMSG pParams ) { CAddress * pAddress; pAddress = (CAddress *) GetHandleTableEntry(pParams->Param1); DeleteHandleTableEntry (pParams->Param1); if (NULL != pAddress) { pAddress->MSPEvent(); // // address is addref'd when event // is packaged. // pAddress->Release(); } } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Class : CEventMasks // Method : SetSubEventFlag // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CEventMasks::SetSubEventFlag( DWORD dwEvent, // The event DWORD dwFlag, // The flag that should be set BOOL bEnable ) { // // Enter critical section // //m_cs.Lock(); // // Prepare the subevent flag // DWORD dwSubEventFlag = 0; dwSubEventFlag = (dwFlag == EM_ALLSUBEVENTS ) ? EM_ALLSUBEVENTS : GET_SUBEVENT_FLAG( dwFlag ); // // Set the mask for the events // switch( dwEvent ) { case EM_ALLEVENTS: case TE_TAPIOBJECT: if( bEnable ) { // Set the bit m_dwTapiObjectMask = m_dwTapiObjectMask | dwSubEventFlag; } else { // Reset the bit m_dwTapiObjectMask = m_dwTapiObjectMask & ( ~dwSubEventFlag ); } if( dwEvent == TE_TAPIOBJECT) { break; } case TE_ADDRESS: if( bEnable ) { // Set the bit m_dwAddressMask = m_dwAddressMask | dwSubEventFlag; } else { // Reset the bit m_dwAddressMask = m_dwAddressMask & ( ~dwSubEventFlag ); } if( dwEvent == TE_ADDRESS) { break; } case TE_CALLNOTIFICATION: if( bEnable ) { // Set the bit m_dwCallNotificationMask = m_dwCallNotificationMask | dwSubEventFlag; } else { // Reset the bit m_dwCallNotificationMask = m_dwCallNotificationMask & ( ~dwSubEventFlag ); } if( dwEvent == TE_CALLNOTIFICATION) { break; } case TE_CALLSTATE: if( bEnable ) { // Set the bit m_dwCallStateMask = m_dwCallStateMask | dwSubEventFlag; } else { // Reset the bit m_dwCallStateMask = m_dwCallStateMask & ( ~dwSubEventFlag ); } if( dwEvent == TE_CALLSTATE) { break; } case TE_CALLMEDIA: if( bEnable ) { // Set the bit m_dwCallMediaMask = m_dwCallMediaMask | dwSubEventFlag; } else { // Reset the bit m_dwCallMediaMask = m_dwCallMediaMask & ( ~dwSubEventFlag ); } if( dwEvent == TE_CALLMEDIA) { break; } case TE_CALLHUB: if( bEnable ) { // Set the bit m_dwCallHubMask = m_dwCallHubMask | dwSubEventFlag; } else { // Reset the bit m_dwCallHubMask = m_dwCallHubMask & ( ~dwSubEventFlag ); } if( dwEvent == TE_CALLHUB) { break; } case TE_CALLINFOCHANGE: if( bEnable ) { // Set the bit m_dwCallInfoChangeMask = m_dwCallInfoChangeMask | dwSubEventFlag; } else { // Reset the bit m_dwCallInfoChangeMask = m_dwCallInfoChangeMask & ( ~dwSubEventFlag ); } if( dwEvent == TE_CALLINFOCHANGE) { break; } case TE_QOSEVENT: if( bEnable ) { // Set the bit m_dwQOSEventMask = m_dwQOSEventMask | dwSubEventFlag; } else { // Reset the bit m_dwQOSEventMask = m_dwQOSEventMask & ( ~dwSubEventFlag ); } if( dwEvent == TE_QOSEVENT) { break; } case TE_FILETERMINAL: if( bEnable ) { // Set the bit m_dwFileTerminalMask = m_dwFileTerminalMask | dwSubEventFlag; } else { // Reset the bit m_dwFileTerminalMask = m_dwFileTerminalMask & ( ~dwSubEventFlag ); } if( dwEvent == TE_FILETERMINAL) { break; } case TE_PRIVATE: if( bEnable ) { // Set the entire mask m_dwPrivateMask = EM_ALLSUBEVENTS; } else { // Reset the entire mask m_dwPrivateMask = 0; } if( dwEvent == TE_PRIVATE) { break; } case TE_ADDRESSDEVSPECIFIC: if( bEnable ) { // Set the bit m_dwAddressDevSpecificMask = m_dwAddressDevSpecificMask | dwSubEventFlag; } else { // Reset the bit m_dwAddressDevSpecificMask = m_dwAddressDevSpecificMask & ( ~dwSubEventFlag ); } if( dwEvent == TE_ADDRESSDEVSPECIFIC) { break; } case TE_PHONEDEVSPECIFIC: if( bEnable ) { // Set the bit m_dwPhoneDevSpecificMask = m_dwPhoneDevSpecificMask | dwSubEventFlag; } else { // Reset the bit m_dwPhoneDevSpecificMask = m_dwPhoneDevSpecificMask & ( ~dwSubEventFlag ); } if( dwEvent == TE_PHONEDEVSPECIFIC) { break; } } // // Leave critical section // //m_cs.Unlock(); return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Class : CEventMasks // Method : GetSubEventFlag // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CEventMasks::GetSubEventFlag( DWORD dwEvent, // The event DWORD dwFlag, // The flag that should be setted BOOL* pEnable ) { // // Enter critical section // //m_cs.Lock(); // // Prepare the subevent flag // DWORD dwSubEventFlag = 0; dwSubEventFlag = GET_SUBEVENT_FLAG( dwFlag ); // // Reset thre flag // *pEnable = FALSE; // // Get the flag for the events // switch( dwEvent ) { case TE_TAPIOBJECT: *pEnable = ((m_dwTapiObjectMask & dwSubEventFlag) != 0); break; case TE_ADDRESS: *pEnable = ((m_dwAddressMask & dwSubEventFlag) != 0); break; case TE_CALLNOTIFICATION: *pEnable = ((m_dwCallNotificationMask & dwSubEventFlag) != 0); break; case TE_CALLSTATE: *pEnable = ((m_dwCallStateMask & dwSubEventFlag) != 0); break; case TE_CALLMEDIA: *pEnable = ((m_dwCallMediaMask & dwSubEventFlag) != 0); break; case TE_CALLHUB: *pEnable = ((m_dwCallHubMask & dwSubEventFlag) != 0); break; case TE_CALLINFOCHANGE: *pEnable = ((m_dwCallInfoChangeMask & dwSubEventFlag) != 0); break; case TE_QOSEVENT: *pEnable = ((m_dwQOSEventMask & dwSubEventFlag) != 0); break; case TE_FILETERMINAL: *pEnable = ((m_dwFileTerminalMask & dwSubEventFlag) != 0); break; case TE_PRIVATE: // We don't have subevents for private events *pEnable = ( m_dwPrivateMask != 0); break; case TE_ADDRESSDEVSPECIFIC: // We don't have subevents for TE_ADDRESSDEVSPECIFIC events *pEnable = ( m_dwAddressDevSpecificMask != 0); break; case TE_PHONEDEVSPECIFIC: // We don't have subevents for TE_PHONEDEVSPECIFIC events *pEnable = ( m_dwPhoneDevSpecificMask != 0); break; } // // Leave critical section // //m_cs.Unlock(); return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Class : CEventMasks // Method : GetSubEventMask // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ DWORD CEventMasks::GetSubEventMask( TAPI_EVENT TapiEvent ) { // // Enter critical section // //m_cs.Lock(); DWORD dwSubEventMask = EM_NOSUBEVENTS; switch( TapiEvent ) { case TE_TAPIOBJECT: dwSubEventMask = m_dwTapiObjectMask; break; case TE_ADDRESS: dwSubEventMask = m_dwAddressMask; break; case TE_CALLNOTIFICATION: dwSubEventMask = m_dwCallNotificationMask; break; case TE_CALLSTATE: dwSubEventMask = m_dwCallStateMask; break; case TE_CALLMEDIA: dwSubEventMask = m_dwCallMediaMask; break; case TE_CALLHUB: dwSubEventMask = m_dwCallHubMask; break; case TE_CALLINFOCHANGE: dwSubEventMask = m_dwCallInfoChangeMask; break; case TE_QOSEVENT: dwSubEventMask = m_dwQOSEventMask; break; case TE_FILETERMINAL: dwSubEventMask = m_dwFileTerminalMask; break; case TE_PRIVATE: dwSubEventMask = m_dwPrivateMask; break; case TE_ADDRESSDEVSPECIFIC: dwSubEventMask = m_dwAddressDevSpecificMask; break; case TE_PHONEDEVSPECIFIC: dwSubEventMask = m_dwPhoneDevSpecificMask; break; default: dwSubEventMask = EM_NOSUBEVENTS; break; } // // Leave critical section // //m_cs.Unlock(); return dwSubEventMask; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Class : CEventMasks // Method : IsSubEventValid // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ BOOL CEventMasks::IsSubEventValid( TAPI_EVENT TapiEvent, DWORD dwSubEvent, BOOL bAcceptAllSubEvents, BOOL bCallLevel ) { BOOL bValid = TRUE; switch( TapiEvent ) { case TE_TAPIOBJECT: // // Just at the address level // if( bCallLevel) { bValid = FALSE; break; } // // ALLSUBEVENTS // if( bAcceptAllSubEvents ) { // // We could accept 'ALLSUBEVENTS' flag // when we try to set for all subevents // if(dwSubEvent == EM_ALLSUBEVENTS) { break; } } // // In CTapiObjectEvent::get_Address we accept just // these three subevents // if( (dwSubEvent != TE_ADDRESSCREATE) && (dwSubEvent != TE_ADDRESSREMOVE) && (dwSubEvent != TE_ADDRESSCLOSE) ) { bValid = FALSE; } break; case TE_ADDRESS: // // Just at the address level // if( bCallLevel) { bValid = FALSE; break; } // // ALLSUBEVENTS // if( bAcceptAllSubEvents ) { // // We could accept 'ALLSUBEVENTS' flag // when we try to set for all subevents // if(dwSubEvent == EM_ALLSUBEVENTS) { break; } } if( AE_LASTITEM < dwSubEvent ) { bValid = FALSE; } break; case TE_CALLNOTIFICATION: // // Just at the address level // if( bCallLevel ) { bValid = FALSE; break; } // // Accept at address and call level // ALLSUBEVENTS // if( bAcceptAllSubEvents ) { // // We could accept 'ALLSUBEVENTS' flag // when we try to set for all subevents // if(dwSubEvent == EM_ALLSUBEVENTS) { break; } } if( CNE_LASTITEM < dwSubEvent ) { bValid = FALSE; } break; case TE_CALLSTATE: // // Accept at address and call level // ALLSUBEVENTS // if( bAcceptAllSubEvents ) { // // We could accept 'ALLSUBEVENTS' flag // when we try to set for all subevents // if(dwSubEvent == EM_ALLSUBEVENTS) { break; } } if( CS_LASTITEM < dwSubEvent ) { bValid = FALSE; } break; case TE_CALLMEDIA: // // Accept at address and call level // ALLSUBEVENTS // if( bAcceptAllSubEvents ) { // // We could accept 'ALLSUBEVENTS' flag // when we try to set for all subevents // if(dwSubEvent == EM_ALLSUBEVENTS) { break; } } if( CME_LASTITEM < dwSubEvent ) { bValid = FALSE; } break; case TE_CALLHUB: // // Accept at address and call level // ALLSUBEVENTS // if( bAcceptAllSubEvents ) { // // We could accept 'ALLSUBEVENTS' flag // when we try to set for all subevents // if(dwSubEvent == EM_ALLSUBEVENTS) { break; } } if( CHE_LASTITEM < dwSubEvent ) { bValid = FALSE; } break; case TE_CALLINFOCHANGE: // // Accept at address and call level // ALLSUBEVENTS // if( bAcceptAllSubEvents ) { // // We could accept 'ALLSUBEVENTS' flag // when we try to set for all subevents // if(dwSubEvent == EM_ALLSUBEVENTS) { break; } } if( CIC_LASTITEM < dwSubEvent ) { bValid = FALSE; } break; case TE_QOSEVENT: // // Accept at address and call level // ALLSUBEVENTS // if( bAcceptAllSubEvents ) { // // We could accept 'ALLSUBEVENTS' flag // when we try to set for all subevents // if(dwSubEvent == EM_ALLSUBEVENTS) { break; } } if( QE_LASTITEM < dwSubEvent ) { bValid = FALSE; } break; case TE_FILETERMINAL: // // Accept at address and call level // ALLSUBEVENTS // if( bAcceptAllSubEvents ) { // // We could accept 'ALLSUBEVENTS' flag // when we try to set for all subevents // if(dwSubEvent == EM_ALLSUBEVENTS) { break; } } if( TMS_LASTITEM < dwSubEvent ) { bValid = FALSE; } break; case TE_PRIVATE: case TE_ADDRESSDEVSPECIFIC: case TE_PHONEDEVSPECIFIC: // // Accept at address and call level // ALLSUBEVENTS // if( bAcceptAllSubEvents ) { // // We could accept 'ALLSUBEVENTS' flag // when we try to set for all subevents // if(dwSubEvent == EM_ALLSUBEVENTS) { break; } } else { // we accept just all subevents because // we don't have subevents bValid = TRUE; break; } break; default: // // Invalid event type // bValid = FALSE; break; } LOG((TL_TRACE, "IsSubEventValid - exit %d", bValid)); return bValid; } HRESULT CEventMasks::CopyEventMasks( CEventMasks* pEventMasks ) { // // Enter critical section // //m_cs.Lock(); pEventMasks->m_dwTapiObjectMask = m_dwTapiObjectMask; pEventMasks->m_dwAddressMask = m_dwAddressMask; pEventMasks->m_dwCallNotificationMask = m_dwCallNotificationMask; pEventMasks->m_dwCallStateMask = m_dwCallStateMask; pEventMasks->m_dwCallMediaMask = m_dwCallMediaMask; pEventMasks->m_dwCallHubMask = m_dwCallHubMask; pEventMasks->m_dwCallInfoChangeMask = m_dwCallInfoChangeMask; pEventMasks->m_dwQOSEventMask = m_dwQOSEventMask; pEventMasks->m_dwFileTerminalMask = m_dwFileTerminalMask; pEventMasks->m_dwPrivateMask = m_dwPrivateMask; pEventMasks->m_dwAddressDevSpecificMask = m_dwAddressDevSpecificMask; pEventMasks->m_dwPhoneDevSpecificMask = m_dwPhoneDevSpecificMask; // // Leave critical section // //m_cs.Unlock(); return S_OK; } ULONG64 CEventMasks::GetTapiSrvEventMask( IN BOOL bCallLevel ) { // // Convert flags to server side 64 bit masks // ULONG64 ulEventMask = EM_LINE_CALLSTATE | // TE_CALLSTATE EM_LINE_APPNEWCALL | // TE_CALLNOTIFICATION EM_PHONE_CLOSE | // TE_PHONEEVENT EM_PHONE_STATE | // TE_PHONEEVENT EM_PHONE_BUTTONMODE | // TE_PHONEEVENT EM_PHONE_BUTTONSTATE | // TE_PHONEVENT EM_LINE_APPNEWCALLHUB | // TE_CALLHUB EM_LINE_CALLHUBCLOSE | // TE_CALLHUB EM_LINE_CALLINFO; // TE_CALLINFOCHAnGE BOOL bEnable = FALSE; if( !bCallLevel) { // // These flags will be not read if we // ask for call level // // TE_TAPIOBJECT - TE_ADDRESSCREATE // At address level GetSubEventFlag(TE_TAPIOBJECT, TE_ADDRESSCREATE, &bEnable); if( bEnable ) { ulEventMask |= EM_LINE_CREATE; } // TE_TAPIOBJECT - TE_ADDRESSREMOVE // At address level GetSubEventFlag(TE_TAPIOBJECT, TE_ADDRESSREMOVE, &bEnable); if( bEnable ) { ulEventMask |= EM_LINE_REMOVE; } // TE_TAPIOBJECT - TE_ADDRESSCLOSE // At address level GetSubEventFlag(TE_TAPIOBJECT, TE_ADDRESSCLOSE, &bEnable); if( bEnable ) { ulEventMask |= EM_LINE_CLOSE; } // AE_NEWTERMINAL : ignore private MSP events // AE_REMOVETERMINAL : ignore private MSP events // // We read also the flags for call level, // so go ahead. } // TE_CALLNOTIFICATION - CNE_OWNER // At call level // We pass EM_LINE_APPNEWCALL for TE_CALLNOTIFICATION everytime because // we need this events for internal TAPI3 status // See ulEventMask declaration // TE_CALLSTATE - All the subevents // At call level // We always pass EM_LINE_CALLSTATE for TE_CALLSTATE because // we need this event for internal TAPI3 status // See ulEventMask declaration // TE_CALLHUB - CHE_CALLHUBNEW // At call level // We always pass EM_LINE_APPNEWCALLHUB, EM_LINE_CALLHUBCLOSE // for TE_CALLHUB because // we need this event for internal TAPI3 status // See ulEventMask declaration // TE_CALLINFOCHANGE - All the subevents // At call level // We always pass EM_LINE_CALLINFO for TE_CALLINFOChANGE because // we need this event for internal TAPI3 status // See ulEventMask declaration // TE_QOSEVENT - All the subevents // At call level if ( m_dwQOSEventMask ) { ulEventMask |= EM_LINE_QOSINFO; } if ( m_dwAddressDevSpecificMask ) { ulEventMask |= EM_LINE_DEVSPECIFIC | EM_LINE_DEVSPECIFICEX; } if ( m_dwPhoneDevSpecificMask ) { ulEventMask |= EM_PHONE_DEVSPECIFIC; } // TE_FILTETERMIAL it is an MSP stuff // TE_PRIVATE it is an SMP stuff return ulEventMask; } DWORD CEventMasks::GetTapiSrvLineStateMask() { // // These flags shuld be read just // at address level // DWORD dwLineDevStateSubMasks = 0; BOOL bEnable = FALSE; // TE_ADDRESS - AE_STATE // At address level GetSubEventFlag(TE_ADDRESS, AE_STATE, &bEnable); if( bEnable ) { dwLineDevStateSubMasks |= LINEDEVSTATE_CONNECTED | LINEDEVSTATE_INSERVICE | LINEDEVSTATE_OUTOFSERVICE | LINEDEVSTATE_MAINTENANCE | LINEDEVSTATE_REMOVED | LINEDEVSTATE_DISCONNECTED | LINEDEVSTATE_LOCK | LINEDEVSTATE_MSGWAITON | LINEDEVSTATE_MSGWAITOFF ; } // TE_ADDRESS - AE_CAPSCHANGE // At address level GetSubEventFlag(TE_ADDRESS, AE_CAPSCHANGE, &bEnable); if( bEnable ) { dwLineDevStateSubMasks |= LINEDEVSTATE_CAPSCHANGE; } // TE_ADDRESS - AE_RINGING // At address level GetSubEventFlag(TE_ADDRESS, AE_RINGING, &bEnable); if( bEnable ) { dwLineDevStateSubMasks |= LINEDEVSTATE_RINGING; } // TE_ADDRESS - AE_CONFIGCHANGE // At address level GetSubEventFlag(TE_ADDRESS, AE_CONFIGCHANGE, &bEnable); if( bEnable ) { dwLineDevStateSubMasks |= LINEDEVSTATE_CONFIGCHANGE; } return dwLineDevStateSubMasks; } DWORD CEventMasks::GetTapiSrvAddrStateMask() { // // These flags should be read just // at address level // DWORD dwAddrStateSubMasks = 0; BOOL bEnable = FALSE; // TE_ADDRESS - AE_CAPSCHANGE // Address level GetSubEventFlag(TE_ADDRESS, AE_CAPSCHANGE, &bEnable); if( bEnable ) { dwAddrStateSubMasks |= LINEADDRESSSTATE_CAPSCHANGE | LINEDEVSTATE_CAPSCHANGE; } // TE_ADDRESS - AE_FORWARD // Address level GetSubEventFlag(TE_ADDRESS, AE_FORWARD, &bEnable); if( bEnable ) { dwAddrStateSubMasks |= LINEADDRESSSTATE_FORWARD; } return dwAddrStateSubMasks; } /*++ SetTapiSrvAddressEventMask Set the event mask to the TapiSrv level for an address It's called immediatly after we open a line --*/ HRESULT CEventMasks::SetTapiSrvAddressEventMask( IN HLINE hLine ) { LOG((TL_TRACE, "SetTapiSrvAddressEventMask - Enter")); HRESULT hr = E_FAIL; // // Get the TapiSrvEvent masks // ULONG64 ulEventMasks = 0; DWORD dwLineDevStateSubMasks = 0; DWORD dwAddrStateSubMasks = 0; ulEventMasks = GetTapiSrvEventMask( FALSE // Address level ); LOG((TL_INFO, "GetTapiSrvEventMask returns %x", ulEventMasks)); dwLineDevStateSubMasks = GetTapiSrvLineStateMask(); LOG((TL_INFO, "GetTapiSrvLineStateMask returns %x", dwLineDevStateSubMasks)); dwAddrStateSubMasks = GetTapiSrvAddrStateMask(); LOG((TL_INFO, "GetTapiSrvAddrStateMask returns %x", dwAddrStateSubMasks)); hr = tapiSetEventFilterMasks ( TAPIOBJ_HLINE, hLine, ulEventMasks ); if (hr == 0) { hr = tapiSetEventFilterSubMasks ( TAPIOBJ_HLINE, hLine, EM_LINE_LINEDEVSTATE, dwLineDevStateSubMasks ); } if (hr == 0) { hr = tapiSetEventFilterSubMasks ( TAPIOBJ_HLINE, hLine, EM_LINE_ADDRESSSTATE, dwAddrStateSubMasks ); } if (hr != 0) { hr = mapTAPIErrorCode(hr); LOG((TL_ERROR, "CEventMasks::SetTapiSrvAddressEventMask - failed TapiSrv 0x%08x", hr)); // Leave critical section return hr; } LOG((TL_TRACE, "SetTapiSrvAddressEventMask - Exit 0x%08x", hr)); return hr; } HRESULT CEventMasks::SetTapiSrvCallEventMask( IN HCALL hCall ) { LOG((TL_TRACE, "SetTapiSrvCallEventMask - Enter. call handle[%lx]", hCall)); HRESULT hr = E_FAIL; // // Get the TapiSrvEvent masks // ULONG64 ulEventMasks = 0; ulEventMasks = GetTapiSrvEventMask( TRUE // Call level ); LOG((TL_INFO, "GetTapiSrvEventMask returns %x", ulEventMasks)); hr = tapiSetEventFilterMasks ( TAPIOBJ_HCALL, hCall, ulEventMasks ); if (hr != 0) { LOG((TL_ERROR, "CEventMasks::SetTapiSrvCallEventMaskr - TapiSrv failed 0x%08x", hr)); return hr; } LOG((TL_TRACE, "SetTapiSrvCallEventMask - Exit 0x%08x", hr)); return hr; } // // ITAddress methods // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // get_State // // retries the current ADDRESS_STATE of the address // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= HRESULT STDMETHODCALLTYPE CAddress::get_State( ADDRESS_STATE * pAddressState ) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_State enter" )); if (TAPIIsBadWritePtr( pAddressState, sizeof( ADDRESS_STATE ) ) ) { LOG((TL_ERROR, "get_State - bad pointer")); return E_POINTER; } Lock(); *pAddressState = m_AddressState; Unlock(); LOG((TL_TRACE, "get_State exit - return %lx", hr)); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // GetAddressName // Copy address name to ppName // The application must free the name returned through sysfreestirng. // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT STDMETHODCALLTYPE CAddress::get_AddressName( BSTR * ppName ) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_AddressName enter" )); LOG((TL_TRACE, " ppName --------->%p", ppName )); if ( TAPIIsBadWritePtr( ppName, sizeof( BSTR ) ) ) { LOG((TL_ERROR, "get_AddressName - bad pointer")); return E_POINTER; } Lock(); if ( m_dwAddressFlags & ADDRESSFLAG_DEVCAPSCHANGE ) { hr = UpdateLineDevCaps(); if ( SUCCEEDED(hr) ) { hr = SaveAddressName( m_pDevCaps ); } m_dwAddressFlags &= ~ADDRESSFLAG_DEVCAPSCHANGE; } *ppName = SysAllocString( m_szAddressName ); Unlock(); if (NULL == *ppName) { LOG((TL_ERROR, "get_AddressName exit - return E_OUTOFMEMORY")); return E_OUTOFMEMORY; } LOG((TL_TRACE, "get_AddressName exit - return %lx", hr )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // get_ServiceProviderName // Get the name of the service provider that owns this line/ // address. // Note that we don't get the name on startup - we only get // it if it is requested. This shouldn't be used too often. // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT STDMETHODCALLTYPE CAddress::get_ServiceProviderName( BSTR * ppName ) { HRESULT hr = S_OK; LPVARSTRING pVarString = NULL; DWORD dwProviderID; LPLINEPROVIDERLIST pProviderList = NULL; LOG((TL_TRACE, "get_ServiceProviderName enter" )); if (TAPIIsBadWritePtr( ppName, sizeof( BSTR ) ) ) { LOG((TL_ERROR, "get_ServiceProviderName - bad pointer")); return E_POINTER; } Lock(); // // if we have already determined the sp name, // just return it. // if (NULL != m_szProviderName) { *ppName = SysAllocString( m_szProviderName ); Unlock(); if (NULL == *ppName) { LOG((TL_ERROR, "get_ServiceProviderName - alloc ppName failed" )); return E_OUTOFMEMORY; } LOG((TL_TRACE, "get_ServiceProviderName - exit - return SUCCESS" )); return S_OK; } Unlock(); // // get the provider list // hr = LineGetProviderList( &pProviderList ); if (S_OK != hr) { if (NULL != pProviderList ) { ClientFree( pProviderList ); } LOG((TL_ERROR, "get_ServiceProvideName - LineGetProviderList returned %lx", hr )); return hr; } LPLINEPROVIDERENTRY pProvEntry; PWSTR pszProviderName; DWORD dwCount; hr = S_OK; pProvEntry = (LPLINEPROVIDERENTRY)( ( (LPBYTE) pProviderList ) + pProviderList->dwProviderListOffset ); Lock(); // // make sure the name was not set by another thread while we were waiting // for the lock. if it was, do nothing. // if (NULL == m_szProviderName) { // // search through the list for the provider id, until done with all // providers or encounter an error // for ( dwCount = 0; dwCount < pProviderList->dwNumProviders; dwCount++ ) { if (pProvEntry->dwPermanentProviderID == m_dwProviderID) { // // it's a match! copy the name, if we can. // m_szProviderName = (PWSTR)ClientAlloc( pProvEntry->dwProviderFilenameSize + sizeof(WCHAR) ); if (NULL == m_szProviderName) { LOG((TL_ERROR, "get_ServiceProviderName - alloc m_szProviderName failed" )); hr = E_OUTOFMEMORY; } else { // // save it in the object // memcpy( m_szProviderName, ((LPBYTE)pProviderList) + pProvEntry->dwProviderFilenameOffset, pProvEntry->dwProviderFilenameSize ); } // // found a match. m_szProviderName contains the string, or hr // contains the error if failed. // break; } pProvEntry++; } // // did we find it? // if (dwCount == pProviderList->dwNumProviders) { LOG((TL_ERROR, "get_ServiceProviderName - could not find provider in list" )); // // if we looped through the whole list but did not find a match, hr // should still be S_OK // // assert to protect from future code changes erroneously // overwritingthe error code. // _ASSERTE(SUCCEEDED(hr)); // // couldn't find the provider. // hr = TAPI_E_NODRIVER; } } // if (NULL == m_szProviderName) // // if hr does not contain an error, the m_szProviderName must contain a // valid string // if (SUCCEEDED(hr)) { _ASSERTE( NULL != m_szProviderName ); *ppName = SysAllocString( m_szProviderName ); if (NULL == *ppName) { // // could not allocated string // LOG((TL_ERROR, "get_ServiceProviderName - failed to allocate memory for provider name string" )); hr = E_OUTOFMEMORY; } } Unlock(); ClientFree( pProviderList ); LOG((TL_TRACE, "get_ServiceProviderName exit - return %lx", hr)); return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // get_TAPIObject // // return the owning tapi object // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT STDMETHODCALLTYPE CAddress::get_TAPIObject( ITTAPI ** ppTapiObject ) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_TAPIObject enter" )); if (TAPIIsBadWritePtr( ppTapiObject, sizeof( ITTAPI * ) ) ) { LOG((TL_ERROR, "get_TAPIObject - bad pointer")); return E_POINTER; } *ppTapiObject = m_pTAPI; m_pTAPI->AddRef(); LOG((TL_TRACE, "get_TAPIObject exit - return %lx", hr )); return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // GetTapi // // private method to get the tapi object // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ CTAPI * CAddress::GetTapi(BOOL bAddRefTapi) { CTAPI * p = NULL; Lock(); // // get a pointer to tapi object // if( m_pTAPI != NULL ) { p = dynamic_cast(m_pTAPI); } // // addref tapi if needed and if possible // if ( (NULL != p) && bAddRefTapi) { // // we have an object and we need to addref it before returing // p->AddRef(); } Unlock(); LOG((TL_TRACE, "GetTapi - returning [%p]", p)); return p; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // InternalCreateCall // // called by a couple of places to create a call. // // pszDestAddress // destaddress of the call // // cp // current call privilege // // hCall // tapi2 call handle // // bExpose // is this a hidden call? // // ppCall // return call object here // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddress::InternalCreateCall( PWSTR pszDestAddress, long lAddressType, long lMediaType, CALL_PRIVILEGE cp, BOOL bNeedToNotify, HCALL hCall, BOOL bExpose, CCall ** ppCall ) { HRESULT hr; LOG((TL_TRACE, "InternalCreateCall enter" )); // // create & initialize a new call object // CComObject * pCall; hr = CComObject::CreateInstance( &pCall ); if (NULL == pCall) { LOG((TL_ERROR, "InternalCreateCall - could not create call instance" )); return E_OUTOFMEMORY; } // // initialize the call object. // // note: getting address lock while initializing a // call object can lead to deadlocks // hr = pCall->Initialize( this, pszDestAddress, lAddressType, lMediaType, cp, bNeedToNotify, bExpose, hCall, &m_EventMasks ); if (S_OK != hr) { delete pCall; LOG((TL_ERROR, "InternalCreateCall failed - Call object failed init - %lx", hr )); return hr; } // // serialize call creation with call cleanup (which happens when tapi tells // us it is being shutdown). // Lock(); // // tapi object already signaled shutdown? // if (m_bTapiSignaledShutdown) { Unlock(); // // tapi object already notified us of its shutdown and we already did // cleanup. no need to create any new calls // LOG((TL_ERROR, "InternalCreateCall - tapi object shut down. cannot create call" )); // // we have no use for the call object // pCall->Release(); if (bNeedToNotify) { // // compensate for the extra refcount added if bNeedToNotify is on // pCall->Release(); } pCall = NULL; return TAPI_E_WRONG_STATE; } if (bExpose) { ITCallInfo * pITCallInfo; pITCallInfo = dynamic_cast(pCall); // // save the call in this address's list // hr = AddCall( pITCallInfo ); } // // the call was created and initialized, it is now safe for call cleanup // logic to kick in if it was waiting for the lock // Unlock(); // // return it // *ppCall = pCall; LOG((TL_TRACE, "InternalCreateCall exit - return S_OK" )); return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // CreateCall // // An application calls this method to create an outgoing call object // // lpszDestAddress // DestAddress of the call // // ppCall // return call object here // // // returns // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT STDMETHODCALLTYPE CAddress::CreateCall( BSTR lpszDestAddress, long lAddressType, long lMediaType, ITBasicCallControl ** ppCall ) { HRESULT hr; CCall * pCall; LOG((TL_TRACE, "CreateCall enter" )); if (TAPIIsBadWritePtr( ppCall, sizeof(ITBasicCallControl *) ) ) { LOG((TL_ERROR, "CreateCall - bad pointer")); return E_POINTER; } if ((lpszDestAddress != NULL) && IsBadStringPtrW( lpszDestAddress, -1 )) // NULL is ok { LOG((TL_ERROR, "CreateCall - bad string")); return E_POINTER; } // // use internal function // hr = InternalCreateCall( lpszDestAddress, lAddressType, lMediaType, CP_OWNER, FALSE, NULL, TRUE, &pCall ); if (S_OK != hr) { LOG((TL_ERROR, "CreateCall - InternalCreateCall failed hr = %lx", hr)); return hr; } // // put result in out pointer - also // increments the ref count // hr = pCall->QueryInterface( IID_ITBasicCallControl, (void **) ppCall ); // // internalcreatecall has a reference - don't keep it // pCall->Release(); if (S_OK != hr) { LOG((TL_ERROR, "CreateCall - saving call failed" )); return hr; } LOG((TL_TRACE, "CreateCall exit - return SUCCESS" )); return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // get_Calls // return a collection of calls that this address currently // owns // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT STDMETHODCALLTYPE CAddress::get_Calls( VARIANT * pVariant ) { HRESULT hr; IDispatch * pDisp; LOG((TL_TRACE, "get_Calls enter" )); if (TAPIIsBadWritePtr( pVariant, sizeof(VARIANT) ) ) { LOG((TL_ERROR, "get_Calls - bad pointer")); return E_POINTER; } CComObject< CTapiCollection< ITCallInfo > > * p; CComObject< CTapiCollection< ITCallInfo > >::CreateInstance( &p ); if (NULL == p) { LOG((TL_ERROR, "get_Calls - could not create collection" )); return E_OUTOFMEMORY; } Lock(); // initialize hr = p->Initialize( m_CallArray ); Unlock(); if (S_OK != hr) { LOG((TL_ERROR, "get_Calls - could not initialize collection" )); delete p; return hr; } // get the IDispatch interface hr = p->_InternalQueryInterface( IID_IDispatch, (void **) &pDisp ); if (S_OK != hr) { LOG((TL_ERROR, "get_Calls - could not get IDispatch interface" )); delete p; return hr; } // put it in the variant VariantInit(pVariant); pVariant->vt = VT_DISPATCH; pVariant->pdispVal = pDisp; LOG((TL_TRACE, "get_Calls - exit - return %lx", hr )); return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // EnumerateCalls // returns an enumeration of calls the this address currently owns // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT STDMETHODCALLTYPE CAddress::EnumerateCalls( IEnumCall ** ppCallEnum ) { HRESULT hr = S_OK; LOG((TL_TRACE, "EnumerateCalls enter" )); LOG((TL_TRACE, " ppCallEnum----->%p", ppCallEnum )); if (TAPIIsBadWritePtr(ppCallEnum, sizeof( ppCallEnum ) ) ) { LOG((TL_ERROR, "EnumerateCalls - bad pointer")); return E_POINTER; } // // create the enumerator // CComObject< CTapiEnum< IEnumCall, ITCallInfo, &IID_IEnumCall > > * p; hr = CComObject< CTapiEnum< IEnumCall, ITCallInfo, &IID_IEnumCall > > ::CreateInstance( &p ); if (S_OK != hr) { LOG((TL_ERROR, "EnumerateCalls - could not create enum" )); return hr; } Lock(); // // initialize it with our call list // p->Initialize( m_CallArray ); Unlock(); // // return it // *ppCallEnum = p; LOG((TL_TRACE, "EnumerateCalls exit - return %lx", hr )); return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // FinalRelease // Clean up anything in the address object. // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void CAddress::FinalRelease() { CTAPI * pCTapi; LOG((TL_TRACE, "FinalRelease[%p] - enter", this)); Lock(); // remove from the handle hash table, so any more messages // from msp callback events are ignored // RemoveHandleFromHashTable(m_MSPContext); m_MSPContext = NULL; pCTapi = GetTapi(); if( NULL == pCTapi ) { LOG((TL_ERROR, "dynamic cast operation failed")); } else { pCTapi->InvalidateBuffer( BUFFERTYPE_LINEDEVCAP, (UINT_PTR)this ); pCTapi->InvalidateBuffer( BUFFERTYPE_ADDRCAP, (UINT_PTR)this ); } if ( NULL != m_szAddress ) { ClientFree( m_szAddress); m_szAddress = NULL; } if ( NULL != m_szAddressName) { LOG((TL_INFO, "FinalRelease - m_szAddressName is [%ls]", m_szAddressName )); ClientFree( m_szAddressName ); m_szAddressName = NULL; } if ( NULL != m_szProviderName ) { ClientFree( m_szProviderName ); m_szProviderName = NULL; } // // release calls // m_CallArray.Shutdown(); // // release terminals // m_TerminalArray.Shutdown(); // // release addresslines // PtrList::iterator l; for (l = m_AddressLinesPtrList.begin(); l != m_AddressLinesPtrList.end(); l++) { HRESULT hr; AddressLineStruct * pLine; pLine = (AddressLineStruct *)(*l); if (pLine == m_pCallHubTrackingLine) { // this line is used for call hub tracking // make sure we don't try and delete this again below m_pCallHubTrackingLine = NULL; } LineClose( &(pLine->t3Line) ); ClientFree (pLine); } if (m_pCallHubTrackingLine != NULL) { LineClose( &(m_pCallHubTrackingLine->t3Line) ); } // // free the msp // if ( NULL != m_pMSPAggAddress ) { ITMSPAddress * pMSPAddress = GetMSPAddress(); pMSPAddress->Shutdown(); pMSPAddress->Release(); m_pMSPAggAddress->Release(); m_pMSPAggAddress = NULL; } // // unregister the msp wait // event in the thread pool // if ( NULL != m_hWaitEvent ) { LOG((TL_TRACE, "FinalRelease - unregistering callback")); UnregisterWaitEx( m_hWaitEvent, INVALID_HANDLE_VALUE); m_hWaitEvent = NULL; } // // close the msp event // if ( NULL != m_hMSPEvent ) { CloseHandle(m_hMSPEvent ); } // // release the private object // if ( NULL != m_pPrivate ) { m_pPrivate->Release(); } m_pTAPI->Release(); m_pTAPI = NULL; Unlock(); LOG((TL_TRACE, "FinalRelease - exit")); } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // CreateWaveMSPObject // // special case - creates the wavemsp object // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CreateWaveMSPObject( IUnknown * pUnk, IUnknown ** ppMSPAggAddress ) { HRESULT hr = S_OK; LOG((TL_TRACE, "CreateWaveMSPObject - enter")); hr = CoCreateInstance( CLSID_WAVEMSP, pUnk, CLSCTX_INPROC_SERVER, IID_IUnknown, (void **) ppMSPAggAddress ); if (!SUCCEEDED(hr)) { LOG((TL_ERROR, "CreateWaveMSPObject failed to CoCreate - %lx", hr)); return hr; } LOG((TL_TRACE, "CreateWaveMSPObject - exit")); return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // CreateWaveInfo // // for a wave device address, get the wave device IDs to give // to the wavemsp // // First DWORD = Command Second DWORD Third DWORD // 0 Set wave IDs for call WaveIn ID WaveOut ID // 1 Start streaming // 2 Stop streaming // 3 Set wave IDs for address WaveIn ID WaveOut ID // 4 Wave IDS for address not available // 5 stop streaming because a blocking tapi functions was called // 6 // 7 // 8 full duplex support // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= HRESULT CreateWaveInfo( HLINE hLine, DWORD dwAddressID, HCALL hCall, DWORD dwCallSelect, BOOL bFullDuplex, LPDWORD pdwIDs ) { LPVARSTRING pVarString; HRESULT hr; if ( bFullDuplex ) { hr = LineGetID( hLine, dwAddressID, hCall, dwCallSelect, &pVarString, L"wave/in/out" ); if (!SUCCEEDED(hr)) { if (NULL != pVarString) { ClientFree( pVarString ); } LOG((TL_ERROR, "LineGetID failed for waveinout device - %lx", hr )); return hr; } pdwIDs[1] = ((LPDWORD)(pVarString+1))[0]; pdwIDs[2] = ((LPDWORD)(pVarString+1))[1]; ClientFree( pVarString ); return S_OK; } // // get the wave/in id // hr = LineGetID( hLine, dwAddressID, hCall, dwCallSelect, &pVarString, L"wave/in" ); if (!SUCCEEDED(hr)) { if (NULL != pVarString) { ClientFree( pVarString ); } LOG((TL_ERROR, "LineGetID failed for wavein device - %lx", hr )); return hr; } // // saveit // pdwIDs[1] = *((LPDWORD)(pVarString+1)); ClientFree( pVarString ); // // get the waveout id // hr = LineGetID( hLine, dwAddressID, hCall, dwCallSelect, &pVarString, L"wave/out" ); if (!SUCCEEDED(hr)) { if (NULL != pVarString) { ClientFree( pVarString ); } LOG((TL_ERROR, "LineGetID failed for waveout device - %lx", hr )); return hr; } // // save it // pdwIDs[2] = *((LPDWORD)(pVarString+1)); ClientFree( pVarString ); return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddress::InitializeWaveDeviceIDs( HLINE hLine ) { DWORD adwIDs[3]; HRESULT hr; hr = CreateWaveInfo( hLine, GetAddressID(), NULL, LINECALLSELECT_ADDRESS, HasFullDuplexWaveDevice(), adwIDs ); if ( SUCCEEDED(hr) ) { adwIDs[0] = 3; } else { adwIDs[0] = 4; } hr = ReceiveTSPData( NULL, (LPBYTE)adwIDs, sizeof(adwIDs) ); if ( TAPI_VERSION3_0 <= m_dwAPIVersion ) { adwIDs[0] = 8; if ( m_dwAddressFlags & ADDRESSFLAG_WAVEFULLDUPLEX ) { adwIDs[1] = 1; } else { adwIDs[1] = 0; } hr = ReceiveTSPData( NULL, (LPBYTE)adwIDs, sizeof(adwIDs) ); } return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // SaveAddressName // // saves the address name based on the linename in devcaps // // called in lock // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddress::SaveAddressName( LPLINEDEVCAPS pDevCaps ) { PWSTR pAddressName = NULL; PWSTR pAddressString = NULL; DWORD dwAddressStringSize = 0; // // save the line name // if ( pDevCaps->dwNumAddresses > 1 ) { pAddressString = MyLoadString( IDS_ADDRESS ); if ( NULL == pAddressString ) { return E_UNEXPECTED; } dwAddressStringSize = (lstrlenW( pAddressString ) + 1) * sizeof(WCHAR); // // need to add some room for whitespace // dwAddressStringSize += 10 * sizeof(WCHAR); } if (0 != pDevCaps->dwLineNameSize) { DWORD dwSize; dwSize = pDevCaps->dwLineNameSize + sizeof(WCHAR); dwSize += dwAddressStringSize; pAddressName = (PWSTR) ClientAlloc(dwSize); if (NULL == pAddressName) { LOG((TL_ERROR, "Initialize - alloc pAddressName failed" )); if ( NULL != pAddressString ) { ClientFree( pAddressString ); } return E_OUTOFMEMORY; } memcpy( pAddressName, ((LPBYTE)(pDevCaps)) + pDevCaps->dwLineNameOffset, pDevCaps->dwLineNameSize ); } else { PWSTR pTempBuffer; DWORD dwSize = 0; pTempBuffer = MyLoadString( IDS_LINE ); if ( NULL == pTempBuffer ) { LOG((TL_ERROR, "Initialize - couldn't load LINE resource")); if ( NULL != pAddressString ) { ClientFree( pAddressString ); } return E_UNEXPECTED; } dwSize = (lstrlenW( pTempBuffer ) + 1) * sizeof(WCHAR); dwSize += dwAddressStringSize; // // need some whitespace // dwSize += 5 * sizeof(WCHAR); pAddressName = (PWSTR) ClientAlloc( dwSize ); if ( NULL == pAddressName ) { ClientFree( pTempBuffer ); if ( NULL != pAddressString ) { ClientFree( pAddressString ); } return E_OUTOFMEMORY; } wsprintfW( pAddressName, L"%s %d", pTempBuffer, m_dwDeviceID ); ClientFree( pTempBuffer ); } // // append the address # if there is more than one address on the line // if (pDevCaps->dwNumAddresses > 1) { wsprintfW( pAddressName, L"%s - %s %d", pAddressName, pAddressString, m_dwAddressID ); } if ( NULL != pAddressString ) { ClientFree( pAddressString ); } if ( NULL != m_szAddressName ) { ClientFree( m_szAddressName); } m_szAddressName = pAddressName; return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Initialize // Init the CAddress object // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddress::Initialize( ITTAPI * pTapi, HLINEAPP hLineApp, #ifdef USE_PHONEMSP HPHONEAPP hPhoneApp, #endif USE_PHONEMSP DWORD dwAPIVersion, DWORD dwDeviceID, DWORD dwAddressID, DWORD dwProviderID, LPLINEDEVCAPS pDevCaps, DWORD dwEventFilterMask ) { LONG lResult; HRESULT hr; T3LINE t3Line; #ifdef USE_PHONEMSP BOOL bPreferPhoneMSPForProvider = FALSE; #endif USE_PHONEMSP t3Line.hLine = NULL; t3Line.dwAddressLineStructHandle = 0; LOG((TL_TRACE, "Initialize[%p] enter", this )); LOG((TL_INFO, " hLineApp ---------->%lx", hLineApp )); #ifdef USE_PHONEMSP LOG((TL_INFO, " hPhoneApp --------->%lx", hPhoneApp )); #endif USE_PHONEMSP LOG((TL_INFO, " dwAPIVersion ------>%lx", dwAPIVersion )); LOG((TL_INFO, " dwDeviceID -------->%lx", dwDeviceID )); LOG((TL_INFO, " dwAddressID ------->%lx", dwAddressID )); LOG((TL_INFO, " pDevCaps ---------->%p", pDevCaps )); Lock(); // // save relevant info // m_pTAPI = pTapi; m_dwDeviceID = dwDeviceID; m_dwAddressID = dwAddressID; m_dwMediaModesSupported = pDevCaps->dwMediaModes; m_hLineApp = hLineApp; #ifdef USE_PHONEMSP m_hPhoneApp = hPhoneApp; #endif USE_PHONEMSP m_dwAPIVersion = dwAPIVersion; m_AddressState = AS_INSERVICE; m_pCallHubTrackingLine = NULL; m_dwProviderID = dwProviderID; m_pPrivate = NULL; m_szAddressName = NULL; m_pAddressCaps = NULL; m_pDevCaps = NULL; // // Read the event filter mask from TAPIobject // SetEventFilterMask( dwEventFilterMask ); AddRef(); m_pTAPI->AddRef(); // // default address type // if (m_dwAPIVersion >= TAPI_VERSION3_0) { // // save msp and address types support // if ( (pDevCaps->dwDevCapFlags) & LINEDEVCAPFLAGS_MSP ) { m_dwAddressFlags |= ADDRESSFLAG_MSP; LOG((TL_INFO, "Initialize - has an msp" )); } if ( (pDevCaps->dwDevCapFlags) & LINEDEVCAPFLAGS_PRIVATEOBJECTS ) { m_dwAddressFlags |= ADDRESSFLAG_PRIVATEOBJECTS; LOG((TL_INFO, "Initialize - has private object" )); } if ( (pDevCaps->dwDevCapFlags) & LINEDEVCAPFLAGS_CALLHUB ) { m_dwAddressFlags |= ADDRESSFLAG_CALLHUB; LOG((TL_INFO, "Initialize - supports callhubs" )); } if ( (pDevCaps->dwDevCapFlags) & LINEDEVCAPFLAGS_CALLHUBTRACKING ) { m_dwAddressFlags |= ADDRESSFLAG_CALLHUBTRACKING; LOG((TL_INFO, "Initialize - supports callhub tracking" )); } } // // check for wave device if it doesn't // have it's own MSP // // the sp lets tapi know of wave support through the // device classes field, as well // // so, go through the array // and look for the appropriate string // if ( !(m_dwAddressFlags & ADDRESSFLAG_MSP) && (m_dwAPIVersion >= TAPI_VERSION2_0 ) ) { if (0 != pDevCaps->dwDeviceClassesOffset) { PWSTR pszDevices; // // look for full duplex // if not full duplex then // look for wave out // look for wave in // if not wave then // look for wave // pszDevices = (PWSTR)( ( (PBYTE)pDevCaps ) + pDevCaps->dwDeviceClassesOffset ); while (NULL != *pszDevices) { if (0 == lstrcmpiW(pszDevices, L"wave/in/out")) { m_dwAddressFlags |= ADDRESSFLAG_WAVEFULLDUPLEX; LOG((TL_INFO, "Initialize - supports full duplex wave")); break; } pszDevices += (lstrlenW(pszDevices) + 1 ); } if (!HasWaveDevice()) { pszDevices = (PWSTR)( ( (PBYTE)pDevCaps ) + pDevCaps->dwDeviceClassesOffset ); // // look for wave out // while (NULL != *pszDevices) { if (0 == lstrcmpiW(pszDevices, L"wave/out")) { m_dwAddressFlags |= ADDRESSFLAG_WAVEOUTDEVICE; LOG((TL_INFO, "Initialize - supports wave/out device" )); break; } pszDevices += (lstrlenW(pszDevices) +1); } pszDevices = (PWSTR)( ( (PBYTE)pDevCaps ) + pDevCaps->dwDeviceClassesOffset ); // // look for wave in // while (NULL != *pszDevices) { if (0 == lstrcmpiW(pszDevices, L"wave/in")) { m_dwAddressFlags |= ADDRESSFLAG_WAVEINDEVICE; LOG((TL_INFO, "Initialize - supports wave/in device" )); break; } pszDevices += (lstrlenW(pszDevices) +1); } if (!HasWaveDevice()) { pszDevices = (PWSTR)( ( (PBYTE)pDevCaps ) + pDevCaps->dwDeviceClassesOffset ); // // look for just wave // some sps don't differentiate between wave out and wave in // while (NULL != *pszDevices) { if (0 == lstrcmpiW(pszDevices, L"wave")) { m_dwAddressFlags |= (ADDRESSFLAG_WAVEINDEVICE|ADDRESSFLAG_WAVEOUTDEVICE); LOG((TL_INFO, "Initialize - supports wave device" )); break; } pszDevices += (lstrlenW(pszDevices) + 1); } } } } } IUnknown * pUnk; _InternalQueryInterface(IID_IUnknown, (void**)&pUnk); #ifdef USE_PHONEMSP if ( HasWaveDevice() || ( NULL != GetHPhoneApp() ) ) #else if ( HasWaveDevice() ) #endif USE_PHONEMSP { t3Line.hLine = NULL; t3Line.pAddress = this; t3Line.dwAddressLineStructHandle = 0; hr = LineOpen( GetHLineApp(), GetDeviceID(), GetAddressID(), &t3Line, GetAPIVersion(), LINECALLPRIVILEGE_NONE, LINEMEDIAMODE_UNKNOWN, 0, NULL, this, GetTapi(), FALSE // no need to add to line hash table ); if (S_OK != hr) { LOG((TL_ERROR, "Initialize failed to open the line")); t3Line.hLine = NULL; t3Line.dwAddressLineStructHandle = 0; } // // Try to set the event filter mask to the TapiSrv level // hr = m_EventMasks.SetTapiSrvAddressEventMask( t3Line.hLine ); if( FAILED(hr) ) { LOG((TL_ERROR, "SetTapiSrvAddressEventMask failed ")); } m_hLine = t3Line.hLine; } #ifdef USE_PHONEMSP { HKEY hKey; TCHAR szProviderKeyName[256]; DWORD dwDataType; DWORD dwDataSize = sizeof(DWORD); if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Telephony\\TAPI3", 0, KEY_READ, &hKey ) == ERROR_SUCCESS) { // form reg name wsprintf(szProviderKeyName, ("PreferPhoneMSPForProvider%d"), m_dwProviderID); RegQueryValueEx(hKey, szProviderKeyName, 0, &dwDataType, (LPBYTE) &bPreferPhoneMSPForProvider, &dwDataSize ); RegCloseKey(hKey); } } #endif USE_PHONEMSP if ( (m_dwAddressFlags & ADDRESSFLAG_MSP) ) { // // CreateMSPObject // hr = CreateMSPObject( m_dwDeviceID, pUnk, &m_pMSPAggAddress ); if (S_OK != hr) { LOG((TL_ERROR, "Initialize - CreateMSPObject return %lx", hr)); m_dwAddressFlags = m_dwAddressFlags & ~(ADDRESSFLAG_MSP); } } else { #ifdef USE_PHONEMSP if(bPreferPhoneMSPForProvider == TRUE) { // Create the Phone MSP as preference // if ( NULL != GetHPhoneApp() ) { hr = CreatePhoneDeviceMSP( pUnk, t3Line.hLine, &m_pMSPAggAddress ); if (!SUCCEEDED(hr)) { LOG((TL_ERROR, "Initialize - failed to create phone msp object - %lx", hr)); } } // // if it's a wave device, create wavemsp object // else if ( HasWaveDevice() ) { hr = CreateWaveMSPObject( pUnk, &m_pMSPAggAddress ); if (!SUCCEEDED(hr)) { LOG((TL_ERROR, "Initialize - failed to create wave msp object - %lx", hr)); m_dwAddressFlags = m_dwAddressFlags & ~(ADDRESSFLAG_WAVEINDEVICE | ADDRESSFLAG_WAVEOUTDEVICE | ADDRESSFLAG_WAVEFULLDUPLEX); } } } else #endif USE_PHONEMSP { // // if it's a wave device, create wavemsp object as preference // if ( HasWaveDevice() ) { hr = CreateWaveMSPObject( pUnk, &m_pMSPAggAddress ); if (!SUCCEEDED(hr)) { LOG((TL_ERROR, "Initialize - failed to create wave msp object - %lx", hr)); m_dwAddressFlags = m_dwAddressFlags & ~(ADDRESSFLAG_WAVEINDEVICE | ADDRESSFLAG_WAVEOUTDEVICE | ADDRESSFLAG_WAVEFULLDUPLEX); } } #ifdef USE_PHONEMSP // Create the Phone MSP // else if ( NULL != GetHPhoneApp() ) { hr = CreatePhoneDeviceMSP( pUnk, t3Line.hLine, &m_pMSPAggAddress ); if (!SUCCEEDED(hr)) { LOG((TL_ERROR, "Initialize - failed to create phone msp object - %lx", hr)); } } #endif USE_PHONEMSP } } pUnk->Release(); if (NULL != m_pMSPAggAddress) { m_hMSPEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); if ( NULL == m_hMSPEvent ) { LOG((TL_ERROR, "Initialize - can't create MSP event")); m_dwAddressFlags = m_dwAddressFlags & ~(ADDRESSFLAG_AMREL); // // release msp object, so we are not tempted to do Shutdown on it // later without having (successfully) initialized it first // m_pMSPAggAddress->Release(); m_pMSPAggAddress = NULL; } else { // Create a context handle to give the Callback & associate it with this object // in the global handle hash table m_MSPContext = GenerateHandleAndAddToHashTable((ULONG_PTR)this); LOG((TL_INFO, "Initialize - Map MSP handle %p to Address object %p", m_MSPContext, this )); BOOL fSuccess = RegisterWaitForSingleObject( & m_hWaitEvent, m_hMSPEvent, MSPEventCallback, (PVOID)m_MSPContext, INFINITE, WT_EXECUTEDEFAULT ); if ( ( ! fSuccess ) || ( NULL == m_hWaitEvent ) ) { LOG((TL_ERROR, "Initialize - RegisterWaitForSingleObject failed")); m_dwAddressFlags = m_dwAddressFlags & ~(ADDRESSFLAG_AMREL); m_pMSPAggAddress->Release(); m_pMSPAggAddress = NULL; } else { ITMSPAddress * pMSPAddress = GetMSPAddress(); hr = pMSPAddress->Initialize( (MSP_HANDLE)m_hMSPEvent ); if ( SUCCEEDED(hr) && HasWaveDevice() ) { InitializeWaveDeviceIDs( t3Line.hLine ); } pMSPAddress->Release(); if (!SUCCEEDED(hr)) { LOG((TL_ERROR, "Initialize - failed to initialize msp object - %lx", hr)); UnregisterWait( m_hWaitEvent ); m_hWaitEvent = NULL; m_dwAddressFlags = m_dwAddressFlags & ~(ADDRESSFLAG_AMREL); m_pMSPAggAddress->Release(); m_pMSPAggAddress = NULL; } } } } if ( NULL != t3Line.hLine ) { LineClose( &t3Line ); } // // get the address caps structure // hr = UpdateAddressCaps(); if (S_OK != hr) { LOG((TL_ERROR, "Initialize - LineGetAddressCaps failed - return %lx", hr )); Unlock(); LOG((TL_ERROR, hr, "Initialize - exit LineGetAddressCaps failed")); return hr; } // // save the address name // if (0 != m_pAddressCaps->dwAddressSize) { m_szAddress = (PWSTR) ClientAlloc (m_pAddressCaps->dwAddressSize + sizeof(WCHAR)); if (NULL == m_szAddress) { LOG((TL_ERROR, "Initialize - alloc m_szAddress failed" )); Unlock(); LOG((TL_ERROR, E_OUTOFMEMORY, "Initialize - exit alloc m_szAddress failed")); return E_OUTOFMEMORY; } memcpy( m_szAddress, ((LPBYTE)(m_pAddressCaps)) + m_pAddressCaps->dwAddressOffset, m_pAddressCaps->dwAddressSize ); LOG((TL_INFO, "CAddress - Address is '%ls'", m_szAddress )); } hr = SaveAddressName( pDevCaps ); if ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "Initialize - SaveAddressName failed %lx", hr)); ClientFree(m_szAddress); /*This is to take care of AV*/ m_szAddress = NULL; Unlock(); LOG((TL_ERROR, hr, "Initialize - exit SaveAddressName failed")); return hr; } LOG((TL_INFO, "CAddress - m_szAddressName is '%ls'", m_szAddressName )); LOG((TL_TRACE, "Initialize - exit S_OK" )); Unlock(); return S_OK; } #ifdef USE_PHONEMSP //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // CreatePhoneDeviceMSP // This address has a tapi phone devices, so create // the relevant terminals // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddress::CreatePhoneDeviceMSP( IUnknown * pUnk, HLINE hLine, IUnknown ** ppMSPAggAddress ) { HRESULT hr = S_OK; BOOL bSucceeded = FALSE; LPPHONECAPS pPhoneCaps; DWORD dwPhoneDevice; LPVARSTRING pVarString = NULL; CComAggObject * pPhoneMSP; CPhoneMSP * pCPhoneMSP; ITMSPAddress * pMSPAddress; LOG((TL_TRACE, "CreatePhoneTerminal enter" )); // // get the related phone device id // hr = LineGetID( hLine, GetAddressID(), NULL, LINECALLSELECT_ADDRESS, &pVarString, L"tapi/phone" ); // // there is no phone device // if (S_OK != hr) { if ( NULL != pVarString ) { ClientFree( pVarString ); /*This is to take care of AV*/ pVarString = NULL; } return hr; } // // get the phone device id at the endo // of the var string // if (pVarString->dwStringSize < sizeof(DWORD)) { LOG((TL_ERROR, "CreatePhoneDeviceMSP - dwStringSize < 4" )); LOG((TL_ERROR, "CreatePhoneDeviceMSP exit - return LINEERR_OPERATIONFAILED" )); ClientFree( pVarString ); /*This is to take care of AV*/ pVarString = NULL; return mapTAPIErrorCode( LINEERR_OPERATIONFAILED ); } // // get the phone device // dwPhoneDevice = (DWORD) ( * ( ( (PBYTE)pVarString ) + pVarString->dwStringOffset ) ); ClientFree( pVarString ); /*This is to take care of AV*/ pVarString = NULL; // // create the msp object // pPhoneMSP = new CComAggObject(pUnk); /*NikhilB: This is to take care of an AV*/ if ( NULL == pPhoneMSP ) { LOG((TL_ERROR, "Could not allocate for phone MSP object" )); return E_OUTOFMEMORY; } // // save the aggregated interface in // the msppointer // pPhoneMSP->QueryInterface( IID_IUnknown, (void **)ppMSPAggAddress ); // // get to the real object // pMSPAddress = GetMSPAddress(); pCPhoneMSP = dynamic_cast(pMSPAddress); // // initialize it // hr = pCPhoneMSP->InitializeTerminals( GetHPhoneApp(), m_dwAPIVersion, dwPhoneDevice, this ); pCPhoneMSP->Release(); if ( !SUCCEEDED(hr) ) { } LOG((TL_TRACE, "CreatePhoneDeviceMSP exit - return %lx", hr )); return hr; } #endif USE_PHONEMSP //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // AddCall // Keep track of calls // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= HRESULT CAddress::AddCall( ITCallInfo * pCallInfo ) { Lock(); m_CallArray.Add( pCallInfo ); Unlock(); return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // RemoveCall // // remove call from address's list // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= HRESULT CAddress::RemoveCall( ITCallInfo * pCallInfo ) { Lock(); m_CallArray.Remove( pCallInfo ); Unlock(); return S_OK; } // ITMediaSupport methods HRESULT STDMETHODCALLTYPE CAddress::get_MediaTypes( long * plMediaTypes ) { LOG((TL_TRACE, "get_MediaTypes enter" )); LOG((TL_TRACE, " plMediaType ------->%p", plMediaTypes )); if (TAPIIsBadWritePtr( plMediaTypes, sizeof( long ) ) ) { LOG((TL_ERROR, "get_MediaTypes - bad pointer")); return E_POINTER; } *plMediaTypes = (long)m_dwMediaModesSupported; if (*plMediaTypes & LINEMEDIAMODE_INTERACTIVEVOICE) { *plMediaTypes |= LINEMEDIAMODE_AUTOMATEDVOICE; } *plMediaTypes &= ALLMEDIAMODES; return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // QueryMediaType // find out of mediatype is supported // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= HRESULT STDMETHODCALLTYPE CAddress::QueryMediaType( long lMediaType, VARIANT_BOOL * pbSupport ) { HRESULT hr = S_OK; DWORD dwMediaMode; LOG((TL_TRACE, "QueryMediaType enter")); LOG((TL_TRACE, " lMediaType--------->%lx", lMediaType)); LOG((TL_TRACE, " pbSupport---------->%p", pbSupport)); if ( TAPIIsBadWritePtr( pbSupport, sizeof(VARIANT_BOOL) ) ) { LOG((TL_ERROR, "QueryMediaType - inval pointer")); return E_POINTER; } // // get the tapi mediamode that // the application is asking about // if (GetMediaMode( lMediaType, &dwMediaMode ) ) { *pbSupport = VARIANT_TRUE; } else { *pbSupport = VARIANT_FALSE; } LOG((TL_TRACE, "QueryMediaType exit - return success")); return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // AddCallNotification // // Adds a callback to notify on call events // // dwPrivs // IN tapi 2 style Privileges // // dwMediaModes // IN tapi 2 style mediamodes // // pNotification // IN the callback to notify // // pulRegiser // OUT the unique ID of the callback (so they can unregister) // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddress::AddCallNotification( DWORD dwPrivs, DWORD dwMediaModes, long lInstance, PVOID * ppRegister ) { HRESULT hr; AddressLineStruct * pAddressLine; // // create addressline // pAddressLine = (AddressLineStruct *)ClientAlloc( sizeof( AddressLineStruct ) ); if (NULL == pAddressLine) { LOG((TL_ERROR, "AddCallNotification - pAddressLine is NULL")); return E_OUTOFMEMORY; } // // initialize // pAddressLine->dwPrivs = dwPrivs; pAddressLine->t3Line.pAddress = this; pAddressLine->t3Line.dwAddressLineStructHandle = 0; pAddressLine->InitializeRefcount(1); pAddressLine->lCallbackInstance = lInstance; if (ALLMEDIATYPES == dwMediaModes) { pAddressLine->dwMediaModes = GetMediaModes(); } else { pAddressLine->dwMediaModes = dwMediaModes; // // if we are listening on any audio mode // if (pAddressLine->dwMediaModes & AUDIOMEDIAMODES) { // // add in all the audio modes that we support // pAddressLine->dwMediaModes |= (GetMediaModes() & AUDIOMEDIAMODES); } } // // get a line // hr = LineOpen( GetHLineApp(), GetDeviceID(), GetAddressID(), &(pAddressLine->t3Line), GetAPIVersion(), pAddressLine->dwPrivs, pAddressLine->dwMediaModes, pAddressLine, NULL, (CAddress *)this, GetTapi() ); if (!SUCCEEDED(hr)) { LOG((TL_ERROR, "AddCallNotification - LineOpen failed %lx", hr)); ClientFree( pAddressLine ); return hr; } // // Try to set the event filter mask to the TapiSrv level // hr = m_EventMasks.SetTapiSrvAddressEventMask( pAddressLine->t3Line.hLine ); if( FAILED(hr) ) { LOG((TL_ERROR, "AddCallNotification - SetTapiSrvAddressEventMask failed 0x%08x", hr)); LineClose( &(pAddressLine->t3Line) ); ClientFree( pAddressLine ); return hr; } // Fix for bug 263866 & 250924 // if ( m_dwAddressFlags & ADDRESSFLAG_MSP ) { hr = LineCreateMSPInstance( pAddressLine->t3Line.hLine, GetAddressID() ); if ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "AddCallNotification - LineCreateMSPInstance failed %lx", hr)); LineClose( &(pAddressLine->t3Line) ); ClientFree( pAddressLine ); return hr; } } // Tell TAPISRV what status messages we want // NOTE : if the lines SP doesn't support TSPI_lineSetStatusMessages // TAPISRV will fail this with LINEERR_OPERATIONUNAVAIL LineSetStatusMessages( &(pAddressLine->t3Line), ALL_LINEDEVSTATE_MESSAGES, ALL_LINEADDRESSSTATE_MESSAGES ); // // ZoltanS fix: enable callhub notifications only if the app // hasn't already told us it doesn't want them // if ( m_fEnableCallHubTrackingOnLineOpen ) { LINECALLHUBTRACKINGINFO lchti; lchti.dwTotalSize = sizeof(lchti); lchti.dwCurrentTracking = LINECALLHUBTRACKING_ALLCALLS; hr = LineSetCallHubTracking( &(pAddressLine->t3Line), &lchti ); if ( S_OK != hr ) { LOG((TL_ERROR, "AddCallNotification - LineSetCallHubTracking failed %lx", hr )); LineClose( &(pAddressLine->t3Line) ); ClientFree( pAddressLine ); return hr; } } if (m_pCallHubTrackingLine) { MaybeCloseALine( &m_pCallHubTrackingLine ); m_pCallHubTrackingLine = pAddressLine; pAddressLine->AddRef(); } // // save the line in the address's list // hr = AddNotificationLine( pAddressLine );; if ( S_OK != hr ) { LOG((TL_ERROR, "AddCallNotification - AddNotificationLine failed %lx", hr )); LineClose( &(pAddressLine->t3Line) ); ClientFree( pAddressLine ); } else { // // fill in pulRegister // *ppRegister = (PVOID) pAddressLine; } return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // RemoveCallNotification // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddress::RemoveCallNotification( PVOID pRegister ) { AddressLineStruct *pLine = (AddressLineStruct *)pRegister; MaybeCloseALine( &pLine ); return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // FindOrOpenALine // // Attempts to find a line that's already open. If so, keeps a // pointer to it. If not opens the line. // // dwMediaModes // IN tapi 2 style mediamodes // // ppAddressLine // OUT addresslinestruct associated with this request // // RETURNS // // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddress::FindOrOpenALine( DWORD dwMediaModes, AddressLineStruct ** ppAddressLine ) { HRESULT hr = S_OK; LOG((TL_TRACE, "FindOrOpenALine - enter" )); Lock(); // // if there is already a line, // just return it // if ( m_AddressLinesPtrList.size() > 0 ) { LOG((TL_INFO, "Found a line that is already open" )); *ppAddressLine = (AddressLineStruct *)*( m_AddressLinesPtrList.begin() ); (*ppAddressLine)->AddRef(); LOG((TL_TRACE, "FindOrOpenALine - exit")); Unlock(); return S_OK; } // // we didn't have an address // LOG((TL_INFO, "Did not find an already open line")); // // create a new addressline // AddressLineStruct * pLine = (AddressLineStruct *)ClientAlloc( sizeof(AddressLineStruct) ); if (NULL == pLine) { LOG((TL_ERROR, "FindOrOpenALine - alloc pLine failed" )); Unlock(); return E_OUTOFMEMORY; } // // initialize // pLine->dwMediaModes = dwMediaModes; pLine->dwPrivs = LINECALLPRIVILEGE_NONE; pLine->t3Line.pAddress = this; pLine->t3Line.dwAddressLineStructHandle = 0; pLine->InitializeRefcount(1); pLine->lCallbackInstance = 0; LOG((TL_INFO, "FindOrOpenALine - Opening a line" )); // // open the line // hr = LineOpen( GetHLineApp(), GetDeviceID(), GetAddressID(), &(pLine->t3Line), GetAPIVersion(), LINECALLPRIVILEGE_NONE, dwMediaModes, pLine, NULL, this, GetTapi() ); if (S_OK != hr) { LOG((TL_ERROR, "FindOrOpenALine - LineOpen failed %lx", hr )); ClientFree( pLine ); Unlock(); return hr; } // // Try to set the event filter mask to the TapiSrv level // hr = m_EventMasks.SetTapiSrvAddressEventMask( pLine->t3Line.hLine ); if( FAILED(hr) ) { LOG((TL_ERROR, "FindOrOpenALine - SetTapiSrvAddressEventMask failed 0x%08x", hr)); LineClose( &(pLine->t3Line) ); ClientFree( pLine ); Unlock(); return hr; } if ( m_dwAddressFlags & ADDRESSFLAG_MSP ) { hr = LineCreateMSPInstance( pLine->t3Line.hLine, GetAddressID() ); if ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "FindOrOpenALine - LineCreateMSPInstance failed %lx", hr)); LineClose( &(pLine->t3Line) ); ClientFree( pLine ); Unlock(); return hr; } } // Tell TAPISRV what status messages we want // NOTE : if the lines SP doesn't support TSPI_lineSetStatusMessages // TAPISRV will fail this with LINEERR_OPERATIONUNAVAIL LineSetStatusMessages( &(pLine->t3Line), ALL_LINEDEVSTATE_MESSAGES, ALL_LINEADDRESSSTATE_MESSAGES ); // // ZoltanS fix: enable callhub notifications only if the app // hasn't already told us it doesn't want them // if ( m_fEnableCallHubTrackingOnLineOpen ) { LINECALLHUBTRACKINGINFO lchti; lchti.dwTotalSize = sizeof(lchti); lchti.dwCurrentTracking = LINECALLHUBTRACKING_ALLCALLS; hr = LineSetCallHubTracking( &(pLine->t3Line), &lchti ); if ( S_OK != hr ) { LOG((TL_ERROR, "FindOrOpenALine - LineSetCallHubTracking failed %lx", hr )); LineClose( &(pLine->t3Line) ); ClientFree( pLine ); Unlock(); return hr; } } // // Add this line to our list of open lines. This is independent of // the callhub tracking stuff above. // hr = AddNotificationLine( pLine ); if ( S_OK != hr ) { LOG((TL_ERROR, "FindOrOpenALine - AddNotificationLine failed %lx", hr )); LineClose( &(pLine->t3Line) ); ClientFree( pLine ); } else { *ppAddressLine = pLine; } LOG((TL_TRACE, "FindOrOpenALine - exit")); Unlock(); return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // MaybeCloseALine // After a call is done, close the line if it's not being // used for monitoring. // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddress::MaybeCloseALine( AddressLineStruct ** ppAddressLine ) { HRESULT hr = S_OK; LOG((TL_TRACE, "MaybeCloseALine - enter")); Lock(); if (NULL == *ppAddressLine || !IsValidAddressLine(*ppAddressLine)) { Unlock(); return S_OK; } // // decrement reference count on the the address line // DWORD dwAddressLineRefcount = (*ppAddressLine)->Release(); // // if ref count is 0, close line // if ( 0 == dwAddressLineRefcount ) { m_AddressLinesPtrList.remove( (PVOID)*ppAddressLine ); // // clean handle table. // try { DWORD dwAddressLineHandle = (*ppAddressLine)->t3Line.dwAddressLineStructHandle; DeleteHandleTableEntry(dwAddressLineHandle); } catch(...) { LOG((TL_ERROR, "MaybeCloseALine - exception accessing address line's handle" )); _ASSERTE(FALSE); } // // attempt to close the line // LOG((TL_INFO, "MaybeCloseALine - Calling LineClose" )); if ( m_dwAddressFlags & ADDRESSFLAG_MSP ) { LineCloseMSPInstance( (*ppAddressLine)->t3Line.hLine ); } // // release the lock and call lineclose // Unlock(); // // now that the line was removed from our list of managed lines and all // the calls have been notified, we can close the line and free the // structure // hr = LineClose( &((*ppAddressLine)->t3Line) ); ClientFree( *ppAddressLine ); } else { Unlock(); // // otherwise, decrement the dwRefCount count // LOG((TL_INFO, "MaybeCloseALine - Not calling line close - decrementing number of addresses using line" )); } *ppAddressLine = NULL; LOG((TL_TRACE, "MaybeCloseALine - exit")); return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // SetCallHubTracking // // called by the tapi object to start callhub tracking on this // address // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddress::SetCallHubTracking( BOOL bSet ) { HRESULT hr = S_OK; LINECALLHUBTRACKINGINFO lchti; Lock(); // // Check if we have to make any change now. // if ( bSet == m_fEnableCallHubTrackingOnLineOpen ) { // // already doing the right thing // Unlock(); return S_OK; } // // ZoltanS: make sure we don't clobber this setting in other methods // (e.g., AddCallNotification or FindOrOpenALine) where the // default call notification behavior (true) would otherwise // be set. // m_fEnableCallHubTrackingOnLineOpen = bSet; // // need an hline to call setcallhubtracking // if ( m_pCallHubTrackingLine == NULL ) { hr = FindOrOpenALine( LINEMEDIAMODE_INTERACTIVEVOICE, &m_pCallHubTrackingLine ); if ( !SUCCEEDED( hr ) ) { LOG((TL_ERROR, "SCHT - FindOrOpen failed %lx", hr)); Unlock(); return hr; } // // ZoltanS fix: // FindOrOpenALine does callhubtracking for non-sp // tracking capable lines, but only if it is opening // the line (rather than just finding it in our list. // So we still need to do LineSetCallHubTracking below, // even for an SPCallHubTrackingAddress. // } // // tell the sp to track callhubs // ZeroMemory( &lchti, sizeof(lchti) ); lchti.dwTotalSize = sizeof(lchti); lchti.dwCurrentTracking = bSet? LINECALLHUBTRACKING_ALLCALLS : LINECALLHUBTRACKING_NONE; // // ZoltanS: Only pass this flag if it applies. // Note: LineSetCallHubTracking apparently ignores its first argument // if the tracking level is set to LINECALLHUBTRACKING_NONE; otherwise // we would also have to FindOrOpenALine if we are unsetting. // if ( bSet && IsSPCallHubTrackingAddress() ) { lchti.dwCurrentTracking |= LINECALLHUBTRACKING_PROVIDERLEVEL; } hr = LineSetCallHubTracking( &(m_pCallHubTrackingLine->t3Line), &lchti ); if ( !SUCCEEDED( hr ) ) { LOG((TL_ERROR, "SCHT - LSCHT failed %lx", hr)); if ( bSet ) { MaybeCloseALine( &m_pCallHubTrackingLine ); m_pCallHubTrackingLine = NULL; } Unlock(); return hr; } // // Also properly set callhub tracking on lines that were // opened for call notification // PtrList::iterator l; for (l = m_AddressLinesPtrList.begin(); l != m_AddressLinesPtrList.end(); l++) { AddressLineStruct * pLine; pLine = (AddressLineStruct *)(*l); if (pLine != m_pCallHubTrackingLine) { LineSetCallHubTracking( &(pLine->t3Line), &lchti ); } } // // close it if unsetting // if ( !bSet ) { MaybeCloseALine( &m_pCallHubTrackingLine ); m_pCallHubTrackingLine = NULL; } Unlock(); return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // DoesThisAddressSupportCallHubs // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ DWORD CAddress::DoesThisAddressSupportCallHubs( CCall * pCall ) { HCALL hCall; LINECALLINFO * pCallInfo; HRESULT hr; // // does the sp tell us it supports callhubs? // if ( IsSPCallHubAddress() ) { return CALLHUBSUPPORT_FULL; } // // have we already determined that it doesn't? // if ( m_dwAddressFlags & ADDRESSFLAG_NOCALLHUB ) { return CALLHUBSUPPORT_NONE; } // // otherwise - hack - see if the dwrelatedcallid // field is non-zero in this call. // if so, it does callhubs, // hCall = pCall->GetHCall(); hr = LineGetCallInfo( hCall, &pCallInfo ); if ( SUCCEEDED( hr ) ) { if ( 0 != pCallInfo->dwCallID ) { Lock(); m_dwAddressFlags |= ADDRESSFLAG_CALLHUB; Unlock(); ClientFree( pCallInfo ); return CALLHUBSUPPORT_FULL; } else { Lock(); m_dwAddressFlags |= ADDRESSFLAG_NOCALLHUB; Unlock(); ClientFree( pCallInfo ); return CALLHUBSUPPORT_NONE; } } return CALLHUBSUPPORT_UNKNOWN; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // CreateForwardInfoObject // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddress::CreateForwardInfoObject( ITForwardInformation ** ppForwardInfo ) { CComObject< CForwardInfo > * p; HRESULT hr = S_OK; LOG((TL_TRACE, "CreatForwardInfoObject - enter")); if (TAPIIsBadWritePtr(ppForwardInfo , sizeof(ITForwardInformation *) ) ) { LOG((TL_ERROR, "CreateForwardInfoObject - bad pointer")); return E_POINTER; } // // create object // CComObject< CForwardInfo >::CreateInstance( &p ); if ( NULL == p ) { LOG((TL_ERROR, "Create forward object failed")); return E_OUTOFMEMORY; } // // init // hr = p->Initialize(); if ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "Initialize forward object failed")); delete p; return hr; } // // return // hr = p->QueryInterface( IID_ITForwardInformation, (void**)ppForwardInfo ); if ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "CreateForwardobject failed - %lx", hr)); delete p; return hr; } LOG((TL_TRACE, "CreateForwardObject - exit success")); return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Forward - simple forwarding // // will unconditially forward to pDestAddress // // if pDestAddress is NULL, will cancel forwarding // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddress::Forward( ITForwardInformation * pForwardInfo, ITBasicCallControl * pCall ) { HRESULT hr; LINEFORWARDLIST * pList; AddressLineStruct * pLine; HCALL hCall = NULL; CForwardInfo * pFI; CCall * pCCall; LONG lCap; if ( IsBadReadPtr( pForwardInfo, sizeof( ITForwardInformation * ) ) ) { LOG((TL_ERROR, "Forward - bad pForwardInfo")); return E_POINTER; } hr = get_AddressCapability( AC_ADDRESSCAPFLAGS, &lCap ); if ( !SUCCEEDED(hr) ) { return hr; } if ( lCap & LINEADDRCAPFLAGS_FWDCONSULT ) { if ( IsBadReadPtr( pCall, sizeof(ITBasicCallControl *) ) ) { LOG((TL_ERROR, "Forward - Need consultation call")); return E_INVALIDARG; } pCCall = dynamic_cast(pCall); if ( NULL == pCCall ) { LOG((TL_ERROR, "Forward - invalid call")); return E_POINTER; } } pFI = dynamic_cast(pForwardInfo); if ( NULL == pFI ) { return E_POINTER; } hr = pFI->CreateForwardList( &pList ); if ( !SUCCEEDED(hr) ) { return hr; } // // get a line // hr = FindOrOpenALine( LINEMEDIAMODE_INTERACTIVEVOICE, &pLine ); if ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "Forward - FindOrOpen failed - %lx", hr)); ClientFree( pList ); return hr; } // // call forward // // DWORD dwRings; pForwardInfo->get_NumRingsNoAnswer( (long *)&dwRings ); hr = LineForward( &(pLine->t3Line), m_dwAddressID, pList, dwRings, &hCall ); ClientFree( pList ); if ( ((long)hr) < 0 ) { LOG((TL_ERROR, "Forward failed sync - %lx", hr)); MaybeCloseALine( &pLine ); return hr; } hr = WaitForReply( hr ); if ( lCap & LINEADDRCAPFLAGS_FWDCONSULT ) { pCCall->Lock(); pCCall->FinishSettingUpCall( hCall ); pCCall->Unlock(); } else { HRESULT hr2; if( hCall != NULL ) { hr2 = LineDrop( hCall, NULL, 0 ); if ( ((long)hr2) > 0 ) { hr2 = WaitForReply( hr2 ); } LineDeallocateCall( hCall ); } } MaybeCloseALine( &pLine ); if ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "Forward failed async - %lx", hr)); return hr; } LOG((TL_TRACE, "Forward - Exit")); return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CAddress // Interface : ITAddress // Method : get_CurrentForwardInfo // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddress::get_CurrentForwardInfo( ITForwardInformation ** ppForwardInfo ) { HRESULT hr = S_OK; AddressLineStruct * pLine = NULL; LINEADDRESSSTATUS * pAddressStatus = NULL; LINEFORWARD * plineForward = NULL; DWORD dwNumEntries = 0; DWORD dwCount = 0; PWSTR pszCallerAddress = NULL; PWSTR pszDestddress = NULL; LOG((TL_TRACE, "get_CurrentForwardInfo - enter")); hr = CreateForwardInfoObject(ppForwardInfo); if ( SUCCEEDED(hr) ) { hr = FindOrOpenALine( LINEMEDIAMODE_INTERACTIVEVOICE, &pLine ); if ( SUCCEEDED(hr) ) { hr = LineGetAddressStatus( &(pLine->t3Line), m_dwAddressID, &pAddressStatus ); if ( SUCCEEDED(hr) ) { (*ppForwardInfo)->put_NumRingsNoAnswer(pAddressStatus->dwNumRingsNoAnswer); // // if there is forwarding // dwNumEntries = pAddressStatus->dwForwardNumEntries; plineForward = (LINEFORWARD *) (((LPBYTE)pAddressStatus) + pAddressStatus->dwForwardOffset); for (dwCount = 0; dwCount != dwNumEntries; dwCount++) { if (plineForward->dwCallerAddressOffset > 0) // Caller address is not used for some forward modes { pszCallerAddress = (PWSTR) (((LPBYTE)pAddressStatus) + plineForward->dwCallerAddressOffset); } pszDestddress = (PWSTR) (((LPBYTE)pAddressStatus) + plineForward->dwDestAddressOffset); if ( m_dwAPIVersion >= TAPI_VERSION3_1 ) { // // We have negotiated TAPI3.1 or better, so we can get the address types. // ITForwardInformation2 * pForwardInfo2; // // Get the ITForwardInformation2 interface so we can call SetForwardType2 // hr = (*ppForwardInfo)->QueryInterface( IID_ITForwardInformation2, (void **)&pForwardInfo2 ); if ( SUCCEEDED(hr) ) { pForwardInfo2->SetForwardType2(plineForward->dwForwardMode, pszDestddress, plineForward->dwDestAddressType, pszCallerAddress, plineForward->dwCallerAddressType ); pForwardInfo2->Release(); } else { LOG((TL_ERROR, "get_CurrentForwardInfo - QueryInterface failed - %lx", hr)); // // If for some reason the QI fails, break out of the loop // break; } } else { (*ppForwardInfo)->SetForwardType(plineForward->dwForwardMode, pszDestddress, pszCallerAddress ); } plineForward++; } ClientFree( pAddressStatus ); } else { LOG((TL_ERROR, "get_CurrentForwardInfo - LineGetAddressStatus failed ")); } MaybeCloseALine( &pLine ); } else { LOG((TL_ERROR, "get_CurrentForwardInfo - FindOrOpen failed")); } } else { LOG((TL_ERROR, "get_CurrentForwardInfo - failed to create")); } LOG((TL_TRACE, hr, "get_CurrentForwardInfo - exit")); return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddress::get_DialableAddress( BSTR * ppDialableAddress ) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_DialableAddress - Enter")); if (TAPIIsBadWritePtr(ppDialableAddress , sizeof(BSTR) ) ) { LOG((TL_ERROR, "get_DialableAddress - bad pointer")); return E_POINTER; } *ppDialableAddress = SysAllocString( m_szAddress ); if ( ( NULL == *ppDialableAddress ) && ( NULL != m_szAddress ) ) { LOG((TL_TRACE, "SysAllocString Failed" )); hr = E_OUTOFMEMORY; } LOG((TL_TRACE, "get_DialableAddress - Exit")); return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddress::put_MessageWaiting( VARIANT_BOOL fMessageWaiting ) { HRESULT hr = S_OK; AddressLineStruct * pLine = NULL; LOG((TL_TRACE, "put_MessageWaiting - Enter")); hr = FindOrOpenALine( LINEMEDIAMODE_INTERACTIVEVOICE, &pLine ); if ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "put_MessageWaiting - findoropen failed %lx", hr)); return hr; } hr = LineSetLineDevStatus( &(pLine->t3Line), LINEDEVSTATUSFLAGS_MSGWAIT, fMessageWaiting?-1:0 ); if ( ((LONG)hr) < 0 ) { LOG((TL_TRACE, "put_MessageWaiting failed sync - %lx", hr)); MaybeCloseALine( &pLine ); return hr; } // Wait for the async reply & map it's tapi2 code T3 hr = WaitForReply( hr ); MaybeCloseALine( &pLine ); if ( !SUCCEEDED(hr) ) { LOG((TL_TRACE, "put_MessageWaiting failed async - %lx", hr)); return hr; } LOG((TL_TRACE, "put_MessageWaiting - Exit")); return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddress::get_MessageWaiting( VARIANT_BOOL * pfMessageWaiting ) { HRESULT hr = S_OK; LINEDEVSTATUS * pDevStatus; AddressLineStruct * pLine; LOG((TL_TRACE, "get_MessageWaiting - Enter")); if (TAPIIsBadWritePtr(pfMessageWaiting , sizeof(VARIANT_BOOL) ) ) { LOG((TL_ERROR, "get_MessageWaiting - bad pointer")); return E_POINTER; } hr = FindOrOpenALine( LINEMEDIAMODE_INTERACTIVEVOICE, &pLine ); if ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "FindOrOpenALine failed - %lx", hr )); return hr; } hr = LineGetLineDevStatus( pLine->t3Line.hLine, &pDevStatus ); MaybeCloseALine( &pLine ); if ( !SUCCEEDED( hr ) ) { LOG((TL_ERROR, "LineGetDevStatus failed - %lx", hr )); return hr; } if ( pDevStatus->dwDevStatusFlags & LINEDEVSTATUSFLAGS_MSGWAIT ) { *pfMessageWaiting = VARIANT_TRUE; } else { *pfMessageWaiting = VARIANT_FALSE; } ClientFree( pDevStatus ); if ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "Bad pointer in get_MessageWaiting")); return hr; } LOG((TL_TRACE, "get_MessageWaiting - Exit")); return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddress::put_DoNotDisturb( VARIANT_BOOL fDoNotDisturb ) { HRESULT hr = S_OK; LINEFORWARDLIST lfl; HCALL hCall = NULL; AddressLineStruct * pLine; // // do not disturb is acheived through calling // lineforward with NULL for the dest address // LOG((TL_TRACE, "put_DoNotDisturb - Enter")); // // if we are setting dnd, create a lineforwardlist // structure // if ( fDoNotDisturb ) { ZeroMemory( &lfl, sizeof( LINEFORWARDLIST ) ); lfl.dwTotalSize = sizeof( LINEFORWARDLIST ); lfl.dwNumEntries = 1; // // there is only one item, and the dest address // is NULL // lfl.ForwardList[0].dwForwardMode = LINEFORWARDMODE_UNCOND; } // // get a line to use // hr = FindOrOpenALine( LINEMEDIAMODE_INTERACTIVEVOICE, &pLine ); if ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "put_DoNotDisturb - FindOrOpen failed %lx", hr)); return hr; } // // call line forward // if fDND is false, the LINEFORWARDLIST structure pointer // should be NULL. This clears any fowarding on that // line. // hr = LineForward( &(pLine->t3Line), m_dwAddressID, fDoNotDisturb?&lfl:NULL, 0, &hCall ); if ( ((long)hr) < 0 ) { LOG((TL_ERROR, "put_DND - linefoward failed sync - %lx", hr)); MaybeCloseALine( &pLine ); return hr; } // Wait for the async reply & map it's tapi2 code T3 hr = WaitForReply( hr ); if ( NULL != hCall ) { T3CALL t3Call; HRESULT hr2; t3Call.hCall = hCall; hr2 = LineDrop( t3Call.hCall, NULL, 0 ); if ( ((long)hr2) > 0 ) { hr2 = WaitForReply( hr2 ) ; } hr2 = LineDeallocateCall( t3Call.hCall ); } // // we are no longer using the line // MaybeCloseALine( &pLine ); if ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "put_DND - linefoware failed async - %lx", hr)); return hr; } LOG((TL_TRACE, "put_DoNotDisturb - Exit")); return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddress::get_DoNotDisturb( VARIANT_BOOL * pfDoNotDisturb ) { HRESULT hr = S_OK; AddressLineStruct * pLine; LINEADDRESSSTATUS * pAddressStatus; LINEDEVSTATUS * pDevStatus = NULL; // // donotdisturb is implemented through // line forward. // to get_DND, check the forward state // LOG((TL_TRACE, "get_DoNotDisturb - Enter")); if (TAPIIsBadWritePtr(pfDoNotDisturb , sizeof(VARIANT_BOOL) ) ) { LOG((TL_ERROR, "pfDoNotDisturb - bad pointer")); return E_POINTER; } hr = FindOrOpenALine( LINEMEDIAMODE_INTERACTIVEVOICE, &pLine ); if ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "get_DND - FindOrOpen failed %lx", hr)); return hr; } hr = LineGetLineDevStatus( pLine->t3Line.hLine, &pDevStatus ); if ( !SUCCEEDED(hr) ) { MaybeCloseALine( &pLine ); return hr; } if ( !(pDevStatus->dwLineFeatures & LINEFEATURE_FORWARD ) ) { LOG((TL_INFO, "get_DND - not supported")); MaybeCloseALine( &pLine ); if(pDevStatus != NULL) { ClientFree(pDevStatus); } return TAPI_E_NOTSUPPORTED; } // finished with pDevStatus if(pDevStatus != NULL) { ClientFree(pDevStatus); } // // get the addresss status // hr = LineGetAddressStatus( &(pLine->t3Line), m_dwAddressID, &pAddressStatus ); if ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "get_DND - LineGetAddressStatus failed - %lx", hr)); MaybeCloseALine( &pLine ); return hr; } // // initialize to false // *pfDoNotDisturb = VARIANT_FALSE; if ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "get_DND - bad pointer")); return E_OUTOFMEMORY; } // // if there is forwarding // if ( 0 != pAddressStatus->dwForwardNumEntries ) { LINEFORWARD * pfl; pfl = (LINEFORWARD *) (((LPBYTE)pAddressStatus) + pAddressStatus->dwForwardOffset); // // and the dest address is NULL // if ( 0 == pfl->dwDestAddressOffset ) { // // DND is set // *pfDoNotDisturb = VARIANT_TRUE; } } MaybeCloseALine( &pLine ); ClientFree( pAddressStatus ); LOG((TL_TRACE, "get_DoNotDisturb - Exit")); return S_OK; } // // itaddresscapabilities // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddress::get_AddressCapability( ADDRESS_CAPABILITY AddressCap, long * plCapability ) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_AddressCapability - Enter")); if ( TAPIIsBadWritePtr( plCapability, sizeof(long) ) ) { LOG((TL_ERROR, "get_AddressCapability - bad pointer")); return E_POINTER; } Lock(); hr = UpdateAddressCaps(); if ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "get_AddressCapability - could not get addresscaps")); Unlock(); return E_UNEXPECTED; } switch (AddressCap) { case AC_LINEID: *plCapability = m_dwDeviceID; break; case AC_ADDRESSID: *plCapability = m_dwAddressID; break; case AC_ADDRESSTYPES: case AC_BEARERMODES: case AC_MONITORDIGITSUPPORT: case AC_GENERATEDIGITSUPPORT: case AC_GENERATETONEMODES: case AC_GENERATETONEMAXNUMFREQ: case AC_MONITORTONEMAXNUMFREQ: case AC_MONITORTONEMAXNUMENTRIES: case AC_DEVCAPFLAGS: case AC_ANSWERMODES: case AC_LINEFEATURES: case AC_SETTABLEDEVSTATUS: case AC_PERMANENTDEVICEID: case AC_GATHERDIGITSMINTIMEOUT: case AC_GATHERDIGITSMAXTIMEOUT: case AC_GENERATEDIGITMINDURATION: case AC_GENERATEDIGITMAXDURATION: case AC_GENERATEDIGITDEFAULTDURATION: { hr = UpdateLineDevCaps(); if ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "get_AddressCap - could not get devcaps - %lx", hr)); Unlock(); return hr; } switch (AddressCap) { case AC_ADDRESSTYPES: if ( m_dwAPIVersion >= TAPI_VERSION3_0 ) { *plCapability = m_pDevCaps->dwAddressTypes; } else { *plCapability = LINEADDRESSTYPE_PHONENUMBER; } break; case AC_BEARERMODES: *plCapability = m_pDevCaps->dwBearerModes; break; case AC_MONITORDIGITSUPPORT: *plCapability = m_pDevCaps->dwMonitorDigitModes; break; case AC_GENERATEDIGITSUPPORT: *plCapability = m_pDevCaps->dwGenerateDigitModes; break; case AC_GENERATETONEMODES: *plCapability = m_pDevCaps->dwGenerateToneModes; break; case AC_GENERATETONEMAXNUMFREQ: *plCapability = m_pDevCaps->dwGenerateToneMaxNumFreq; break; case AC_MONITORTONEMAXNUMFREQ: *plCapability = m_pDevCaps->dwMonitorToneMaxNumFreq; break; case AC_MONITORTONEMAXNUMENTRIES: *plCapability = m_pDevCaps->dwMonitorToneMaxNumEntries; break; case AC_DEVCAPFLAGS: *plCapability = m_pDevCaps->dwDevCapFlags; break; case AC_ANSWERMODES: *plCapability = m_pDevCaps->dwAnswerMode; break; case AC_LINEFEATURES: *plCapability = m_pDevCaps->dwLineFeatures; break; case AC_SETTABLEDEVSTATUS: if ( m_dwAPIVersion >= TAPI_VERSION2_0 ) { *plCapability = m_pDevCaps->dwSettableDevStatus; } else hr = TAPI_E_NOTSUPPORTED; break; case AC_PERMANENTDEVICEID: *plCapability = m_pDevCaps->dwPermanentLineID; break; case AC_GATHERDIGITSMINTIMEOUT: *plCapability = m_pDevCaps->dwGatherDigitsMinTimeout; break; case AC_GATHERDIGITSMAXTIMEOUT: *plCapability = m_pDevCaps->dwGatherDigitsMaxTimeout; break; case AC_GENERATEDIGITMINDURATION: *plCapability = m_pDevCaps->MinDialParams.dwDigitDuration; break; case AC_GENERATEDIGITMAXDURATION: *plCapability = m_pDevCaps->MaxDialParams.dwDigitDuration; break; case AC_GENERATEDIGITDEFAULTDURATION: *plCapability = m_pDevCaps->DefaultDialParams.dwDigitDuration; break; } break; } case AC_MAXACTIVECALLS: case AC_MAXONHOLDCALLS: case AC_MAXONHOLDPENDINGCALLS: case AC_MAXNUMCONFERENCE: case AC_MAXNUMTRANSCONF: case AC_PARKSUPPORT: case AC_CALLERIDSUPPORT: case AC_CALLEDIDSUPPORT: case AC_CONNECTEDIDSUPPORT: case AC_REDIRECTIONIDSUPPORT: case AC_REDIRECTINGIDSUPPORT: case AC_ADDRESSCAPFLAGS: case AC_CALLFEATURES1: case AC_CALLFEATURES2: case AC_REMOVEFROMCONFCAPS: case AC_REMOVEFROMCONFSTATE: case AC_TRANSFERMODES: case AC_ADDRESSFEATURES: case AC_PREDICTIVEAUTOTRANSFERSTATES: case AC_MAXCALLDATASIZE: case AC_FORWARDMODES: case AC_MAXFORWARDENTRIES: case AC_MAXSPECIFICENTRIES: case AC_MINFWDNUMRINGS: case AC_MAXFWDNUMRINGS: case AC_MAXCALLCOMPLETIONS: case AC_CALLCOMPLETIONCONDITIONS: case AC_CALLCOMPLETIONMODES: { hr = UpdateAddressCaps(); if ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "get_AddressCaps - could not update caps - %lx", hr)); Unlock(); return hr; } switch (AddressCap) { case AC_MAXACTIVECALLS: *plCapability = m_pAddressCaps->dwMaxNumActiveCalls; break; case AC_MAXONHOLDCALLS: *plCapability = m_pAddressCaps->dwMaxNumOnHoldCalls; break; case AC_MAXONHOLDPENDINGCALLS: *plCapability = m_pAddressCaps->dwMaxNumOnHoldPendingCalls; break; case AC_MAXNUMCONFERENCE: *plCapability = m_pAddressCaps->dwMaxNumConference; break; case AC_MAXNUMTRANSCONF: *plCapability = m_pAddressCaps->dwMaxNumTransConf; break; case AC_PARKSUPPORT: *plCapability = m_pAddressCaps->dwParkModes; break; case AC_CALLERIDSUPPORT: *plCapability = m_pAddressCaps->dwCallerIDFlags; break; case AC_CALLEDIDSUPPORT: *plCapability = m_pAddressCaps->dwCalledIDFlags; break; case AC_CONNECTEDIDSUPPORT: *plCapability = m_pAddressCaps->dwConnectedIDFlags; break; case AC_REDIRECTIONIDSUPPORT: *plCapability = m_pAddressCaps->dwRedirectionIDFlags; break; case AC_REDIRECTINGIDSUPPORT: *plCapability = m_pAddressCaps->dwRedirectingIDFlags; break; case AC_ADDRESSCAPFLAGS: *plCapability = m_pAddressCaps->dwAddrCapFlags; break; case AC_CALLFEATURES1: *plCapability = m_pAddressCaps->dwCallFeatures; break; case AC_CALLFEATURES2: if ( m_dwAPIVersion < TAPI_VERSION2_0 ) { hr = TAPI_E_NOTSUPPORTED; } else { *plCapability = m_pAddressCaps->dwCallFeatures2; } break; case AC_REMOVEFROMCONFCAPS: *plCapability = m_pAddressCaps->dwRemoveFromConfCaps; break; case AC_REMOVEFROMCONFSTATE: *plCapability = m_pAddressCaps->dwRemoveFromConfState; break; case AC_TRANSFERMODES: *plCapability = m_pAddressCaps->dwTransferModes; break; case AC_ADDRESSFEATURES: *plCapability = m_pAddressCaps->dwAddressFeatures; break; case AC_PREDICTIVEAUTOTRANSFERSTATES: if ( m_dwAPIVersion < TAPI_VERSION2_0 ) { hr = TAPI_E_NOTSUPPORTED; } else { *plCapability = m_pAddressCaps->dwPredictiveAutoTransferStates; } break; case AC_MAXCALLDATASIZE: if ( m_dwAPIVersion < TAPI_VERSION2_0 ) { hr = TAPI_E_NOTSUPPORTED; } else { *plCapability = m_pAddressCaps->dwMaxCallDataSize; } break; case AC_FORWARDMODES: *plCapability = m_pAddressCaps->dwForwardModes; break; case AC_MAXFORWARDENTRIES: *plCapability = m_pAddressCaps->dwMaxForwardEntries; break; case AC_MAXSPECIFICENTRIES: *plCapability = m_pAddressCaps->dwMaxSpecificEntries; break; case AC_MINFWDNUMRINGS: *plCapability = m_pAddressCaps->dwMinFwdNumRings; break; case AC_MAXFWDNUMRINGS: *plCapability = m_pAddressCaps->dwMaxFwdNumRings; break; case AC_MAXCALLCOMPLETIONS: *plCapability = m_pAddressCaps->dwMaxCallCompletions; break; case AC_CALLCOMPLETIONCONDITIONS: *plCapability = m_pAddressCaps->dwCallCompletionConds; break; case AC_CALLCOMPLETIONMODES: *plCapability = m_pAddressCaps->dwCallCompletionModes; break; } break; } default: LOG((TL_ERROR, "get_AddressCapability - bad addrcap")); Unlock(); return E_INVALIDARG; } LOG((TL_TRACE, "get_AddressCapability - Exit - result - %lx", hr)); Unlock(); return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddress::get_AddressCapabilityString( ADDRESS_CAPABILITY_STRING AddressCapString, BSTR * ppCapabilityString ) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_AddressCapabilityString - Enter")); if ( TAPIIsBadWritePtr( ppCapabilityString, sizeof(BSTR) ) ) { LOG((TL_ERROR, "get_AddressCapabilityString - bad pointer")); return E_POINTER; } *ppCapabilityString = NULL; Lock(); // // note on: // ACS_ADDRESSDEVICESPECIFIC // ACS_LINEDEVICESPECIFIC: // ACS_PROVIDERSPECIFIC: // ACS_SWITCHSPECIFIC: // // These buffers in LINEDEVCAPS and LINEADDRESSCAPS may or may not be strings. However // in TAPI 3, we define them as strings. // // The algorithm for moving them from the tapi 2 structure to the tapi 3 string is: // // if the size of the buffer is evenly divisible by sizeof(WCHAR) // then it's definitely not a string (we only support WCHAR) // so we will just copy the buffer straight into the returned string, and append a // NULL at the end // else // if the buffer already has a null at the end, don't copy it, because SysAllocStringByteLen // always appends a NULL and double NULLs frighten VB. // // It can still be a "buffer" and not a string even if it is divisible by sizeof WCHAR, but for // this it does matter, since we are using SysAllocStringByteLen to copy the buffer no // matter what // switch (AddressCapString) { case ACS_ADDRESSDEVICESPECIFIC: hr = UpdateAddressCaps(); if ( !SUCCEEDED(hr) ) { Unlock(); return hr; } if ( m_pAddressCaps->dwDevSpecificSize != 0 ) { LPWSTR pHold; DWORD dwSize; dwSize = m_pAddressCaps->dwDevSpecificSize; // // is size divisible by sizeof(WCHAR)? // if (0 == (dwSize % sizeof(WCHAR))) { // // yes - get to the last character in the string // pHold = (LPWSTR)(((LPBYTE)(m_pAddressCaps)) + m_pAddressCaps->dwDevSpecificOffset), (dwSize-sizeof(WCHAR))/sizeof(WCHAR); // // is the last character a NULL? // if (*pHold == NULL) { // // yes, so don't copy it // dwSize-=sizeof(WCHAR); } } // // Alloc and copy into return string. SysAllocStringByteLen always // appends a NULL // *ppCapabilityString = SysAllocStringByteLen( (LPSTR)(((LPBYTE)(m_pAddressCaps)) + m_pAddressCaps->dwDevSpecificOffset), dwSize ); if ( NULL == *ppCapabilityString ) { LOG((TL_ERROR, "get_AddressCapabilityString - SysAllocString Failed")); hr = E_OUTOFMEMORY; } } break; case ACS_PROTOCOL: case ACS_LINEDEVICESPECIFIC: case ACS_PROVIDERSPECIFIC: case ACS_SWITCHSPECIFIC: case ACS_PERMANENTDEVICEGUID: { hr = UpdateLineDevCaps(); if ( !SUCCEEDED(hr) ) { Unlock(); return hr; } switch (AddressCapString) { case ACS_PROTOCOL: { LPWSTR pwstr; if ( m_dwAPIVersion >= TAPI_VERSION3_0 ) { IID iid; iid = m_pDevCaps->ProtocolGuid; StringFromIID(iid, &pwstr); } else { StringFromIID( TAPIPROTOCOL_PSTN, &pwstr ); } *ppCapabilityString = SysAllocString( pwstr ); if ( NULL == *ppCapabilityString ) { LOG((TL_ERROR, "get_AddressCapabilityString - SysAllocString Failed")); hr = E_OUTOFMEMORY; } CoTaskMemFree( pwstr ); break; } case ACS_LINEDEVICESPECIFIC: if ( m_pDevCaps->dwDevSpecificSize != 0 ) { LPWSTR pHold; DWORD dwSize; dwSize = m_pDevCaps->dwDevSpecificSize; // // is size divisible by sizeof(WCHAR)? // if (0 == (dwSize % sizeof(WCHAR))) { // // yes - get to the last character in the string // pHold = (LPWSTR)(((LPBYTE)(m_pDevCaps)) + m_pDevCaps->dwDevSpecificOffset) + (dwSize-sizeof(WCHAR))/sizeof(WCHAR); // // is the last character a NULL? // if (*pHold == NULL) { // // yes, so don't copy it // dwSize-=sizeof(WCHAR); } } // // Alloc and copy into return string. SysAllocStringByteLen always // appends a NULL // *ppCapabilityString = SysAllocStringByteLen( (LPSTR)(((LPBYTE)(m_pDevCaps)) + m_pDevCaps->dwDevSpecificOffset), dwSize ); if ( NULL == *ppCapabilityString ) { LOG((TL_ERROR, "get_AddressCapabilityString - SysAllocString Failed")); hr = E_OUTOFMEMORY; } } break; case ACS_PROVIDERSPECIFIC: if ( m_pDevCaps->dwProviderInfoSize != 0 ) { LPWSTR pHold; DWORD dwSize; dwSize = m_pDevCaps->dwProviderInfoSize; // // is size divisible by sizeof(WCHAR)? // if (0 == (dwSize % sizeof(WCHAR))) { // // yes - get to the last character in the string // pHold = (LPWSTR)(((LPBYTE)(m_pDevCaps)) + m_pDevCaps->dwProviderInfoOffset) + (dwSize-sizeof(WCHAR))/sizeof(WCHAR); // // is the last character a NULL? // if (*pHold == NULL) { // // yes, so don't copy it // dwSize-=sizeof(WCHAR); } } // // Alloc and copy into return string. SysAllocStringByteLen always // appends a NULL // *ppCapabilityString = SysAllocStringByteLen( (LPSTR)(((LPBYTE)(m_pDevCaps)) + m_pDevCaps->dwProviderInfoOffset), dwSize ); if ( NULL == *ppCapabilityString ) { LOG((TL_ERROR, "get_AddressCapabilityString - SysAllocString Failed")); hr = E_OUTOFMEMORY; } } break; case ACS_SWITCHSPECIFIC: if ( m_pDevCaps->dwSwitchInfoSize != 0 ) { LPWSTR pHold; DWORD dwSize; dwSize = m_pDevCaps->dwSwitchInfoSize; // // is size divisible by sizeof(WCHAR)? // if (0 == (dwSize % sizeof(WCHAR))) { // // yes - get to the last character in the string // pHold = (LPWSTR)(((LPBYTE)(m_pDevCaps)) + m_pDevCaps->dwSwitchInfoOffset) + (dwSize-sizeof(WCHAR))/sizeof(WCHAR); // // is the last character a NULL? // if (*pHold == NULL) { // // yes, so don't copy it // dwSize-=sizeof(WCHAR); } } // // Alloc and copy into return string. SysAllocStringByteLen always // appends a NULL // *ppCapabilityString = SysAllocStringByteLen( (LPSTR)(((LPBYTE)(m_pDevCaps)) + m_pDevCaps->dwSwitchInfoOffset), dwSize ); if ( NULL == *ppCapabilityString ) { LOG((TL_ERROR, "get_AddressCapabilityString - SysAllocString Failed")); hr = E_OUTOFMEMORY; } } break; case ACS_PERMANENTDEVICEGUID: { LPWSTR pwstrGUIDText; if ( m_dwAPIVersion >= TAPI_VERSION2_2 ) { IID iid; iid = m_pDevCaps->PermanentLineGuid; StringFromIID(iid, &pwstrGUIDText); *ppCapabilityString = SysAllocString( pwstrGUIDText ); if ( NULL == *ppCapabilityString ) { LOG((TL_ERROR, "get_AddressCapabilityString - SysAllocString Failed")); hr = E_OUTOFMEMORY; } CoTaskMemFree( pwstrGUIDText ); } else { // return with NULL string & error code hr = TAPI_E_NOTSUPPORTED; } break; } default: break; } break; } default: LOG((TL_ERROR, "get_AddressCapabilityString - invalid cap")); Unlock(); return E_INVALIDARG; } LOG((TL_TRACE, "get_AddressCapabilityString - Exit - result - %lx", hr)); Unlock(); return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CreateBstrCollection( IN BSTR * pBstr, IN DWORD dwCount, OUT VARIANT * pVariant ) { // // create the collection object // CComObject * pCollection; HRESULT hr = CComObject::CreateInstance( &pCollection ); if ( FAILED(hr) ) { LOG((TL_ERROR, "CreateBstrCollection - " "can't create collection - exit 0x%lx", hr)); return hr; } // // get the Collection's IDispatch interface // IDispatch * pDispatch; hr = pCollection->_InternalQueryInterface(__uuidof(IDispatch), (void **) &pDispatch ); if ( FAILED(hr) ) { LOG((TL_ERROR, "CreateBstrCollection - " "QI for IDispatch on collection failed - exit 0x%lx", hr)); delete pCollection; return hr; } // // Init the collection using an iterator -- pointers to the beginning and // the ending element plus one. // hr = pCollection->Initialize( dwCount, pBstr, pBstr + dwCount); if ( FAILED(hr) ) { LOG((TL_ERROR, "CreateBstrCollection - " "Initialize on collection failed - exit 0x%lx", hr)); pDispatch->Release(); return hr; } // // put the IDispatch interface pointer into the variant // LOG((TL_ERROR, "CreateBstrCollection - " "placing IDispatch value %p in variant", pDispatch)); VariantInit(pVariant); pVariant->vt = VT_DISPATCH; pVariant->pdispVal = pDispatch; LOG((TL_TRACE, "CreateBstrCollection - exit S_OK")); return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CreateBstrEnumerator( IN BSTR * begin, IN BSTR * end, OUT IEnumBstr ** ppIEnum ) { typedef CSafeComEnum CEnumerator; HRESULT hr; CComObject *pEnum = NULL; hr = CComObject::CreateInstance(&pEnum); if (pEnum == NULL) { LOG((TL_ERROR, "CreateBstrEnumerator - " "Could not create enumerator object, 0x%lx", hr)); return hr; } IEnumBstr * pIEnum; hr = pEnum->_InternalQueryInterface( __uuidof(IEnumBstr), (void**)&pIEnum ); if (FAILED(hr)) { LOG((TL_ERROR, "CreateBstrEnumerator - " "query enum interface failed, 0x%lx", hr)); delete pEnum; return hr; } hr = pEnum->Init(begin, end, NULL, AtlFlagCopy); if (FAILED(hr)) { LOG((TL_ERROR, "CreateBstrEnumerator - " "init enumerator object failed, 0x%lx", hr)); pIEnum->Release(); return hr; } *ppIEnum = pIEnum; LOG((TL_TRACE, "CreateBstrEnumerator - exit S_OK")); return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddress::get_CallTreatments(VARIANT * pVariant ) { HRESULT hr = E_NOTIMPL; LOG((TL_TRACE, "get_CallTreatments - Enter")); LOG((TL_TRACE, "get_CallTreatments - Exit - result - %lx", hr)); return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddress::EnumerateCallTreatments(IEnumBstr ** ppEnumCallTreatment ) { HRESULT hr = E_NOTIMPL; LOG((TL_TRACE, "EnumerateCallTreatments - Enter")); LOG((TL_TRACE, "EnumerateCallTreatments - Exit - result - %lx", hr)); return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddress::get_CompletionMessages(VARIANT * pVariant) { HRESULT hr = E_NOTIMPL; LOG((TL_TRACE, "get_CompletionMessages - Enter")); LOG((TL_TRACE, "get_CompletionMessages - Exit - result - %lx", hr)); return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddress::EnumerateCompletionMessages(IEnumBstr ** ppEnumCompletionMessage) { HRESULT hr = E_NOTIMPL; LOG((TL_TRACE, "EnumerateCompletionMessages - Enter")); LOG((TL_TRACE, "EnumerateCompletionMessages - Exit - result - %lx", hr)); return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddress::get_DeviceClasses(VARIANT * pVariant) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_DeviceClasses - Enter")); // // Check arguments. // if ( TAPIIsBadWritePtr( pVariant, sizeof( VARIANT ) ) ) { LOG((TL_ERROR, "get_DeviceClasses - bad pointer")); return E_POINTER; } Lock(); hr = UpdateLineDevCaps(); if ( SUCCEEDED(hr) ) { if ( (m_dwAPIVersion >= TAPI_VERSION2_0) && (0 != m_pDevCaps->dwDeviceClassesOffset) ) { PWSTR pszDevices; DWORD dwNumDeviceClasses; // // first count the device classes // dwNumDeviceClasses = 0; pszDevices = (PWSTR)( ( (PBYTE)m_pDevCaps ) + m_pDevCaps->dwDeviceClassesOffset ); while (NULL != *pszDevices) { dwNumDeviceClasses++; pszDevices += (lstrlenW(pszDevices) + 1 ); } // // allocate an array of BSTR pointers // BSTR *DeviceClasses = (BSTR *)ClientAlloc(sizeof(BSTR *) * dwNumDeviceClasses); if (DeviceClasses == NULL) { LOG((TL_ERROR, "get_DeviceClasses - out of memory")); Unlock(); return E_OUTOFMEMORY; } // // allocate all the BSTRs, copying the device class names // DWORD dwCount = 0; pszDevices = (PWSTR)( ( (PBYTE)m_pDevCaps ) + m_pDevCaps->dwDeviceClassesOffset ); for (DWORD i = 0; i < dwNumDeviceClasses; i++) { LOG((TL_INFO, "get_DeviceClasses - got '%ws'", pszDevices)); DeviceClasses[i] = SysAllocString(pszDevices); if (DeviceClasses[i] == NULL) { LOG((TL_ERROR, "get_DeviceClasses - out of memory")); hr = E_OUTOFMEMORY; break; } dwCount++; pszDevices += (lstrlenW(pszDevices) + 1 ); } if ( FAILED(hr) ) { // release all the BSTRs and the array. for (i = 0; i < dwCount; i ++) { SysFreeString(DeviceClasses[i]); } ClientFree(DeviceClasses); Unlock(); return hr; } hr = CreateBstrCollection(DeviceClasses, dwCount, pVariant); // if the collection is not created, release all the BSTRs. if (FAILED(hr)) { LOG((TL_ERROR, "get_DeviceClasses - unable to create collection")); for (i = 0; i < dwCount; i ++) { SysFreeString(DeviceClasses[i]); } } // delete the pointer array. ClientFree(DeviceClasses); } else { LOG((TL_ERROR, "get_DeviceClasses - no device classes")); // // create an empty collection // hr = CreateBstrCollection(NULL, 0, pVariant); if (FAILED(hr)) { LOG((TL_ERROR, "get_DeviceClasses - unable to create collection")); } } } Unlock(); LOG((TL_TRACE, "get_DeviceClasses - Exit - result - %lx", hr)); return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddress::EnumerateDeviceClasses(IEnumBstr ** ppEnumDeviceClass) { HRESULT hr = S_OK; LOG((TL_TRACE, "EnumerateDeviceClasses - Enter")); // // Check arguments. // if ( TAPIIsBadWritePtr( ppEnumDeviceClass, sizeof( IEnumBstr * ) ) ) { LOG((TL_ERROR, "EnumerateDeviceClasses - bad pointer")); return E_POINTER; } Lock(); hr = UpdateLineDevCaps(); if ( SUCCEEDED(hr) ) { if ( (m_dwAPIVersion >= TAPI_VERSION2_0) && (0 != m_pDevCaps->dwDeviceClassesOffset) ) { PWSTR pszDevices; DWORD dwNumDeviceClasses; // // first count the device classes // dwNumDeviceClasses = 0; pszDevices = (PWSTR)( ( (PBYTE)m_pDevCaps ) + m_pDevCaps->dwDeviceClassesOffset ); while (NULL != *pszDevices) { dwNumDeviceClasses++; pszDevices += (lstrlenW(pszDevices) + 1 ); } // // allocate an array of BSTR pointers // BSTR *DeviceClasses = (BSTR *)ClientAlloc(sizeof(BSTR *) * dwNumDeviceClasses); if (DeviceClasses == NULL) { LOG((TL_ERROR, "EnumerateDeviceClasses - out of memory")); Unlock(); return E_OUTOFMEMORY; } // // allocate all the BSTRs, copying the device class names // DWORD dwCount = 0; pszDevices = (PWSTR)( ( (PBYTE)m_pDevCaps ) + m_pDevCaps->dwDeviceClassesOffset ); for (DWORD i = 0; i < dwNumDeviceClasses; i++) { LOG((TL_INFO, "EnumerateDeviceClasses - got '%ws'", pszDevices)); DeviceClasses[i] = SysAllocString(pszDevices); if (DeviceClasses[i] == NULL) { LOG((TL_ERROR, "EnumerateDeviceClasses - out of memory")); hr = E_OUTOFMEMORY; break; } dwCount++; pszDevices += (lstrlenW(pszDevices) + 1 ); } if ( FAILED(hr) ) { // release all the BSTRs and the array. for (i = 0; i < dwCount; i ++) { SysFreeString(DeviceClasses[i]); } ClientFree(DeviceClasses); Unlock(); return hr; } hr = CreateBstrEnumerator(DeviceClasses, DeviceClasses + dwCount, ppEnumDeviceClass); if (FAILED(hr)) { LOG((TL_ERROR, "EnumerateDeviceClasses - unable to create enum")); } // release all the BSTRs as the enumerator made a copy of them for (i = 0; i < dwCount; i ++) { SysFreeString(DeviceClasses[i]); } // delete the pointer array. ClientFree(DeviceClasses); } else { LOG((TL_ERROR, "EnumerateDeviceClasses - no device classes")); // // create an empty enumeration // hr = CreateBstrEnumerator(NULL, NULL, ppEnumDeviceClass); if (FAILED(hr)) { LOG((TL_ERROR, "EnumerateDeviceClasses - unable to create enumeration")); } } } Unlock(); LOG((TL_TRACE, "EnumerateDeviceClasses - Exit - result - %lx", hr)); return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void HandleLineDevStateMessage( CTAPI * pTapi, PASYNCEVENTMSG pParams ) { LOG((TL_TRACE, "HandleLineDevStateMessage - enter. tapi[%p]", pTapi)); CAddress * pAddress; if ( LINEDEVSTATE_REINIT == pParams->Param1 ) { LOG((TL_TRACE, "HandleLineDevStateMessage - LINEDEVSTATE_REINIT")); pTapi->AddRef(); //This is to remove the bug, 4 RE_INIT messages for two objects. pTapi->HandleReinit(); pTapi->Release(); LOG((TL_TRACE, "HandleLineDevStateMessage - exit")); return; } if ( LINEDEVSTATE_TRANSLATECHANGE == pParams->Param1 ) { CTapiObjectEvent::FireEvent( pTapi, TE_TRANSLATECHANGE, NULL, 0, NULL ); return; } if ( !FindAddressObject( (HLINE)(pParams->hDevice), &pAddress ) ) { LOG((TL_WARN, "Can't process LINE_LINEDEVSTATE message")); LOG((TL_WARN, " - cannot find hLine %lx", pParams->hDevice)); return; } switch ( pParams->Param1 ) { case LINEDEVSTATE_CONNECTED: case LINEDEVSTATE_INSERVICE: { pAddress->InService( pParams->Param1 ); break; } case LINEDEVSTATE_OUTOFSERVICE: case LINEDEVSTATE_MAINTENANCE: case LINEDEVSTATE_REMOVED: case LINEDEVSTATE_DISCONNECTED: case LINEDEVSTATE_LOCK: pAddress->OutOfService( pParams->Param1 ); break; case LINEDEVSTATE_MSGWAITON: CAddressEvent::FireEvent( pAddress, AE_MSGWAITON, NULL ); break; case LINEDEVSTATE_MSGWAITOFF: CAddressEvent::FireEvent( pAddress, AE_MSGWAITOFF, NULL ); break; // the line has been opened or // closed by another app case LINEDEVSTATE_OPEN: case LINEDEVSTATE_CLOSE: break; case LINEDEVSTATE_CAPSCHANGE: pAddress->CapsChange( FALSE ); break; case LINEDEVSTATE_CONFIGCHANGE: { CAddressEvent::FireEvent( pAddress, AE_CONFIGCHANGE, NULL ); break; } case LINEDEVSTATE_RINGING: { CAddressEvent::FireEvent( pAddress, AE_RINGING, NULL ); break; } case LINEDEVSTATE_DEVSPECIFIC: case LINEDEVSTATE_OTHER: case LINEDEVSTATE_NUMCALLS: case LINEDEVSTATE_NUMCOMPLETIONS: case LINEDEVSTATE_TERMINALS: case LINEDEVSTATE_ROAMMODE: case LINEDEVSTATE_BATTERY: case LINEDEVSTATE_SIGNAL: case LINEDEVSTATE_COMPLCANCEL: LOG((TL_INFO, "LINE_LINEDEVSTATE message not handled - %lx", pParams->Param1)); break; default: LOG((TL_WARN, "Unknown LINE_LINEDEVSTATE message - %lx", pParams->Param1)); break; } //FindAddressObject addrefs the address objct pAddress->Release(); LOG((TL_TRACE, "HandleLineDevStateMessage - exit.")); return; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void HandleAddressStateMessage( PASYNCEVENTMSG pParams ) { CAddress * pAddress; if ( !FindAddressObject( (HLINE)(pParams->hDevice), &pAddress ) ) { LOG((TL_WARN, "Can't process LINE_LINEDEVSTATE message")); LOG((TL_WARN, " - cannot find hLine %lx", pParams->hDevice)); return; } switch ( pParams->Param1 ) { case LINEADDRESSSTATE_FORWARD: { CAddressEvent::FireEvent( pAddress, AE_FORWARD, NULL ); break; } case LINEADDRESSSTATE_CAPSCHANGE: { pAddress->CapsChange( TRUE ); break; } case LINEADDRESSSTATE_OTHER: case LINEADDRESSSTATE_DEVSPECIFIC: case LINEADDRESSSTATE_INUSEZERO: case LINEADDRESSSTATE_INUSEONE: case LINEADDRESSSTATE_INUSEMANY: case LINEADDRESSSTATE_NUMCALLS: case LINEADDRESSSTATE_TERMINALS: LOG((TL_WARN, "HandleAddressStateMessage - not handled %lx", pParams->Param1)); break; default: LOG((TL_WARN, "HandleAddressStateMessage - Unknown %lx", pParams->Param1)); break; } //FindAddressObject addrefs the address objct pAddress->Release(); return; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void CAddress::InService( DWORD dwType ) { BOOL bEvent = FALSE; switch( dwType ) { case LINEDEVSTATE_CONNECTED: case LINEDEVSTATE_INSERVICE: default: break; } Lock(); if ( AS_INSERVICE != m_AddressState ) { m_AddressState = AS_INSERVICE; bEvent = TRUE; } Unlock(); if (bEvent) { CAddressEvent::FireEvent( this, AE_STATE, NULL ); } } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void CAddress::OutOfService( DWORD dwType ) { BOOL bEvent = FALSE; switch ( dwType ) { case LINEDEVSTATE_OUTOFSERVICE: case LINEDEVSTATE_MAINTENANCE: case LINEDEVSTATE_REMOVED: case LINEDEVSTATE_DISCONNECTED: case LINEDEVSTATE_LOCK: default: break; } Lock(); if ( AS_OUTOFSERVICE != m_AddressState ) { m_AddressState = AS_OUTOFSERVICE; bEvent = TRUE; } Unlock(); if ( bEvent ) { CAddressEvent::FireEvent( this, AE_STATE, NULL ); } } void CAddress::CapsChange( BOOL bAddress ) { Lock(); if (bAddress) { m_dwAddressFlags |= ADDRESSFLAG_ADDRESSCAPSCHANGE; } else { m_dwAddressFlags |= ADDRESSFLAG_DEVCAPSCHANGE; } Unlock(); CAddressEvent::FireEvent( this, AE_CAPSCHANGE, NULL ); } // // CAddressEvent // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddressEvent::FireEvent( CAddress * pCAddress, ADDRESS_EVENT Event, ITTerminal * pTerminal ) { HRESULT hr = S_OK; CComObject * p; IDispatch * pDisp; // // Check the event filter mask // just if is the AE_NEWTERMINAL or AE_REMOVETERMINAL // These two events are MSP events and are not filtered by // TapiSrv // DWORD dwEventFilterMask = 0; dwEventFilterMask = pCAddress->GetSubEventsMask( TE_ADDRESS ); if( !( dwEventFilterMask & GET_SUBEVENT_FLAG(Event))) { STATICLOG((TL_ERROR, "This event is filtered - %lx", Event)); return S_OK; } // // create event // hr = CComObject::CreateInstance( &p ); if ( !SUCCEEDED(hr) ) { STATICLOG((TL_ERROR, "Could not create AddressEvent object - %lx", hr)); return hr; } // // initialize // p->m_Event = Event; p->m_pAddress = dynamic_cast(pCAddress); p->m_pAddress->AddRef(); p->m_pTerminal = pTerminal; if ( NULL != pTerminal ) { pTerminal->AddRef(); } #if DBG p->m_pDebug = (PWSTR) ClientAlloc( 1 ); #endif // // get idisp interface // hr = p->QueryInterface( IID_IDispatch, (void **)&pDisp ); if ( !SUCCEEDED(hr) ) { STATICLOG((TL_ERROR, "Could not get disp interface of AddressEvent object %lx", hr)); delete p; return hr; } // // get callback // // // fire event // (pCAddress->GetTapi())->Event( TE_ADDRESS, pDisp ); // // release stuff // pDisp->Release(); return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // finalrelease // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void CAddressEvent::FinalRelease() { LOG((TL_INFO, "CAddressEvent - FinalRelease")); m_pAddress->Release(); if ( NULL != m_pTerminal ) { m_pTerminal->Release(); } #if DBG ClientFree( m_pDebug ); #endif } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // get_Address // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddressEvent::get_Address( ITAddress ** ppAddress ) { if (TAPIIsBadWritePtr(ppAddress , sizeof(ITAddress *) ) ) { LOG((TL_ERROR, "get_Address - bad pointer")); return E_POINTER; } *ppAddress = m_pAddress; (*ppAddress)->AddRef(); return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // get_Terminal // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddressEvent::get_Terminal( ITTerminal ** ppTerminal ) { if ( TAPIIsBadWritePtr( ppTerminal , sizeof(ITTerminal *) ) ) { LOG((TL_ERROR, "get_Terminal - bad pointer")); return E_POINTER; } if ((m_Event != AE_NEWTERMINAL) && (m_Event != AE_REMOVETERMINAL)) { LOG((TL_ERROR, "get_Terminal - wrong event")); return TAPI_E_WRONGEVENT; } *ppTerminal = m_pTerminal; if ( NULL != m_pTerminal ) { m_pTerminal->AddRef(); } return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // get_Event // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddressEvent::get_Event( ADDRESS_EVENT * pEvent ) { if (TAPIIsBadWritePtr(pEvent , sizeof(ADDRESS_EVENT) ) ) { LOG((TL_ERROR, "get_Event - bad pointer")); return E_POINTER; } *pEvent = m_Event; return S_OK; } /////////////////////////////////////////////////////////////////////////////// // // CAddressDevSpecificEvent // // static HRESULT CAddressDevSpecificEvent::FireEvent( CAddress * pCAddress, CCall * pCall, long l1, long l2, long l3 ) { STATICLOG((TL_INFO, "CAddressDevSpecificEvent::FireEvent - enter")); // // try to create the event // CComObject *pEventObject = NULL; HRESULT hr = CComObject::CreateInstance(&pEventObject); if ( FAILED(hr) ) { STATICLOG((TL_ERROR, "CAddressDevSpecificEvent::FireEvent - failed to create CAddressDevSpecificEvent. hr = %lx", hr)); return hr; } // // initialize the event with the data we received // // // get ITAddress from CAddress we received // hr = pCAddress->_InternalQueryInterface(IID_ITAddress, (void**)(&(pEventObject->m_pAddress)) ); if (FAILED(hr)) { STATICLOG((TL_ERROR, "CAddressDevSpecificEvent::FireEvent - failed to create get ITAddress interface from address. hr = %lx", hr)); delete pEventObject; return hr; } // // get ITCallInfo interface from CCall we received // if (NULL != pCall) { hr = pCall->_InternalQueryInterface(IID_ITCallInfo, (void**)(&(pEventObject->m_pCall)) ); if (FAILED(hr)) { STATICLOG((TL_ERROR, "CAddressDevSpecificEvent::FireEvent - failed to create get ITAddress interface from address. hr = %lx", hr)); // // no need to release event's data members, event's destructor will do // this for us // 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, "CAddressDevSpecificEvent::FireEvent - Could not get disp interface of AddressEvent object %lx", hr)); // // no need to release event's data members, event's destructor will do // this for us // // // 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 = (pCAddress->GetTapi())->Event(TE_ADDRESSDEVSPECIFIC, pDispatch); // // succeeded or not, we no longer need a reference to the event object // pDispatch->Release(); pDispatch = NULL; STATICLOG((TL_INFO, "CAddressDevSpecificEvent::FireEvent - exit, hr = %lx", hr)); return hr; } /////////////////////////////////////////////////////////////////////////////// CAddressDevSpecificEvent::CAddressDevSpecificEvent() :m_pAddress(NULL), m_pCall(NULL) { LOG((TL_INFO, "CAddressDevSpecificEvent - enter")); #if DBG m_pDebug = NULL; #endif LOG((TL_INFO, "CAddressDevSpecificEvent - exit")); } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // ~CAddressDevSpecificEvent // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ CAddressDevSpecificEvent::~CAddressDevSpecificEvent() { LOG((TL_INFO, "~CAddressDevSpecificEvent - enter")); if (NULL != m_pAddress) { m_pAddress->Release(); m_pAddress = NULL; } if (NULL != m_pCall) { m_pCall->Release(); m_pCall = NULL; } #if DBG ClientFree( m_pDebug ); #endif LOG((TL_INFO, "~CAddressDevSpecificEvent - exit")); } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // get_Address // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddressDevSpecificEvent::get_Address( ITAddress ** ppAddress ) { LOG((TL_TRACE, "get_Address - enter")); // // good out pointer? // if (TAPIIsBadWritePtr(ppAddress , sizeof(ITAddress *) ) ) { LOG((TL_ERROR, "get_Address - bad pointer at [%p]", ppAddress)); return E_POINTER; } // // return addreff'd address // _ASSERTE(NULL != m_pAddress); *ppAddress = m_pAddress; (*ppAddress)->AddRef(); LOG((TL_TRACE, "get_Address - enter. address[%p]", (*ppAddress) )); return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // get_Address // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddressDevSpecificEvent::get_Call( ITCallInfo ** ppCall ) { LOG((TL_TRACE, "get_Call - enter")); // // good out pointer? // if (TAPIIsBadWritePtr(ppCall, sizeof(ITCallInfo*) ) ) { LOG((TL_ERROR, "get_Call - bad pointer at [%p]", ppCall)); return E_POINTER; } // // return addreff'd call // HRESULT hr = S_OK; if ( NULL != m_pCall ) { // // this event is call specific // *ppCall = m_pCall; (*ppCall)->AddRef(); } else { // // this event was not call specific // LOG((TL_WARN, "get_Call - no call")); hr = TAPI_E_CALLUNAVAIL; } LOG(( TL_TRACE, "get_Call - enter. call [%p]. hr = %lx", (*ppCall), hr )); return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // get_lParam1 // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddressDevSpecificEvent::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 CAddressDevSpecificEvent::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 CAddressDevSpecificEvent::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; } /////////////////////////////////////////////////////////////////////////////// //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Initialize // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CForwardInfo::Initialize() { HRESULT hr = S_OK; ZeroMemory( m_ForwardStructs, sizeof( MYFORWARDSTRUCT ) * NUMFORWARDTYPES ); m_lNumRings = 0; return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // GetForwardOffset // // maps a forward type to an offset for the array // in the // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ DWORD GetForwardOffset( DWORD dwForwardType ) { switch (dwForwardType) { case LINEFORWARDMODE_UNCOND: return 0; case LINEFORWARDMODE_UNCONDINTERNAL: return 1; case LINEFORWARDMODE_UNCONDEXTERNAL: return 2; case LINEFORWARDMODE_UNCONDSPECIFIC: return 3; case LINEFORWARDMODE_BUSY: return 4; case LINEFORWARDMODE_BUSYINTERNAL: return 5; case LINEFORWARDMODE_BUSYEXTERNAL: return 6; case LINEFORWARDMODE_BUSYSPECIFIC: return 7; case LINEFORWARDMODE_NOANSW: return 8; case LINEFORWARDMODE_NOANSWINTERNAL: return 9; case LINEFORWARDMODE_NOANSWEXTERNAL: return 10; case LINEFORWARDMODE_NOANSWSPECIFIC: return 11; case LINEFORWARDMODE_BUSYNA: return 12; case LINEFORWARDMODE_BUSYNAINTERNAL: return 13; case LINEFORWARDMODE_BUSYNAEXTERNAL: return 14; case LINEFORWARDMODE_BUSYNASPECIFIC: return 15; case LINEFORWARDMODE_UNKNOWN: return 16; case LINEFORWARDMODE_UNAVAIL: return 17; default: return 0; } return 0; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // put_NumRingsNoAnswer // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CForwardInfo::put_NumRingsNoAnswer( long lNumRings ) { HRESULT hr = S_OK; Lock(); m_lNumRings = lNumRings; Unlock(); return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // get_NumRingsNoAnswer // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CForwardInfo::get_NumRingsNoAnswer( long * plNumRings ) { if (TAPIIsBadWritePtr(plNumRings , sizeof(long) ) ) { LOG((TL_ERROR, "get_NumRingsNoAnswer - bad pointer")); return E_POINTER; } Lock(); *plNumRings = m_lNumRings; Unlock(); return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // SetForwardType // // save the forward type. overwrite and free is there is already // a matching type // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CForwardInfo::SetForwardType( long ForwardType, BSTR pDestAddress, BSTR pCallerAddress ) { HRESULT hr; LOG((TL_TRACE, "SetForwardType - enter")); hr = SetForwardType2( ForwardType, pDestAddress, 0, pCallerAddress, 0 ); LOG((TL_TRACE, "SetForwardType - exit - %lx", hr)); return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // SetForwardType2 // // save the forward type. overwrite and free is there is already // a matching type // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CForwardInfo::SetForwardType2( long ForwardType, BSTR pDestAddress, long DestAddressType, BSTR pCallerAddress, long CallerAddressType ) { HRESULT hr = S_OK; DWORD dwCount; LOG((TL_TRACE, "SetForwardType2 - enter")); // // check forwardtype // if ( !IsOnlyOneBitSetInDWORD( ForwardType ) ) { LOG((TL_ERROR, "ForwardType has more than one bit set")); return E_INVALIDARG; } // // check destaddress // if ( pDestAddress == NULL ) { LOG((TL_ERROR, "Forward destaddress cannot be NULL")); return E_INVALIDARG; } if ( IsBadStringPtrW( pDestAddress, -1 ) ) { LOG((TL_ERROR, "Forward destaddress invalid")); return E_POINTER; } // // check calleraddress // if ( FORWARDMODENEEDSCALLER( ForwardType ) ) { if ( NULL == pCallerAddress ) { LOG((TL_ERROR, "Forward type needs calleraddress")); return E_INVALIDARG; } if ( IsBadStringPtrW( pCallerAddress, -1 ) ) { LOG((TL_ERROR, "Forward calleraddress invalid")); return E_POINTER; } } Lock(); // // find correct structure in array // MYFORWARDSTRUCT * pStruct = NULL; pStruct = &(m_ForwardStructs[GetForwardOffset(ForwardType)]); // // free alloced stuff // if ( NULL != pStruct->bstrDestination ) { SysFreeString( pStruct->bstrDestination ); pStruct->bstrDestination = NULL; } if ( NULL != pStruct->bstrCaller ) { SysFreeString( pStruct->bstrCaller ); pStruct->bstrCaller = NULL; } // // save stuff // pStruct->bstrDestination = SysAllocString( pDestAddress ); if ( NULL == pStruct->bstrDestination ) { Unlock(); LOG((TL_ERROR, "Could not alloc dest in put_Forward")); return E_OUTOFMEMORY; } if ( NULL != pCallerAddress ) { pStruct->bstrCaller = SysAllocString( pCallerAddress ); if ( NULL == pStruct->bstrCaller ) { LOG((TL_ERROR, "Could not calloc caller in put_Forward")); SysFreeString( pStruct->bstrDestination ); Unlock(); return E_OUTOFMEMORY; } } pStruct->dwDestAddressType = DestAddressType; pStruct->dwCallerAddressType = CallerAddressType; pStruct->dwForwardType = ForwardType; Unlock(); LOG((TL_TRACE, "SetForwardType2 - exit - success")); return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // get_ForwardTypeDestination // // will return null if nothing saved // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CForwardInfo::get_ForwardTypeDestination( long ForwardType, BSTR * ppDestAddress ) { HRESULT hr = S_OK; DWORD dwCount; LOG((TL_TRACE, "get_ForwardTypeDest - enter")); // // check forwardtype // if ( !IsOnlyOneBitSetInDWORD( ForwardType ) ) { LOG((TL_ERROR, "ForwardType has more than one bit set")); return E_INVALIDARG; } if ( TAPIIsBadWritePtr( ppDestAddress, sizeof( BSTR ) ) ) { LOG((TL_ERROR, "Bad pointer in get_ForwardTypeDest")); return E_POINTER; } *ppDestAddress = NULL; Lock(); dwCount = GetForwardOffset( ForwardType ); if ( NULL != m_ForwardStructs[dwCount].bstrDestination ) { *ppDestAddress = SysAllocString( m_ForwardStructs[dwCount].bstrDestination ); if ( NULL == *ppDestAddress ) { LOG((TL_ERROR, "OutOfMemory in get_ForwardTypeDest")); Unlock(); return E_POINTER; } } Unlock(); LOG((TL_TRACE, "get_ForwardTypeDest - exit")); return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // get_ForwardTypeDestinationAddressType // // will return null if nothing saved // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CForwardInfo::get_ForwardTypeDestinationAddressType( long ForwardType, long * pDestAddressType ) { HRESULT hr = S_OK; DWORD dwCount; LOG((TL_TRACE, "get_ForwardTypeDestinationAddressType - enter")); // // check forwardtype // if ( !IsOnlyOneBitSetInDWORD( ForwardType ) ) { LOG((TL_ERROR, "ForwardType has more than one bit set")); return E_INVALIDARG; } if ( TAPIIsBadWritePtr( pDestAddressType, sizeof( long ) ) ) { LOG((TL_ERROR, "Bad pointer in get_ForwardTypeDestinationAddressType")); return E_POINTER; } Lock(); dwCount = GetForwardOffset( ForwardType ); *pDestAddressType = m_ForwardStructs[dwCount].dwDestAddressType; Unlock(); LOG((TL_TRACE, "get_ForwardTypeDestinationAddressType - exit")); return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // get_ForwardTypeCaller // // gets the caller save for the specifies forward type // // will return NULL in ppCallerAddress if nothing saved // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CForwardInfo::get_ForwardTypeCaller( long ForwardType, BSTR * ppCallerAddress ) { HRESULT hr = S_OK; DWORD dwCount; LOG((TL_TRACE, "get_ForwardTypeCaller - enter")); // // check forwardtype // if ( !IsOnlyOneBitSetInDWORD( ForwardType ) ) { LOG((TL_ERROR, "ForwardType has more than one bit set")); return E_INVALIDARG; } if ( TAPIIsBadWritePtr( ppCallerAddress, sizeof( BSTR ) ) ) { LOG((TL_ERROR, "Bad pointer in get_ForwardTypeCaller")); return E_POINTER; } *ppCallerAddress = NULL; Lock(); dwCount = GetForwardOffset( ForwardType ); if ( NULL != m_ForwardStructs[dwCount].bstrCaller ) { *ppCallerAddress = SysAllocString( m_ForwardStructs[dwCount].bstrCaller ); if ( NULL == *ppCallerAddress ) { LOG((TL_ERROR, "OutOfMemory in get_ForwardTypeCaller")); Unlock(); return E_POINTER; } } Unlock(); LOG((TL_TRACE, "get_ForwardTypeDest - exit")); return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // get_ForwardTypeCallerAddressType // // will return null if nothing saved // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CForwardInfo::get_ForwardTypeCallerAddressType( long ForwardType, long * pCallerAddressType ) { HRESULT hr = S_OK; DWORD dwCount; LOG((TL_TRACE, "get_ForwardTypeCallerAddressType - enter")); // // check forwardtype // if ( !IsOnlyOneBitSetInDWORD( ForwardType ) ) { LOG((TL_ERROR, "ForwardType has more than one bit set")); return E_INVALIDARG; } if ( TAPIIsBadWritePtr( pCallerAddressType, sizeof( long ) ) ) { LOG((TL_ERROR, "Bad pointer in get_ForwardTypeCallerAddressType")); return E_POINTER; } Lock(); dwCount = GetForwardOffset( ForwardType ); *pCallerAddressType = m_ForwardStructs[dwCount].dwCallerAddressType; Unlock(); LOG((TL_TRACE, "get_ForwardTypeCallerAddressType - exit")); return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // GetForwardType // // get the destination and caller based on the type // // simply use the vb functions to do this. // // will return success even if no info - both addresses will // be NULL in that case // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CForwardInfo::GetForwardType( long ForwardType, BSTR * ppDestinationAddress, BSTR * ppCallerAddress ) { HRESULT hr = S_OK; LOG((TL_TRACE, "GetForwardType - enter")); hr = get_ForwardTypeDestination( ForwardType, ppDestinationAddress ); if ( !SUCCEEDED(hr) ) { return hr; } hr = get_ForwardTypeCaller( ForwardType, ppCallerAddress ); if ( !SUCCEEDED(hr) ) { SysFreeString( *ppDestinationAddress ); return hr; } LOG((TL_TRACE, "GetForwardType - exit")); return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // GetForwardType2 // // get the destination and caller based on the type // // simply use the vb functions to do this. // // will return success even if no info - both addresses will // be NULL in that case // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CForwardInfo::GetForwardType2( long ForwardType, BSTR * ppDestinationAddress, long * pDestAddressType, BSTR * ppCallerAddress, long * pCallerAddressType ) { HRESULT hr = S_OK; LOG((TL_TRACE, "GetForwardType2 - enter")); hr = get_ForwardTypeDestination( ForwardType, ppDestinationAddress ); if ( !SUCCEEDED(hr) ) { return hr; } hr = get_ForwardTypeDestinationAddressType( ForwardType, pDestAddressType ); if ( !SUCCEEDED(hr) ) { SysFreeString( *ppDestinationAddress ); return hr; } hr = get_ForwardTypeCaller( ForwardType, ppCallerAddress ); if ( !SUCCEEDED(hr) ) { SysFreeString( *ppDestinationAddress ); return hr; } hr = get_ForwardTypeCallerAddressType( ForwardType, pCallerAddressType ); if ( !SUCCEEDED(hr) ) { SysFreeString( *ppDestinationAddress ); SysFreeString( *ppCallerAddress ); return hr; } LOG((TL_TRACE, "GetForwardType2 - exit")); return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Clear // // clears & frees all info in the forward object // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CForwardInfo::Clear() { HRESULT hr = S_OK; DWORD dwCount; LOG((TL_TRACE, "Clear - enter")); Lock(); // // go through all the structs and free // related memory // for (dwCount = 0; dwCount < NUMFORWARDTYPES; dwCount++) { if ( NULL != m_ForwardStructs[dwCount].bstrDestination ) { SysFreeString( m_ForwardStructs[dwCount].bstrDestination ); } if ( NULL != m_ForwardStructs[dwCount].bstrCaller ) { SysFreeString( m_ForwardStructs[dwCount].bstrCaller ); } } // // zero out stuff // ZeroMemory( m_ForwardStructs, sizeof( MYFORWARDSTRUCT ) * NUMFORWARDTYPES ); Unlock(); LOG((TL_TRACE, "Clear - exit")); return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // CreateForwardList // // Creates a LINEFORWARDLIST structure based on the info // in the object // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CForwardInfo::CreateForwardList( LINEFORWARDLIST ** ppList ) { LINEFORWARDLIST * pList; DWORD dwCount; DWORD dwSize = 0; DWORD dwOffset; DWORD dwNumEntries = 0; Lock(); // // count the number of entries that are filled // for (dwCount = 0; dwCount < NUMFORWARDTYPES; dwCount++) { if ( 0 != m_ForwardStructs[dwCount].dwForwardType ) { dwSize += ( (lstrlenW( m_ForwardStructs[dwCount].bstrDestination ) + 1) * sizeof(WCHAR*)); dwSize += ( (lstrlenW( m_ForwardStructs[dwCount].bstrCaller ) + 1) * sizeof(WCHAR*)); dwNumEntries++; } } if ( 0 == dwNumEntries ) { Unlock(); *ppList = NULL; return S_OK; } dwSize += sizeof (LINEFORWARDLIST) + sizeof (LINEFORWARD) * dwNumEntries + dwSize; // // alloc structure // pList = (LINEFORWARDLIST *)ClientAlloc( dwSize ); if ( NULL == pList ) { LOG((TL_ERROR, "CreateForwardList - OutOfMemory")); Unlock(); return E_OUTOFMEMORY; } // // init // pList->dwTotalSize = dwSize; pList->dwNumEntries = dwNumEntries; // // offset should be past the fixed part of the structure // dwOffset = sizeof( LINEFORWARDLIST ) + sizeof( LINEFORWARD ) * dwNumEntries; dwNumEntries = 0; // // go through entries again // for (dwCount = 0; dwCount < NUMFORWARDTYPES; dwCount++) { if ( 0 != m_ForwardStructs[dwCount].dwForwardType ) { DWORD dwSize; LINEFORWARD * pEntry = &(pList->ForwardList[dwNumEntries]); // // save the type // pEntry->dwForwardMode = m_ForwardStructs[dwCount].dwForwardType; // // save destination - should always be a destination if // there is a type // pEntry->dwDestAddressType = m_ForwardStructs[dwCount].dwDestAddressType; pEntry->dwDestAddressSize = (lstrlenW(m_ForwardStructs[dwCount].bstrDestination) + 1) * sizeof( WCHAR ); pEntry->dwDestAddressOffset = dwOffset; lstrcpyW( (PWSTR)(((PBYTE)pList)+dwOffset), m_ForwardStructs[dwCount].bstrDestination ); // // fixup offset // dwOffset += pEntry->dwDestAddressSize; // // if there is a caller, do the same // if ( NULL != m_ForwardStructs[dwCount].bstrCaller ) { pEntry->dwCallerAddressType = m_ForwardStructs[dwCount].dwCallerAddressType; pEntry->dwCallerAddressSize = (lstrlenW(m_ForwardStructs[dwCount].bstrCaller) + 1) * sizeof( WCHAR ); pEntry->dwCallerAddressOffset = dwOffset; lstrcpyW( (PWSTR)(((PBYTE)pList)+dwOffset), m_ForwardStructs[dwCount].bstrCaller ); dwOffset += pEntry->dwCallerAddressSize; } dwNumEntries++; } } // // return it // *ppList = pList; Unlock(); return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // FinalRelease() // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void CForwardInfo::FinalRelease() { // // simply clear it // Clear(); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CAddress // Interface : ITAddressTranslation // Method : TranslateAddress // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddress::TranslateAddress( BSTR pAddressToTranslate, long ulCard, long ulTranslateOptions, ITAddressTranslationInfo ** ppTranslated ) { HRESULT hr = S_OK; LPLINETRANSLATEOUTPUT pTranslateOutput = NULL; PWSTR pszDialableString = NULL; PWSTR pszDisplayableString = NULL; CComObject< CAddressTranslationInfo > * pTranslationInfo = NULL; long lCap = 0; BOOL bUsePSTNAddressTranslation = TRUE; HLINEAPP hLineApp; DWORD dwDeviceID; LOG((TL_TRACE, "TranslateAddress - enter" )); if ( !TAPIIsBadWritePtr( ppTranslated, sizeof(ITAddressTranslationInfo *) ) ) { // ppTranslated OK if ( !IsBadStringPtrW( pAddressToTranslate, -1 ) ) { // pAddressToTranslate OK // Check Addresscap bit hr = get_AddressCapability( AC_ADDRESSCAPFLAGS, &lCap ); if ( SUCCEEDED(hr) ) { if ( lCap & LINEADDRCAPFLAGS_NOPSTNADDRESSTRANSLATION ) { bUsePSTNAddressTranslation = FALSE; } } // create Translate Info object hr = CComObject< CAddressTranslationInfo >::CreateInstance( &pTranslationInfo ); if ( SUCCEEDED(hr) ) { // Translate or copy ? if (bUsePSTNAddressTranslation) { LOG((TL_INFO, "TranslateAddress - Do address translation" )); Lock(); hLineApp = m_hLineApp; dwDeviceID = m_dwDeviceID; Unlock(); hr= LineTranslateAddress( hLineApp, dwDeviceID, TAPI_CURRENT_VERSION, (LPCWSTR)pAddressToTranslate, ulCard, ulTranslateOptions, &pTranslateOutput); if(SUCCEEDED(hr) ) { // Pull String info out of LPLINETRANSLATEOUTPUT structure pszDialableString = (PWSTR) ((BYTE*)(pTranslateOutput) + pTranslateOutput->dwDialableStringOffset); pszDisplayableString = (PWSTR) ((BYTE*)(pTranslateOutput) + pTranslateOutput->dwDisplayableStringOffset); hr = pTranslationInfo->Initialize(pszDialableString, pszDisplayableString, pTranslateOutput->dwCurrentCountry, pTranslateOutput->dwDestCountry, pTranslateOutput->dwTranslateResults ); } else // LinetranslateAddress failed { LOG((TL_ERROR, "TranslateAddress - LineTranslateAddress failed" )); } } else // copy input string unmodified { LOG((TL_INFO, "TranslateAddress - No address translation" )); hr = pTranslationInfo->Initialize(pAddressToTranslate, pAddressToTranslate, 0, 0, LINETRANSLATERESULT_NOTRANSLATION ); } // end if (bUsePSTNAddressTranslation) // // Did we translate & initialize output object ? if ( SUCCEEDED(hr) ) { hr = pTranslationInfo->QueryInterface(IID_ITAddressTranslationInfo,(void**)ppTranslated); if ( SUCCEEDED(hr) ) { LOG((TL_TRACE, "TranslateAddress - success")); hr = S_OK; } else { LOG((TL_ERROR, "TranslateAddress - Bad pointer" )); delete pTranslationInfo; } } else // object failed to initialize { LOG((TL_ERROR, "TranslateAddress - Initialize TranslateInfo object failed" )); delete pTranslationInfo; } } else // Create instance failed { LOG((TL_ERROR, "TranslateAddress - Create TranslateInfo object failed" )); } } else // pAddressToTranslate bad { LOG((TL_ERROR, "TranslateAddress -pAddressToTranslate invalid")); hr = E_POINTER; } } else // ppTranslated bad { LOG((TL_ERROR, "TranslateAddress - Bad ppTranslated Pointer" )); hr = E_POINTER; } if(pTranslateOutput != NULL) { ClientFree(pTranslateOutput); } LOG((TL_TRACE, hr, "TranslateAddress - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // TranslateDialog // // simply call LineTranslateDialog // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddress::TranslateDialog( TAPIHWND hwndOwner, BSTR pAddressIn ) { HRESULT hr = E_NOTIMPL; HLINEAPP hLineApp; DWORD dwDeviceID; DWORD dwAPIVersion; LOG((TL_TRACE, "TranslateDialog - enter:%p", hwndOwner )); Lock(); hLineApp = m_hLineApp; dwDeviceID = m_dwDeviceID; dwAPIVersion = m_dwAPIVersion; Unlock(); hr = LineTranslateDialog( dwDeviceID, dwAPIVersion, (HWND)hwndOwner, pAddressIn ); LOG((TL_TRACE, "TranslateDialog - exit - return %lx", hr)); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CAddress // Interface : ITAddressTranslation // Method : EnumerateLocations // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddress::EnumerateLocations (IEnumLocation ** ppEnumLocation ) { HRESULT hr = S_OK; LPLINETRANSLATECAPS pTranslateCaps = NULL; DWORD dwNumLocations; DWORD dwCount; LPLINELOCATIONENTRY pEntry = NULL; PWSTR pszLocationName; PWSTR pszCityCode; PWSTR pszLocalAccessCode; PWSTR pszLongDistanceAccessCode; PWSTR pszTollPrefixList; PWSTR pszCancelCallWaitingCode; DWORD dwPermanentLocationID; DWORD dwCountryCode; DWORD dwPreferredCardID; DWORD dwCountryID; DWORD dwOptions; LOG((TL_TRACE, "EnumerateLocations - enter" )); if ( TAPIIsBadWritePtr( ppEnumLocation, sizeof(IEnumLocation *) ) ) { LOG((TL_ERROR, "EnumerateLocations - Bad Pointer" )); hr = E_POINTER; } else // Ok Pointer { // // create the enumerator // CComObject< CTapiEnum > * pEnum; hr = CComObject< CTapiEnum > ::CreateInstance( &pEnum ); if (SUCCEEDED(hr) ) { // // initialize it with our Locations list // pEnum->Initialize(); hr = LineGetTranslateCaps(m_hLineApp, TAPI_CURRENT_VERSION, &pTranslateCaps); if(SUCCEEDED(hr) ) { dwNumLocations = pTranslateCaps->dwNumLocations ; // Find positionn of 1st LINELOCATIONENTRY structure in the LINETRANSLATECAPS structure pEntry = (LPLINELOCATIONENTRY) ((BYTE*)(pTranslateCaps) + pTranslateCaps->dwLocationListOffset ); for (dwCount = 0; dwCount < dwNumLocations; dwCount++) { // Pull Location Info out of LINELOCATIONENTRY structure pszLocationName = (PWSTR) ((BYTE*)(pTranslateCaps) + pEntry->dwLocationNameOffset); pszCityCode = (PWSTR) ((BYTE*)(pTranslateCaps) + pEntry->dwCityCodeOffset); pszLocalAccessCode = (PWSTR) ((BYTE*)(pTranslateCaps) + pEntry->dwLocalAccessCodeOffset); pszLongDistanceAccessCode = (PWSTR) ((BYTE*)(pTranslateCaps) + pEntry->dwLongDistanceAccessCodeOffset); pszTollPrefixList = (PWSTR) ((BYTE*)(pTranslateCaps) + pEntry->dwTollPrefixListOffset); pszCancelCallWaitingCode = (PWSTR) ((BYTE*)(pTranslateCaps) + pEntry->dwCancelCallWaitingOffset); dwPermanentLocationID = pEntry->dwPermanentLocationID; dwCountryCode = pEntry->dwCountryCode; dwPreferredCardID = pEntry->dwPreferredCardID; dwCountryID = pEntry->dwCountryID; dwOptions = pEntry->dwOptions; // create our new LocationInfo Object CComObject * pLocationInfo; CComObject::CreateInstance( &pLocationInfo ); if (SUCCEEDED(hr) ) { // initialize the new LocationInfo Object hr = pLocationInfo->Initialize( pszLocationName, pszCityCode, pszLocalAccessCode, pszLongDistanceAccessCode, pszTollPrefixList, pszCancelCallWaitingCode , dwPermanentLocationID, dwCountryCode, dwPreferredCardID, dwCountryID, dwOptions ); if (SUCCEEDED(hr) ) { // Add it to the enumerator hr = pEnum->Add(pLocationInfo); if (SUCCEEDED(hr)) { LOG((TL_INFO, "EnumerateLocations - Added LocationInfo object to enum")); } else { LOG((TL_INFO, "EnumerateLocations - Add LocationInfo object failed")); delete pLocationInfo; } } else { LOG((TL_ERROR, "EnumerateLocations - Init LocationInfo object failed")); delete pLocationInfo; } } else // CComObject::CreateInstance failed { LOG((TL_ERROR, "EnumerateLocations - Create LocationInfo object failed")); } // Try next location in list pEntry++; } //for(dwCount.....) // // return the Enumerator // *ppEnumLocation = pEnum; } else // LineGetTranslateCaps failed { LOG((TL_ERROR, "EnumerateLocations - LineGetTranslateCaps failed" )); pEnum->Release(); } } else // CComObject::CreateInstance failed { LOG((TL_ERROR, "EnumerateLocations - could not create enum" )); } // finished with TAPI memory block so release if ( pTranslateCaps != NULL ) ClientFree( pTranslateCaps ); } LOG((TL_TRACE, hr, "EnumerateLocations - exit" )); return hr; } STDMETHODIMP CAddress::get_Locations( VARIANT * pVariant ) { IEnumLocation * pEnumLocation; HRESULT hr; CComObject< CTapiCollection< ITLocationInfo > > * p; LocationArray TempLocationArray; ITLocationInfo * pLocation; if ( TAPIIsBadWritePtr( pVariant, sizeof( VARIANT ) ) ) { LOG((TL_ERROR, "get_locations - bad pointer")); return E_POINTER; } // // create collection object // CComObject< CTapiCollection< ITLocationInfo > >::CreateInstance( &p ); if (NULL == p) { LOG((TL_ERROR, "get_Locations - could not create collection" )); return E_OUTOFMEMORY; } hr = EnumerateLocations ( &pEnumLocation ); if ( !SUCCEEDED(hr) ) { delete p; LOG((TL_ERROR, "get_locations - enumerate locations failed")); return hr; } while (TRUE) { hr = pEnumLocation->Next(1, &pLocation, NULL); if ( S_OK != hr ) { break; } TempLocationArray.Add( pLocation ); pLocation->Release(); } pEnumLocation->Release(); p->Initialize( TempLocationArray ); TempLocationArray.Shutdown(); IDispatch * pDisp; // // get the IDispatch interface // hr = p->_InternalQueryInterface( IID_IDispatch, (void **) &pDisp ); if (S_OK != hr) { LOG((TL_ERROR, "get_Locations - could not get IDispatch interface" )); delete p; return hr; } // // put it in the variant // VariantInit(pVariant); pVariant->vt = VT_DISPATCH; pVariant->pdispVal = pDisp; LOG((TL_TRACE, "get_Locations exit - return success")); return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CAddress // Interface : ITAddressTranslation // Method : EnumerateCallingCards // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddress::EnumerateCallingCards (IEnumCallingCard ** ppCallingCards ) { HRESULT hr = S_OK; LPLINETRANSLATECAPS pTranslateCaps = NULL; DWORD dwNumCards; DWORD dwCount; LPLINECARDENTRY pEntry = NULL; PWSTR pszCardName; PWSTR pszSameAreaDialingRule; PWSTR pszLongDistanceDialingRule; PWSTR pszInternationalDialingRule; DWORD dwPermanentCardID; DWORD dwNumberOfDigits; DWORD dwOptions; LOG((TL_TRACE, "EnumerateCallingCards - enter" )); if ( TAPIIsBadWritePtr( ppCallingCards, sizeof(IEnumCallingCard *) ) ) { LOG((TL_ERROR, "EnumerateCallingCards - Bad Pointer" )); hr = E_POINTER; } else // Ok Pointer { // // create the enumerator // CComObject< CTapiEnum > * pEnum; hr = CComObject< CTapiEnum > ::CreateInstance( &pEnum ); if ( SUCCEEDED(hr) ) { // // initialize it with our Locations list // pEnum->Initialize(); hr = LineGetTranslateCaps(m_hLineApp, TAPI_CURRENT_VERSION, &pTranslateCaps); if( SUCCEEDED(hr) ) { dwNumCards = pTranslateCaps->dwNumCards ; // Find positionn of 1st LINECARDENTRY structure in the LINETRANSLATECAPS structure pEntry = (LPLINECARDENTRY) ((BYTE*)(pTranslateCaps) + pTranslateCaps->dwCardListOffset ); for (dwCount = 0; dwCount < dwNumCards; dwCount++) { // Pull Location Info out of LINECARDENTRY structure pszCardName = (PWSTR) ((BYTE*)(pTranslateCaps) + pEntry->dwCardNameOffset); pszSameAreaDialingRule = (PWSTR) ((BYTE*)(pTranslateCaps) + pEntry->dwSameAreaRuleOffset); pszLongDistanceDialingRule = (PWSTR) ((BYTE*)(pTranslateCaps) + pEntry->dwLongDistanceRuleOffset); pszInternationalDialingRule = (PWSTR) ((BYTE*)(pTranslateCaps) + pEntry->dwInternationalRuleOffset); dwPermanentCardID = pEntry->dwPermanentCardID; dwNumberOfDigits = pEntry->dwCardNumberDigits; dwOptions = pEntry->dwOptions; // create our new CallingCard Object CComObject * pCallingCard; CComObject::CreateInstance( &pCallingCard ); if (SUCCEEDED(hr) ) { // initialize the new CallingCard Object hr = pCallingCard->Initialize( pszCardName, pszSameAreaDialingRule, pszLongDistanceDialingRule, pszInternationalDialingRule, dwPermanentCardID, dwNumberOfDigits, dwOptions ); if (SUCCEEDED(hr) ) { // Add it to the enumerator hr = pEnum->Add(pCallingCard); if (SUCCEEDED(hr)) { LOG((TL_INFO, "EnumerateCallingCards - Added CallingCard object to enum")); } else { LOG((TL_INFO, "EnumertateCallingCards - Add CallingCard object failed")); delete pCallingCard; } } else { LOG((TL_ERROR, "EnumerateCallingCards - Init CallingCard object failed")); delete pCallingCard; } } else // CComObject::CreateInstance failed { LOG((TL_ERROR, "EnumerateCallingCards - Create CallingCard object failed")); } // Try next card in list pEntry++; } //for(dwCount.....) // // return the Enumerator // *ppCallingCards = pEnum; } else // LineGetTranslateCaps failed { LOG((TL_ERROR, "EnumerateCallingCards - LineGetTranslateCaps failed" )); pEnum->Release(); } } else // CComObject::CreateInstance failed { LOG((TL_ERROR, "EnumerateCallingCards - could not create enum" )); } // finished with TAPI memory block so release if ( pTranslateCaps != NULL ) ClientFree( pTranslateCaps ); } LOG((TL_TRACE, hr, "EnumerateCallingCards - exit" )); return hr; } STDMETHODIMP CAddress::get_CallingCards( VARIANT * pVariant ) { IEnumCallingCard * pEnumCallingCards; HRESULT hr; CComObject< CTapiCollection< ITCallingCard > > * p; CallingCardArray TempCallingCardArray; ITCallingCard * pCallingCard; if ( TAPIIsBadWritePtr( pVariant, sizeof( VARIANT ) ) ) { LOG((TL_ERROR, "get_CallingCard - bad pointer")); return E_POINTER; } // // create collection object // CComObject< CTapiCollection< ITCallingCard > >::CreateInstance( &p ); if (NULL == p) { LOG((TL_ERROR, "get_CallingCards - could not create collection" )); return E_OUTOFMEMORY; } hr = EnumerateCallingCards ( &pEnumCallingCards ); if ( !SUCCEEDED(hr) ) { delete p; LOG((TL_ERROR, "get_CallingCards - enumerate callingcards failed")); return hr; } while (TRUE) { hr = pEnumCallingCards->Next(1, &pCallingCard, NULL); if ( S_OK != hr ) { break; } TempCallingCardArray.Add( pCallingCard ); pCallingCard->Release(); } pEnumCallingCards->Release(); p->Initialize( TempCallingCardArray ); TempCallingCardArray.Shutdown(); IDispatch * pDisp; // // get the IDispatch interface // hr = p->_InternalQueryInterface( IID_IDispatch, (void **) &pDisp ); if (S_OK != hr) { LOG((TL_ERROR, "get_CallingCards - could not get IDispatch interface" )); delete p; return hr; } // // put it in the variant // VariantInit(pVariant); pVariant->vt = VT_DISPATCH; pVariant->pdispVal = pDisp; LOG((TL_TRACE, "get_CallingCards exit - return success")); return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CAddress // Method : GetPhoneArrayFromTapiAndPrune // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddress::GetPhoneArrayFromTapiAndPrune( PhoneArray *pPhoneArray, BOOL bPreferredOnly ) { HRESULT hr; CTAPI * pCTapi; ITPhone * pPhone; CPhone * pCPhone; LOG((TL_TRACE, "GetPhoneArrayFromTapiAndPrune enter")); if ( IsBadReadPtr( pPhoneArray, sizeof( PhoneArray ) ) ) { LOG((TL_ERROR, "GetPhoneArrayFromTapiAndPrune - bad pointer")); return E_POINTER; } pCTapi = GetTapi(); if( NULL == pCTapi ) { LOG((TL_ERROR, "dynamic cast operation failed")); hr = E_POINTER; } else { hr = pCTapi->GetPhoneArray( pPhoneArray ); if ( SUCCEEDED(hr) ) { // // Go through the phones // for(int iCount = 0; iCount < pPhoneArray->GetSize(); iCount++) { pPhone = (*pPhoneArray)[iCount]; pCPhone = dynamic_cast(pPhone); if ( NULL == pCPhone ) { // // We have a bad pointer in our phone array. // Lets skip it and move on. // _ASSERTE(FALSE); continue; } // // Is the phone on this address? // if ( bPreferredOnly ? pCPhone->IsPhoneOnPreferredAddress(this) : pCPhone->IsPhoneOnAddress(this) ) { LOG((TL_INFO, "GetPhoneArrayFromTapiAndPrune - found matching phone - %p", pPhone)); } else { // No, remove it from the array pPhoneArray->RemoveAt(iCount); iCount--; } } } } LOG((TL_TRACE, "GetPhoneArrayFromTapiAndPrune - exit - return %lx", hr )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CAddress // Interface : ITAddress2 // Method : get_Phones // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddress::get_Phones( VARIANT * pPhones ) { HRESULT hr; IDispatch * pDisp; PhoneArray PhoneArray; LOG((TL_TRACE, "get_Phones enter")); if ( TAPIIsBadWritePtr( pPhones, sizeof( VARIANT ) ) ) { LOG((TL_ERROR, "get_Phones - bad pointer")); return E_POINTER; } hr = GetPhoneArrayFromTapiAndPrune( &PhoneArray, FALSE ); if ( SUCCEEDED(hr) ) { CComObject< CTapiCollection< ITPhone > > * p; CComObject< CTapiCollection< ITPhone > >::CreateInstance( &p ); if (NULL == p) { LOG((TL_ERROR, "get_Phones - could not create collection" )); PhoneArray.Shutdown(); return E_OUTOFMEMORY; } // get the IDispatch interface hr = p->_InternalQueryInterface( IID_IDispatch, (void **) &pDisp ); if (S_OK != hr) { LOG((TL_ERROR, "get_Phones - could not get IDispatch interface" )); delete p; return hr; } Lock(); // initialize hr = p->Initialize( PhoneArray ); Unlock(); PhoneArray.Shutdown(); if (S_OK != hr) { LOG((TL_ERROR, "get_Phones - could not initialize collection" )); pDisp->Release(); return hr; } // put it in the variant VariantInit(pPhones); pPhones->vt = VT_DISPATCH; pPhones->pdispVal = pDisp; } LOG((TL_TRACE, "get_Phones - exit - return %lx", hr )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CAddress // Interface : ITAddress2 // Method : EnumeratePhones // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddress::EnumeratePhones( IEnumPhone ** ppEnumPhone ) { HRESULT hr; PhoneArray PhoneArray; LOG((TL_TRACE, "EnumeratePhones - enter")); LOG((TL_TRACE, " ppEnumPhone----->%p", ppEnumPhone )); if ( TAPIIsBadWritePtr( ppEnumPhone, sizeof( IEnumPhone * ) ) ) { LOG((TL_ERROR, "EnumeratePhones - bad pointer")); return E_POINTER; } hr = GetPhoneArrayFromTapiAndPrune( &PhoneArray, FALSE ); if ( SUCCEEDED(hr) ) { // // create the enumerator // CComObject< CTapiEnum< IEnumPhone, ITPhone, &IID_IEnumPhone > > * p; try { hr = CComObject< CTapiEnum< IEnumPhone, ITPhone, &IID_IEnumPhone > > ::CreateInstance( &p ); } catch(...) { LOG((TL_ERROR, "EnumeratePhones - failed to create phone enumeration. exception thrown." )); hr = E_OUTOFMEMORY; } if (S_OK != hr) { LOG((TL_ERROR, "EnumeratePhones - could not create enum" )); PhoneArray.Shutdown(); return hr; } Lock(); // initialize it with our phone list p->Initialize( PhoneArray ); Unlock(); PhoneArray.Shutdown(); // // return it // *ppEnumPhone = p; } LOG((TL_TRACE, "EnumeratePhones - exit - return %lx", hr )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CAddress // Interface : ITAddress2 // Method : get_PreferredPhones // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddress::get_PreferredPhones( VARIANT * pPhones ) { HRESULT hr; IDispatch * pDisp; PhoneArray PhoneArray; LOG((TL_TRACE, "get_PreferredPhones enter")); if ( TAPIIsBadWritePtr( pPhones, sizeof( VARIANT ) ) ) { LOG((TL_ERROR, "get_PreferredPhones - bad pointer")); return E_POINTER; } hr = GetPhoneArrayFromTapiAndPrune( &PhoneArray, TRUE ); if ( SUCCEEDED(hr) ) { CComObject< CTapiCollection< ITPhone > > * p; CComObject< CTapiCollection< ITPhone > >::CreateInstance( &p ); if (NULL == p) { LOG((TL_ERROR, "get_PreferredPhones - could not create collection" )); PhoneArray.Shutdown(); return E_OUTOFMEMORY; } // get the IDispatch interface hr = p->_InternalQueryInterface( IID_IDispatch, (void **) &pDisp ); if (S_OK != hr) { LOG((TL_ERROR, "get_PreferredPhones - could not get IDispatch interface" )); delete p; return hr; } Lock(); // initialize hr = p->Initialize( PhoneArray ); Unlock(); PhoneArray.Shutdown(); if (S_OK != hr) { LOG((TL_ERROR, "get_PreferredPhones - could not initialize collection" )); pDisp->Release(); return hr; } // put it in the variant VariantInit(pPhones); pPhones->vt = VT_DISPATCH; pPhones->pdispVal = pDisp; } LOG((TL_TRACE, "get_PreferredPhones - exit - return %lx", hr )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CAddress // Interface : ITAddress2 // Method : EnumeratePreferredPhones // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddress::EnumeratePreferredPhones( IEnumPhone ** ppEnumPhone ) { HRESULT hr; PhoneArray PhoneArray; LOG((TL_TRACE, "EnumeratePreferredPhones - enter")); LOG((TL_TRACE, " ppEnumPhone----->%p", ppEnumPhone )); if ( TAPIIsBadWritePtr( ppEnumPhone, sizeof( IEnumPhone * ) ) ) { LOG((TL_ERROR, "EnumeratePreferredPhones - bad pointer")); return E_POINTER; } hr = GetPhoneArrayFromTapiAndPrune( &PhoneArray, TRUE ); if ( SUCCEEDED(hr) ) { // // create the enumerator // CComObject< CTapiEnum< IEnumPhone, ITPhone, &IID_IEnumPhone > > * p; hr = CComObject< CTapiEnum< IEnumPhone, ITPhone, &IID_IEnumPhone > > ::CreateInstance( &p ); if (S_OK != hr) { LOG((TL_ERROR, "EnumeratePreferredPhones - could not create enum" )); PhoneArray.Shutdown(); return hr; } Lock(); // initialize it with our phone list p->Initialize( PhoneArray ); Unlock(); PhoneArray.Shutdown(); // // return it // *ppEnumPhone = p; } LOG((TL_TRACE, "EnumeratePreferredPhones - exit - return %lx", hr )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CAddress // Interface : ITAddress2 // Method : GetPhoneFromTerminal // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddress::GetPhoneFromTerminal( ITTerminal * pTerminal, ITPhone ** ppPhone ) { HRESULT hr = E_FAIL; PhoneArray PhoneArray; ITStaticAudioTerminal * pStaticAudioTerminal; LONG lMediaType; TERMINAL_DIRECTION nDir; LOG((TL_TRACE, "GetPhoneFromTerminal - enter")); if ( TAPIIsBadWritePtr( ppPhone, sizeof( ITPhone * ) ) || IsBadReadPtr( pTerminal, sizeof( ITTerminal ) ) ) { LOG((TL_ERROR, "GetPhoneFromTerminal - bad pointer")); return E_POINTER; } *ppPhone = NULL; if ( SUCCEEDED(pTerminal->get_MediaType(&lMediaType)) && SUCCEEDED(pTerminal->get_Direction(&nDir)) && (lMediaType == TAPIMEDIATYPE_AUDIO) ) { hr = pTerminal->QueryInterface(IID_ITStaticAudioTerminal, (void **) &pStaticAudioTerminal); if ( SUCCEEDED(hr) ) { LONG lWaveId; hr = pStaticAudioTerminal->get_WaveId(&lWaveId); if ( SUCCEEDED(hr) ) { LOG((TL_INFO, "GetPhoneFromTerminal - got terminal wave id %d", lWaveId)); hr = GetPhoneArrayFromTapiAndPrune( &PhoneArray, FALSE ); if ( SUCCEEDED(hr) ) { ITPhone * pPhone; CPhone * pCPhone; int iPhoneCount; hr = TAPI_E_NODEVICE; for(iPhoneCount = 0; iPhoneCount < PhoneArray.GetSize(); iPhoneCount++) { pPhone = PhoneArray[iPhoneCount]; pCPhone = dynamic_cast(pPhone); if ( NULL == pCPhone ) { // // We have a bad pointer in our phone array. // Lets skip it and move on. // _ASSERTE(FALSE); continue; } if (pCPhone->IsPhoneUsingWaveID( lWaveId, nDir )) { *ppPhone = pPhone; pPhone->AddRef(); hr = S_OK; break; } } PhoneArray.Shutdown(); } } pStaticAudioTerminal->Release(); } } LOG((TL_TRACE, "GetPhoneFromTerminal - exit - return %lx", hr )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CAddress // Interface : ITAddress2 // Method : put_EventFilter // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddress::put_EventFilter( TAPI_EVENT TapiEvent, long lSubEvent, VARIANT_BOOL bEnable ) { LOG((TL_TRACE, "put_EventFilter - enter")); // // Validates the pair TapiEvent - lSubEvent // Accept also all subevents // if( !m_EventMasks.IsSubEventValid( TapiEvent, lSubEvent, TRUE, FALSE) ) { LOG((TL_ERROR, "put_EventFilter - " "This event can't be set: %x, return E_INVALIDARG", TapiEvent )); return E_INVALIDARG; } // Enter critical section Lock(); // Set the subevent flag HRESULT hr = E_FAIL; hr = SetSubEventFlag( TapiEvent, (DWORD)lSubEvent, (bEnable == VARIANT_TRUE) ); // Leave critical section Unlock(); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CAddress // Interface : ITAddress2 // Method : get_EventFilter // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddress::get_EventFilter( TAPI_EVENT TapiEvent, long lSubEvent, VARIANT_BOOL* pEnable ) { LOG((TL_TRACE, "get_EventFilter - enter")); // // Validates output argument // if( IsBadReadPtr(pEnable, sizeof(VARIANT_BOOL)) ) { LOG((TL_ERROR, "get_EventFilter - " "invalid VARIANT_BOOL pointer, return E_POINTER" )); return E_POINTER; } // // Validates the pair TapiEvent - lSubEvent // Don't accept all subevents // if( !m_EventMasks.IsSubEventValid( TapiEvent, lSubEvent, FALSE, FALSE) ) { LOG((TL_ERROR, "get_EventFilter - " "This event can't be set: %x, return E_INVALIDARG", TapiEvent )); return E_INVALIDARG; } // Enter critical section Lock(); // // Get the subevent mask for that (event, subevent) pair // BOOL bEnable = FALSE; HRESULT hr = GetSubEventFlag( TapiEvent, (DWORD)lSubEvent, &bEnable); if( FAILED(hr) ) { LOG((TL_ERROR, "get_EventFilter - " "GetSubEventFlag failed, return 0x%08x", hr )); // Leave critical section Unlock(); return hr; } // // Set the output argument // *pEnable = bEnable ? VARIANT_TRUE : VARIANT_FALSE; // Leave critical section Unlock(); LOG((TL_TRACE, "get_EventFilter - exit S_OK")); return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CAddress // Interface : ITAddress2 // Method : DeviceSpecific // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddress::DeviceSpecific( IN ITCallInfo *pCall, 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; } // // see if the call is obviously bad, and try to get call object pointer if // it is good // CCall *pCallObject = NULL; if ( (NULL != pCall) ) { // // does it point to readable memory at all? // if ( IsBadReadPtr(pCall, sizeof(ITCallInfo)) ) { LOG((TL_ERROR, "DeviceSpecific - unreadable call pointer [%p]", pCall)); return E_POINTER; } // // see if call is pointing to a real call object // try { pCallObject = dynamic_cast(pCall); } catch (...) { // // call pointer is really really bad // LOG((TL_ERROR, "DeviceSpecific - exception casting call pointer to a call object, bad call [%p]", pCall)); } // // if we could not get the call object pointer, this is not a good call // if (NULL == pCallObject) { LOG((TL_ERROR, "DeviceSpecific - could not get call object from call pointer -- bad call pointer argument [%p]", pCall)); return E_POINTER; } } // received call pointer that is NULL? // // by this point we know pCall is either NULL or we have a call pointer // that seems (but not guaranteed) to be good // // // prepare all the data for the call to lineDevSpecific // // // get hcall from the call // HCALL hCall = NULL; if (NULL != pCallObject) { hCall = pCallObject->GetHCall(); // // if we there is no call handle, return an error -- the app did not // called Connect on the call // if (NULL == hCall) { LOG((TL_ERROR, "DeviceSpecific - no call handle. hr = TAPI_E_INVALCALLSTATE", pCall)); return TAPI_E_INVALCALLSTATE; } } // // starting to access data members. lock. // Lock(); // // get a line to use to communicate devspecific information // AddressLineStruct *pAddressLine = NULL; HRESULT hr = FindOrOpenALine(m_dwMediaModesSupported, &pAddressLine); if (FAILED(hr)) { Unlock(); LOG((TL_TRACE, "DeviceSpecific - FindOrOpenALine failed. hr = %lx", hr)); return hr; } DWORD dwAddressID = m_dwAddressID; Unlock(); // // make the tapisrv call // hr = lineDevSpecific( pAddressLine->t3Line.hLine, dwAddressID, hCall, pbDataArray, dwSize ); // // no longer need the line. if registered for address notifications, the // line will remain opened. otherwise, if no one has the line open, it will // close -- we are not processing incoming events anyway. // MaybeCloseALine(&pAddressLine); LOG((TL_TRACE, "DeviceSpecific - exit. hr = %lx", hr)); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CAddress // Interface : ITAddress2 // Method : DeviceSpecificVariant // // this is the scriptable version of DeviceSpecific // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddress::DeviceSpecificVariant( IN ITCallInfo *pCall, 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(pCall, 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 : CAddress // Interface : ITAddress2 // Method : NegotiateExtVersion // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddress::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 = lineNegotiateExtVersion( m_hLineApp, 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; } // // ----------------------- CAddressTranslationInfo ----------------------------- // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CAddressTranslationInfo // Method : Initialize // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddressTranslationInfo::Initialize( PWSTR pszDialableString, PWSTR pszDisplayableString, DWORD dwCurrentCountry, DWORD dwDestCountry, DWORD dwTranslateResults ) { HRESULT hr = S_OK; LOG((TL_TRACE, "Initialize - enter" )); Lock(); m_dwCurrentCountryCode = dwCurrentCountry; m_dwDestinationCountryCode = dwDestCountry; m_dwTranslationResults = dwTranslateResults; m_szDialableString = NULL; m_szDialableString = NULL; // copy the Dialable String if (pszDialableString!= NULL) { m_szDialableString = (PWSTR) ClientAlloc((lstrlenW(pszDialableString) + 1) * sizeof (WCHAR)); if (m_szDialableString != NULL) { lstrcpyW(m_szDialableString, pszDialableString); // Now copy the Displayable String if (pszDisplayableString!= NULL) { m_szDisplayableString = (PWSTR) ClientAlloc((lstrlenW(pszDisplayableString) + 1) * sizeof (WCHAR)); if (m_szDisplayableString != NULL) { lstrcpyW(m_szDisplayableString, pszDisplayableString); } else { LOG((TL_ERROR, "Initialize - Alloc m_szDisplayableString failed" )); ClientFree( pszDialableString ); pszDialableString = NULL; hr = E_OUTOFMEMORY; } } } else { LOG((TL_ERROR, "Initialize - Alloc m_szDialableString failed" )); hr = E_OUTOFMEMORY; } } Unlock(); LOG((TL_TRACE, hr, "Initialize - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CAddressTranslationInfo // Method : FinalRelease // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void CAddressTranslationInfo::FinalRelease() { LOG((TL_TRACE, "FinalRelease - enter" )); if (m_szDialableString != NULL) { ClientFree( m_szDialableString); } if (m_szDisplayableString != NULL) { ClientFree( m_szDisplayableString); } LOG((TL_TRACE, "FinalRelease - exit" )); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CAddressTranslationInfo // Interface : ITAddressTranslationInfo // Method : get_CurrentCountryCode // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddressTranslationInfo::get_CurrentCountryCode(long * CountryCode ) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_CurrentCountryCode - enter" )); Lock(); if ( TAPIIsBadWritePtr( CountryCode , sizeof(long) ) ) { LOG((TL_ERROR, "get_CurrentCountryCode - Bad Pointer" )); hr = E_POINTER; } else // Ok Pointer { *CountryCode = m_dwCurrentCountryCode; } Unlock(); LOG((TL_TRACE, hr, "get_CurrentCountryCode - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CAddressTranslationInfo // Interface : ITAddressTranslationInfo // Method : get_DestinationCountryCode // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddressTranslationInfo::get_DestinationCountryCode(long * CountryCode ) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_DestinationCountryCode - enter" )); Lock(); if ( TAPIIsBadWritePtr( CountryCode , sizeof(long) ) ) { LOG((TL_ERROR, "get_DestinationCountryCode - Bad Pointer" )); hr = E_POINTER; } else // Ok Pointer { *CountryCode = m_dwDestinationCountryCode; } Unlock(); LOG((TL_TRACE, hr, "get_DestinationCountryCode - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CAddressTranslationInfo // Interface : ITAddressTranslationInfo // Method : get_TranslationResult // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddressTranslationInfo::get_TranslationResults(long * Results ) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_TranslationResults - enter" )); Lock(); if ( TAPIIsBadWritePtr( Results , sizeof(long) ) ) { LOG((TL_ERROR, "get_TranslationResults - Bad Pointer" )); hr = E_POINTER; } else // Ok Pointer { *Results = m_dwTranslationResults; } Unlock(); LOG((TL_TRACE, hr, "get_TranslationResults - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CAddressTranslationInfo // Interface : ITAddressTranslationInfo // Method : get_DialableString // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddressTranslationInfo::get_DialableString(BSTR * ppDialableString) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_DialableString - enter" )); Lock(); if ( TAPIIsBadWritePtr( ppDialableString, sizeof(BSTR) ) ) { LOG((TL_ERROR, "get_DialableString - Bad Pointer" )); hr = E_POINTER; } else // Ok Pointer { *ppDialableString = SysAllocString( m_szDialableString ); if ( ( NULL == *ppDialableString ) && ( NULL != m_szDialableString ) ) { LOG((TL_TRACE, "SysAllocString Failed" )); hr = E_OUTOFMEMORY; } } Unlock(); LOG((TL_TRACE, hr, "get_DialableString - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CAddressTranslationInfo // Interface : ITAddressTranslationInfo // Method : get_DisplayableString // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddressTranslationInfo::get_DisplayableString(BSTR * ppDisplayableString) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_DisplayableString - enter" )); Lock(); if ( TAPIIsBadWritePtr( ppDisplayableString, sizeof(BSTR) ) ) { LOG((TL_ERROR, "get_DisplayableString - Bad Pointer" )); hr = E_POINTER; } else // Ok Pointer { *ppDisplayableString = SysAllocString( m_szDisplayableString ); if ( ( NULL == *ppDisplayableString ) && ( NULL != m_szDisplayableString ) ) { LOG((TL_TRACE, "SysAllocString Failed" )); hr = E_OUTOFMEMORY; } } Unlock(); LOG((TL_TRACE, hr, "get_DisplayableString - exit" )); return hr; } // // ----------------------- CCallingCard ----------------------------- // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CCallingCard // Method : Initialize // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CCallingCard::Initialize( PWSTR pszCardName, PWSTR pszSameAreaDialingRule, PWSTR pszLongDistanceDialingRule, PWSTR pszInternationalDialingRule, DWORD dwPermanentCardID, DWORD dwNumberOfDigits, DWORD dwOptions ) { HRESULT hr = S_OK; LOG((TL_TRACE, "Initialize - enter" )); Lock(); m_dwPermanentCardID = dwPermanentCardID; m_dwNumberOfDigits = dwNumberOfDigits; m_dwOptions = dwOptions; m_szCardName = NULL; m_szSameAreaDialingRule = NULL; m_szLongDistanceDialingRule = NULL; m_szInternationalDialingRule = NULL; // copy the Card Name if (pszCardName != NULL) { m_szCardName = (PWSTR) ClientAlloc((lstrlenW(pszCardName) + 1) * sizeof (WCHAR)); if (m_szCardName != NULL) { lstrcpyW(m_szCardName, pszCardName); } else { LOG((TL_ERROR, "Initialize - Alloc m_szCardName failed" )); hr = E_OUTOFMEMORY; } } // copy the Same Area Dialing Rule if (pszSameAreaDialingRule != NULL) { m_szSameAreaDialingRule = (PWSTR) ClientAlloc((lstrlenW(pszSameAreaDialingRule) + 1) * sizeof (WCHAR)); if (m_szSameAreaDialingRule != NULL) { lstrcpyW(m_szSameAreaDialingRule, pszSameAreaDialingRule); } else { LOG((TL_ERROR, "Initialize - Alloc m_szSameAreaDialingRule failed" )); hr = E_OUTOFMEMORY; } } // copy the Long Distance Dialing Rule if (pszLongDistanceDialingRule != NULL) { m_szLongDistanceDialingRule = (PWSTR) ClientAlloc((lstrlenW(pszLongDistanceDialingRule) + 1) * sizeof (WCHAR)); if (m_szLongDistanceDialingRule != NULL) { lstrcpyW(m_szLongDistanceDialingRule, pszLongDistanceDialingRule); } else { LOG((TL_ERROR, "Initialize - Alloc m_szLongDistanceDialingRule failed" )); hr = E_OUTOFMEMORY; } } //copy the International Dialing Rule if (pszInternationalDialingRule != NULL) { m_szInternationalDialingRule = (PWSTR) ClientAlloc((lstrlenW(pszInternationalDialingRule) + 1) * sizeof (WCHAR)); if (m_szInternationalDialingRule != NULL) { lstrcpyW(m_szInternationalDialingRule, pszInternationalDialingRule); } else { LOG((TL_ERROR, "Initialize - Alloc m_szInternationalDialingRule failed" )); hr = E_OUTOFMEMORY; } } Unlock(); LOG((TL_TRACE, hr, "Initialize - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CCallingCard // Method : FinalRelease // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void CCallingCard::FinalRelease() { LOG((TL_TRACE, "FinalRelease - enter" )); if (m_szCardName != NULL) { ClientFree(m_szCardName); } if (m_szSameAreaDialingRule != NULL) { ClientFree(m_szSameAreaDialingRule); } if (m_szLongDistanceDialingRule != NULL) { ClientFree(m_szLongDistanceDialingRule); } if (m_szInternationalDialingRule != NULL) { ClientFree(m_szInternationalDialingRule); } LOG((TL_TRACE, "FinalRelease - exit" )); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CCallingCard // Interface : ITCallingCard // Method : get_PermanentCardID // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CCallingCard::get_PermanentCardID(long * ulCardID) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_PermanentCardID - enter" )); Lock(); if ( TAPIIsBadWritePtr( ulCardID, sizeof(long) ) ) { LOG((TL_ERROR, "get_PermanentCardID - Bad Pointer" )); hr = E_POINTER; } else // Ok Pointer { *ulCardID= m_dwPermanentCardID; } Unlock(); LOG((TL_TRACE, hr, "get_PermanentCardID - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CCallingCard // Interface : ITCallingCard // Method : get_NumberOfDigits // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CCallingCard::get_NumberOfDigits(long * ulDigits) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_NumberOfDigits - enter" )); Lock(); if ( TAPIIsBadWritePtr( ulDigits, sizeof(long) ) ) { LOG((TL_ERROR, "get_NumberOfDigits - Bad Pointer" )); hr = E_POINTER; } else // Ok Pointer { *ulDigits= m_dwNumberOfDigits; } Unlock(); LOG((TL_TRACE, hr, "get_NumberOfDigits - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CCallingCard // Interface : ITCallingCard // Method : get_Options // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CCallingCard::get_Options(long * ulOptions) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_Options - enter" )); Lock(); if ( TAPIIsBadWritePtr( ulOptions, sizeof(long) ) ) { LOG((TL_ERROR, "get_Options - Bad Pointer" )); hr = E_POINTER; } else // Ok Pointer { *ulOptions= m_dwOptions; } Unlock(); LOG((TL_TRACE, hr, "get_Options - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CCallingCard // Interface : ITCallingCard // Method : get_CardName // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CCallingCard::get_CardName(BSTR * ppCardName) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_CardName - enter" )); Lock(); if ( TAPIIsBadWritePtr( ppCardName, sizeof(BSTR) ) ) { LOG((TL_ERROR, "get_CardName - Bad Pointer" )); hr = E_POINTER; } else // Ok Pointer { *ppCardName = SysAllocString( m_szCardName ); if ( ( NULL == *ppCardName ) && ( NULL != m_szCardName ) ) { LOG((TL_TRACE, "SysAllocString Failed" )); hr = E_OUTOFMEMORY; } } Unlock(); LOG((TL_TRACE, hr, "get_CardName - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CCallingCard // Interface : ITCallingCard // Method : get_SameAreaDialingRule // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CCallingCard::get_SameAreaDialingRule(BSTR * ppRule) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_SameAreaDialingRule - enter" )); Lock(); if ( TAPIIsBadWritePtr( ppRule, sizeof(BSTR) ) ) { LOG((TL_ERROR, "get_SameAreaDialingRule - Bad Pointer" )); hr = E_POINTER; } else // Ok Pointer { *ppRule = SysAllocString( m_szSameAreaDialingRule ); if ( ( NULL == *ppRule ) && ( NULL != m_szSameAreaDialingRule ) ) { LOG((TL_TRACE, "SysAllocString Failed" )); hr = E_OUTOFMEMORY; } } Unlock(); LOG((TL_TRACE, hr, "get_SameAreaDialingRule - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CCallingCard // Interface : ITCallingCard // Method : get_LongDistanceDialingRule // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CCallingCard::get_LongDistanceDialingRule(BSTR * ppRule) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_LongDistanceDialingRule - enter" )); Lock(); if ( TAPIIsBadWritePtr( ppRule, sizeof(BSTR) ) ) { LOG((TL_ERROR, "get_LongDistanceDialingRule - Bad Pointer" )); hr = E_POINTER; } else // Ok Pointer { *ppRule = SysAllocString( m_szLongDistanceDialingRule ); if ( ( NULL == *ppRule ) && ( NULL != m_szLongDistanceDialingRule ) ) { LOG((TL_TRACE, "SysAllocString Failed" )); hr = E_OUTOFMEMORY; } } Unlock(); LOG((TL_TRACE, hr, "get_LongDistanceDialingRule - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CCallingCard // Interface : ITCallingCard // Method : get_InternationalDialingRule // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CCallingCard::get_InternationalDialingRule(BSTR * ppRule) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_InternationalDialingRule - enter" )); Lock(); if ( TAPIIsBadWritePtr( ppRule, sizeof(BSTR) ) ) { LOG((TL_ERROR, "get_InternationalDialingRule - Bad Pointer" )); hr = E_POINTER; } else // Ok Pointer { *ppRule = SysAllocString( m_szInternationalDialingRule ); if ( ( NULL == *ppRule ) && ( NULL != m_szInternationalDialingRule ) ) { LOG((TL_TRACE, "SysAllocString Failed" )); hr = E_OUTOFMEMORY; } } Unlock(); LOG((TL_TRACE, hr, "get_InternationalDialingRule - exit" )); return hr; } // // ----------------------- CLocationInfo ----------------------------- // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CLocationInfo // Method : Initialize // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CLocationInfo::Initialize( PWSTR pszLocationName, PWSTR pszCityCode, PWSTR pszLocalAccessCode, PWSTR pszLongDistanceAccessCode, PWSTR pszTollPrefixList, PWSTR pszCancelCallWaitingCode , DWORD dwPermanentLocationID, DWORD dwCountryCode, DWORD dwPreferredCardID, DWORD dwCountryID, DWORD dwOptions ) { HRESULT hr = S_OK; LOG((TL_TRACE, "Initialize - enter" )); Lock(); m_dwPermanentLocationID = dwPermanentLocationID; m_dwCountryCode = dwCountryCode; m_dwPreferredCardID = dwPreferredCardID; m_dwCountryID = dwCountryID; m_dwOptions = dwOptions; m_szLocationName = NULL; m_szCityCode = NULL; m_szLocalAccessCode = NULL; m_szLongDistanceAccessCode = NULL; m_szTollPrefixList = NULL; m_szCancelCallWaitingCode = NULL; // copy the Location Name if (pszLocationName!= NULL) { m_szLocationName = (PWSTR) ClientAlloc((lstrlenW(pszLocationName) + 1) * sizeof (WCHAR)); if (m_szLocationName != NULL) { lstrcpyW(m_szLocationName, pszLocationName); } else { LOG((TL_ERROR, "Initialize - Alloc m_szDialableString failed" )); hr = E_OUTOFMEMORY; } } // copy the City Code if (pszCityCode != NULL) { m_szCityCode = (PWSTR) ClientAlloc((lstrlenW(pszCityCode) + 1) * sizeof (WCHAR)); if (m_szCityCode != NULL) { lstrcpyW(m_szCityCode , pszCityCode); } else { LOG((TL_ERROR, "Initialize - Alloc m_szCityCode failed" )); hr = E_OUTOFMEMORY; } } // copy the Local Access Code if (pszLocalAccessCode != NULL) { m_szLocalAccessCode = (PWSTR) ClientAlloc((lstrlenW(pszLocalAccessCode) + 1) * sizeof (WCHAR)); if (m_szLocalAccessCode != NULL) { lstrcpyW(m_szLocalAccessCode, pszLocalAccessCode); } else { LOG((TL_ERROR, "Initialize - Alloc m_szLocalAccessCode failed" )); hr = E_OUTOFMEMORY; } } // copy the Long Distance Access Code if (pszLongDistanceAccessCode != NULL) { m_szLongDistanceAccessCode = (PWSTR) ClientAlloc((lstrlenW(pszLongDistanceAccessCode) + 1) * sizeof (WCHAR)); if (m_szLongDistanceAccessCode != NULL) { lstrcpyW(m_szLongDistanceAccessCode, pszLongDistanceAccessCode); } else { LOG((TL_ERROR, "Initialize - Alloc m_szLongDistanceAccessCode failed" )); hr = E_OUTOFMEMORY; } } // copy the Toll Prefix List if (pszTollPrefixList != NULL) { m_szTollPrefixList = (PWSTR) ClientAlloc((lstrlenW(pszTollPrefixList) + 1) * sizeof (WCHAR)); if (m_szTollPrefixList != NULL) { lstrcpyW(m_szTollPrefixList, pszTollPrefixList); } else { LOG((TL_ERROR, "Initialize - Alloc m_szTollPrefixList failed" )); hr = E_OUTOFMEMORY; } } // copy the Cancel Call Waiting Code if (pszCancelCallWaitingCode != NULL) { m_szCancelCallWaitingCode = (PWSTR) ClientAlloc((lstrlenW(pszCancelCallWaitingCode) + 1) * sizeof (WCHAR)); if (m_szCancelCallWaitingCode != NULL) { lstrcpyW(m_szCancelCallWaitingCode, pszCancelCallWaitingCode); } else { LOG((TL_ERROR, "Initialize - Alloc m_szCancelCallWaitingCode failed" )); hr = E_OUTOFMEMORY; } } Unlock(); LOG((TL_TRACE, hr, "Initialize - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CLocationInfo // Method : FinalRelease // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void CLocationInfo::FinalRelease() { LOG((TL_TRACE, "FinalRelease - enter" )); if (m_szLocationName != NULL) { ClientFree( m_szLocationName); } if (m_szCityCode != NULL) { ClientFree( m_szCityCode); } if (m_szLocalAccessCode != NULL) { ClientFree( m_szLocalAccessCode); } if (m_szLongDistanceAccessCode != NULL) { ClientFree( m_szLongDistanceAccessCode); } if (m_szTollPrefixList != NULL) { ClientFree( m_szTollPrefixList); } if (m_szCancelCallWaitingCode != NULL) { ClientFree( m_szCancelCallWaitingCode); } LOG((TL_TRACE, "FinalRelease - exit" )); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CLocationInfo // Interface : ITLocationInfo // Method : get_PermanentLocationID // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CLocationInfo::get_PermanentLocationID(long * ulLocationID ) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_PermanentLocationID - enter" )); Lock(); if ( TAPIIsBadWritePtr( ulLocationID , sizeof(long) ) ) { LOG((TL_ERROR, "get_PermanentLocationID - Bad Pointer" )); hr = E_POINTER; } else // Ok Pointer { *ulLocationID = m_dwPermanentLocationID; } Unlock(); LOG((TL_TRACE, hr, "get_PermanentLocationID - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CLocationInfo // Interface : ITLocationInfo // Method : get_CountryCode // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CLocationInfo::get_CountryCode(long * ulCountryCode) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_CountryCode - enter" )); Lock(); if ( TAPIIsBadWritePtr( ulCountryCode, sizeof(long) ) ) { LOG((TL_ERROR, "get_CountryCode - Bad Pointer" )); hr = E_POINTER; } else // Ok Pointer { *ulCountryCode= m_dwCountryCode; } Unlock(); LOG((TL_TRACE, hr, "get_CountryCode - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CLocationInfo // Interface : ITLocationInfo // Method : get_CountryID // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CLocationInfo::get_CountryID(long * ulCountryID) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_CountryID - enter" )); Lock(); if ( TAPIIsBadWritePtr( ulCountryID, sizeof(long) ) ) { LOG((TL_ERROR, "get_CountryID - Bad Pointer" )); hr = E_POINTER; } else // Ok Pointer { *ulCountryID= m_dwCountryID; } Unlock(); LOG((TL_TRACE, hr, "get_CountryID - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CLocationInfo // Interface : ITLocationInfo // Method : get_Options // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CLocationInfo::get_Options(long * Options) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_Options - enter" )); Lock(); if ( TAPIIsBadWritePtr( Options, sizeof(long) ) ) { LOG((TL_ERROR, "get_Options - Bad Pointer" )); hr = E_POINTER; } else // Ok Pointer { *Options= m_dwOptions; } Unlock(); LOG((TL_TRACE, hr, "get_Options - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CLocationInfo // Interface : ITLocationInfo // Method : get_PreferredCardID // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CLocationInfo::get_PreferredCardID(long * ulCardID) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_PreferredCardID - enter" )); Lock(); if ( TAPIIsBadWritePtr( ulCardID, sizeof(long) ) ) { LOG((TL_ERROR, "get_PreferredCardID - Bad Pointer" )); hr = E_POINTER; } else // Ok Pointer { *ulCardID= m_dwPreferredCardID; } Unlock(); LOG((TL_TRACE, hr, "get_PreferredCardID - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CLocationInfo // Interface : ITLocationInfo // Method : get_LocationName // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CLocationInfo::get_LocationName(BSTR * ppLocationName) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_LocationName - enter" )); Lock(); if ( TAPIIsBadWritePtr( ppLocationName, sizeof(BSTR) ) ) { LOG((TL_ERROR, "get_LocationName - Bad Pointer" )); hr = E_POINTER; } else // Ok Pointer { *ppLocationName = SysAllocString( m_szLocationName ); if ( ( NULL == *ppLocationName ) && ( NULL != m_szLocationName ) ) { LOG((TL_TRACE, "SysAllocString Failed" )); hr = E_OUTOFMEMORY; } } Unlock(); LOG((TL_TRACE, hr, "gget_LocationName - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CLocationInfo // Interface : ITLocationInfo // Method : get_CityCode // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CLocationInfo::get_CityCode(BSTR * ppCode) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_CityCode - enter" )); Lock(); if ( TAPIIsBadWritePtr( ppCode, sizeof(BSTR) ) ) { LOG((TL_ERROR, "get_CityCode - Bad Pointer" )); hr = E_POINTER; } else // Ok Pointer { *ppCode = SysAllocString( m_szCityCode ); if ( ( NULL == *ppCode ) && ( NULL != m_szCityCode ) ) { LOG((TL_TRACE, "SysAllocString Failed" )); hr = E_OUTOFMEMORY; } } Unlock(); LOG((TL_TRACE, hr, "get_CityCode - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CLocationInfo // Interface : ITLocationInfo // Method : get_LocalAccessCode // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CLocationInfo::get_LocalAccessCode(BSTR * ppCode) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_LocalAccessCode - enter" )); Lock(); if ( TAPIIsBadWritePtr( ppCode, sizeof(BSTR) ) ) { LOG((TL_ERROR, "get_LocalAccessCode - Bad Pointer" )); hr = E_POINTER; } else // Ok Pointer { *ppCode = SysAllocString( m_szLocalAccessCode ); if ( ( NULL == *ppCode ) && ( NULL != m_szLocalAccessCode ) ) { LOG((TL_TRACE, "SysAllocString Failed" )); hr = E_OUTOFMEMORY; } } Unlock(); LOG((TL_TRACE, hr, "get_LocalAccessCode - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CLocationInfo // Interface : ITLocationInfo // Method : get_LongDistanceAccessCode // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CLocationInfo::get_LongDistanceAccessCode(BSTR * ppCode ) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_LongDistanceAccessCode - enter" )); Lock(); if ( TAPIIsBadWritePtr( ppCode , sizeof(BSTR) ) ) { LOG((TL_ERROR, "get_LongDistanceAccessCode - Bad Pointer" )); hr = E_POINTER; } else // Ok Pointer { *ppCode = SysAllocString( m_szLongDistanceAccessCode); if ( ( NULL == *ppCode ) && ( NULL != m_szLongDistanceAccessCode ) ) { LOG((TL_TRACE, "SysAllocString Failed" )); hr = E_OUTOFMEMORY; } } Unlock(); LOG((TL_TRACE, hr, "get_LongDistanceAccessCode - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CLocationInfo // Interface : ITLocationInfo // Method : get_TollPrefixList // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CLocationInfo::get_TollPrefixList(BSTR * ppTollList) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_TollPrefixList - enter" )); Lock(); if ( TAPIIsBadWritePtr( ppTollList, sizeof(BSTR) ) ) { LOG((TL_ERROR, "get_TollPrefixList - Bad Pointer" )); hr = E_POINTER; } else // Ok Pointer { *ppTollList = SysAllocString( m_szTollPrefixList ); if ( ( NULL == *ppTollList ) && ( NULL != m_szTollPrefixList ) ) { LOG((TL_TRACE, "SysAllocString Failed" )); hr = E_OUTOFMEMORY; } } Unlock(); LOG((TL_TRACE, hr, "get_TollPrefixList - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CLocationInfo // Interface : ITLocationInfo // Method : get_CancelCallWaitingCode // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CLocationInfo::get_CancelCallWaitingCode(BSTR * ppCode) { HRESULT hr = S_OK; LOG((TL_TRACE, "get_CancelCallWaitingCode - enter" )); Lock(); if ( TAPIIsBadWritePtr( ppCode, sizeof(BSTR) ) ) { LOG((TL_ERROR, "get_CancelCallWaitingCode - Bad Pointer" )); hr = E_POINTER; } else // Ok Pointer { *ppCode = SysAllocString( m_szCancelCallWaitingCode ); if ( ( NULL == *ppCode ) && ( NULL != m_szCancelCallWaitingCode ) ) { LOG((TL_TRACE, "SysAllocString Failed" )); hr = E_OUTOFMEMORY; } } Unlock(); LOG((TL_TRACE, hr, "get_CancelCallWaitingCode - exit" )); return hr; } BOOL CAddress::GetMediaMode( long lMediaType, DWORD * pdwMediaMode ) { DWORD dwRet = (DWORD)lMediaType; DWORD dwHold; if (dwRet & AUDIOMEDIAMODES) { dwHold = m_dwMediaModesSupported & AUDIOMEDIAMODES; if ( dwHold == AUDIOMEDIAMODES ) { dwHold = LINEMEDIAMODE_AUTOMATEDVOICE; } dwRet &= ~AUDIOMEDIAMODES; dwRet |= dwHold; } *pdwMediaMode = dwRet; if ( (dwRet == 0) || ((dwRet & m_dwMediaModesSupported) != dwRet) ) { return FALSE; } return TRUE; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // get_LineID // // returns the tapi 2 device ID for this line // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddress::get_LineID( long * plLineID ) { LOG((TL_TRACE, "get_LineID - enter")); if ( TAPIIsBadWritePtr( plLineID, sizeof(long) ) ) { LOG((TL_ERROR, "get_LineID - bad pointer")); return E_POINTER; } Lock(); *plLineID = m_dwDeviceID; Unlock(); LOG((TL_TRACE, "get_LineID - exit")); return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // get_AddressID // // returns the tapi 2 address ID of this address // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddress::get_AddressID( long * plAddressID ) { LOG((TL_TRACE, "get_AddressID - enter")); if ( TAPIIsBadWritePtr( plAddressID, sizeof(long) ) ) { LOG((TL_ERROR, "get_AddressID - bad pointer")); return E_POINTER; } Lock(); *plAddressID = m_dwAddressID; Unlock(); LOG((TL_TRACE, "get_AddressID - exit")); return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // CAddress::UpdateAddressCaps // // must be called in lock // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddress::UpdateAddressCaps() { HRESULT hr = S_OK; if ( NULL == m_pAddressCaps ) { LPLINEADDRESSCAPS pTemp; CTAPI * pCTapi; pCTapi = GetTapi(); if( NULL == pCTapi ) { LOG((TL_ERROR, "dynamic cast operation failed")); hr = E_POINTER; } else { hr = pCTapi->GetBuffer( BUFFERTYPE_ADDRCAP, (UINT_PTR)this, (LPVOID*)&m_pAddressCaps ); } if ( !SUCCEEDED(hr) ) { return hr; } pTemp = m_pAddressCaps; hr = LineGetAddressCaps( m_hLineApp, m_dwDeviceID, m_dwAddressID, m_dwAPIVersion, &m_pAddressCaps ); if ( !SUCCEEDED(hr) ) { return hr; } if ( m_pAddressCaps != pTemp ) { pCTapi->SetBuffer( BUFFERTYPE_ADDRCAP, (UINT_PTR)this, (LPVOID)m_pAddressCaps ); } } return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // CAddress::UpdateLineDevCaps // // must be called in lock // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddress::UpdateLineDevCaps() { HRESULT hr = S_OK; if ( NULL == m_pDevCaps ) { LPLINEDEVCAPS pTemp; CTAPI * pCTapi; pCTapi = GetTapi(); if( NULL == pCTapi ) { LOG((TL_ERROR, "dynamic cast operation failed")); hr = E_POINTER; } else { hr = pCTapi->GetBuffer( BUFFERTYPE_LINEDEVCAP, (UINT_PTR)this, (LPVOID*)&m_pDevCaps ); } if ( !SUCCEEDED(hr) ) { return hr; } pTemp = m_pDevCaps; hr = LineGetDevCaps( m_hLineApp, m_dwDeviceID, m_dwAPIVersion, &m_pDevCaps ); if ( !SUCCEEDED(hr) ) { return hr; } if ( m_pDevCaps != pTemp ) { pCTapi->SetBuffer( BUFFERTYPE_LINEDEVCAP, (UINT_PTR)this, (LPVOID)m_pDevCaps ); } } return S_OK; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // SetAddrCapBuffer // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void CAddress::SetAddrCapBuffer( LPVOID pBuf ) { Lock(); m_pAddressCaps = (LPLINEADDRESSCAPS)pBuf; Unlock(); } void CAddress::SetLineDevCapBuffer( LPVOID pBuf ) { Lock(); m_pDevCaps = (LPLINEDEVCAPS)pBuf; Unlock(); } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddress::CreateMSPCall( MSP_HANDLE hCall, DWORD dwReserved, long lMediaType, IUnknown * pOuterUnk, IUnknown ** ppStreamControl ) { HRESULT hr = E_FAIL; if ( NULL != m_pMSPAggAddress ) { ITMSPAddress * pMSPAddress = GetMSPAddress(); __try { hr = pMSPAddress->CreateMSPCall( hCall, dwReserved, lMediaType, pOuterUnk, ppStreamControl ); } __except(EXCEPTION_EXECUTE_HANDLER) { // // catch any exceptions thrown by the msp, to protect ouirselves from // misbehaving msps // LOG((TL_ERROR, "CreateMSPCall - MSPAddress::CreateMSPCall threw an exception")); hr = E_OUTOFMEMORY; } pMSPAddress->Release(); } return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddress::ShutdownMSPCall( IUnknown * pStreamControl ) { HRESULT hr = S_FALSE; if ( NULL != m_pMSPAggAddress ) { ITMSPAddress * pMSPAddress = GetMSPAddress(); hr = pMSPAddress->ShutdownMSPCall( pStreamControl ); pMSPAddress->Release(); } return hr; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HRESULT CAddress::ReceiveTSPData( IUnknown * pMSPCall, LPBYTE pBuffer, DWORD dwSize ) { HRESULT hr = E_FAIL; Lock(); if ( NULL != m_pMSPAggAddress ) { ITMSPAddress * pMSPAddress = GetMSPAddress(); hr = pMSPAddress->ReceiveTSPData( pMSPCall, pBuffer, dwSize ); pMSPAddress->Release(); } Unlock(); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // LINE_SENDMSPMESSAGE handler // // give the opaque blob to the msp // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= HRESULT HandleSendMSPDataMessage( PASYNCEVENTMSG pParams ) { CAddress * pAddress; BOOL bSuccess; HRESULT hr = S_OK; IUnknown * pMSPCall = NULL;; LOG((TL_TRACE, "HandleSendMSPDataMessage - enter")); // // find the correct line // bSuccess = FindAddressObject( (HLINE)(pParams->hDevice), &pAddress ); if (bSuccess) { CCall * pCall = NULL; if ( NULL != (HCALL)(pParams->Param1) ) { bSuccess = FindCallObject( (HCALL)(pParams->Param1), &pCall ); if ( !bSuccess ) { LOG((TL_ERROR, "HandleSendMSPDataMessage - couldn't find call %X",pParams->Param1)); //FindAddressObject addrefs the address objct pAddress->Release(); return E_FAIL; } pMSPCall = pCall->GetMSPCall(); } // // the blob is at the end of the fixed // structure // // // get the size of the blob // DWORD dwSize = pParams->Param2; BYTE *pBuffer = NULL; // // if the buffer's not empty, get a pointer to it // if (0 < dwSize) { pBuffer = (LPBYTE)(pParams + 1); } // // call the msp // pAddress->ReceiveTSPData( pMSPCall, pBuffer, dwSize ); if ( pCall ) { pCall->Release(); if ( pMSPCall ) { pMSPCall->Release(); } } hr = S_OK; //FindAddressObject addrefs the address objct pAddress->Release(); } else { LOG((TL_ERROR, "HandleSendMSPDataMessage - failed to find address Object %lx", pParams->hDevice)); hr = E_FAIL; } LOG((TL_TRACE, "HandleSendMSPDataMessage - exit. hr = %lx", hr)); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // HandleSendTSPData // // sends an opaque buffer from the msp to the tsp // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= HRESULT CAddress::HandleSendTSPData( MSP_EVENT_INFO * pEvent ) { LOG((TL_INFO, "HandleSendTSPData - enter pEvent %p", pEvent)); // // see if the event is bad // if (IsBadReadPtr(pEvent, sizeof(MSP_EVENT_INFO) ) ) { LOG((TL_ERROR, "HandleSendTSPData - bad event structure")); return E_POINTER; } HRESULT hr = S_OK; HCALL hCall = NULL; CCall * pCall = NULL; AddressLineStruct * pAddressLine = NULL; // // if we were given msp call handle, find the corresponding call // if ( NULL != pEvent->hCall) { gpHandleHashTable->Lock(); hr = gpHandleHashTable->Find( (ULONG_PTR)pEvent->hCall, (ULONG_PTR *)&pCall); if ( SUCCEEDED(hr) ) { // // found the call, addreff the call and and release the table // LOG((TL_INFO, "HandleSendTSPData - Matched handle %X to Call object %p", pEvent->hCall, pCall )); pCall->AddRef(); gpHandleHashTable->Unlock(); // // get the handle for this call // hCall = pCall->GetHCall(); // // get call's address line, if any // pAddressLine = pCall->GetAddRefMyAddressLine(); LOG((TL_INFO, "HandleSendTSPData - address line[%p] hCall[%lx]", pAddressLine, hCall )); } else { // // there is no corresponding call in the hash table. the call no // longer exists, or msp passed a bugus handle // gpHandleHashTable->Unlock(); LOG((TL_ERROR, "HandleSendTSPData - Couldn't match handle %X to Call object. hr = %lx", pEvent->hCall, hr)); return hr; } } // // by this point we either had msp call handle that is null or successfully // found a matching call object and asked it for its address line // if (NULL == pAddressLine) { // // if we don't have address line, send a message to the first address line on // this address (?) // if ( m_AddressLinesPtrList.size() > 0 ) { PtrList::iterator iter; iter = m_AddressLinesPtrList.begin(); // // send to the tsp // hr = LineReceiveMSPData( ((AddressLineStruct *)(*iter))->t3Line.hLine, hCall, pEvent->MSP_TSP_DATA.pBuffer, pEvent->MSP_TSP_DATA.dwBufferSize ); } else { LOG((TL_ERROR, "HandleSendTSPData - no address lines on the address. E_UNEXPECTED")); hr = E_UNEXPECTED; } } else { // // if we have an address line, send a message to the corresponding line // hr = LineReceiveMSPData( pAddressLine->t3Line.hLine, hCall, pEvent->MSP_TSP_DATA.pBuffer, pEvent->MSP_TSP_DATA.dwBufferSize ); // // no longer need our address line, release it. the line will be closed // if needed // pCall->ReleaseAddressLine(pAddressLine); pAddressLine = NULL; } // // if we have a call, release it // if (NULL != pCall) { pCall->Release(); pCall = NULL; } LOG((TL_INFO, "HandleSendTSPData - finish hr = %lx", hr)); return hr; } // // handle dev specific message // void HandleLineDevSpecificMessage( PASYNCEVENTMSG pParams ) { LOG((TL_INFO, "HandleLineDevSpecificMessage - enter")); // // note: // // unfortunately, the message that we receive does not give us any // indication as to whether hDevice contains a call handle or am address // handle. // // to determine the kind of handle, we have to search both tables. if we // find the corresponding address object, this is a line handle, if we find // a corresponding call, this is a call handle. this brute-force search is // fairly expensive. // // one possible optimization would be to track the number of calls and // addresses and search the smaller table first. however, this would // require tracking overhead (even in the cases where the optimization is // not needed), and for this to work well, we would also need to estimate // the likelyhood of each type of message. which makes this kind of // optimization even more expensive. // // so we will simply check both tables to determine whether we have a call // or an address. // CCall *pCall = NULL; CAddress *pAddress = NULL; // // find the corresponding address // if ( !FindAddressObject( (HLINE)(pParams->hDevice), &pAddress ) ) { LOG((TL_WARN, "HandleLineDevSpecificMessage - FindAddressObject failed to find matching address. searching for call")); pAddress = NULL; // // no address, try to find matching call // if ( !FindCallObject( (HCALL)(pParams->hDevice), &pCall) ) { LOG((TL_ERROR, "HandleLineDevSpecificMessage - FindAddressObject failed to find matching call. ")); return; } } // // if we got a call, get the corresponding address object // if (NULL != pCall) { ITAddress *pITAddress = NULL; HRESULT hr = pCall->get_Address(&pITAddress); if (FAILED(hr)) { LOG((TL_ERROR, "HandleLineDevSpecificMessage - call does not have an address. hr = %lx", hr)); pCall->Release(); pCall = NULL; return; } try { pAddress = dynamic_cast(pITAddress); } catch(...) { LOG((TL_ERROR, "HandleLineDevSpecificMessage - exception using address. address pointer bad")); } // // if the address is bad, return // if (NULL == pAddress) { LOG((TL_ERROR, "HandleLineDevSpecificMessage - no address")); pCall->Release(); pCall = NULL; // // yes, queryinterface returned us an addreffed pITAddress... but // since it does not seem valid anyway, do not bother releasing. // _ASSERTE(FALSE); return; } } // call is not null // // by this time we must have an address and maybe a call. we actually // ensured this in the logic above. this assert is to make this condition // explicit. // _ASSERTE( NULL != pAddress ); // // fire event // CAddressDevSpecificEvent::FireEvent( pAddress, pCall, pParams->Param1, pParams->Param2, pParams->Param3 ); // // undo FindXObject's addreffs // if (NULL != pAddress) { pAddress->Release(); pAddress = NULL; } if (NULL != pCall) { pCall->Release(); pCall = NULL; } LOG((TL_INFO, "HandleLineDevSpecificMessage - exit. ")); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // HandleMSPAddressEvent // // fires an addressevent to the application based on // an event from the MSP // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= HRESULT CAddress::HandleMSPAddressEvent( MSP_EVENT_INFO * pEvent ) { switch ( pEvent->MSP_ADDRESS_EVENT_INFO.Type ) { case ADDRESS_TERMINAL_AVAILABLE: CAddressEvent::FireEvent( this, AE_NEWTERMINAL, pEvent->MSP_ADDRESS_EVENT_INFO.pTerminal ); break; case ADDRESS_TERMINAL_UNAVAILABLE: CAddressEvent::FireEvent( this, AE_REMOVETERMINAL, pEvent->MSP_ADDRESS_EVENT_INFO.pTerminal ); break; default: LOG((TL_ERROR, "HandleMSPAddressEvent - bad event")); break; } return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // HandleMSPCallEvent // // fires a callmediaevent to the application based on an // event from the msp // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= HRESULT CAddress::HandleMSPCallEvent( MSP_EVENT_INFO * pEvent ) { CCall * pCall; ITCallInfo * pCallInfo; CALL_MEDIA_EVENT Event; CALL_MEDIA_EVENT_CAUSE Cause; ITTerminal * pTerminal = NULL; ITStream * pStream = NULL; HRESULT hrEvent = 0; HRESULT hr = S_OK; gpHandleHashTable->Lock(); hr = gpHandleHashTable->Find( (ULONG_PTR)pEvent->hCall, (ULONG_PTR *)&pCall); if ( SUCCEEDED(hr) ) { LOG((TL_INFO, "HandleMSPCallEvent - Matched handle %X to Call object %p", pEvent->hCall, pCall )); pCall->AddRef(); gpHandleHashTable->Unlock(); hr = pCall->QueryInterface( IID_ITCallInfo, (void**) &pCallInfo ); } else // ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "HandleMSPCallEvent - Couldn't match handle %X to Call object ", pEvent->hCall)); gpHandleHashTable->Unlock(); return hr; } // // set up the info for the event // pStream applies to all of the currently-defined events // pStream = pEvent->MSP_CALL_EVENT_INFO.pStream; // // cause is the same, although the MSPI and API use different enumerated types. // Note: this will have to expand to a switch if the order of enums ever gets // out of sync! // Cause = (CALL_MEDIA_EVENT_CAUSE) pEvent->MSP_CALL_EVENT_INFO.Cause; // // Rest depend on the type... // switch ( pEvent->MSP_CALL_EVENT_INFO.Type ) { case CALL_NEW_STREAM: Event = CME_NEW_STREAM; break; case CALL_STREAM_FAIL: Event = CME_STREAM_FAIL; hrEvent = pEvent->MSP_CALL_EVENT_INFO.hrError; break; case CALL_TERMINAL_FAIL: Event = CME_TERMINAL_FAIL; pTerminal = pEvent->MSP_CALL_EVENT_INFO.pTerminal; hrEvent = pEvent->MSP_CALL_EVENT_INFO.hrError; break; case CALL_STREAM_NOT_USED: Event = CME_STREAM_NOT_USED; break; case CALL_STREAM_ACTIVE: Event = CME_STREAM_ACTIVE; break; case CALL_STREAM_INACTIVE: Event = CME_STREAM_INACTIVE; break; default: LOG((TL_ERROR, "HandleMSPCallEvent - bad event")); return E_INVALIDARG; } // // fire the event // CCallMediaEvent::FireEvent( pCallInfo, Event, Cause, dynamic_cast(m_pTAPI), pTerminal, pStream, hrEvent ); // // addref'd above // pCallInfo->Release(); pCall->Release(); return S_OK; } HRESULT CAddress::HandleMSPTTSTerminalEvent( MSP_EVENT_INFO * pEvent ) { if (NULL == pEvent) { LOG((TL_ERROR, "HandleMSPTTSTerminalEvent - pEvent is NULL")); return E_POINTER; } ITAddress *pAddress = dynamic_cast(this); if (pAddress == NULL) { LOG((TL_ERROR, "HandleMSPTTSTerminalEvent - can't cast the address %p to ITAddress", this)); return E_UNEXPECTED; } CCall * pCall = NULL; ITCallInfo * pCallInfo = NULL; gpHandleHashTable->Lock(); HRESULT hr = E_FAIL; hr = gpHandleHashTable->Find( (ULONG_PTR)pEvent->hCall, (ULONG_PTR *)&pCall); if ( SUCCEEDED(hr) ) { LOG((TL_INFO, "HandleMSPTTSTerminalEvent - Matched handle %X to Call object %p", pEvent->hCall, pCall )); pCall->AddRef(); gpHandleHashTable->Unlock(); hr = pCall->QueryInterface( IID_ITCallInfo, (void**) &pCallInfo ); } else // ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "HandleMSPTTSTerminalEvent - Couldn't match handle %X to Call object ", pEvent->hCall)); gpHandleHashTable->Unlock(); return hr; } // // get tapi object and fire the event // hr = CTTSTerminalEvent::FireEvent(GetTapi(), pCallInfo, pEvent->MSP_TTS_TERMINAL_EVENT_INFO.pTTSTerminal, pEvent->MSP_TTS_TERMINAL_EVENT_INFO.hrErrorCode); if (FAILED(hr)) { LOG((TL_ERROR, "HandleMSPTTSTerminalEvent - CFileTerminalEvent::FireEvent failed. hr = %lx", hr)); } // // we addref'd these above, so release now // pCallInfo->Release(); pCall->Release(); return hr; } HRESULT CAddress::HandleMSPASRTerminalEvent( MSP_EVENT_INFO * pEvent ) { if (NULL == pEvent) { LOG((TL_ERROR, "HandleMSPASRTerminalEvent - pEvent is NULL")); return E_POINTER; } ITAddress *pAddress = dynamic_cast(this); if (pAddress == NULL) { LOG((TL_ERROR, "HandleMSPASRTerminalEvent - can't cast the address %p to ITAddress", this)); return E_UNEXPECTED; } CCall * pCall = NULL; ITCallInfo * pCallInfo = NULL; gpHandleHashTable->Lock(); HRESULT hr = E_FAIL; hr = gpHandleHashTable->Find( (ULONG_PTR)pEvent->hCall, (ULONG_PTR *)&pCall); if ( SUCCEEDED(hr) ) { LOG((TL_INFO, "HandleMSPASRTerminalEvent - Matched handle %X to Call object %p", pEvent->hCall, pCall )); pCall->AddRef(); gpHandleHashTable->Unlock(); hr = pCall->QueryInterface( IID_ITCallInfo, (void**) &pCallInfo ); } else // ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "HandleMSPASRTerminalEvent - Couldn't match handle %X to Call object ", pEvent->hCall)); gpHandleHashTable->Unlock(); return hr; } // // get tapi object and fire the event // hr = CASRTerminalEvent::FireEvent(GetTapi(), pCallInfo, pEvent->MSP_ASR_TERMINAL_EVENT_INFO.pASRTerminal, pEvent->MSP_ASR_TERMINAL_EVENT_INFO.hrErrorCode); if (FAILED(hr)) { LOG((TL_ERROR, "HandleMSPASRTerminalEvent - CFileTerminalEvent::FireEvent failed. hr = %lx", hr)); } // // we addref'd these above, so release now // pCallInfo->Release(); pCall->Release(); return hr; } HRESULT CAddress::HandleMSPToneTerminalEvent( MSP_EVENT_INFO * pEvent ) { if (NULL == pEvent) { LOG((TL_ERROR, "HandleMSPToneTerminalEvent - pEvent is NULL")); return E_POINTER; } ITAddress *pAddress = dynamic_cast(this); if (pAddress == NULL) { LOG((TL_ERROR, "HandleMSPToneTerminalEvent - can't cast the address %p to ITAddress", this)); return E_UNEXPECTED; } CCall * pCall = NULL; ITCallInfo * pCallInfo = NULL; gpHandleHashTable->Lock(); HRESULT hr = E_FAIL; hr = gpHandleHashTable->Find( (ULONG_PTR)pEvent->hCall, (ULONG_PTR *)&pCall); if ( SUCCEEDED(hr) ) { LOG((TL_INFO, "HandleMSPToneTerminalEvent - Matched handle %X to Call object %p", pEvent->hCall, pCall )); pCall->AddRef(); gpHandleHashTable->Unlock(); hr = pCall->QueryInterface( IID_ITCallInfo, (void**) &pCallInfo ); } else // ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "HandleMSPToneTerminalEvent - Couldn't match handle %X to Call object ", pEvent->hCall)); gpHandleHashTable->Unlock(); return hr; } // // get tapi object and fire the event // hr = CToneTerminalEvent::FireEvent(GetTapi(), pCallInfo, pEvent->MSP_TONE_TERMINAL_EVENT_INFO.pToneTerminal, pEvent->MSP_TONE_TERMINAL_EVENT_INFO.hrErrorCode); if (FAILED(hr)) { LOG((TL_ERROR, "HandleMSPToneTerminalEvent - CFileTerminalEvent::FireEvent failed. hr = %lx", hr)); } // // we addref'd these above, so release now // pCallInfo->Release(); pCall->Release(); return hr; } HRESULT CAddress::HandleMSPFileTerminalEvent( MSP_EVENT_INFO * pEvent ) { if (NULL == pEvent) { LOG((TL_ERROR, "HandleMSPFileTerminalEvent - pEvent is NULL")); return E_POINTER; } ITAddress *pAddress = dynamic_cast(this); if (pAddress == NULL) { LOG((TL_ERROR, "HandleMSPFileTerminalEvent - can't cast the address %p to ITAddress", this)); return E_UNEXPECTED; } CCall * pCall = NULL; ITCallInfo * pCallInfo = NULL; gpHandleHashTable->Lock(); HRESULT hr = E_FAIL; hr = gpHandleHashTable->Find( (ULONG_PTR)pEvent->hCall, (ULONG_PTR *)&pCall); if ( SUCCEEDED(hr) ) { LOG((TL_INFO, "HandleMSPFileTerminalEvent - Matched handle %X to Call object %p", pEvent->hCall, pCall )); pCall->AddRef(); gpHandleHashTable->Unlock(); hr = pCall->QueryInterface( IID_ITCallInfo, (void**) &pCallInfo ); } else // ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "HandleMSPFileTerminalEvent - Couldn't match handle %X to Call object ", pEvent->hCall)); gpHandleHashTable->Unlock(); return hr; } // // get tapi object and fire the event // hr = CFileTerminalEvent::FireEvent(this, GetTapi(), pCallInfo, pEvent->MSP_FILE_TERMINAL_EVENT_INFO.TerminalMediaState, pEvent->MSP_FILE_TERMINAL_EVENT_INFO.ftecEventCause, pEvent->MSP_FILE_TERMINAL_EVENT_INFO.pParentFileTerminal, pEvent->MSP_FILE_TERMINAL_EVENT_INFO.pFileTrack, pEvent->MSP_FILE_TERMINAL_EVENT_INFO.hrErrorCode); if (FAILED(hr)) { LOG((TL_ERROR, "HandleMSPFileTerminalEvent - CFileTerminalEvent::FireEvent failed. hr = %lx", hr)); } // // we addref'd these above, so release now // pCallInfo->Release(); pCall->Release(); return hr; } HRESULT CAddress::HandleMSPPrivateEvent( MSP_EVENT_INFO * pEvent ) { ITAddress *pAddress = dynamic_cast(this); if (pAddress == NULL) { LOG((TL_ERROR, "HandleMSPPrivateEvent - can't cast the address %p to ITAddress", this)); return E_UNEXPECTED; } CCall * pCall = NULL; ITCallInfo * pCallInfo = NULL; HRESULT hr; gpHandleHashTable->Lock(); hr = gpHandleHashTable->Find( (ULONG_PTR)pEvent->hCall, (ULONG_PTR *)&pCall); if ( SUCCEEDED(hr) ) { LOG((TL_INFO, "HandleMSPPrivateEvent - Matched handle %X to Call object %p", pEvent->hCall, pCall )); pCall->AddRef(); gpHandleHashTable->Unlock(); hr = pCall->QueryInterface( IID_ITCallInfo, (void**) &pCallInfo ); } else // ( !SUCCEEDED(hr) ) { LOG((TL_ERROR, "HandleMSPPrivateEvent - Couldn't match handle %X to Call object ", pEvent->hCall)); gpHandleHashTable->Unlock(); return hr; } CPrivateEvent::FireEvent( GetTapi(), pCallInfo, pAddress, NULL, pEvent->MSP_PRIVATE_EVENT_INFO.pEvent, pEvent->MSP_PRIVATE_EVENT_INFO.lEventCode ); // // addref'd above // pCallInfo->Release(); pCall->Release(); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // ReleaseEvent // // releases any reference counts in the event from // the msp. // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= HRESULT CAddress::ReleaseEvent( MSP_EVENT_INFO * pEvent ) { LOG((TL_TRACE, "ReleaseEvent - enter")); switch ( pEvent->Event ) { case ME_ADDRESS_EVENT: if (NULL != pEvent->MSP_ADDRESS_EVENT_INFO.pTerminal) { (pEvent->MSP_ADDRESS_EVENT_INFO.pTerminal)->Release(); } break; case ME_CALL_EVENT: if (NULL != pEvent->MSP_CALL_EVENT_INFO.pTerminal) { (pEvent->MSP_CALL_EVENT_INFO.pTerminal)->Release(); } if (NULL != pEvent->MSP_CALL_EVENT_INFO.pStream) { (pEvent->MSP_CALL_EVENT_INFO.pStream)->Release(); } break; case ME_TSP_DATA: break; case ME_PRIVATE_EVENT: if ( NULL != pEvent->MSP_PRIVATE_EVENT_INFO.pEvent ) { (pEvent->MSP_PRIVATE_EVENT_INFO.pEvent)->Release(); } break; case ME_FILE_TERMINAL_EVENT: if( NULL != pEvent->MSP_FILE_TERMINAL_EVENT_INFO.pParentFileTerminal) { (pEvent->MSP_FILE_TERMINAL_EVENT_INFO.pParentFileTerminal)->Release(); pEvent->MSP_FILE_TERMINAL_EVENT_INFO.pParentFileTerminal = NULL; } if( NULL != pEvent->MSP_FILE_TERMINAL_EVENT_INFO.pFileTrack ) { (pEvent->MSP_FILE_TERMINAL_EVENT_INFO.pFileTrack)->Release(); pEvent->MSP_FILE_TERMINAL_EVENT_INFO.pFileTrack = NULL; } break; case ME_ASR_TERMINAL_EVENT: if( NULL != pEvent->MSP_ASR_TERMINAL_EVENT_INFO.pASRTerminal) { (pEvent->MSP_ASR_TERMINAL_EVENT_INFO.pASRTerminal)->Release(); } break; case ME_TTS_TERMINAL_EVENT: if( NULL != pEvent->MSP_TTS_TERMINAL_EVENT_INFO.pTTSTerminal) { (pEvent->MSP_TTS_TERMINAL_EVENT_INFO.pTTSTerminal)->Release(); } break; case ME_TONE_TERMINAL_EVENT: if( NULL != pEvent->MSP_TONE_TERMINAL_EVENT_INFO.pToneTerminal) { (pEvent->MSP_TONE_TERMINAL_EVENT_INFO.pToneTerminal)->Release(); } break; default: break; } LOG((TL_TRACE, "ReleaseEvent - finished")); return S_OK; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // HRESULT // CAddress::MSPEvent() // // gets an event buffer from the MSP // and calls the relevant event handler // // this is _only_ called from the asynceventsthread. this is // necessary for synchronization of events. // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= HRESULT CAddress::MSPEvent() { DWORD dwSize; MSP_EVENT_INFO * pEvent = NULL; HRESULT hr; // // Allocate an MSP event buffer -- best guess as to an appropriate // size. We need to free it before returning. // dwSize = sizeof (MSP_EVENT_INFO) + 500; pEvent = (MSP_EVENT_INFO *)ClientAlloc( dwSize ); if ( NULL == pEvent ) { LOG((TL_ERROR, "Alloc failed in MSP event")); return E_OUTOFMEMORY; } pEvent->dwSize = dwSize; // // Get pointer to msp address object. We need to release it before returning. // This must be done while the address object is locked. // Lock(); ITMSPAddress * pMSPAddress = GetMSPAddress(); Unlock(); while (TRUE) { // // Get an event from the event queue. Abort and clean up if // allocation fails. // do { hr = pMSPAddress->GetEvent( &dwSize, (LPBYTE)pEvent ); if ( hr == TAPI_E_NOTENOUGHMEMORY) { ClientFree( pEvent ); pEvent = (MSP_EVENT_INFO *)ClientAlloc( dwSize ); if ( NULL == pEvent ) { LOG((TL_ERROR, "Alloc failed in MSP event")); pMSPAddress->Release(); return E_OUTOFMEMORY; } pEvent->dwSize = dwSize; } } while ( hr == TAPI_E_NOTENOUGHMEMORY ); // // If there is nothing left in the MSP event queue, then stop the // outer while loop. // if ( !SUCCEEDED(hr) ) { break; } // // Call the relevant handler, and do not hold the address lock during // the call. // switch ( pEvent->Event ) { case ME_ADDRESS_EVENT: HandleMSPAddressEvent( pEvent ); break; case ME_CALL_EVENT: HandleMSPCallEvent( pEvent ); break; case ME_TSP_DATA: HandleSendTSPData( pEvent ); break; case ME_PRIVATE_EVENT: HandleMSPPrivateEvent( pEvent ); break; case ME_FILE_TERMINAL_EVENT: HandleMSPFileTerminalEvent( pEvent ); break; case ME_ASR_TERMINAL_EVENT: HandleMSPASRTerminalEvent( pEvent ); break; case ME_TTS_TERMINAL_EVENT: HandleMSPTTSTerminalEvent( pEvent ); break; case ME_TONE_TERMINAL_EVENT: HandleMSPToneTerminalEvent( pEvent ); break; default: break; } // // release any refcounts in the // event // ReleaseEvent( pEvent ); } // // We get here when there is nothing more to retrieve from the // MSP event queue. // pMSPAddress->Release(); ClientFree( pEvent ); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ITMSPAddress * CAddress::GetMSPAddress() { ITMSPAddress * pMSPAddress = NULL; if ( NULL != m_pMSPAggAddress ) { m_pMSPAggAddress->QueryInterface(IID_ITMSPAddress, (void**)&pMSPAddress); } return pMSPAddress; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CAddress::GetID( BSTR pDeviceClass, DWORD * pdwSize, BYTE ** ppDeviceID ) { HRESULT hr; PtrList::iterator iter; LPVARSTRING pVarString = NULL; if ( IsBadStringPtrW( pDeviceClass, -1 ) ) { LOG((TL_ERROR, "GetID - bad string")); return E_POINTER; } if ( TAPIIsBadWritePtr( pdwSize, sizeof(DWORD))) { LOG((TL_ERROR, "GetID - bad size")); return E_POINTER; } if ( TAPIIsBadWritePtr( ppDeviceID, sizeof(BYTE *) ) ) { LOG((TL_ERROR, "GetID - bad pointer")); return E_POINTER; } Lock(); if ( m_AddressLinesPtrList.size() > 0 ) { iter = m_AddressLinesPtrList.begin(); } else { Unlock(); return E_FAIL; } hr = LineGetID( ((AddressLineStruct *)*iter)->t3Line.hLine, m_dwAddressID, NULL, LINECALLSELECT_ADDRESS, &pVarString, pDeviceClass ); Unlock(); if ( SUCCEEDED(hr) ) { *ppDeviceID = (BYTE *)CoTaskMemAlloc( pVarString->dwUsedSize ); if ( *ppDeviceID != NULL ) { CopyMemory( *ppDeviceID, ((LPBYTE)pVarString)+pVarString->dwStringOffset, pVarString->dwStringSize ); *pdwSize = pVarString->dwStringSize; } else { hr = E_OUTOFMEMORY; } } if ( NULL != pVarString ) { ClientFree( pVarString ); } return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CAddress // Interface : ITLegacyAddressMediaControl // Method : GetDevConfig // // Get Device Config // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddress::GetDevConfig( BSTR pDeviceClass, DWORD * pdwSize, BYTE ** ppDeviceConfig ) { HRESULT hr; LPVARSTRING pVarString = NULL; LOG((TL_TRACE, "GetDevConfig - enter")); if ( IsBadStringPtrW( pDeviceClass, -1 ) ) { LOG((TL_ERROR, "GetDevConfig - bad DeviceClass string")); return E_POINTER; } if ( TAPIIsBadWritePtr( pdwSize, sizeof(DWORD))) { LOG((TL_ERROR, "GetDevConfig - bad size")); return E_POINTER; } if ( TAPIIsBadWritePtr( ppDeviceConfig, sizeof(BYTE*) ) ) { LOG((TL_ERROR, "GetDevConfig - bad buffer pointer")); return E_POINTER; } Lock(); hr = LineGetDevConfig(m_dwDeviceID, &pVarString, pDeviceClass ); Unlock(); if ( SUCCEEDED(hr) ) { *ppDeviceConfig = (BYTE *)CoTaskMemAlloc( pVarString->dwUsedSize ); if(*ppDeviceConfig != NULL) { CopyMemory( *ppDeviceConfig, ((LPBYTE)pVarString)+pVarString->dwStringOffset, pVarString->dwStringSize ); *pdwSize = pVarString->dwStringSize; } else { hr = E_OUTOFMEMORY; } } if ( NULL != pVarString ) { ClientFree( pVarString ); } LOG((TL_TRACE, hr, "GetDevConfig - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CAddress // Interface : ITLegacyAddressMediaControl // Method : SetDevConfig // // Set Device Config // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddress::SetDevConfig( BSTR pDeviceClass, DWORD dwSize, BYTE * pDeviceConfig ) { HRESULT hr = S_OK; LOG((TL_TRACE, "SetDevConfig - enter")); if ( IsBadStringPtrW( pDeviceClass, -1) ) { LOG((TL_ERROR, "SetDevConfig - bad string pointer")); return E_POINTER; } if (dwSize == 0) { LOG((TL_ERROR, "SetDevConfig - dwSize = 0")); return E_INVALIDARG; } if (IsBadReadPtr( pDeviceConfig, dwSize) ) { LOG((TL_ERROR, "SetDevConfig - bad pointer")); return E_POINTER; } Lock(); hr = lineSetDevConfigW(m_dwDeviceID, pDeviceConfig, dwSize, pDeviceClass ); Unlock(); LOG((TL_TRACE, hr, "SetDevConfig - exit")); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CAddress // Interface : ITLegacyAddressMediaControl2 // Method : ConfigDialog // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddress::ConfigDialog( HWND hwndOwner, BSTR pDeviceClass ) { HRESULT hr = S_OK; LOG((TL_TRACE, "ConfigDialog - enter")); if ( (pDeviceClass != NULL) && IsBadStringPtrW( pDeviceClass, -1) ) { LOG((TL_ERROR, "ConfigDialog - bad string pointer")); return E_POINTER; } Lock(); hr = LineConfigDialogW( m_dwDeviceID, hwndOwner, pDeviceClass ); Unlock(); LOG((TL_TRACE, hr, "ConfigDialog - exit")); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Class : CAddress // Interface : ITLegacyAddressMediaControl2 // Method : ConfigDialogEdit // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ STDMETHODIMP CAddress::ConfigDialogEdit( HWND hwndOwner, BSTR pDeviceClass, DWORD dwSizeIn, BYTE * pDeviceConfigIn, DWORD * pdwSizeOut, BYTE ** ppDeviceConfigOut ) { HRESULT hr = S_OK; LPVARSTRING pVarString = NULL; LOG((TL_TRACE, "ConfigDialogEdit - enter")); if ( (pDeviceClass != NULL) && IsBadStringPtrW( pDeviceClass, -1) ) { LOG((TL_ERROR, "ConfigDialogEdit - bad string pointer")); return E_POINTER; } if (dwSizeIn == 0) { LOG((TL_ERROR, "ConfigDialogEdit - dwSize = 0")); return E_INVALIDARG; } if (IsBadReadPtr( pDeviceConfigIn, dwSizeIn) ) { LOG((TL_ERROR, "ConfigDialogEdit - bad pointer")); return E_POINTER; } if ( TAPIIsBadWritePtr( pdwSizeOut, sizeof(DWORD))) { LOG((TL_ERROR, "ConfigDialogEdit - bad size")); return E_POINTER; } if ( TAPIIsBadWritePtr( ppDeviceConfigOut, sizeof(BYTE*) ) ) { LOG((TL_ERROR, "ConfigDialogEdit - bad buffer pointer")); return E_POINTER; } Lock(); hr = LineConfigDialogEditW( m_dwDeviceID, hwndOwner, pDeviceClass, pDeviceConfigIn, dwSizeIn, &pVarString ); Unlock(); if ( SUCCEEDED(hr) ) { *ppDeviceConfigOut = (BYTE *)CoTaskMemAlloc( pVarString->dwUsedSize ); if(*ppDeviceConfigOut != NULL) { CopyMemory( *ppDeviceConfigOut, ((LPBYTE)pVarString)+pVarString->dwStringOffset, pVarString->dwStringSize ); *pdwSizeOut = pVarString->dwStringSize; } else { hr = E_OUTOFMEMORY; } } if ( NULL != pVarString ) { ClientFree( pVarString ); } LOG((TL_TRACE, hr, "ConfigDialogEdit - exit")); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= HRESULT HandleLineCloseMessage( PASYNCEVENTMSG pParams ) { CAddress * pAddress; AddressLineStruct * pAddressLine; CTAPI * pTapi; ITAddress * pITAddress; LOG((TL_TRACE, "HandleLineCloseMessage - enter")); if ( !FindAddressObject( (HLINE)(pParams->hDevice), &pAddress ) ) { LOG((TL_TRACE, "HandleLineCloseMessage - FindAddressObject failed. exiting... ")); return S_OK; } pTapi = pAddress->GetTapi(); pAddress->QueryInterface( IID_ITAddress, (void **)&pITAddress ); // // get the lock so that the address line does not go away meanwhile // pAddress->Lock(); // // covert the 32bit address line handle (contained in pParams->OpenContext) // into a pointer value // pAddressLine = (AddressLineStruct *)GetHandleTableEntry(pParams->OpenContext); // // is this a good line anyway? // BOOL bValidLine = pAddress->IsValidAddressLine(pAddressLine); long lCallBackInstance = 0; // // if seems to be a good line, attempt to get callback instance from it. // if (bValidLine) { try { lCallBackInstance = pAddressLine->lCallbackInstance; } catch(...) { LOG((TL_ERROR, "HandleLineCloseMessage - exception getting callback instance from line struc")); _ASSERTE(FALSE); bValidLine = FALSE; } } pAddress->Unlock(); // // if good and known line, attempt to fire an event // if ( bValidLine && pTapi && pTapi->FindRegistration( (PVOID)pAddressLine ) ) { LOG((TL_TRACE, "HandleLineCloseMessage - found registration, firing event")); CTapiObjectEvent::FireEvent( pTapi, TE_ADDRESSCLOSE, pITAddress, lCallBackInstance, NULL ); } else { LOG((TL_TRACE, "HandleLineCloseMessage AddressLine %p not found. calling maybeclosealine", pAddressLine )); pAddress->MaybeCloseALine(&pAddressLine); } pITAddress->Release(); //FindAddressObject addrefs the address objct pAddress->Release(); LOG((TL_TRACE, "HandleLineCloseMessage - exit")); return S_OK; } ///////////////////////////////////////////////////////////////////////////// // IDispatch implementation // typedef IDispatchImpl, &IID_ITAddress2, &LIBID_TAPI3Lib> AddressType; typedef IDispatchImpl, &IID_ITAddressCapabilities, &LIBID_TAPI3Lib> AddressCapabilitiesType; typedef IDispatchImpl, &IID_ITMediaSupport, &LIBID_TAPI3Lib> MediaSupportType; typedef IDispatchImpl, &IID_ITAddressTranslation, &LIBID_TAPI3Lib> AddressTranslationType; typedef IDispatchImpl, &IID_ITLegacyAddressMediaControl2, &LIBID_TAPI3Lib> LegacyAddressMediaControlType; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // CAddress::GetIDsOfNames // // Overide if IDispatch method // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CAddress::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 = AddressType::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid); if (SUCCEEDED(hr)) { LOG((TL_INFO, "GetIDsOfNames - found %S on ITAddress", *rgszNames)); rgdispid[0] |= IDISPADDRESS; return hr; } // If not, then try the Address Capabilities interface hr = AddressCapabilitiesType::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid); if (SUCCEEDED(hr)) { LOG((TL_INFO, "GetIDsOfNames - found %S on ITAddressCapabilities", *rgszNames)); rgdispid[0] |= IDISPADDRESSCAPABILITIES; return hr; } // If not, then try the Media Support interface hr = MediaSupportType::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid); if (SUCCEEDED(hr)) { LOG((TL_INFO, "GetIDsOfNames - found %S on ITMediaSupport", *rgszNames)); rgdispid[0] |= IDISPMEDIASUPPORT; return hr; } // If not, then try the Address Translation interface hr = AddressTranslationType::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid); if (SUCCEEDED(hr)) { LOG((TL_INFO, "GetIDsOfNames - found %S on ITAddressTranslation", *rgszNames)); rgdispid[0] |= IDISPADDRESSTRANSLATION; return hr; } // If not, then try the Legacy Address Media Control interface hr = LegacyAddressMediaControlType::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid); if (SUCCEEDED(hr)) { LOG((TL_INFO, "GetIDsOfNames - found %S on ITLegacyAddressMediaControl", *rgszNames)); rgdispid[0] |= IDISPLEGACYADDRESSMEDIACONTROL; return hr; } // If not, then try the aggregated MSP Address object if (m_pMSPAggAddress != NULL) { IDispatch *pIDispatchMSPAggAddress; m_pMSPAggAddress->QueryInterface(IID_IDispatch, (void**)&pIDispatchMSPAggAddress); hr = pIDispatchMSPAggAddress->GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid); if (SUCCEEDED(hr)) { pIDispatchMSPAggAddress->Release(); LOG((TL_INFO, "GetIDsOfNames - found %S on our aggregated MSP Address", *rgszNames)); rgdispid[0] |= IDISPAGGREGATEDMSPADDRESSOBJ; return hr; } pIDispatchMSPAggAddress->Release(); } LOG((TL_INFO, "GetIDsOfNames - Didn't find %S on our iterfaces", *rgszNames)); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // CAddress::Invoke // // Overide if IDispatch method // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= STDMETHODIMP CAddress::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 IDISPADDRESS: { hr = AddressType::Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr ); break; } case IDISPADDRESSCAPABILITIES: { hr = AddressCapabilitiesType::Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr ); break; } case IDISPMEDIASUPPORT: { hr = MediaSupportType::Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr ); break; } case IDISPADDRESSTRANSLATION: { hr = AddressTranslationType::Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr ); break; } case IDISPLEGACYADDRESSMEDIACONTROL: { hr = LegacyAddressMediaControlType::Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr ); break; } case IDISPAGGREGATEDMSPADDRESSOBJ: { IDispatch *pIDispatchMSPAggAddress = NULL; if (m_pMSPAggAddress != NULL) { m_pMSPAggAddress->QueryInterface(IID_IDispatch, (void**)&pIDispatchMSPAggAddress); hr = pIDispatchMSPAggAddress->Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr ); pIDispatchMSPAggAddress->Release(); } break; } } // end switch (dwInterface) LOG((TL_TRACE, hr, "Invoke - exit" )); return hr; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= // // CAddress::IsValidAddressLine // // returns TRUE if the address line passed in is in the address line list // // This method is not thread safe -- all calls must be protected, unless // bAddRef argument is TRUE // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= BOOL CAddress::IsValidAddressLine(AddressLineStruct *pAddressLine, BOOL bAddref) { if (IsBadReadPtr(pAddressLine, sizeof(AddressLineStruct) ) ) { LOG((TL_WARN, "IsValidAddressLine - unreadeable memory at [%p]", pAddressLine)); return FALSE; } if (bAddref) { Lock(); } PtrList::iterator it = m_AddressLinesPtrList.begin(); PtrList::iterator end = m_AddressLinesPtrList.end(); // iterate through address line list until we find the line for ( ; it != end; it++ ) { if (pAddressLine == (AddressLineStruct *)(*it)) { if (bAddref) { // // addref the line and release the lock // try { pAddressLine->AddRef(); } catch(...) { // // this is a bug. debug. // LOG((TL_INFO, "IsValidAddressLine -- exception while addreffing the line")); _ASSERTE(FALSE); Unlock(); return FALSE; } Unlock(); } LOG((TL_INFO, "IsValidAddressLine returning TRUE")); return TRUE; } } if (bAddref) { Unlock(); } LOG((TL_INFO, "IsValidAddressLine returning FALSE")); return FALSE; } ///////////////////////////////////////////////////////////// // // implementing method from CObjectSafeImpl // // check the aggregated objects to see if they support the interface requested. // if they do, return the non-delegating IUnknown of the object that supports // the interface. // HRESULT CAddress::QIOnAggregates(REFIID riid, IUnknown **ppNonDelegatingUnknown) { // // argument check // if ( TAPIIsBadWritePtr(ppNonDelegatingUnknown, sizeof(IUnknown*)) ) { return E_POINTER; } // // if we fail, at least return consistent values // *ppNonDelegatingUnknown = NULL; // // see if m_pMSPAggAddress or private support the interface riid // HRESULT hr = E_FAIL; Lock(); if (m_pMSPAggAddress) { // // does m_pMSPAggAddress expose this interface? // IUnknown *pUnk = NULL; hr = m_pMSPAggAddress->QueryInterface(riid, (void**)&pUnk); if (SUCCEEDED(hr)) { pUnk->Release(); pUnk = NULL; // // return the mspcall's non-delegating unknown // *ppNonDelegatingUnknown = m_pMSPAggAddress; (*ppNonDelegatingUnknown)->AddRef(); } } if ( FAILED(hr) && m_pPrivate ) { // // bad luck with m_pMSPAggAddress? still have a chance with private // IUnknown *pUnk = NULL; hr = m_pPrivate->QueryInterface(riid, (void**)&pUnk); if (SUCCEEDED(hr)) { pUnk->Release(); pUnk = NULL; *ppNonDelegatingUnknown = m_pPrivate; (*ppNonDelegatingUnknown)->AddRef(); } } Unlock(); return hr; } // // Event filtering methods // /*++ SetEventFilterMask Is called by TAPI object to set the event filter mask to each address The caller method is CTAPI::SetEventFilterToAddresses() dwEventFilterMask is the TAPI event filter mask --*/ HRESULT CAddress::SetEventFilterMask( DWORD dwEventFilterMask ) { LOG((TL_TRACE, "SetEventFilterMask - enter. dwEventFilterMask[%lx]", dwEventFilterMask )); // // Set the event mask for all TAPI events // // TE_ADDRESS SetSubEventFlag( TE_ADDRESS, CEventMasks::EM_ALLSUBEVENTS, (dwEventFilterMask & TE_ADDRESS) ? TRUE : FALSE); // TE_CALLHUB SetSubEventFlag( TE_CALLHUB, CEventMasks::EM_ALLSUBEVENTS, (dwEventFilterMask & TE_CALLHUB) ? TRUE : FALSE); // TE_CALLINFOCHANGE SetSubEventFlag( TE_CALLINFOCHANGE, CEventMasks::EM_ALLSUBEVENTS, (dwEventFilterMask & TE_CALLINFOCHANGE) ? TRUE : FALSE); // TE_CALLMEDIA SetSubEventFlag( TE_CALLMEDIA, CEventMasks::EM_ALLSUBEVENTS, (dwEventFilterMask & TE_CALLMEDIA) ? TRUE : FALSE); // TE_CALLNOTIFICATION SetSubEventFlag( TE_CALLNOTIFICATION, CEventMasks::EM_ALLSUBEVENTS, (dwEventFilterMask & TE_CALLNOTIFICATION) ? TRUE : FALSE); // TE_CALLSTATE SetSubEventFlag( TE_CALLSTATE, CEventMasks::EM_ALLSUBEVENTS, (dwEventFilterMask & TE_CALLSTATE) ? TRUE : FALSE); // TE_FILETERMINAL SetSubEventFlag( TE_FILETERMINAL, CEventMasks::EM_ALLSUBEVENTS, (dwEventFilterMask & TE_FILETERMINAL) ? TRUE : FALSE); // TE_PRIVATE SetSubEventFlag( TE_PRIVATE, CEventMasks::EM_ALLSUBEVENTS, (dwEventFilterMask & TE_PRIVATE) ? TRUE : FALSE); // TE_QOSEVENT SetSubEventFlag( TE_QOSEVENT, CEventMasks::EM_ALLSUBEVENTS, (dwEventFilterMask & TE_QOSEVENT) ? TRUE : FALSE); // TE_ADDRESSDEVSPECIFIC SetSubEventFlag( TE_ADDRESSDEVSPECIFIC, CEventMasks::EM_ALLSUBEVENTS, (dwEventFilterMask & TE_ADDRESSDEVSPECIFIC) ? TRUE : FALSE); // TE_PHONEDEVSPECIFIC SetSubEventFlag( TE_PHONEDEVSPECIFIC, CEventMasks::EM_ALLSUBEVENTS, (dwEventFilterMask & TE_PHONEDEVSPECIFIC) ? TRUE : FALSE); LOG((TL_TRACE, "SetEventFilterMask exit S_OK")); return S_OK; } /*++ SetSubEventFlag Sets in m_EventFilterMasks array the bitflag for an subevent Is called by CAddress::SetEventFilterMask --*/ HRESULT CAddress::SetSubEventFlag( TAPI_EVENT TapiEvent, DWORD dwSubEvent, BOOL bEnable ) { LOG((TL_TRACE, "SetSubEventFlag - enter. event [%lx] subevent[%lx] enable?[%d]", TapiEvent, dwSubEvent, bEnable )); HRESULT hr = S_OK; // // Set the mask for the event // hr = m_EventMasks.SetSubEventFlag( TapiEvent, dwSubEvent, bEnable); if( SUCCEEDED(hr) ) { hr = SetSubEventFlagToCalls( TapiEvent, dwSubEvent, bEnable ); } LOG((TL_TRACE, "SetSubEventFlag exit 0x%08x", hr)); return hr; } /*++ GetSubEventFlag It is calle by get_EventFilter() method --*/ HRESULT CAddress::GetSubEventFlag( TAPI_EVENT TapiEvent, DWORD dwSubEvent, BOOL* pEnable ) { LOG((TL_TRACE, "GetSubEventFlag enter" )); HRESULT hr = E_FAIL; // // Get the subevent falg // hr = m_EventMasks.GetSubEventFlag( TapiEvent, dwSubEvent, pEnable ); LOG((TL_TRACE, "GetSubEventFlag exit 0x%08x", hr)); return hr; } /*++ SetSubEventFlagToCalls Sets the flags to all calls Is called by SetSubEventFlag() method --*/ HRESULT CAddress::SetSubEventFlagToCalls( TAPI_EVENT TapiEvent, DWORD dwSubEvent, BOOL bEnable ) { LOG((TL_TRACE, "SetSubEventFlagToCalls enter" )); HRESULT hr = S_OK; // // Apply the sub event filter mask to all the calls on this address // for (int nCall = 0; nCall < m_CallArray.GetSize() ; nCall++ ) { CCall * pCall = NULL; pCall = dynamic_cast(m_CallArray[nCall]); if ( NULL != pCall ) { hr = pCall->SetSubEventFlag( TapiEvent, dwSubEvent, bEnable ); if( FAILED(hr) ) { break; } } } LOG((TL_TRACE, "SetSubEventFlagToCalls exit 0x%08x", hr)); return hr; } /*++ GetSubEventsMask Is called by SetSubEventFlag to get the sub events mask for a specific TAPI_EVENT Assumed is called into a Lock statement --*/ DWORD CAddress::GetSubEventsMask( IN TAPI_EVENT TapiEvent ) { LOG((TL_TRACE, "GetSubEventsMask - enter")); DWORD dwSubEventFlag = m_EventMasks.GetSubEventMask( TapiEvent ); LOG((TL_TRACE, "GetSubEventsMask - exit %ld", dwSubEventFlag)); return dwSubEventFlag; } /*++ GetEventMasks It is called by CCall::Initialize() --*/ HRESULT CAddress::GetEventMasks( OUT CEventMasks* pEventMasks ) { LOG((TL_TRACE, "GetEventMasks - enter")); m_EventMasks.CopyEventMasks( pEventMasks ); LOG((TL_TRACE, "GetEventMasks - exit S_OK")); return S_OK; } //////////////////////////////////////////// // // RegisterNotificationCookie // // adds the specified cookie to the list of cookies on this address // HRESULT CAddress::RegisterNotificationCookie(long lCookie) { HRESULT hr = S_OK; LOG((TL_INFO, "RegisterNotificationCookie - adding cookie %lx to m_NotificationCookies list", lCookie )); Lock(); try { m_NotificationCookies.push_back(lCookie); } catch(...) { LOG((TL_ERROR, "RegisterNotificationCookie - failed to add a cookie to m_NotificationCookies list - alloc failure" )); hr = E_OUTOFMEMORY; } Unlock(); return hr; } //////////////////////////////////////////// // // RemoveNotificationCookie // // removes the specified cookie from this address's cookies // HRESULT CAddress::RemoveNotificationCookie(long lCookie) { HRESULT hr = S_OK; LOG((TL_INFO, "RemoveNotificationCookie - removing cookie %lx from m_NotificationCookies list", lCookie )); Lock(); m_NotificationCookies.remove(lCookie); Unlock(); return hr; } //////////////////////////////////////////// // // UnregisterAllCookies // // removes all cookies from this address's cookie list // // for each valid cookie, call RemoveCallNotification // void CAddress::UnregisterAllCookies() { LOG((TL_TRACE, "UnregisterAllCookies entering. this[%p]", this)); Lock(); LongList::iterator it = m_NotificationCookies.begin(); LongList::iterator end = m_NotificationCookies.end(); // // if there are any cookies, remove the corresponding registeritems // from the handlehashtable // // also, unregister call notification for these cookies, to make sure // everything is cleaned up (and in particular that lineCloseMSPInstance // gets called if needed so the tsp gets notified that the msp is going // away // for ( ; it != end; it++ ) { long lCookie = (long)(*it); LOG((TL_INFO, "UnregisterAllCookies removing handle %lx", lCookie)); // // get register item, so we can unregister call notifications with it. // REGISTERITEM *pRegisterItem = (REGISTERITEM*) GetHandleTableEntry(lCookie); // // remove the entry from the handle table // RemoveHandleFromHashTable(lCookie); // // if we did not get a good registeritem that corresponds to this cookie, // go on to the next cookie // if ( (NULL == pRegisterItem) || IsBadReadPtr(pRegisterItem, sizeof(REGISTERITEM)) ) { LOG((TL_INFO, "UnregisterAllCookies - no corresponfing registeritem for cookie 0x%lx", lCookie)); continue; } // // if the register item is not RA_ADDRESS, ignore it and go on to // the next cookie. // if (RA_ADDRESS != pRegisterItem->dwType) { LOG((TL_INFO, "UnregisterAllCookies - cookie 0x%lx is of type 0x%lx, not RA_ADDRESS", lCookie, pRegisterItem->dwType)); continue; } // // remove call notification for this cookie, since the app did not // do this. best effort -- ignore the error code. // LOG((TL_INFO, "UnregisterAllCookies - removing call notification for cookie 0x%lx", lCookie)); RemoveCallNotification(pRegisterItem->pRegister); } // // clear cookie list // m_NotificationCookies.clear(); Unlock(); LOG((TL_TRACE, "UnregisterAllCookies exiting")); } /////////////////////////////////////////////////////////////////////////////// // // CAddress::AddressOnTapiShutdown // // this function is called by the owner tapi object when it is going away. // // we then propagate tapi shutdown notification to each call, so the calls // can do their clean up // void CAddress::AddressOnTapiShutdown() { LOG((TL_TRACE, "AddressOnTapiShutdown - enter")); // // protect access to m_CallArray // Lock(); // // tell each call to clean up // int nCalls = m_CallArray.GetSize(); for (int i = 0; i < nCalls; i++) { ITCallInfo *pCallInfo = m_CallArray[i]; try { // // get a pointer to the call object // CCall *pCallObject = dynamic_cast(pCallInfo); if (NULL == pCallObject) { // // the pointer is not pointing to a call object. this is odd // and is worth debugging // LOG((TL_ERROR, "AddressOnTapiShutdown - invalid call pointer[%p] in the call array", pCallInfo)); _ASSERTE(FALSE); } else { // // tell the call that it's time to go // pCallObject->CallOnTapiShutdown(); } } catch(...) { // // not only is the pointer not pointing to a call object, but it is // also pointing to memory that is not readable. how did this happen? // LOG((TL_ERROR, "AddressOnTapiShutdown - unreadable call pointer[%p] in the call array", pCallInfo)); _ASSERTE(FALSE); } } // // set the flag so no new calls are created following this // m_bTapiSignaledShutdown = TRUE; // // unregister the msp wait event in the thread pool. we don't want to get // any callbacks after tapi has shut down // if ( NULL != m_hWaitEvent ) { LOG((TL_TRACE, "AddressOnTapiShutdown - unregistering the MSPEventCallback callback")); UnregisterWaitEx( m_hWaitEvent, INVALID_HANDLE_VALUE); m_hWaitEvent = NULL; } Unlock(); LOG((TL_TRACE, "AddressOnTapiShutdown - finish")); }