mirror of https://github.com/tongzx/nt5src
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
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"));
|
|
}
|
|
|