|
|
// File: imanager.cpp
#include "precomp.h"
extern "C" { #include "t120.h"
} #include <version.h>
#include <confcli.h>
#include "icall.h"
#include "icall_in.h"
#include "imanager.h"
#include "ichnlvid.h"
#include "isysinfo.h"
#include <tsecctrl.h>
#include <imbft.h>
#include <objbase.h>
#include <regentry.h>
#include <initguid.h>
// GUID to receive userdata from "callto:" via INmCall::GetUserData
//
// {068B0780-718C-11d0-8B1A-00A0C91BC90E}
DEFINE_GUID(GUID_CallToUserData, 0x068b0780, 0x718c, 0x11d0, 0x8b, 0x1a, 0x0, 0xa0, 0xc9, 0x1b, 0xc9, 0x0e);
class CH323ChannelEvent { private: ICommChannel *m_pIChannel; IH323Endpoint *m_lpConnection; DWORD m_dwStatus;
public: static DWORD ms_msgChannelEvent;
CH323ChannelEvent(ICommChannel *pIChannel, IH323Endpoint *lpConnection, DWORD dwStatus): m_pIChannel(pIChannel), m_lpConnection(lpConnection), m_dwStatus(dwStatus) { if(!ms_msgChannelEvent) { ms_msgChannelEvent = RegisterWindowMessage(_TEXT("NetMeeting::H323ChannelEvent")); } m_pIChannel->AddRef(); m_lpConnection->AddRef(); }
~CH323ChannelEvent() { m_pIChannel->Release(); m_lpConnection->Release(); }
ICommChannel* GetChannel() { return m_pIChannel; } IH323Endpoint* GetEndpoint() { return m_lpConnection; } DWORD GetStatus() { return m_dwStatus; }
};
//static
DWORD CH323ChannelEvent::ms_msgChannelEvent = 0;
static HRESULT OnNotifyConferenceCreated(IUnknown *pManagerNotify, PVOID pv, REFIID riid); static HRESULT OnNotifyCallCreated(IUnknown *pManagerNotify, PVOID pv, REFIID riid);
GUID g_csguidRosterCaps = GUID_CAPS; GUID g_csguidSecurity = GUID_SECURITY; GUID g_csguidMeetingSettings = GUID_MTGSETTINGS; GUID g_csguidUserString = GUID_CallToUserData; GUID g_csguidNodeIdTag = GUID_NODEID;
// this guid is dynamically created each time we start
GUID g_guidLocalNodeId;
CH323UI* g_pH323UI = NULL; INodeController* g_pNodeController = NULL; SOCKADDR_IN g_sinGateKeeper;
const TCHAR cszDllHiddenWndClassName[] = _TEXT("OPNCUI_HiddenWindow");
COprahNCUI *COprahNCUI::m_pOprahNCUI = NULL;
static const IID * g_apiidCP_Manager[] = { {&IID_INmManagerNotify} };
COprahNCUI::COprahNCUI(OBJECTDESTROYEDPROC ObjectDestroyed) : RefCount(ObjectDestroyed), CConnectionPointContainer(g_apiidCP_Manager, ARRAY_ELEMENTS(g_apiidCP_Manager)), m_uCaps(0), m_pQoS(NULL), m_pPreviewChannel(NULL), m_fAllowAV(TRUE), m_pAVConnection(NULL), m_hwnd(NULL), m_pSysInfo(NULL), m_pOutgoingCallManager(NULL), m_pIncomingCallManager(NULL), m_pConfObject(NULL) { DbgMsg(iZONE_OBJECTS, "Obj: %08X created CNmManager", this); // DllLock() is called by CClClassFactory::CreateInstance
m_pOprahNCUI = this;
ClearStruct(&g_sinGateKeeper); g_sinGateKeeper.sin_addr.s_addr = INADDR_NONE;
m_pSysInfo = new CNmSysInfo(); }
COprahNCUI::~COprahNCUI() { // need to unregister the H323 callback
// need to unregister the T120 callback
delete m_pIncomingCallManager; m_pIncomingCallManager = NULL;
delete m_pOutgoingCallManager; m_pOutgoingCallManager = NULL;
if( m_pSysInfo ) { m_pSysInfo->Release(); m_pSysInfo = NULL; }
if (m_pConfObject) { // turn off stream notifications
if (g_pH323UI) { IMediaChannelBuilder *pStreamProvider = NULL; pStreamProvider = g_pH323UI->GetStreamProvider(); if (pStreamProvider) { pStreamProvider->SetStreamEventObj(NULL); pStreamProvider->Release(); } }
m_pConfObject->Release(); m_pConfObject = NULL; }
if (NULL != m_pPreviewChannel) { m_pPreviewChannel->Release(); m_pPreviewChannel = NULL; }
// Shutdown H323
delete g_pH323UI; g_pH323UI = NULL;
if (NULL != m_hwnd) { HWND hwnd = m_hwnd; m_hwnd = NULL;
#if 0 // if we start leaking th CH323ChannelEvents we may need to reenable this
MSG msg; while (::PeekMessage(&msg, hwnd, CH323ChannelEvent::ms_msgChannelEvent, CH323ChannelEvent::ms_msgChannelEvent, PM_REMOVE)) { CH323ChannelEvent *pEvent = reinterpret_cast<CH323ChannelEvent*>(msg.lParam); delete pEvent; } #endif
::DestroyWindow(hwnd); }
if (0==UnregisterClass(cszDllHiddenWndClassName, GetInstanceHandle())) { ERROR_OUT(("COprahNCUI::~COprahNCUI - failed to unregister window class")); } // cleanup the node controller:
if (NULL != g_pNodeController) { g_pNodeController->ReleaseInterface(); g_pNodeController = NULL; } // Shutdown QoS
delete m_pQoS; m_pQoS = NULL;
m_pOprahNCUI = NULL;
DbgMsg(iZONE_OBJECTS, "Obj: %08X destroyed CNmManager", this); }
BSTR COprahNCUI::GetUserName() { return m_pSysInfo ? m_pSysInfo->GetUserName() : NULL; }
UINT COprahNCUI::GetOutgoingCallCount() { return m_pOutgoingCallManager->GetCallCount(); }
VOID COprahNCUI::OnOutgoingCallCreated(INmCall* pCall) { // notify the UI about this outgoing call
NotifySink(pCall, OnNotifyCallCreated);
if (!m_pConfObject->IsConferenceCreated()) { m_pConfObject->OnConferenceCreated(); NotifySink((INmConference*) m_pConfObject, OnNotifyConferenceCreated); } }
VOID COprahNCUI::OnOutgoingCallCanceled(COutgoingCall* pCall) { m_pOutgoingCallManager->RemoveFromList(pCall); }
VOID COprahNCUI::OnIncomingCallAccepted() { if (!m_pConfObject->IsConferenceCreated()) { m_pConfObject->OnConferenceCreated(); NotifySink((INmConference*) m_pConfObject, OnNotifyConferenceCreated); } }
VOID COprahNCUI::OnIncomingCallCreated(INmCall* pCall) { NotifySink(pCall, OnNotifyCallCreated); }
VOID COprahNCUI::CancelCalls() { m_pOutgoingCallManager->CancelCalls(); m_pIncomingCallManager->CancelCalls(); } BOOL COprahNCUI::AcquireAV(IH323Endpoint* pConnection) { if (NULL == m_pAVConnection) { m_pAVConnection = pConnection; TRACE_OUT(("AV acquired")); return TRUE; } TRACE_OUT(("AV not acquired")); return FALSE; }
BOOL COprahNCUI::ReleaseAV(IH323Endpoint* pConnection) { if (m_pAVConnection == pConnection) { m_pAVConnection = NULL; TRACE_OUT(("AV released")); return TRUE; } return FALSE; }
HRESULT COprahNCUI::AllowH323(BOOL fAllowAV) { m_fAllowAV = fAllowAV; if (m_pConfObject->IsConferenceActive()) { // Force a roster update
CONF_HANDLE hConf = m_pConfObject->GetConfHandle(); if (NULL != hConf) { ASSERT(g_pNodeController); hConf->UpdateUserData(); } } return S_OK; }
CREQ_RESPONSETYPE COprahNCUI::OnH323IncomingCall(IH323Endpoint* pConnection, P_APP_CALL_SETUP_DATA lpvMNMData) { CREQ_RESPONSETYPE resp = m_pIncomingCallManager->OnIncomingH323Call(this, pConnection, lpvMNMData);
if ((CRR_REJECT == resp) || (CRR_BUSY == resp) || (CRR_SECURITY_DENIED == resp)) { ReleaseAV(pConnection); }
return resp; }
VOID COprahNCUI::OnH323Connected(IH323Endpoint * lpConnection) { DebugEntry(COprahNCUI::OnH323Connected);
if (!m_pOutgoingCallManager->OnH323Connected(lpConnection)) { m_pIncomingCallManager->OnH323Connected(lpConnection); } DebugExitVOID(COprahNCUI::OnH323Connected); }
VOID COprahNCUI::OnH323Disconnected(IH323Endpoint * lpConnection) { DebugEntry(COprahNCUI::OnH323Disconnected);
if (!m_pOutgoingCallManager->OnH323Disconnected(lpConnection)) { m_pIncomingCallManager->OnH323Disconnected(lpConnection); }
m_pConfObject->OnH323Disconnected(lpConnection, IsOwnerOfAV(lpConnection));
ReleaseAV(lpConnection);
DebugExitVOID(COprahNCUI::OnH323Disconnected); }
VOID COprahNCUI::OnT120ChannelOpen(ICommChannel *pIChannel, IH323Endpoint * lpConnection, DWORD dwStatus) { DebugEntry(COprahNCUI::OnT120ChannelOpen);
m_pOutgoingCallManager->OnT120ChannelOpen(pIChannel, lpConnection, dwStatus);
DebugExitVOID(COprahNCUI::OnT120ChannelOpen); }
VOID COprahNCUI::OnVideoChannelStatus(ICommChannel *pIChannel, IH323Endpoint * lpConnection, DWORD dwStatus) { DebugEntry(COprahNCUI::OnVideoChannelStatus);
m_pConfObject->OnVideoChannelStatus(pIChannel, lpConnection, dwStatus);
DebugExitVOID(COprahNCUI::OnVideoChannelStatus); }
VOID COprahNCUI::OnAudioChannelStatus(ICommChannel *pIChannel, IH323Endpoint * lpConnection, DWORD dwStatus) { DebugEntry(COprahNCUI::OnAudioChannelStatus);
m_pConfObject->OnAudioChannelStatus(pIChannel, lpConnection, dwStatus);
DebugExitVOID(COprahNCUI::OnAudioChannelStatus); }
BOOL COprahNCUI::GetULSName(CRosterInfo *pri) { if (FIsLoggedOn()) { RegEntry reULS( ISAPI_KEY _TEXT("\\") REGKEY_USERDETAILS, HKEY_CURRENT_USER); CUSTRING custrULSName(reULS.GetString(REGVAL_ULS_RES_NAME)); if ((NULL != (PWSTR)custrULSName) && (L'\0' != ((PWSTR)custrULSName)[0])) { pri->AddItem(g_cwszULSTag, (PWSTR)custrULSName); return TRUE; } } return FALSE; }
VOID COprahNCUI::GetRosterInfo(CRosterInfo *pri) { RegEntry reULS( ISAPI_KEY _TEXT("\\") REGKEY_USERDETAILS, HKEY_CURRENT_USER);
// This code is here in addition to the code above to fix bug 3367.
// Add the single IP address to the list that is obtained by calling
// gethostname() and then gethostbyname().
// This shouldn't be detrimental, even though we may end up adding the
// same IP address that has already been added by the code above.
// This is because the code that looks for matching IP addresses searches
// through all of them until it finds a match.
CHAR szHostName[MAX_PATH]; if (SOCKET_ERROR != gethostname(szHostName, CCHMAX(szHostName))) { HOSTENT* phe = gethostbyname(szHostName); if (NULL != phe) { ASSERT(phe->h_addrtype == AF_INET); ASSERT(phe->h_length == sizeof(DWORD));
struct in_addr in; in.s_addr = *((DWORD *)phe->h_addr); CHAR szIPAddress[MAX_PATH]; lstrcpyn(szIPAddress, inet_ntoa(in), CCHMAX(szIPAddress)); pri->AddItem( g_cwszIPTag, CUSTRING(szIPAddress)); } }
// Add the build/version string
pri->AddItem(g_cwszVerTag, (PWSTR)VER_PRODUCTVERSION_DWSTR); if (FIsLoggedOn()) { CUSTRING custrULSName(reULS.GetString(REGVAL_ULS_RES_NAME)); if ((NULL != (PWSTR)custrULSName) && (L'\0' != ((PWSTR)custrULSName)[0])) { pri->AddItem(g_cwszULSTag, (PWSTR)custrULSName); } }
CUSTRING custrULSEmail(reULS.GetString(REGVAL_ULS_EMAIL_NAME)); if ((NULL != (PWSTR)custrULSEmail) && (L'\0' != ((PWSTR)custrULSEmail)[0])) { pri->AddItem(g_cwszULS_EmailTag, (PWSTR)custrULSEmail); }
CUSTRING custrULSLocation(reULS.GetString(REGVAL_ULS_LOCATION_NAME)); if ((NULL != (PWSTR)custrULSLocation) && (L'\0' != ((PWSTR)custrULSLocation)[0])) { pri->AddItem(g_cwszULS_LocationTag, (PWSTR)custrULSLocation); }
CUSTRING custrULSPhoneNum(reULS.GetString(REGVAL_ULS_PHONENUM_NAME)); if ((NULL != (PWSTR)custrULSPhoneNum) && (L'\0' != ((PWSTR)custrULSPhoneNum)[0])) { pri->AddItem(g_cwszULS_PhoneNumTag, (PWSTR)custrULSPhoneNum); } }
ULONG COprahNCUI::GetRosterCaps() { ULONG uCaps = m_uCaps;
CNmMember * pMember = m_pConfObject->GetLocalMember(); if (NULL != pMember) { DWORD dwFlags = pMember->GetDwFlags(); if (dwFlags & PF_MEDIA_VIDEO) { uCaps |= CAPFLAG_VIDEO_IN_USE; } if (dwFlags & PF_MEDIA_AUDIO) { uCaps |= CAPFLAG_AUDIO_IN_USE; } if (dwFlags & PF_MEDIA_DATA) { uCaps |= CAPFLAG_DATA_IN_USE; } if (dwFlags & PF_H323) { uCaps |= CAPFLAG_H323_IN_USE; } }
if (!m_fAllowAV) { uCaps &= ~(CAPFLAGS_AV_ALL); }
return uCaps; }
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::OnUpdateUserData(CONF_HANDLE hConference) { CRosterInfo ri;
// This string will contain addresses in the form:
// L"TCP:157.55.143.3\0TCP:157.55.143.4\0\0" - 512 character max for now
WCHAR wszAddresses[512]; ASSERT(g_pNodeController); ASSERT(hConference); if (NOERROR == hConference->GetLocalAddressList(wszAddresses, CCHMAX(wszAddresses))) { ri.Load(wszAddresses); }
// First, handle roster information
GetRosterInfo(&ri);
PVOID pvData; UINT cbDataLen; if (SUCCEEDED(ri.Save(&pvData, &cbDataLen))) { ASSERT(g_pNodeController); ASSERT(hConference); hConference->SetUserData(&g_csguidRostInfo, cbDataLen, pvData); }
// Next, handle caps information
ULONG uCaps = GetRosterCaps(); ASSERT(g_pNodeController); ASSERT(hConference); hConference->SetUserData(&g_csguidRosterCaps, sizeof(uCaps), &uCaps);
// Next, handle credentials
if ( hConference->IsSecure() ) { BYTE * pb = NULL; ULONG cb = GetAuthenticatedName(&pb); if (cb > 0) { ASSERT(g_pNodeController); ASSERT(hConference); TRACE_OUT(("COprahNCUI::OnUpdateUserData: adding %d bytes SECURITY data", cb)); hConference->SetUserData(&g_csguidSecurity, cb, pb); } else { WARNING_OUT(("OnUpdateUserData: 0 bytes security data?")); } delete [] pb; }
// Next, set meeting settings if we hosted the meeting
ASSERT(m_pConfObject); if (m_pConfObject->IsHosting() == S_OK) { NM30_MTG_PERMISSIONS attendeePermissions = m_pConfObject->GetConfAttendeePermissions();
WARNING_OUT(("Hosted Meeting Settings 0x%08lx", attendeePermissions));
hConference->SetUserData(&g_csguidMeetingSettings, sizeof(attendeePermissions), &attendeePermissions); }
ULONG nRecords; GCCUserData ** ppUserData = NULL; if (m_pSysInfo) { m_pSysInfo->GetUserDataList(&nRecords,&ppUserData); for (unsigned int i = 0; i < nRecords; i++) { // Do not add user data that was already set above.
if (memcmp(ppUserData[i]->octet_string->value,(PVOID)&g_csguidRostInfo,sizeof(GUID)) == 0) continue; if (memcmp(ppUserData[i]->octet_string->value,(PVOID)&g_csguidRosterCaps,sizeof(GUID)) == 0) continue; if (memcmp(ppUserData[i]->octet_string->value,(PVOID)&g_csguidSecurity,sizeof(GUID)) == 0) continue; if (memcmp(ppUserData[i]->octet_string->value,(PVOID)&g_csguidMeetingSettings,sizeof(GUID)) == 0) continue;
ASSERT(g_pNodeController); ASSERT(hConference); hConference->SetUserData((GUID *)(ppUserData[i]->octet_string->value), ppUserData[i]->octet_string->length - sizeof(GUID), ppUserData[i]->octet_string->value + sizeof(GUID)); } }
// only add the LocalNodeId to the roster if H323 is enabled
if (IsH323Enabled()) { hConference->SetUserData((GUID *)(&g_csguidNodeIdTag), sizeof(GUID), (PVOID)&g_guidLocalNodeId); } return S_OK; } HRESULT COprahNCUI::OnIncomingInviteRequest(CONF_HANDLE hConference, PCWSTR pcwszNodeName, PT120PRODUCTVERSION pRequestorVersion, PUSERDATAINFO pUserDataInfoEntries, UINT cUserDataEntries, BOOL fSecure) { DebugEntry(COprahNCUI::OnIncomingInviteRequest);
// Fix an AV problem ONLY for RTC client
if (m_pConfObject == NULL) { return S_OK; } 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 { m_pIncomingCallManager->OnIncomingT120Call( this, TRUE, hConference, pcwszNodeName, pUserDataInfoEntries, cUserDataEntries, 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, PT120PRODUCTVERSION pRequestorVersion, PUSERDATAINFO pUserDataInfoEntries, UINT cUserDataEntries) { DebugEntry(COprahNCUI::OnIncomingJoinRequest);
// 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, pUserDataInfoEntries, cUserDataEntries, 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->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, PT120PRODUCTVERSION pVersion, PWSTR* ppwszConfDescriptors) { DebugEntry(COprahNCUI::OnQueryRemoteResult);
if (NO_ERROR == hResult) { TRACE_OUT(("COprahNCUI: OnQueryRemoteResult Success!")); } else { TRACE_OUT(("COprahNCUI: OnQueryRemoteResult Failure!")); }
m_pOutgoingCallManager->OnQueryRemoteResult(pvCallerContext, hResult, fMCU, ppwszConferenceNames, pVersion, ppwszConfDescriptors); DebugExitHRESULT(COprahNCUI::OnQueryRemoteResult, S_OK); return S_OK; }
HRESULT COprahNCUI::OnInviteResult( CONF_HANDLE hConference, REQUEST_HANDLE hRequest, UINT uNodeID, HRESULT hResult, PT120PRODUCTVERSION pVersion) { DebugEntry(COprahNCUI::OnInviteResult);
if (hConference == m_pConfObject->GetConfHandle()) { m_pOutgoingCallManager->OnInviteResult( hConference, hRequest, uNodeID, hResult, pVersion); }
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();
m_pOutgoingCallManager->OnConferenceEnded(hConference);
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 (hConf == m_pConfObject->GetConfHandle()) { m_pConfObject->OnRosterChanged(pRoster); } return S_OK; }
ULONG STDMETHODCALLTYPE COprahNCUI::AddRef(void) { return RefCount::AddRef(); } ULONG STDMETHODCALLTYPE COprahNCUI::Release(void) { return RefCount::Release(); }
HRESULT STDMETHODCALLTYPE COprahNCUI::QueryInterface(REFIID riid, PVOID *ppv) { HRESULT hr = S_OK;
if ((riid == IID_INmManager2) || (riid == IID_INmManager) || (riid == IID_IUnknown)) { *ppv = (INmManager2 *)this; ApiDebugMsg(("COprahNCUI::QueryInterface()")); } else if (riid == IID_IConnectionPointContainer) { *ppv = (IConnectionPointContainer *) this; ApiDebugMsg(("COprahNCUI::QueryInterface(): Returning IConnectionPointContainer.")); } else { hr = E_NOINTERFACE; *ppv = NULL; ApiDebugMsg(("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(ULONG *puOptions, ULONG *puchCaps) { HRESULT hr = S_OK;
// puOptions is UNUSED
ASSERT(puchCaps);
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(this);
WNDCLASS wcHidden = { 0L, COprahNCUI::WndProc, 0, 0, GetInstanceHandle(), NULL, NULL, NULL, NULL, cszDllHiddenWndClassName };
if (!RegisterClass(&wcHidden)) { ERROR_OUT(("COprahNCUI::Initialize -- failed to register HiddenWnd class")); return(E_OUTOFMEMORY); }
// Create a hidden window for event processing:
m_hwnd = ::CreateWindow(cszDllHiddenWndClassName, _TEXT(""), WS_POPUP, // not visible!
0, 0, 0, 0, NULL, NULL, GetInstanceHandle(), NULL);
if (NULL == m_hwnd) { return E_FAIL; }
//
// INIT QOS only if AV is in the picture (otherwise, there's nothing
// to arbitrate).
//
if (CAPFLAGS_AV_STREAMS & *puchCaps) { m_pQoS = new CQoS(); if (NULL != m_pQoS) { hr = m_pQoS->Initialize(); if (FAILED(hr)) { WARNING_OUT(("CQoS::Init() failed!"));
// let NetMeeting hobble along without QoS.
delete m_pQoS; m_pQoS = NULL; hr = S_FALSE; // we can live without QOS
} } else { WARNING_OUT(("Could not allocate CQoS object")); } }
//
// IF DATA CONFERENCING IS ALLOWED
//
if (CAPFLAG_DATA & *puchCaps) { //
// Create the node controller
//
hr = ::T120_CreateNodeController(&g_pNodeController, this); if (FAILED(hr)) { ERROR_OUT(("T120_CreateNodeController() failed!")); return hr; } }
// Initialize audio/video
if (CAPFLAGS_AV_ALL & *puchCaps) { g_pH323UI = new CH323UI(); if (NULL != g_pH323UI) { hr = g_pH323UI->Init(m_hwnd, ::GetInstanceHandle(), *puchCaps, this, this); if (FAILED(hr)) { WARNING_OUT(("CH323UI::Init() failed!")); delete g_pH323UI; g_pH323UI = NULL; *puchCaps &= ~(CAPFLAGS_AV_ALL); hr = S_FALSE; // We can run without AV
} else { if (CAPFLAGS_VIDEO & *puchCaps) { // if we can get a Preview channel, we can send video
m_pPreviewChannel = CNmChannelVideo::CreatePreviewChannel(); if (NULL == m_pPreviewChannel) { *puchCaps &= ~CAPFLAG_SEND_VIDEO; } }
if (m_pConfObject && (CAPFLAGS_AV_STREAMS & *puchCaps)) { IMediaChannelBuilder *pStreamProvider;
pStreamProvider = g_pH323UI->GetStreamProvider(); if (pStreamProvider) { pStreamProvider->SetStreamEventObj(m_pConfObject); pStreamProvider->Release(); } }
} } else { ERROR_OUT(("Could not allocate CH323UI object")); } }
m_uCaps = *puchCaps;
return CoCreateGuid(&g_guidLocalNodeId); }
HRESULT COprahNCUI::GetSysInfo(INmSysInfo **ppSysInfo) { HRESULT hr = S_OK;
if( ppSysInfo ) { if(m_pSysInfo ) { m_pSysInfo->AddRef(); *ppSysInfo = m_pSysInfo; } else { hr = E_OUTOFMEMORY; } } else { hr = E_POINTER; }
return hr; }
HRESULT COprahNCUI::EnumConference(IEnumNmConference **ppEnum) { return E_NOTIMPL; }
HRESULT COprahNCUI::CreateConference( INmConference **ppConference, BSTR bstrName, BSTR bstrPassword, ULONG uchCaps) { return(CreateConferenceEx(ppConference, bstrName, bstrPassword, uchCaps, NM_PERMIT_ALL, (UINT)-1)); }
HRESULT COprahNCUI::EnumCall(IEnumNmCall **ppEnum) { return E_NOTIMPL; }
HRESULT COprahNCUI::CreateCall( INmCall **ppCall, NM_CALL_TYPE callType, NM_ADDR_TYPE addrType, BSTR bstrAddress, INmConference * pConference) { return E_NOTIMPL; }
HRESULT COprahNCUI::CallConference( INmCall **ppCall, NM_CALL_TYPE callType, NM_ADDR_TYPE addrType, BSTR bstrAddress, BSTR bstrConfToJoin, BSTR bstrPassword) { return E_NOTIMPL; }
STDMETHODIMP COprahNCUI::GetPreviewChannel(INmChannelVideo **ppChannelVideo) { HRESULT hr = E_POINTER; if (NULL != ppChannelVideo) { *ppChannelVideo = m_pPreviewChannel; if (NULL != m_pPreviewChannel) { m_pPreviewChannel->AddRef(); hr = S_OK; } else { hr = E_FAIL; } } return hr; }
STDMETHODIMP COprahNCUI::CreateASObject ( IUnknown * pNotify, ULONG flags, IUnknown ** ppAS ) { return(::CreateASObject((IAppSharingNotify *)pNotify, flags, (IAppSharing **)ppAS)); }
HRESULT COprahNCUI::CallEx( INmCall **ppCall, DWORD dwFlags, NM_ADDR_TYPE addrType, BSTR bstrName, BSTR bstrSetup, BSTR bstrDest, BSTR bstrAlias, BSTR bstrURL, BSTR bstrConference, BSTR bstrPassword, BSTR bstrUserData) { DebugEntry(COprahNCUI::CallEx);
HRESULT hr = m_pOutgoingCallManager->Call( ppCall, this, dwFlags, addrType, bstrName, bstrSetup, bstrDest, bstrAlias, bstrURL, bstrConference, bstrPassword, bstrUserData);
DebugExitHRESULT(COprahNCUI::CallEx, hr); return hr; }
HRESULT COprahNCUI::CreateConferenceEx ( INmConference **ppConference, BSTR bstrName, BSTR bstrPassword, DWORD uchCaps, DWORD attendeePermissions, DWORD maxParticipants ) { if (NULL == ppConference) { ERROR_OUT(("CreateConferenceEx: null ppConference passed in")); return E_POINTER; }
if (maxParticipants < 2) { ERROR_OUT(("CreateConferenceEx: bad maxParticipants %d", maxParticipants)); return E_INVALIDARG; }
if (m_pConfObject->IsConferenceActive()) { WARNING_OUT(("CreateConference is failing because IsConferenceActive return TRUE")); return NM_CALLERR_IN_CONFERENCE; }
m_pConfObject->SetConfName(bstrName); if (uchCaps & NMCH_SRVC) m_pConfObject->SetConfHashedPassword(bstrPassword); else m_pConfObject->SetConfPassword(bstrPassword);
if (uchCaps & NMCH_SECURE) m_pConfObject->SetConfSecurity(TRUE); else m_pConfObject->SetConfSecurity(FALSE);
m_pConfObject->SetConfAttendeePermissions(attendeePermissions); m_pConfObject->SetConfMaxParticipants(maxParticipants);
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; }
VOID SetBandwidth(UINT uBandwidth) { COprahNCUI *pOprahNCUI = COprahNCUI::GetInstance(); if (NULL != pOprahNCUI) { pOprahNCUI->SetBandwidth(uBandwidth); } if (NULL != g_pH323UI) { //Inform the NAC of the connection speed
g_pH323UI->SetBandwidth(uBandwidth); } }
//
// BOGUS LAURABU!
// Do we need this HWND anymore? The hidden window is used now only to
// pass to H323, which passes it to the MediaStream interfaces in the NAC,
// which passes it to DirectX.
//
LRESULT CALLBACK COprahNCUI::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { // if ms_msgChannelEvent is 0, that means that we are not initialized
// RegisterWindowMessage returns MSGIds in the range 0xC000 through 0xFFFF
if(CH323ChannelEvent::ms_msgChannelEvent && CH323ChannelEvent::ms_msgChannelEvent == uMsg) { COprahNCUI *pOprahNCUI = COprahNCUI::GetInstance(); if (pOprahNCUI) { CH323ChannelEvent *pEvent = reinterpret_cast<CH323ChannelEvent*>(lParam); if(pEvent) { // if we're shutting down m_hwnd will be NULL
if (pOprahNCUI->m_hwnd) { pOprahNCUI->_ChannelEvent( pEvent->GetChannel(), pEvent->GetEndpoint(), pEvent->GetStatus()); } delete pEvent; } else { WARNING_OUT(("Why are we getting a NULL pEvent?")); } } return 1; }
return DefWindowProc(hwnd, uMsg, wParam, lParam); }
PIUnknown NewNmManager(OBJECTDESTROYEDPROC ObjectDestroyed) { COprahNCUI *pManager = new COprahNCUI(ObjectDestroyed); if (NULL != pManager) { return (INmManager2 *) pManager; } return NULL; }
VOID COprahNCUI::_ChannelEvent (ICommChannel *pIChannel, IH323Endpoint * lpConnection, DWORD dwStatus ) { ASSERT(pIChannel); GUID guidMedia; if (SUCCEEDED(pIChannel->GetMediaType(&guidMedia))) { if (MEDIA_TYPE_H323AUDIO == guidMedia) { OnAudioChannelStatus(pIChannel, lpConnection, dwStatus); } else if (MEDIA_TYPE_H323VIDEO == guidMedia) { OnVideoChannelStatus(pIChannel, lpConnection, dwStatus); } else if (MEDIA_TYPE_H323_T120 == guidMedia) { switch (dwStatus) { case CHANNEL_OPEN_ERROR: case CHANNEL_OPEN: case CHANNEL_CLOSED: case CHANNEL_REJECTED: case CHANNEL_NO_CAPABILITY: OnT120ChannelOpen(pIChannel, lpConnection, dwStatus); break; default: WARNING_OUT(("COprahNCUI::ChannelEvent - unrecognized T120 status")); break; } } else { WARNING_OUT(("COprahNCUI::ChannelEvent - unknown media type")); } } else { WARNING_OUT(("COprahNCUI::ChannelEvent - pIChannel->GetMediaType() failed")); } }
STDMETHODIMP COprahNCUI::ChannelEvent (ICommChannel *pIChannel, IH323Endpoint * lpConnection, DWORD dwStatus ) { ASSERT(pIChannel); GUID guidMedia; if (SUCCEEDED(pIChannel->GetMediaType(&guidMedia))) { if (MEDIA_TYPE_H323_T120 == guidMedia) { if (NULL != m_hwnd) { CH323ChannelEvent* pEvent = new CH323ChannelEvent( pIChannel, lpConnection, dwStatus); if (pEvent) { PostMessage(m_hwnd, CH323ChannelEvent::ms_msgChannelEvent, 0, reinterpret_cast<LPARAM>(pEvent)); return S_OK; } } } else { _ChannelEvent(pIChannel, lpConnection, dwStatus); return S_OK; } }
return E_FAIL; }
#ifdef DEBUG
VOID TraceStatus(DWORD dwStatus) { switch(dwStatus) { case CONNECTION_DISCONNECTED: TRACE_OUT(("COprahNCUI::CallEvent: CONNECTION_DISCONNECTED")); break;
case CONNECTION_CONNECTED: TRACE_OUT(("COprahNCUI::CallEvent: CONNECTION_CONNECTED")); break;
case CONNECTION_RECEIVED_DISCONNECT: TRACE_OUT(( "COprahNCUI::CallEvent: RECEIVED_DISCONNECT")); break;
case CONNECTION_PROCEEDING: TRACE_OUT(("COprahNCUI::CallEvent: CONNECTION_PROCEEDING")); break;
case CONNECTION_REJECTED: TRACE_OUT(("COprahNCUI::CallEvent: CONNECTION_REJECTED")); break;
default: TRACE_OUT(("COprahNCUI::CallEvent: dwStatus = %d", dwStatus)); break; } } #endif
STDMETHODIMP COprahNCUI::CallEvent(IH323Endpoint * lpConnection, DWORD dwStatus) {
DebugEntry(COprahNCUI::CallEvent); IH323CallControl * pH323CallControl = g_pH323UI->GetH323CallControl(); #ifdef DEBUG
TraceStatus(dwStatus); #endif
switch (dwStatus) { case CONNECTION_DISCONNECTED: OnH323Disconnected(lpConnection); break;
case CONNECTION_CONNECTED: // This is currently interpreted as CONNECTION_CAPABILITIES_READY.
// Lower layers are continuing to post CONNECTION_CONNECTED only after
// capabilities are exchanged. note that channels may be opened while
// inside OnH323Connected();
OnH323Connected(lpConnection); break; }
DebugExitVOID(COprahNCUI::CallEvent); return S_OK; }
STDMETHODIMP COprahNCUI::GetMediaChannel (GUID *pmediaID, BOOL bSendDirection, IMediaChannel **ppI) { // delegate to the appropriate stream provider. For the time being
// there is only one provider that does both audio & video
return g_pH323UI->GetMediaChannel (pmediaID, bSendDirection, ppI); }
|