|
|
#include "precomp.h"
// NetMeeting stuff
#include "AtlExeModule.h"
#include "ConfUtil.h"
#include "NmLdap.h"
#include "call.h"
#include "common.h"
#include "ConfMan.h"
#include "cmd.h"
#include "conf.h"
#include "iAppLdr.h"
#include "confroom.h"
#include "ConfPolicies.h"
#include "cmd.h"
#include "ConfWnd.h"
#include "Taskbar.h"
#include "certui.h"
// NetMeeting SDK includes
#include "NmEnum.h"
#include "NmManager.h"
#include "NmConference.h"
#include "NmCall.h"
#include "SDKWindow.h"
#include "dlgCall2.h"
bool g_bSDKPostNotifications; extern BOOL g_fLoggedOn; extern INmSysInfo2 * g_pNmSysInfo; extern GUID g_csguidSecurity;
//static
CSimpleArray<CNmManagerObj*>* CNmManagerObj::ms_pManagerObjList = NULL; bool g_bOfficeModeSuspendNotifications = false; DWORD CNmManagerObj::ms_dwID = 1;
BOOL InitAppletSDK(void); void CleanupAppletSDK(void);
///////////////////////////////////////////////
// Construction\Destruction
///////////////////////////////////////////////
CNmManagerObj::CNmManagerObj() : m_bInitialized(false), m_chCaps(NMCH_NONE), m_bNmActive(false), m_bSentConferenceCreated(false), m_dwID(0), m_dwSysInfoID(0), m_uOptions(0)
{ DBGENTRY(CNmManagerObj::CNmManagerObj);
CNmManagerObj* p = const_cast<CNmManagerObj*>(this); ms_pManagerObjList->Add(p); DBGEXIT(CNmManagerObj::CNmManagerObj); }
CNmManagerObj::~CNmManagerObj() { DBGENTRY(CNmManagerObj::~CNmManagerObj);
CNmManagerObj* p = const_cast<CNmManagerObj*>(this); ms_pManagerObjList->Remove(p);
// Free our conferencing objects
while(m_SDKConferenceObjs.GetSize()) { CComPtr<INmConference> sp = m_SDKConferenceObjs[0]; m_SDKConferenceObjs.RemoveAt(0); sp.p->Release(); }
// Free our conferencing objects
while(m_SDKCallObjs.GetSize()) { CComPtr<INmCall> sp = m_SDKCallObjs[0]; m_SDKCallObjs.RemoveAt(0); sp.p->Release(); }
m_spInternalNmManager = NULL;
DBGEXIT(CNmManagerObj::~CNmManagerObj); }
HRESULT CNmManagerObj::FinalConstruct() { DBGENTRY(CNmManagerObj::FinalContstruct); HRESULT hr = S_OK;
m_bInitialized = false; m_dwInternalNmManagerAdvise = 0;
DBGEXIT_HR(CNmManagerObj::FinalContstruct,hr); return hr; }
ULONG CNmManagerObj::InternalRelease() { ATLASSERT(m_dwRef > 0);
--m_dwRef;
if((1 == m_dwRef) && m_dwInternalNmManagerAdvise) { ++m_dwRef; DWORD dwAdvise = m_dwInternalNmManagerAdvise; m_dwInternalNmManagerAdvise = 0; AtlUnadvise(m_spInternalNmManager, IID_INmManagerNotify, dwAdvise); --m_dwRef; }
return m_dwRef;
}
void CNmManagerObj::FinalRelease() { DBGENTRY(CNmManagerObj::FinalRelease); if(m_bInitialized) { switch(m_uOptions) { case NM_INIT_CONTROL: // Even though we have the NM_INIT_CONTROL flag set here
// We may not me in INIT_CONTROL mode. NetMeeting may have
// already been up when we initialized. In that case the UI is active
if(_Module.InitControlMode()) { // If we are the last NmManager object with NM_INIT_CONTROL, then
// we should switch the UI mode away from InitControl
if((GetManagerCount(NM_INIT_CONTROL) == 1)) { if(!_Module.IsSDKCallerRTC()) { _Module.SetInitControlMode(FALSE); ::AddTaskbarIcon(::GetHiddenWindow()); } } } break;
case NM_INIT_OBJECT: // Check to see if this is the last "office" client
if (GetManagerCount(NM_INIT_OBJECT) == 1) { CConfMan::AllowAV(TRUE); } break;
default: break; } }
DBGEXIT(CNmManagerObj::FinalRelease); }
/*static*/ HRESULT CNmManagerObj::InitSDK() { DBGENTRY(CNmManagerObj::InitSDK); HRESULT hr = S_OK;
g_bSDKPostNotifications = false;
ms_pManagerObjList = new CSimpleArray<CNmManagerObj*>; if(!ms_pManagerObjList) { hr = E_OUTOFMEMORY; }
::InitAppletSDK(); InitPluggableTransportSDK();
DBGEXIT_HR(CNmManagerObj::InitSDK,hr); return hr; }
/*static*/void CNmManagerObj::CleanupSDK() { DBGENTRY(CNmManagerObj::CleanupSDK);
::CleanupAppletSDK(); CleanupPluggableTransportSDK();
delete ms_pManagerObjList;
DBGEXIT(CNmManagerObj::CleanupSDK); }
///////////////////////////////////////////////
// INmManager methods
///////////////////////////////////////////////
STDMETHODIMP CNmManagerObj::Initialize( ULONG * puOptions, ULONG *puchCaps) { DBGENTRY(CNmManagerObj::Initialize); HRESULT hr = S_OK;
// If the remote control service is running, this will bring up a dialog
// that the user can choose weather or not to kill the remote control session
// If they do want to kill the session then the mananger object will initialize properly
if(!CheckRemoteControlService()) { return E_FAIL; }
m_uOptions = puOptions ? *puOptions : NM_INIT_NORMAL;
if(puOptions && (*puOptions > NM_INIT_BACKGROUND)) { hr = E_INVALIDARG; goto end; }
if(!m_bInitialized) { bool bStartedNetMeeting = false;
if(!g_pInternalNmManager) { if(NM_INIT_NO_LAUNCH == m_uOptions) { // We don't launch NetMeeting in this case...
m_bNmActive = false; goto end; }
if (NM_INIT_CONTROL == m_uOptions) { _Module.SetInitControlMode(TRUE); } hr = InitConfExe(NM_INIT_NORMAL == m_uOptions);
bStartedNetMeeting = SUCCEEDED(hr); }
if(SUCCEEDED(hr)) { if(NM_INIT_OBJECT == m_uOptions) { if (!_Module.IsUIVisible()) { CConfMan::AllowAV(FALSE); } }
m_bNmActive = true;
CFt::EnsureLoadFtApplet();
m_spInternalNmManager = g_pInternalNmManager;
// The old NetMeeting ignored this param...
// for the time being, we are ignoring it too.
//m_chCaps = puchCaps ? *puchCaps : NMCH_ALL;
m_chCaps = NMCH_ALL;
hr = AtlAdvise(m_spInternalNmManager,GetUnknown(),IID_INmManagerNotify, &m_dwInternalNmManagerAdvise); } } else { hr = E_FAIL; }
end:
m_bInitialized = SUCCEEDED(hr); if(m_bInitialized) { INmConference2* pConf = ::GetActiveConference(); if(pConf) { ConferenceCreated(pConf); // If there is no manager notify hooked in, we simply
// sync up with the Internal conference object state
IConnectionPointImpl<CNmManagerObj, &IID_INmManagerNotify, CComDynamicUnkArray>* pCP = this; if((0 == pCP->m_vec.GetSize()) && !m_bSentConferenceCreated) { // It must be the first conference, because we are newly-initialized
ASSERT(m_SDKConferenceObjs[0]);
// Sinc up the channels, etc.
com_cast<IInternalConferenceObj>(m_SDKConferenceObjs[0])->FireNotificationsToSyncToInternalObject(); } } }
DBGEXIT_HR(CNmManagerObj::Initialize,hr); return hr; }
// This is not guarenteed to work if called from conf.exe's process!!!
STDMETHODIMP CNmManagerObj::GetSysInfo(INmSysInfo **ppSysInfo) { DBGENTRY(CNmManagerObj::GetSysInfo); HRESULT hr = S_OK;
hr = CoCreateInstance(CLSID_NmSysInfo, NULL, CLSCTX_ALL, IID_INmSysInfo, reinterpret_cast<void**>(ppSysInfo));
if(*ppSysInfo) { m_dwID = ++ms_dwID; com_cast<IInternalSysInfoObj>(*ppSysInfo)->SetID(m_dwID); }
DBGEXIT_HR(CNmManagerObj::GetSysInfo,hr); return hr; }
STDMETHODIMP CNmManagerObj::CreateConference(INmConference **ppConference, BSTR bstrName, BSTR bstrPassword, ULONG uchCaps) { DBGENTRY(CNmManagerObj::CreateConference); HRESULT hr = S_OK;
if(m_bInitialized) { if(m_bNmActive) { if(ppConference) { if(m_spInternalNmManager) { switch(ConfPolicies::GetSecurityLevel()) { case REQUIRED_POL_SECURITY: m_chCaps = uchCaps | NMCH_SECURE; break; case DISABLED_POL_SECURITY: m_chCaps = uchCaps & ~NMCH_SECURE; break; default: m_chCaps = uchCaps; break; }
if(OfficeMode()) g_bOfficeModeSuspendNotifications = true;
CComPtr<INmConference> spInternalINmConference; hr = m_spInternalNmManager->CreateConference(&spInternalINmConference, bstrName, bstrPassword, m_chCaps); if(SUCCEEDED(hr)) { // This was created by the previous call
*ppConference = GetSDKConferenceFromInternalConference(spInternalINmConference);
if(*ppConference) { (*ppConference)->AddRef(); } else { hr = E_UNEXPECTED; } }
if(OfficeMode()) g_bOfficeModeSuspendNotifications = false; } else { hr = E_UNEXPECTED; } } else { hr = E_POINTER; } } else { hr = NM_E_NOT_ACTIVE; } } else { hr = NM_E_NOT_INITIALIZED; }
DBGEXIT_HR(CNmManagerObj::CreateConference,hr); return hr; }
STDMETHODIMP CNmManagerObj::EnumConference(IEnumNmConference **ppEnum) { DBGENTRY(CNmManagerObj::EnumConference); HRESULT hr = S_OK;
if(m_bInitialized) { if(m_bNmActive) { hr = CreateEnumFromSimpleAryOfInterface<IEnumNmConference, INmConference>(m_SDKConferenceObjs, ppEnum); } else { hr = NM_E_NOT_ACTIVE; } } else { hr = NM_E_NOT_INITIALIZED; }
DBGEXIT_HR(CNmManagerObj::EnumConference,hr); return hr; }
STDMETHODIMP CNmManagerObj::CreateCall(INmCall **ppCall, NM_CALL_TYPE callType, NM_ADDR_TYPE addrType, BSTR bstrAddr, INmConference *pConference) { DBGENTRY(CNmManagerObj::CreateCall); HRESULT hr = S_OK;
if(!m_bInitialized) { hr = NM_E_NOT_INITIALIZED; goto end; }
if(!m_bNmActive) { hr = NM_E_NOT_ACTIVE; goto end; }
if(m_spInternalNmManager) { if(!pConference) { // Get the active conference
pConference = _GetActiveConference();
if(!pConference) { // There is no active conf, so create a new one
CComPtr<INmConference> spInternalINmConference;
// TODO: What about NMCH_SECURE?
ULONG ulCaps = NMCH_AUDIO | NMCH_VIDEO | NMCH_DATA | NMCH_SHARE | NMCH_FT;
CCalltoParams params; bool bSecure = FALSE;
LPTSTR szName; hr = BSTR_to_LPTSTR (&szName, bstrAddr); if (SUCCEEDED(hr)) { params.SetParams(szName); bSecure = params.GetBooleanParam("secure",bSecure); delete (szName); }
if(ConfPolicies::OutgoingSecurityPreferred() || bSecure) { ulCaps |= NMCH_SECURE; }
hr = m_spInternalNmManager->CreateConference(&spInternalINmConference, NULL, NULL, ulCaps); if(SUCCEEDED(hr)) { // the above call to CreateConference generates a callback, so we have this object now!
pConference = GetSDKConferenceFromInternalConference(spInternalINmConference); } } }
CComPtr<INmCall> spInternalINmCall;
if(SUCCEEDED(hr)) { if(addrType == NM_ADDR_CALLTO) { ASSERT( g_pCCallto != NULL );
if(NM_CALL_DEFAULT == callType) { LPTSTR szName; hr = BSTR_to_LPTSTR (&szName, bstrAddr); if (SUCCEEDED(hr)) { hr = g_pCCallto->Callto(szName, // pointer to the callto url to try to place the call with...
NULL, // pointer to the display name to use...
NM_ADDR_CALLTO, // callto type to resolve this callto as...
false, // the pszCallto parameter is to be interpreted as a pre-unescaped addressing component vs a full callto...
NULL, // security preference, NULL for none. must be "compatible" with secure param if present...
false, // whether or not save in mru...
false, // whether or not to perform user interaction on errors...
NULL, // if bUIEnabled is true this is the window to parent error/status windows to...
&spInternalINmCall ); // out pointer to INmCall * to receive INmCall * generated by placing call...
delete (szName); } else { goto end; } } else { hr = E_INVALIDARG; goto end; } } else { hr = SdkPlaceCall(callType, addrType, bstrAddr, NULL, NULL, &spInternalINmCall); }
if(SUCCEEDED(hr)) { CallCreated(spInternalINmCall);
if(ppCall) { *ppCall = GetSDKCallFromInternalCall(spInternalINmCall); if(*ppCall) { (*ppCall)->AddRef(); } } } } } else { hr = E_UNEXPECTED; ERROR_OUT(("Why don't we have a manager object")); }
end: DBGEXIT_HR(CNmManagerObj::CreateCall,hr); return hr; }
STDMETHODIMP CNmManagerObj::CallConference(INmCall **ppCall, NM_CALL_TYPE callType, NM_ADDR_TYPE addrType, BSTR bstrAddr, BSTR bstrConferenceName, BSTR bstrPassword) { DBGENTRY(CNmManagerObj::CallConference); HRESULT hr = S_OK; if(!m_bInitialized) { hr = NM_E_NOT_INITIALIZED; goto end; }
if(!m_bNmActive) { hr = NM_E_NOT_ACTIVE; goto end; }
{ CComPtr<INmCall> spInternalINmCall;
hr = SdkPlaceCall(callType, addrType, bstrAddr, bstrConferenceName, bstrPassword, &spInternalINmCall); if(SUCCEEDED(hr)) { CallCreated(spInternalINmCall); *ppCall = GetSDKCallFromInternalCall(spInternalINmCall); if(*ppCall) { (*ppCall)->AddRef(); } } }
end: DBGEXIT_HR(CNmManagerObj::CallConference,hr); return hr; }
STDMETHODIMP CNmManagerObj::EnumCall(IEnumNmCall **ppEnum) { DBGENTRY(CNmManagerObj::EnumCall); HRESULT hr = S_OK;
if(m_bInitialized) { if(m_bNmActive) { hr = CreateEnumFromSimpleAryOfInterface<IEnumNmCall, INmCall>(m_SDKCallObjs, ppEnum); } else { hr = NM_E_NOT_ACTIVE; } } else { hr = NM_E_NOT_INITIALIZED; }
DBGEXIT_HR(CNmManagerObj::EnumCall,hr); return hr; }
///////////////////////////////////////////////
// INmObject methods
///////////////////////////////////////////////
STDMETHODIMP CNmManagerObj::CallDialog(long hwnd, int cdOptions) { DBGENTRY(CNmManagerObj::CallDialog); HRESULT hr = S_OK;
CFindSomeone::findSomeone(GetConfRoom());
g_bSDKPostNotifications = true;
if(OfficeMode() && !m_bSentConferenceCreated) { Fire_ConferenceCreated(m_SDKConferenceObjs[0]); }
g_bSDKPostNotifications = false;
DBGEXIT_HR(CNmManagerObj::CallDialog,hr); return hr;
}
extern "C" { BOOL WINAPI StartStopOldWB(LPCTSTR lpsz); }
STDMETHODIMP CNmManagerObj::ShowLocal(NM_APPID id) { if(!m_bInitialized) { return NM_E_NOT_INITIALIZED; }
if(!m_bNmActive) { return NM_E_NOT_ACTIVE; }
switch (id) { case NM_APPID_WHITEBOARD: StartStopOldWB(NULL); return S_OK;
case NM_APPID_T126_WHITEBOARD: return (T120_NO_ERROR == ::T120_LoadApplet(APPLET_ID_WB, TRUE , 0, FALSE, NULL)) ? S_OK : E_FAIL;
case NM_APPID_CHAT: return (T120_NO_ERROR == T120_LoadApplet(APPLET_ID_CHAT, TRUE , 0, FALSE, NULL)) ? S_OK : E_FAIL;
case NM_APPID_FILE_TRANSFER: return CFt::ShowFtUI();
case NM_APPID_APPSHARING: if(g_pConfRoom && g_pConfRoom->IsSharingAllowed()) { g_pConfRoom->CmdShowSharing(); return S_OK; } return NM_E_SHARING_NOT_AVAILABLE;
default: ERROR_OUT(("Unknown flag passed to ShowLocal")); break; }
return E_INVALIDARG; }
STDMETHODIMP CNmManagerObj::VerifyUserInfo(UINT_PTR hwnd, NM_VUI options) { ASSERT(0); return E_UNEXPECTED; }
////////////////////////////////////////////////////////////
// IInternalConfExe
////////////////////////////////////////////////////////////
STDMETHODIMP CNmManagerObj::LoggedIn() { DBGENTRY(STDMETHODIMP CNmManagerObj::LoggedIn); HRESULT hr = g_fLoggedOn ? S_OK : S_FALSE;
DBGEXIT_HR(STDMETHODIMP CNmManagerObj::LoggedIn,hr); return hr; }
STDMETHODIMP CNmManagerObj::IsRunning() { DBGENTRY(STDMETHODIMP CNmManagerObj::IsRunning); HRESULT hr = g_pInternalNmManager ? S_OK : S_FALSE;
DBGEXIT_HR(STDMETHODIMP CNmManagerObj::IsRunning,hr); return hr; }
STDMETHODIMP CNmManagerObj::InConference() { DBGENTRY(STDMETHODIMP CNmManagerObj::InConference); HRESULT hr = ::FIsConferenceActive() ? S_OK : S_FALSE;
DBGEXIT_HR(STDMETHODIMP CNmManagerObj::InConference,hr); return hr; }
STDMETHODIMP CNmManagerObj::LDAPLogon(BOOL bLogon) { DBGENTRY(STDMETHODIMP CNmManagerObj::LDAPLogon); HRESULT hr = S_OK;
if(g_pLDAP) { hr = bLogon ? g_pLDAP->LogonAsync() : g_pLDAP->Logoff(); } else { hr = E_FAIL; }
DBGEXIT_HR(STDMETHODIMP CNmManagerObj::LDAPLogon,hr); return hr; }
STDMETHODIMP CNmManagerObj::GetLocalCaps(DWORD* pdwLocalCaps) { DBGENTRY(STDMETHODIMP CNmManagerObj::); HRESULT hr = S_OK;
*pdwLocalCaps = g_uMediaCaps;
DBGEXIT_HR(STDMETHODIMP CNmManagerObj::,hr); return hr; }
STDMETHODIMP CNmManagerObj::IsNetMeetingRunning() { return g_pInternalNmManager ? S_OK : S_FALSE; }
STDMETHODIMP CNmManagerObj::GetActiveConference(INmConference** ppConf) { if(ppConf && ms_pManagerObjList && m_dwSysInfoID) { for(int i = 0; i < ms_pManagerObjList->GetSize(); ++i) { if((*ms_pManagerObjList)[i]->m_dwID == m_dwSysInfoID) { if((*ms_pManagerObjList)[i]->m_SDKConferenceObjs.GetSize() != 0) { *ppConf = (*ms_pManagerObjList)[i]->m_SDKConferenceObjs[0]; (*ppConf)->AddRef(); return S_OK; } } } }
return E_FAIL; }
//--------------------------------------------------------------------------//
// CNmManagerObj::ShellCalltoProtocolHandler. //
//--------------------------------------------------------------------------//
STDMETHODIMP CNmManagerObj::ShellCalltoProtocolHandler ( BSTR url, BOOL bStrict ){ ASSERT( g_pCCallto != NULL );
HRESULT result = S_OK; if(!g_pInternalNmManager) { if(!CheckRemoteControlService()) { return E_FAIL; }
result = InitConfExe(); }
if( SUCCEEDED( result ) ) { LPTSTR szName; result = BSTR_to_LPTSTR (&szName, url); if (SUCCEEDED(result)) { if(CCallto::DoUserValidation(szName)) { result = g_pCCallto->Callto(szName, // pointer to the callto url to try to place the call with...
NULL, // pointer to the display name to use...
NM_ADDR_CALLTO, // callto type to resolve this callto as...
false, // the pszCallto parameter is to be interpreted as a pre-unescaped addressing component vs a full callto...
NULL, // security preference, NULL for none. must be "compatible" with secure param if present...
false, // whether or not save in mru...
true, // whether or not to perform user interaction on errors...
NULL, // if bUIEnabled is true this is the window to parent error/status windows to...
NULL ); // out pointer to INmCall * to receive INmCall * generated by placing call...
}
delete (szName); } }
return( result );
} // End of CNmManagerObj::ShellCalltoProtocolHandler.
//--------------------------------------------------------------------------//
// CNmManagerObj::Launch. //
//--------------------------------------------------------------------------//
STDMETHODIMP CNmManagerObj::Launch() { if(_Module.InitControlMode()) { return E_FAIL; } else { if(!g_pInternalNmManager) { if(!CheckRemoteControlService()) { return E_FAIL; }
InitConfExe(); } else { ::CreateConfRoomWindow(); } }
return S_OK;
} // End of CNmManagerObj::Launch.
LPTSTR StripDoubleQuotes(LPTSTR sz) { BOOL fSkippedQuote = FALSE;
if (sz) { int cchLength;
// Skip past first quote
if (fSkippedQuote = (*sz == '"')) sz++;
cchLength = lstrlen(sz);
//
// NOTE:
// There may be DBCS implications with this. Hence we check to see
// if we skipped the first quote; we assume that if the file name
// starts with a quote it must end with one also. But we need to check
// it out.
//
// Strip last quote
if (fSkippedQuote && (cchLength > 0) && (sz[cchLength - 1] == '"')) { BYTE * pLastQuote = (BYTE *)&sz[cchLength - 1]; *pLastQuote = '\0'; } }
return sz; }
STDMETHODIMP CNmManagerObj::LaunchApplet(NM_APPID appid, BSTR strCmdLine) {
if(!g_pInternalNmManager) { if(!CheckRemoteControlService()) { return E_FAIL; }
InitConfExe(); }
LPTSTR szName = NULL; BSTR_to_LPTSTR (&szName, strCmdLine);
switch(appid) { case NM_APPID_WHITEBOARD: CmdShowOldWhiteboard(strCmdLine ? StripDoubleQuotes(szName) : NULL); break;
case NM_APPID_T126_WHITEBOARD: ::CmdShowNewWhiteboard(strCmdLine ? StripDoubleQuotes(szName) : NULL); break;
case NM_APPID_CHAT: CmdShowChat(); break; }
if(szName) { delete (szName); }
return S_OK; }
STDMETHODIMP CNmManagerObj::GetUserData(REFGUID rguid, BYTE **ppb, ULONG *pcb) { if(g_pNmSysInfo) { return g_pNmSysInfo->GetUserData(rguid, ppb, pcb); }
return NM_E_NOT_ACTIVE; }
STDMETHODIMP CNmManagerObj::SetUserData(REFGUID rguid, BYTE *pb, ULONG cb) { //
// Special case this guid to allow changing cert via SetUserData
//
if ( g_csguidSecurity == rguid ) { return SetCertFromCertInfo ( (PCERT_INFO) pb ); } if(g_pNmSysInfo) { return g_pNmSysInfo->SetUserData(rguid, pb, cb); }
return NM_E_NOT_ACTIVE; }
STDMETHODIMP CNmManagerObj::DisableH323(BOOL bDisableH323) { if(!g_pInternalNmManager) { _Module.SetSDKDisableH323(bDisableH323); return S_OK; }
return NM_E_ALREADY_RUNNING; }
STDMETHODIMP CNmManagerObj::SetCallerIsRTC (BOOL bCallerIsRTC) { if(!g_pInternalNmManager) { _Module.SetSDKCallerIsRTC(bCallerIsRTC); return S_OK; }
return NM_E_ALREADY_RUNNING; }
STDMETHODIMP CNmManagerObj::DisableInitialILSLogon(BOOL bDisable) { if(!g_pInternalNmManager) { _Module.SetSDKDisableInitialILSLogon(bDisable); return S_OK; }
return NM_E_ALREADY_RUNNING; }
///////////////////////////////////////////////
// INmManagerNotify methods:
///////////////////////////////////////////////
STDMETHODIMP CNmManagerObj::NmUI(CONFN uNotify) { DBGENTRY(CNmManagerObj::NmUI); HRESULT hr = S_OK;
// We should not be sending other notifactions
ASSERT(CONFN_NM_STARTED == uNotify); hr = Fire_NmUI(uNotify);
DBGEXIT_HR(CNmManagerObj::NmUI,hr); return hr; }
STDMETHODIMP CNmManagerObj::ConferenceCreated(INmConference *pInternalConference) { DBGENTRY(CNmManagerOebj::ConferenceCreated); HRESULT hr = S_OK;
CComPtr<INmConference> spConf;
hr = CNmConferenceObj::CreateInstance(this, pInternalConference, &spConf);
if(SUCCEEDED(hr)) { spConf.p->AddRef(); m_SDKConferenceObjs.Add(spConf.p); Fire_ConferenceCreated(spConf);
if(!CFt::IsFtActive() && FileTransferNotifications()) { CFt::StartNewConferenceSession(); } }
DBGEXIT_HR(CNmManagerObj::ConferenceCreated,hr); return hr; }
STDMETHODIMP CNmManagerObj::CallCreated(INmCall *pInternalCall) { DBGENTRY(CNmManagerObj::CallCreated); HRESULT hr = S_OK;
if(m_bInitialized) { if(NULL == GetSDKCallFromInternalCall(pInternalCall)) { // First we make sure that we don't have the call object yet
CComPtr<INmCall> spCall; hr = CNmCallObj::CreateInstance(this, pInternalCall, &spCall);
if(SUCCEEDED(hr)) { spCall.p->AddRef(); m_SDKCallObjs.Add(spCall.p); Fire_CallCreated(spCall); } } }
DBGEXIT_HR(CNmManagerObj::CallCreated,hr); return hr; }
///////////////////////////////////////////////
// Notifications
///////////////////////////////////////////////
HRESULT CNmManagerObj::Fire_ConferenceCreated(INmConference *pConference) { DBGENTRY(CNmManagerObj::Fire_ConferenceCreated); HRESULT hr = S_OK;
// Som SDK clients need this to come in at a specific time....
if(m_bSentConferenceCreated || OfficeMode() && g_bOfficeModeSuspendNotifications) { // We don't have to notify anyone at all...
return S_OK; }
if(!g_bSDKPostNotifications) { IConnectionPointImpl<CNmManagerObj, &IID_INmManagerNotify, CComDynamicUnkArray>* pCP = this;
for(int i = 0; i < pCP->m_vec.GetSize(); ++i ) { m_bSentConferenceCreated = true;
INmManagerNotify* pNotify = reinterpret_cast<INmManagerNotify*>(pCP->m_vec.GetAt(i));
if(pNotify) { pNotify->ConferenceCreated(pConference);
// Sinc up the channels, etc.
com_cast<IInternalConferenceObj>(pConference)->FireNotificationsToSyncToInternalObject();
} } } else { hr = CSDKWindow::PostConferenceCreated(this, pConference); }
DBGEXIT_HR(CNmManagerObj::Fire_ConferenceCreated,hr); return hr; }
HRESULT CNmManagerObj::Fire_CallCreated(INmCall* pCall) { DBGENTRY(CNmManagerObj::Fire_CallCreated); HRESULT hr = S_OK;
// Always send Outgoing call notifications
// Only send incoming call notifications to INIT CONTROL clients.
if((S_OK != pCall->IsIncoming()) || _Module.InitControlMode()) { if(!g_bSDKPostNotifications) { IConnectionPointImpl<CNmManagerObj, &IID_INmManagerNotify, CComDynamicUnkArray>* pCP = this;
for(int i = 0; i < pCP->m_vec.GetSize(); ++i ) { INmManagerNotify* pNotify = reinterpret_cast<INmManagerNotify*>(pCP->m_vec.GetAt(i));
if(pNotify) { pNotify->CallCreated(pCall); } } } else { hr = CSDKWindow::PostCallCreated(this, pCall); } }
DBGEXIT_HR(CNmManagerObj::Fire_CallCreated,hr); return hr; }
HRESULT CNmManagerObj::Fire_NmUI(CONFN uNotify) { DBGENTRY(CNmManagerObj::Fire_NmUI); HRESULT hr = S_OK;
// notice the InSendMessage statement.
// The problem is that we can get this notificaiton in
// response to the taskbar icon being clicked. In that case
// an inter-thread SendMessage is occuring. If we try to make
// the NmUi call, we will get RPC_E_CANTCALLOUT_INPUTSYNCCALL
if(!g_bSDKPostNotifications && !InSendMessage()) { IConnectionPointImpl<CNmManagerObj, &IID_INmManagerNotify, CComDynamicUnkArray>* pCP = this;
for(int i = 0; i < pCP->m_vec.GetSize(); ++i ) { INmManagerNotify* pNotify = reinterpret_cast<INmManagerNotify*>(pCP->m_vec.GetAt(i)); if(pNotify) { pNotify->NmUI(uNotify); } } } else { hr = CSDKWindow::PostManagerNmUI(this, uNotify); }
DBGEXIT_HR(CNmManagerObj::Fire_NmUI,hr); return hr; }
///////////////////////////////////////////////
// Helper Fns
///////////////////////////////////////////////
INmConference* CNmManagerObj::_GetActiveConference() { INmConference* pConf = NULL;
if(m_SDKConferenceObjs.GetSize()) { pConf = m_SDKConferenceObjs[0]; }
return pConf; }
INmCall* CNmManagerObj::GetSDKCallFromInternalCall(INmCall* pInternalCall) {
INmCall* pRet = NULL;
for( int i = 0; i < m_SDKCallObjs.GetSize(); ++i) { CComQIPtr<IInternalCallObj> spInternal = m_SDKCallObjs[i]; ASSERT(spInternal);
CComPtr<INmCall> spCall; if(SUCCEEDED(spInternal->GetInternalINmCall(&spCall))) { if(spCall.IsEqualObject(pInternalCall)) { pRet = m_SDKCallObjs[i]; break; } } }
return pRet; }
INmConference* CNmManagerObj::GetSDKConferenceFromInternalConference(INmConference* pInternalConference) {
INmConference* pRet = NULL;
for( int i = 0; i < m_SDKConferenceObjs.GetSize(); ++i) { CComQIPtr<IInternalConferenceObj> spInternal = m_SDKConferenceObjs[i]; ASSERT(spInternal);
CComPtr<INmConference> spConference; if(SUCCEEDED(spInternal->GetInternalINmConference(&spConference))) { if(spConference.IsEqualObject(pInternalConference)) { pRet = m_SDKConferenceObjs[i]; break; } } }
return pRet; }
HRESULT CNmManagerObj::RemoveCall(INmCall* pSDKCallObj) { HRESULT hr = S_OK; for(int i = 0; i < m_SDKCallObjs.GetSize(); ++i) { CComPtr<INmCall> spSDKCallObj = m_SDKCallObjs[i]; if(spSDKCallObj.IsEqualObject(pSDKCallObj)) { m_SDKCallObjs.RemoveAt(i); spSDKCallObj.p->Release(); } }
return hr; }
HRESULT CNmManagerObj::RemoveConference(INmConference* pSDKConferenceObj) { HRESULT hr = S_OK; for(int i = 0; i < m_SDKConferenceObjs.GetSize(); ++i) { CComPtr<INmConference> spSDKConferenceObj = m_SDKConferenceObjs[i]; if(spSDKConferenceObj.IsEqualObject(pSDKConferenceObj)) { m_SDKConferenceObjs.RemoveAt(i); spSDKConferenceObj.p->Release(); } }
return hr; }
bool CNmManagerObj::AudioNotifications() { return m_bInitialized && (m_chCaps & NMCH_AUDIO); }
bool CNmManagerObj::VideoNotifications() { return m_bInitialized && (m_chCaps & NMCH_VIDEO); }
bool CNmManagerObj::DataNotifications() { return m_bInitialized && (m_chCaps & NMCH_DATA); }
bool CNmManagerObj::FileTransferNotifications() { return m_bInitialized && (m_chCaps & NMCH_FT); }
bool CNmManagerObj::AppSharingNotifications() { return m_bInitialized && (m_chCaps & NMCH_SHARE); }
//static
void CNmManagerObj::NetMeetingLaunched() { ASSERT(ms_pManagerObjList);
if(ms_pManagerObjList) { for( int i = 0; i < ms_pManagerObjList->GetSize(); ++i) { (*ms_pManagerObjList)[i]->Fire_NmUI(CONFN_NM_STARTED); } } }
//static
void CNmManagerObj::SharableAppStateChanged(HWND hWnd, NM_SHAPP_STATE state) { if(ms_pManagerObjList) { for( int i = 0; i < ms_pManagerObjList->GetSize(); ++i) { (*ms_pManagerObjList)[i]->_SharableAppStateChanged(hWnd, state); } } }
void CNmManagerObj::_SharableAppStateChanged(HWND hWnd, NM_SHAPP_STATE state) { // Free our conferencing objects
for(int i = 0; i < m_SDKConferenceObjs.GetSize(); ++i) { com_cast<IInternalConferenceObj>(m_SDKConferenceObjs[i])->SharableAppStateChanged(hWnd, state); } }
//static
void CNmManagerObj::AppSharingChannelChanged() { if(ms_pManagerObjList) { for( int i = 0; i < ms_pManagerObjList->GetSize(); ++i) { (*ms_pManagerObjList)[i]->_AppSharingChannelChanged(); } } }
void CNmManagerObj::_AppSharingChannelChanged() { // Free our conferencing objects
for(int i = 0; i < m_SDKConferenceObjs.GetSize(); ++i) { com_cast<IInternalConferenceObj>(m_SDKConferenceObjs[i])->AppSharingChannelChanged(); } }
//static
void CNmManagerObj::AppSharingChannelActiveStateChanged(bool bActive) { if(ms_pManagerObjList) { for( int i = 0; i < ms_pManagerObjList->GetSize(); ++i) { (*ms_pManagerObjList)[i]->_AppSharingChannelActiveStateChanged(bActive); } } }
void CNmManagerObj::_AppSharingChannelActiveStateChanged(bool bActive) { // Free our conferencing objects
for(int i = 0; i < m_SDKConferenceObjs.GetSize(); ++i) { com_cast<IInternalConferenceObj>(m_SDKConferenceObjs[i])->AppSharingStateChanged(bActive); } }
//static
void CNmManagerObj::ASLocalMemberChanged() { if(ms_pManagerObjList) { for( int i = 0; i < ms_pManagerObjList->GetSize(); ++i) { (*ms_pManagerObjList)[i]->_ASLocalMemberChanged(); } } }
void CNmManagerObj::_ASLocalMemberChanged() { // notify our conferencing objects
for(int i = 0; i < m_SDKConferenceObjs.GetSize(); ++i) { com_cast<IInternalConferenceObj>(m_SDKConferenceObjs[i])->ASLocalMemberChanged(); } }
//static
void CNmManagerObj::ASMemberChanged(UINT gccID) { if(ms_pManagerObjList) { for( int i = 0; i < ms_pManagerObjList->GetSize(); ++i) { (*ms_pManagerObjList)[i]->_ASMemberChanged(gccID); } } }
void CNmManagerObj::_ASMemberChanged(UINT gccID) { // notify our conferencing objects
for(int i = 0; i < m_SDKConferenceObjs.GetSize(); ++i) { com_cast<IInternalConferenceObj>(m_SDKConferenceObjs[i])->ASMemberChanged(gccID); } }
// static
void CNmManagerObj::AudioChannelActiveState(BOOL bActive, BOOL bIsIncoming) { if(ms_pManagerObjList) { for( int i = 0; i < ms_pManagerObjList->GetSize(); ++i) { (*ms_pManagerObjList)[i]->_AudioChannelActiveState(bActive, bIsIncoming); } } }
void CNmManagerObj::_AudioChannelActiveState(BOOL bActive, BOOL bIsIncoming) { // notify our conferencing objects
for(int i = 0; i < m_SDKConferenceObjs.GetSize(); ++i) { com_cast<IInternalConferenceObj>(m_SDKConferenceObjs[i])->AudioChannelActiveState(bActive ? TRUE : FALSE, bIsIncoming); } }
// static
void CNmManagerObj::VideoChannelActiveState(BOOL bActive, BOOL bIsIncoming) { if(ms_pManagerObjList) { for( int i = 0; i < ms_pManagerObjList->GetSize(); ++i) { (*ms_pManagerObjList)[i]->_VideoChannelActiveState(bActive, bIsIncoming); } } }
void CNmManagerObj::_VideoChannelActiveState(BOOL bActive, BOOL bIsIncoming) { // notify our conferencing objects
for(int i = 0; i < m_SDKConferenceObjs.GetSize(); ++i) { com_cast<IInternalConferenceObj>(m_SDKConferenceObjs[i])->VideoChannelActiveState(bActive ? TRUE : FALSE, bIsIncoming); } }
// static
void CNmManagerObj::VideoPropChanged(DWORD dwProp, BOOL bIsIncoming) { if(ms_pManagerObjList) { for( int i = 0; i < ms_pManagerObjList->GetSize(); ++i) { (*ms_pManagerObjList)[i]->_VideoPropChanged(dwProp, bIsIncoming); } } }
void CNmManagerObj::_VideoPropChanged(DWORD dwProp, BOOL bIsIncoming) { // notify our conferencing objects
for(int i = 0; i < m_SDKConferenceObjs.GetSize(); ++i) { com_cast<IInternalConferenceObj>(m_SDKConferenceObjs[i])->VideoChannelPropChanged(dwProp, bIsIncoming); } }
// static
void CNmManagerObj::VideoChannelStateChanged(NM_VIDEO_STATE uState, BOOL bIsIncoming) { if(ms_pManagerObjList) { for( int i = 0; i < ms_pManagerObjList->GetSize(); ++i) { (*ms_pManagerObjList)[i]->_VideoChannelStateChanged(uState, bIsIncoming); } } }
void CNmManagerObj::_VideoChannelStateChanged(NM_VIDEO_STATE uState, BOOL bIsIncoming) { // notify our conferencing objects
for(int i = 0; i < m_SDKConferenceObjs.GetSize(); ++i) { com_cast<IInternalConferenceObj>(m_SDKConferenceObjs[i])->VideoChannelStateChanged(uState, bIsIncoming); } }
UINT CNmManagerObj::GetManagerCount(ULONG uOption) { UINT nMgrs = 0; for(int i = 0; i < ms_pManagerObjList->GetSize(); ++i) { if(uOption == (*ms_pManagerObjList)[i]->m_uOptions) { nMgrs++; } } return nMgrs; }
void CNmManagerObj::OnShowUI(BOOL fShow) { _Module.SetUIVisible(fShow);
if (fShow) { CConfMan::AllowAV(TRUE); } else { if(0 != GetManagerCount(NM_INIT_OBJECT)) { CConfMan::AllowAV(FALSE); } } }
HRESULT CNmManagerObj::SdkPlaceCall(NM_CALL_TYPE callType, NM_ADDR_TYPE addrType, BSTR bstrAddr, BSTR bstrConf, BSTR bstrPw, INmCall **ppInternalCall) {
HRESULT hr; LPTSTR szAddr = NULL; LPTSTR szConf = NULL; LPTSTR szPw = NULL;
DWORD dwFlags = MapNmCallTypeToCallFlags(callType, addrType, g_uMediaCaps); if (0 == dwFlags) { hr = NM_CALLERR_MEDIA; goto end; }
{
BSTR_to_LPTSTR (&szAddr, bstrAddr);
if(NM_ADDR_T120_TRANSPORT == addrType) { //
// Check if "+secure=true" parameter was passed
//
CCalltoParams params; bool bSecure = FALSE;
params.SetParams(szAddr); bSecure = params.GetBooleanParam("secure",bSecure);
//
// Yes it was in the parameters.
// Now make sure to remove it
// The addre now is like "111.222.333.444+secure=true"
// The call will only work if we pass the ip address only
//
if(bSecure) {
// Get the syze of the bstr
int cch = lstrlen(szAddr); BYTE *pByte = (BYTE *) szAddr;
for(int i = 0; i < cch;i++) { // Null terminate the string
if(*pByte == '+') { *pByte = '\0'; break; } pByte++; } dwFlags |= CRPCF_SECURE; } } CCallResolver CallResolver(szAddr, addrType); hr = CallResolver.Resolve(); if (FAILED(hr)) { goto end; }
CCall* pCall = new CCall(CallResolver.GetPszAddr(), szAddr, NM_ADDR_CALLTO, FALSE, FALSE);
if(NULL == pCall) { goto end; }
pCall->AddRef(); switch(CallResolver.GetAddrType()) { case NM_ADDR_ULS: case NM_ADDR_IP: case NM_ADDR_MACHINENAME: case NM_ADDR_H323_GATEWAY: ASSERT(FIpAddress(CallResolver.GetPszAddrIP())); /////////////////////////////////////////////
// !!!!! HEY RYAN, WERE FALLING THROUGH !!!!!
/////////////////////////////////////////////
case NM_ADDR_T120_TRANSPORT:
BSTR_to_LPTSTR (&szConf, bstrConf); BSTR_to_LPTSTR (&szPw, bstrPw); hr = pCall->PlaceCall( dwFlags, // dwFlags
CallResolver.GetAddrType(), // addrType
NULL, // szSetup
(NM_ADDR_T120_TRANSPORT == CallResolver.GetAddrType()) ? CallResolver.GetPszAddr() : CallResolver.GetPszAddrIP(), // szDestination
CallResolver.GetPszAddr(),// szAlias
NULL, // szURL
(szConf), // szConference
(szPw), // szPassword
NULL); // szUserData
break;
default: ERROR_OUT(("Don't know this call type")); ASSERT(0); break; }
if( FAILED(hr) && (pCall->GetState() == NM_CALL_INVALID ) ) { // just release the call to free the data
// otherwise wait for the call state to be changed
pCall->Release(); }
if(ppInternalCall && SUCCEEDED(hr)) { *ppInternalCall = pCall->GetINmCall(); (*ppInternalCall)->AddRef(); }
pCall->Release(); }
end:
if( FAILED( hr ) && _Module.IsUIActive() ) { DisplayCallError( hr, szAddr ); }
delete szAddr; delete szConf; delete szPw;
return hr; }
DWORD CNmManagerObj::MapNmCallTypeToCallFlags(NM_CALL_TYPE callType, NM_ADDR_TYPE addrType, UINT uCaps) { DWORD dwFlags = 0; BOOL fForceSecure = FALSE;
// Check global conference status
if (INmConference *pConf = ::GetActiveConference()) { // We are in a conference. Use the conference security setting.
DWORD dwCaps;
if ((S_OK == pConf->GetNmchCaps(&dwCaps)) && (NMCH_SECURE & dwCaps)) { fForceSecure = TRUE; } } else { fForceSecure = (REQUIRED_POL_SECURITY == ConfPolicies::GetSecurityLevel()); }
switch(addrType) { case NM_ADDR_T120_TRANSPORT: dwFlags = CRPCF_T120 | CRPCF_DATA; if(ConfPolicies::OutgoingSecurityPreferred() || fForceSecure) { dwFlags |= CRPCF_SECURE; }
break;
default: switch (callType) { case NM_CALL_T120: if (fForceSecure) { dwFlags = CRPCF_T120 | CRPCF_DATA | CRPCF_SECURE; } else { dwFlags = CRPCF_T120 | CRPCF_DATA; } break;
case NM_CALL_H323: if (!fForceSecure) { dwFlags = CRPCF_H323CC; if (uCaps & (CAPFLAG_RECV_AUDIO | CAPFLAG_SEND_AUDIO)) dwFlags |= CRPCF_AUDIO; if (uCaps & (CAPFLAG_RECV_VIDEO | CAPFLAG_SEND_VIDEO)) dwFlags |= CRPCF_VIDEO; } break;
case NM_CALL_DEFAULT: if (fForceSecure) { dwFlags = CRPCF_T120 | CRPCF_DATA | CRPCF_SECURE; } else { dwFlags = CRPCF_DEFAULT; // strip AV if policies prohibit
if((uCaps & (CAPFLAG_RECV_AUDIO |CAPFLAG_SEND_AUDIO)) == 0) { dwFlags &= ~CRPCF_AUDIO; } if((uCaps & (CAPFLAG_RECV_VIDEO |CAPFLAG_SEND_VIDEO)) == 0) { dwFlags &= ~CRPCF_VIDEO; } } break;
default: dwFlags = 0; break; } }
return dwFlags; }
|