661 lines
14 KiB
C++
661 lines
14 KiB
C++
// File: imanager.cpp
|
|
|
|
#include "precomp.h"
|
|
|
|
extern "C"
|
|
{
|
|
#include "t120.h"
|
|
}
|
|
#include <version.h>
|
|
#include "icall.h"
|
|
#include "icall_in.h"
|
|
#include "imanager.h"
|
|
#include <objbase.h>
|
|
|
|
#include <initguid.h>
|
|
|
|
static HRESULT OnNotifyConferenceCreated(IUnknown *pManagerNotify, PVOID pv, REFIID riid);
|
|
static HRESULT OnNotifyCallCreated(IUnknown *pManagerNotify, PVOID pv, REFIID riid);
|
|
|
|
|
|
|
|
INodeController* g_pNodeController = NULL;
|
|
|
|
|
|
COprahNCUI *COprahNCUI::m_pOprahNCUI = NULL;
|
|
|
|
static const IID * g_apiidCP_Manager[] =
|
|
{
|
|
{&IID_INmManagerNotify}
|
|
};
|
|
|
|
COprahNCUI::COprahNCUI(void) :
|
|
m_cRef(1),
|
|
CConnectionPointContainer(g_apiidCP_Manager, ARRAY_ELEMENTS(g_apiidCP_Manager)),
|
|
m_pOutgoingCallManager(NULL),
|
|
m_pIncomingCallManager(NULL),
|
|
m_pConfObject(NULL),
|
|
m_bstrUserName(NULL)
|
|
{
|
|
DebugEntry(COprahNCUI::COprahNCUI);
|
|
|
|
m_pOprahNCUI = this;
|
|
|
|
DebugExitVOID(COprahNCUI::COprahNCUI);
|
|
}
|
|
|
|
|
|
COprahNCUI::~COprahNCUI()
|
|
{
|
|
DebugEntry(COprahNCUI::COprahNCUI);
|
|
|
|
if (m_pIncomingCallManager)
|
|
{
|
|
delete m_pIncomingCallManager;
|
|
m_pIncomingCallManager = NULL;
|
|
}
|
|
|
|
if (m_pOutgoingCallManager)
|
|
{
|
|
delete m_pOutgoingCallManager;
|
|
m_pOutgoingCallManager = NULL;
|
|
}
|
|
|
|
if (m_pConfObject)
|
|
{
|
|
m_pConfObject->Release();
|
|
m_pConfObject = NULL;
|
|
}
|
|
|
|
// cleanup the node controller:
|
|
if (g_pNodeController)
|
|
{
|
|
g_pNodeController->ReleaseInterface();
|
|
g_pNodeController = NULL;
|
|
}
|
|
|
|
if (m_bstrUserName)
|
|
{
|
|
SysFreeString(m_bstrUserName);
|
|
m_bstrUserName = NULL;
|
|
}
|
|
|
|
m_pOprahNCUI = NULL;
|
|
|
|
DebugExitVOID(COprahNCUI::~COprahNCUI);
|
|
}
|
|
|
|
|
|
UINT COprahNCUI::GetOutgoingCallCount()
|
|
{
|
|
if (m_pOutgoingCallManager)
|
|
{
|
|
return m_pOutgoingCallManager->GetCallCount();
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
VOID COprahNCUI::OnOutgoingCallCreated(INmCall* pCall)
|
|
{
|
|
// notify the UI about this outgoing call
|
|
NotifySink(pCall, OnNotifyCallCreated);
|
|
|
|
if (m_pConfObject && !m_pConfObject->IsConferenceCreated())
|
|
{
|
|
m_pConfObject->OnConferenceCreated();
|
|
NotifySink((INmConference*) m_pConfObject, OnNotifyConferenceCreated);
|
|
}
|
|
}
|
|
|
|
VOID COprahNCUI::OnOutgoingCallCanceled(COutgoingCall* pCall)
|
|
{
|
|
if (m_pOutgoingCallManager)
|
|
{
|
|
m_pOutgoingCallManager->RemoveFromList(pCall);
|
|
}
|
|
}
|
|
|
|
VOID COprahNCUI::OnIncomingCallAccepted()
|
|
{
|
|
if (m_pConfObject && !m_pConfObject->IsConferenceCreated())
|
|
{
|
|
m_pConfObject->OnConferenceCreated();
|
|
NotifySink((INmConference*) m_pConfObject, OnNotifyConferenceCreated);
|
|
}
|
|
}
|
|
|
|
VOID COprahNCUI::OnIncomingCallCreated(INmCall* pCall)
|
|
{
|
|
NotifySink(pCall, OnNotifyCallCreated);
|
|
}
|
|
|
|
VOID COprahNCUI::CancelCalls()
|
|
{
|
|
if (m_pOutgoingCallManager)
|
|
{
|
|
m_pOutgoingCallManager->CancelCalls();
|
|
}
|
|
|
|
if (m_pIncomingCallManager)
|
|
{
|
|
m_pIncomingCallManager->CancelCalls();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
ULONG COprahNCUI::GetAuthenticatedName(PBYTE * ppb)
|
|
{
|
|
// Buffer created here should be freed by caller.
|
|
|
|
ULONG cb;
|
|
|
|
if (::T120_GetSecurityInfoFromGCCID(0,NULL,&cb)) {
|
|
(*ppb) = new BYTE[cb];
|
|
if ((*ppb) != NULL) {
|
|
::T120_GetSecurityInfoFromGCCID(0,*ppb,&cb);
|
|
return cb;
|
|
}
|
|
}
|
|
(* ppb) = NULL;
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
HRESULT COprahNCUI::OnIncomingInviteRequest(CONF_HANDLE hConference,
|
|
PCWSTR pcwszNodeName,
|
|
BOOL fSecure)
|
|
{
|
|
DebugEntry(COprahNCUI::OnIncomingInviteRequest);
|
|
|
|
if (!m_pConfObject)
|
|
{
|
|
ERROR_OUT(("No m_pConfObject"));
|
|
return E_FAIL;
|
|
}
|
|
|
|
if (!m_pConfObject->OnT120Invite(hConference, fSecure))
|
|
{
|
|
// Respond negatively - already in a call
|
|
TRACE_OUT(("Rejecting invite - already in a call"));
|
|
ASSERT(g_pNodeController);
|
|
ASSERT(hConference);
|
|
hConference->InviteResponse(FALSE);
|
|
}
|
|
else if (m_pIncomingCallManager)
|
|
{
|
|
m_pIncomingCallManager->OnIncomingT120Call( this,
|
|
TRUE,
|
|
hConference,
|
|
pcwszNodeName,
|
|
fSecure);
|
|
|
|
//
|
|
// This will simply notify the UI about the call state.
|
|
//
|
|
m_pConfObject->SetConfSecurity(fSecure);
|
|
}
|
|
|
|
DebugExitHRESULT(COprahNCUI::OnIncomingInviteRequest, S_OK);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT COprahNCUI::OnIncomingJoinRequest( CONF_HANDLE hConference,
|
|
PCWSTR pcwszNodeName)
|
|
{
|
|
DebugEntry(COprahNCUI::OnIncomingJoinRequest);
|
|
|
|
if (m_pIncomingCallManager)
|
|
{
|
|
// shouldn't we be checking for an active conference before accepting a join
|
|
// or will T120 not present this
|
|
|
|
m_pIncomingCallManager->OnIncomingT120Call( this,
|
|
FALSE,
|
|
hConference,
|
|
pcwszNodeName,
|
|
m_pConfObject->IsConfObjSecure());
|
|
}
|
|
|
|
DebugExitHRESULT(COprahNCUI::OnIncomingJoinRequest, S_OK);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT COprahNCUI::OnConferenceStarted(CONF_HANDLE hConference, HRESULT hResult)
|
|
{
|
|
DebugEntry(COprahNCUI::OnConferenceStarted);
|
|
|
|
if (!m_pConfObject)
|
|
{
|
|
ERROR_OUT(("OnConferenceStarted - no m_pConfObject"));
|
|
return E_FAIL;
|
|
}
|
|
|
|
if (m_pConfObject->GetConfHandle() == hConference)
|
|
{
|
|
m_pConfObject->OnConferenceStarted(hConference, hResult);
|
|
|
|
m_pOutgoingCallManager->OnConferenceStarted(hConference, hResult);
|
|
}
|
|
|
|
DebugExitHRESULT(COprahNCUI::OnConferenceStarted, S_OK);
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT COprahNCUI::OnQueryRemoteResult(PVOID pvCallerContext,
|
|
HRESULT hResult,
|
|
BOOL fMCU,
|
|
PWSTR* ppwszConferenceNames,
|
|
PWSTR* ppwszConfDescriptors)
|
|
{
|
|
DebugEntry(COprahNCUI::OnQueryRemoteResult);
|
|
|
|
if (NO_ERROR == hResult)
|
|
{
|
|
TRACE_OUT(("COprahNCUI: OnQueryRemoteResult Success!"));
|
|
}
|
|
else
|
|
{
|
|
TRACE_OUT(("COprahNCUI: OnQueryRemoteResult Failure!"));
|
|
}
|
|
|
|
if (m_pOutgoingCallManager)
|
|
{
|
|
m_pOutgoingCallManager->OnQueryRemoteResult(pvCallerContext,
|
|
hResult,
|
|
fMCU,
|
|
ppwszConferenceNames,
|
|
ppwszConfDescriptors);
|
|
}
|
|
|
|
DebugExitHRESULT(COprahNCUI::OnQueryRemoteResult, S_OK);
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT COprahNCUI::OnInviteResult( CONF_HANDLE hConference,
|
|
REQUEST_HANDLE hRequest,
|
|
UINT uNodeID,
|
|
HRESULT hResult)
|
|
{
|
|
DebugEntry(COprahNCUI::OnInviteResult);
|
|
|
|
if (!m_pConfObject)
|
|
{
|
|
ERROR_OUT(("OnInviteResult - no m_pConfObject"));
|
|
return E_FAIL;
|
|
}
|
|
|
|
|
|
if (hConference == m_pConfObject->GetConfHandle())
|
|
{
|
|
if (m_pOutgoingCallManager)
|
|
{
|
|
m_pOutgoingCallManager->OnInviteResult( hConference,
|
|
hRequest,
|
|
uNodeID,
|
|
hResult);
|
|
}
|
|
}
|
|
|
|
DebugExitHRESULT(COprahNCUI::OnInviteResult, S_OK);
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT COprahNCUI::OnConferenceEnded(CONF_HANDLE hConference)
|
|
{
|
|
DebugEntry(COprahNCUI::OnConferenceEnded);
|
|
|
|
if (m_pConfObject && (hConference == m_pConfObject->GetConfHandle()))
|
|
{
|
|
m_pConfObject->OnConferenceEnded();
|
|
|
|
if (m_pOutgoingCallManager)
|
|
{
|
|
m_pOutgoingCallManager->OnConferenceEnded(hConference);
|
|
}
|
|
|
|
if (m_pIncomingCallManager)
|
|
{
|
|
m_pIncomingCallManager->OnT120ConferenceEnded(hConference);
|
|
}
|
|
}
|
|
|
|
DebugExitHRESULT(COprahNCUI::OnConferenceEnded, S_OK);
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT COprahNCUI::OnRosterChanged(CONF_HANDLE hConf, PNC_ROSTER pRoster)
|
|
{
|
|
TRACE_OUT(("COprahNCUI::OnRosterChanged"));
|
|
|
|
if (!m_pConfObject)
|
|
{
|
|
ERROR_OUT(("OnRosterChanged - no m_pConfObject"));
|
|
return E_FAIL;
|
|
}
|
|
|
|
if (hConf == m_pConfObject->GetConfHandle())
|
|
{
|
|
m_pConfObject->OnRosterChanged(pRoster);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
ULONG STDMETHODCALLTYPE COprahNCUI::AddRef(void)
|
|
{
|
|
++m_cRef;
|
|
return m_cRef;
|
|
}
|
|
|
|
ULONG STDMETHODCALLTYPE COprahNCUI::Release(void)
|
|
{
|
|
if (m_cRef > 0)
|
|
{
|
|
--m_cRef;
|
|
}
|
|
|
|
if (!m_cRef)
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return m_cRef;
|
|
}
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE COprahNCUI::QueryInterface(REFIID riid, PVOID *ppv)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if ((riid == IID_INmManager) || (riid == IID_IUnknown))
|
|
{
|
|
*ppv = (INmManager *)this;
|
|
TRACE_OUT(("COprahNCUI::QueryInterface()"));
|
|
}
|
|
else if (riid == IID_IConnectionPointContainer)
|
|
{
|
|
*ppv = (IConnectionPointContainer *) this;
|
|
TRACE_OUT(("COprahNCUI::QueryInterface(): Returning IConnectionPointContainer."));
|
|
}
|
|
else
|
|
{
|
|
hr = E_NOINTERFACE;
|
|
*ppv = NULL;
|
|
TRACE_OUT(("COprahNCUI::QueryInterface(): Called on unknown interface."));
|
|
}
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
AddRef();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/* I N I T I A L I Z E */
|
|
/*-------------------------------------------------------------------------
|
|
%%Function: Initialize
|
|
|
|
REVIEW: What should the return value be if any of these parts fail
|
|
to initialize or load?
|
|
-------------------------------------------------------------------------*/
|
|
HRESULT COprahNCUI::Initialize
|
|
(
|
|
BSTR szName,
|
|
DWORD_PTR dwCredentials,
|
|
DWORD port,
|
|
DWORD flags
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
ASSERT(!m_bstrUserName);
|
|
SysFreeString(m_bstrUserName);
|
|
m_bstrUserName = SysAllocString(szName);
|
|
|
|
m_pOutgoingCallManager = new COutgoingCallManager;
|
|
if (!m_pOutgoingCallManager)
|
|
{
|
|
ERROR_OUT(("COprahNCUI::Initialize -- failed to create outgoing call mgr"));
|
|
return(E_OUTOFMEMORY);
|
|
}
|
|
|
|
m_pIncomingCallManager = new CIncomingCallManager;
|
|
if (!m_pIncomingCallManager)
|
|
{
|
|
ERROR_OUT(("COprahNCUI::Initialize -- failed to create incoming call mgr"));
|
|
return(E_OUTOFMEMORY);
|
|
}
|
|
|
|
// The lifetime of this object is up to the reference counting crap
|
|
m_pConfObject = new CConfObject;
|
|
if (!m_pConfObject)
|
|
{
|
|
ERROR_OUT(("COprahNCUI::Initialize -- failed to create conf object"));
|
|
return(E_OUTOFMEMORY);
|
|
}
|
|
|
|
m_pConfObject->Init();
|
|
|
|
//
|
|
// Create the node controller
|
|
//
|
|
ASSERT(port == DEFAULT_LISTEN_PORT);
|
|
hr = ::T120_CreateNodeController(&g_pNodeController, this, szName,
|
|
dwCredentials, flags);
|
|
if (FAILED(hr))
|
|
{
|
|
ERROR_OUT(("T120_CreateNodeController() failed!"));
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
HRESULT COprahNCUI::Call
|
|
(
|
|
INmCall **ppCall,
|
|
DWORD dwFlags,
|
|
NM_ADDR_TYPE addrType,
|
|
BSTR bstrAddr,
|
|
BSTR bstrConference,
|
|
BSTR bstrPassword
|
|
)
|
|
{
|
|
BSTR bstrRealAddr;
|
|
|
|
DebugEntry(COprahNCUI::Call);
|
|
|
|
if (addrType == NM_ADDR_MACHINENAME)
|
|
{
|
|
//
|
|
// Convert to IP Address
|
|
//
|
|
int cch;
|
|
TCHAR * pszOemName;
|
|
ULONG ulIpAddress;
|
|
HOSTENT * pHostEnt;
|
|
WCHAR * pwszName;
|
|
|
|
cch = SysStringLen(bstrAddr);
|
|
pszOemName = new TCHAR[cch + 1];
|
|
|
|
if (!pszOemName)
|
|
{
|
|
ERROR_OUT(("Couldn't get OEM Name"));
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, bstrAddr, -1, pszOemName, cch+1, NULL,
|
|
NULL);
|
|
|
|
CharUpper(pszOemName);
|
|
CharToOem(pszOemName, pszOemName);
|
|
|
|
pHostEnt = gethostbyname(pszOemName);
|
|
if (!pHostEnt ||
|
|
(pHostEnt->h_addrtype != AF_INET) ||
|
|
(pHostEnt->h_length != sizeof(ULONG)) ||
|
|
(pHostEnt->h_addr_list[0] == NULL))
|
|
{
|
|
ulIpAddress = 0;
|
|
WARNING_OUT(("gethostbyname failed"));
|
|
}
|
|
else
|
|
{
|
|
ulIpAddress = *reinterpret_cast<ULONG *>(pHostEnt->h_addr_list[0]);
|
|
}
|
|
|
|
delete pszOemName;
|
|
|
|
if (!ulIpAddress)
|
|
{
|
|
ERROR_OUT(("gethostbyname failed, returning"));
|
|
return E_FAIL;
|
|
}
|
|
|
|
pszOemName = inet_ntoa(*reinterpret_cast<in_addr *>(&ulIpAddress));
|
|
cch = lstrlen(pszOemName);
|
|
|
|
pwszName = new WCHAR[cch + 1];
|
|
if (!pwszName)
|
|
{
|
|
ERROR_OUT(("Can't alloc OLE string"));
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, pszOemName, -1, pwszName, cch+1);
|
|
bstrRealAddr = SysAllocString(pwszName);
|
|
|
|
delete pwszName;
|
|
}
|
|
else if (addrType == NM_ADDR_IP)
|
|
{
|
|
bstrRealAddr = SysAllocString(bstrAddr);
|
|
}
|
|
else
|
|
{
|
|
ERROR_OUT(("INmManager::Call - bogus addrType %d", addrType));
|
|
return E_FAIL;
|
|
}
|
|
|
|
HRESULT hr = m_pOutgoingCallManager->Call( ppCall,
|
|
this,
|
|
dwFlags,
|
|
addrType,
|
|
bstrRealAddr,
|
|
bstrConference,
|
|
bstrPassword);
|
|
|
|
SysFreeString(bstrRealAddr);
|
|
|
|
DebugExitHRESULT(COprahNCUI::Call, hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT COprahNCUI::CreateConference
|
|
(
|
|
INmConference **ppConference,
|
|
BSTR bstrName,
|
|
BSTR bstrPassword,
|
|
BOOL fSecure
|
|
)
|
|
{
|
|
if (NULL == ppConference)
|
|
{
|
|
ERROR_OUT(("CreateConferenceEx: null ppConference passed in"));
|
|
return E_POINTER;
|
|
}
|
|
|
|
if (m_pConfObject->IsConferenceActive())
|
|
{
|
|
WARNING_OUT(("CreateConference is failing because IsConferenceActive return TRUE"));
|
|
return NM_CALLERR_IN_CONFERENCE;
|
|
}
|
|
|
|
m_pConfObject->SetConfName(bstrName);
|
|
m_pConfObject->SetConfSecurity(fSecure);
|
|
|
|
if (!m_pConfObject->IsConferenceCreated())
|
|
{
|
|
m_pConfObject->OnConferenceCreated();
|
|
}
|
|
|
|
NotifySink((INmConference*) m_pConfObject, OnNotifyConferenceCreated);
|
|
|
|
*ppConference = m_pConfObject;
|
|
if(*ppConference)
|
|
{
|
|
(*ppConference)->AddRef();
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/* O N N O T I F Y C O N F E R E N C E C R E A T E D */
|
|
/*-------------------------------------------------------------------------
|
|
%%Function: OnNotifyConferenceCreated
|
|
|
|
-------------------------------------------------------------------------*/
|
|
HRESULT OnNotifyConferenceCreated(IUnknown *pManagerNotify, PVOID pv, REFIID riid)
|
|
{
|
|
ASSERT(NULL != pManagerNotify);
|
|
((INmManagerNotify*)pManagerNotify)->ConferenceCreated((INmConference *) pv);
|
|
return S_OK;
|
|
}
|
|
|
|
/* O N N O T I F Y C A L L C R E A T E D */
|
|
/*-------------------------------------------------------------------------
|
|
%%Function: OnNotifyCallCreated
|
|
|
|
-------------------------------------------------------------------------*/
|
|
HRESULT OnNotifyCallCreated(IUnknown *pManagerNotify, PVOID pv, REFIID riid)
|
|
{
|
|
ASSERT(NULL != pManagerNotify);
|
|
((INmManagerNotify*)pManagerNotify)->CallCreated((INmCall *) pv);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/* O N N O T I F Y C A L L S T A T E C H A N G E D */
|
|
/*-------------------------------------------------------------------------
|
|
%%Function: OnNotifyCallStateChanged
|
|
|
|
-------------------------------------------------------------------------*/
|
|
HRESULT OnNotifyCallStateChanged(IUnknown *pCallNotify, PVOID pv, REFIID riid)
|
|
{
|
|
ASSERT(NULL != pCallNotify);
|
|
((INmCallNotify*)pCallNotify)->StateChanged((NM_CALL_STATE)(DWORD_PTR)pv);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
HRESULT WINAPI CreateNmManager(INmManager ** ppMan)
|
|
{
|
|
if (!ppMan)
|
|
return E_POINTER;
|
|
|
|
COprahNCUI *pManager = new COprahNCUI();
|
|
if (!pManager)
|
|
return E_OUTOFMEMORY;
|
|
|
|
*ppMan = (INmManager *)pManager;
|
|
return S_OK;
|
|
}
|
|
|
|
|