Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

13658 lines
336 KiB

/*++
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<CTAPI *>(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<CCall> * pCall;
hr = CComObject<CCall>::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<ITCallInfo *>(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 <ignored> <ignored>
// 2 Stop streaming <ignored> <ignored>
// 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<CPhoneMSP> * 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<CPhoneMSP>(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<CPhoneMSP *>(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<CCall *>(pCall);
if ( NULL == pCCall )
{
LOG((TL_ERROR, "Forward - invalid call"));
return E_POINTER;
}
}
pFI = dynamic_cast<CForwardInfo *>(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<CTapiBstrCollection> * pCollection;
HRESULT hr = CComObject<CTapiBstrCollection>::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<IEnumBstr, &__uuidof(IEnumBstr), BSTR, _CopyBSTR> CEnumerator;
HRESULT hr;
CComObject<CEnumerator> *pEnum = NULL;
hr = CComObject<CEnumerator>::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<CAddressEvent> * 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<CAddressEvent>::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<ITAddress *>(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<CAddressDevSpecificEvent> *pEventObject = NULL;
HRESULT hr = CComObject<CAddressDevSpecificEvent>::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<IEnumLocation, ITLocationInfo, &IID_IEnumLocation> > * pEnum;
hr = CComObject< CTapiEnum<IEnumLocation, ITLocationInfo, &IID_IEnumLocation> > ::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<CLocationInfo> * pLocationInfo;
CComObject<CLocationInfo>::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<IEnumCallingCard, ITCallingCard, &IID_IEnumCallingCard> > * pEnum;
hr = CComObject< CTapiEnum<IEnumCallingCard, ITCallingCard, &IID_IEnumCallingCard> > ::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<CCallingCard> * pCallingCard;
CComObject<CCallingCard>::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<CPhone *>(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;
hr = CComObject< CTapiEnum< IEnumPhone, ITPhone, &IID_IEnumPhone > >
::CreateInstance( &p );
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<CPhone *>(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<CCall*>(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<CAddress*>(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<CTAPI *>(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<ITAddress *>(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<ITAddress *>(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<ITAddress *>(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<ITAddress *>(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<ITAddress *>(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->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<ITAddress2Vtbl<CAddress>, &IID_ITAddress2, &LIBID_TAPI3Lib> AddressType;
typedef IDispatchImpl<ITAddressCapabilitiesVtbl<CAddress>, &IID_ITAddressCapabilities, &LIBID_TAPI3Lib> AddressCapabilitiesType;
typedef IDispatchImpl<ITMediaSupportVtbl<CAddress>, &IID_ITMediaSupport, &LIBID_TAPI3Lib> MediaSupportType;
typedef IDispatchImpl<ITAddressTranslationVtbl<CAddress>, &IID_ITAddressTranslation, &LIBID_TAPI3Lib> AddressTranslationType;
typedef IDispatchImpl<ITLegacyAddressMediaControl2Vtbl<CAddress>, &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<CCall *>(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<CCall *>(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"));
}