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.
607 lines
14 KiB
607 lines
14 KiB
#include "precomp.h"
|
|
#include "NetMeeting.h"
|
|
#include "mslablti.h"
|
|
#include "nameres.h"
|
|
#include "conf.h"
|
|
#include "ConfRoom.h"
|
|
#include "call.h"
|
|
#include "conf.h"
|
|
#include "Callto.h"
|
|
#include "version.h"
|
|
|
|
// NetMeeting SDK includes
|
|
#include "SdkInternal.h"
|
|
#include "NmEnum.h"
|
|
#include "NmMember.h"
|
|
#include "NmManager.h"
|
|
#include "NmConference.h"
|
|
#include "NmCall.h"
|
|
#include "SDKWindow.h"
|
|
#include "NmApp.h"
|
|
|
|
//////////////////////////////////////////
|
|
// Static Data
|
|
//////////////////////////////////////////
|
|
|
|
/*static*/ CSimpleArray<CNetMeetingObj*>* CNetMeetingObj::ms_pNetMeetingObjList = NULL;
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// Construction / Destruction
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
static SIZE s_CreateModeSizeMap[] =
|
|
{
|
|
{ 244, 410 }, // CMainUI::CreateFull
|
|
{ 244, 158 }, // CMainUI::CreateDataOnly
|
|
{ 196, 200 }, // CMainUI::CreatePreviewOnly
|
|
{ 196, 200 }, // CMainUI::CreateRemoteOnly
|
|
{ 180, 148 }, // CMainUI::CreatePreviewNoPause
|
|
{ 180, 148 }, // CMainUI::CreateRemoteNoPause
|
|
{ 240, 318 }, // CMainUI::CreateTelephone
|
|
};
|
|
|
|
|
|
|
|
CNetMeetingObj::CNetMeetingObj()
|
|
: m_pMainView(NULL),
|
|
m_CreateMode(CMainUI::CreateFull)
|
|
{
|
|
DBGENTRY(CNetMeetingObj::CNetMeetingObj);
|
|
|
|
m_bAutoSize = true;
|
|
m_bDrawFromNatural = true;
|
|
m_bWindowOnly = true;
|
|
|
|
SIZE sizehm;
|
|
AtlPixelToHiMetric(&s_CreateModeSizeMap[m_CreateMode], &m_sizeNatural);
|
|
m_sizeExtent = m_sizeNatural;
|
|
|
|
CNetMeetingObj* p = const_cast<CNetMeetingObj*>(this);
|
|
ms_pNetMeetingObjList->Add(p);
|
|
|
|
DBGEXIT(CNetMeetingObj::CNetMeetingObj);
|
|
}
|
|
|
|
CNetMeetingObj::~CNetMeetingObj()
|
|
{
|
|
DBGENTRY(CNetMeetingObj::~CNetMeetingObj);
|
|
|
|
if(m_pMainView)
|
|
{
|
|
m_pMainView->Release();
|
|
m_pMainView = NULL;
|
|
}
|
|
|
|
CNetMeetingObj* p = const_cast<CNetMeetingObj*>(this);
|
|
ms_pNetMeetingObjList->Remove(p);
|
|
|
|
// If we are the last guy on the block, we should delay unload
|
|
if(0 == _Module.GetLockCount())
|
|
{
|
|
_Module.Lock();
|
|
CSDKWindow::PostDelayModuleUnlock();
|
|
}
|
|
|
|
DBGEXIT(CNetMeetingObj::~CNetMeetingObj);
|
|
}
|
|
|
|
|
|
LRESULT CNetMeetingObj::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
|
{
|
|
if(SIZE_MINIMIZED != wParam)
|
|
{
|
|
if(m_pMainView)
|
|
{
|
|
int nWidth = LOWORD(lParam); // width of client area
|
|
int nHeight = HIWORD(lParam); // height of client area
|
|
|
|
::SetWindowPos(m_pMainView->GetWindow(), NULL, 0, 0, nWidth, nHeight, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
LRESULT CNetMeetingObj::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
|
{
|
|
BOOL bInConference;
|
|
if(!_Module.IsUIVisible())
|
|
{
|
|
if(SUCCEEDED(IsInConference(&bInConference)) && bInConference)
|
|
{
|
|
|
|
USES_RES2T
|
|
TCHAR res1[RES_CH_MAX];
|
|
RES2T(IDS_CONTAINER_GOING_AWAY_BUT_ACVITE_CONFERENCE);
|
|
COPY_RES2T(res1);
|
|
|
|
int iRet = ::MessageBox(m_hWnd,
|
|
res1,
|
|
RES2T(IDS_MSGBOX_TITLE),
|
|
MB_SETFOREGROUND | MB_YESNO | MB_ICONQUESTION);
|
|
if(IDNO == iRet)
|
|
{
|
|
UnDock();
|
|
}
|
|
else
|
|
{
|
|
// This means that the user wants to close the conference
|
|
ASSERT(g_pConfRoom);
|
|
if(g_pConfRoom)
|
|
{
|
|
g_pConfRoom->LeaveConference();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT(g_pConfRoom);
|
|
|
|
if(g_pConfRoom)
|
|
{
|
|
// Bring the window to the front
|
|
g_pConfRoom->BringToFront();
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
HRESULT CNetMeetingObj::FinalConstruct()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if(!g_pInternalNmManager)
|
|
{
|
|
|
|
if(!CheckRemoteControlService())
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
hr = InitConfExe(FALSE);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//static
|
|
HRESULT CNetMeetingObj::InitSDK()
|
|
{
|
|
DBGENTRY(CNetMeetingObj::InitSDK);
|
|
HRESULT hr = S_OK;
|
|
|
|
ASSERT(NULL == ms_pNetMeetingObjList);
|
|
|
|
hr = (ms_pNetMeetingObjList = new CSimpleArray<CNetMeetingObj*>) ? S_OK : E_OUTOFMEMORY;
|
|
|
|
DBGEXIT_HR(CNetMeetingObj::InitSDK,hr);
|
|
return hr;
|
|
}
|
|
|
|
//static
|
|
void CNetMeetingObj::CleanupSDK()
|
|
{
|
|
DBGENTRY(CNetMeetingObj::CleanupSDK);
|
|
|
|
if(ms_pNetMeetingObjList)
|
|
{
|
|
delete ms_pNetMeetingObjList;
|
|
}
|
|
|
|
DBGEXIT(CNetMeetingObj::CleanupSDK);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CComControlBase
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
HWND CNetMeetingObj::CreateControlWindow(HWND hWndParent, RECT& rcPos)
|
|
{
|
|
DBGENTRY(CNetMeetingObj::CreateControlWindow);
|
|
|
|
Create(hWndParent, rcPos);
|
|
|
|
if(m_hWnd)
|
|
{
|
|
m_pMainView = new CMainUI;
|
|
|
|
if(m_pMainView)
|
|
{
|
|
m_pMainView->Create(m_hWnd, g_pConfRoom, m_CreateMode, true);
|
|
|
|
RECT rcClient = {0, 0, 0, 0};
|
|
GetClientRect(&rcClient);
|
|
|
|
::SetWindowPos(m_pMainView->GetWindow(), NULL, 0, 0, rcClient.right, rcClient.bottom, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
|
|
ShowWindow(TRUE);
|
|
}
|
|
else
|
|
{
|
|
ERROR_OUT(("Out of memory, new CMainUI failed"));
|
|
}
|
|
}
|
|
|
|
DBGEXIT(CNetMeetingObj::CreateControlWindow);
|
|
return m_hWnd;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// INetMeeting
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
STDMETHODIMP CNetMeetingObj::Version(long *pdwVersion)
|
|
{
|
|
DBGENTRY(CNetMeetingObj::Version);
|
|
HRESULT hr = E_POINTER;
|
|
|
|
if(pdwVersion)
|
|
{
|
|
*pdwVersion = VER_PRODUCTVERSION_DW;
|
|
hr = S_OK;
|
|
}
|
|
|
|
DBGEXIT_HR(CNetMeetingObj::Version,hr);
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CNetMeetingObj::UnDock()
|
|
{
|
|
DBGENTRY(CNetMeetingObj::UnDock);
|
|
HRESULT hr = S_OK;
|
|
|
|
::CreateConfRoomWindow();
|
|
|
|
DBGEXIT_HR(CNetMeetingObj::UnDock,hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CNetMeetingObj::IsInConference(BOOL *pbInConference)
|
|
{
|
|
DBGENTRY(CNetMeetingObj::IsInConference);
|
|
HRESULT hr = S_OK;
|
|
|
|
*pbInConference = FIsConferenceActive();
|
|
|
|
DBGEXIT_HR(CNetMeetingObj::IsInConference,hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CNetMeetingObj::CallTo(BSTR bstrCallToString)
|
|
{
|
|
DBGENTRY( CNetMeetingObj::CallTo );
|
|
|
|
HRESULT hr;
|
|
|
|
ASSERT( g_pCCallto != NULL );
|
|
|
|
LPTSTR szName;
|
|
hr = BSTR_to_LPTSTR (&szName, bstrCallToString);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if(CCallto::DoUserValidation(szName))
|
|
{
|
|
hr = g_pCCallto->Callto( bstrCallToString ?
|
|
szName:
|
|
g_cszEmpty, // 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);
|
|
}
|
|
|
|
DBGEXIT_HR(CNetMeetingObj::CallTo,hr);
|
|
return( S_OK );
|
|
}
|
|
|
|
|
|
STDMETHODIMP CNetMeetingObj::LeaveConference()
|
|
{
|
|
DBGENTRY(CNetMeetingObj::HangUp);
|
|
HRESULT hr = S_OK;
|
|
|
|
CConfRoom::HangUp(FALSE);
|
|
|
|
DBGEXIT_HR(CNetMeetingObj::HangUp,hr);
|
|
return hr;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
// IPersistPropertyBag
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
struct CreateModeMapEntry
|
|
{
|
|
LPCTSTR szName;
|
|
CMainUI::CreateViewMode mode;
|
|
};
|
|
|
|
|
|
static CreateModeMapEntry s_CreateModeMap[] =
|
|
{
|
|
// Note: These are compared with lstrcmpi
|
|
{ _T("Full"), CMainUI::CreateFull },
|
|
{ _T("DataOnly"), CMainUI::CreateDataOnly },
|
|
{ _T("PreviewOnly"), CMainUI::CreatePreviewOnly },
|
|
{ _T("RemoteOnly"), CMainUI::CreateRemoteOnly },
|
|
{ _T("PreviewNoPause"), CMainUI::CreatePreviewNoPause },
|
|
{ _T("RemoteNoPause"), CMainUI::CreateRemoteNoPause },
|
|
{ _T("Telephone"), CMainUI::CreateTelephone },
|
|
};
|
|
|
|
void CNetMeetingObj::_SetMode(LPCTSTR pszMode)
|
|
{
|
|
ULONG nEntries = ARRAY_ELEMENTS(s_CreateModeMap);
|
|
for(ULONG i = 0; i < nEntries; ++i)
|
|
{
|
|
if(!lstrcmpi(s_CreateModeMap[i].szName, pszMode))
|
|
{
|
|
m_CreateMode = s_CreateModeMap[i].mode;
|
|
|
|
SIZE sizehm;
|
|
AtlPixelToHiMetric(&s_CreateModeSizeMap[m_CreateMode], &m_sizeNatural);
|
|
m_sizeExtent = m_sizeNatural;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
//Allow these modes to be sized
|
|
if (CMainUI::CreatePreviewNoPause == m_CreateMode
|
|
|| CMainUI::CreateRemoteNoPause == m_CreateMode
|
|
)
|
|
{
|
|
m_bAutoSize = false;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
STDMETHODIMP CNetMeetingObj::Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog)
|
|
{
|
|
CComVariant var;
|
|
var.vt = VT_BSTR;
|
|
|
|
HRESULT hr = pPropBag->Read(L"MODE", &var, pErrorLog);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if(var.vt == VT_BSTR)
|
|
{
|
|
LPTSTR szName;
|
|
hr = BSTR_to_LPTSTR (&szName, var.bstrVal);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
_SetMode(szName);
|
|
delete (szName);
|
|
}
|
|
}
|
|
}
|
|
|
|
return IPersistPropertyBagImpl<CNetMeetingObj>::Load(pPropBag, pErrorLog);
|
|
}
|
|
|
|
STDMETHODIMP CNetMeetingObj::_ParseInitString(LPCTSTR* ppszInitString, LPTSTR szName, LPTSTR szValue)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if(**ppszInitString)
|
|
{
|
|
|
|
// First read the name
|
|
const TCHAR* pCur = *ppszInitString;
|
|
|
|
// Skip Whitespace
|
|
while(*pCur == ' ')
|
|
{
|
|
pCur = CharNext(pCur);
|
|
}
|
|
|
|
bool bEqFound = false;
|
|
|
|
while( *pCur != '=' && *pCur != ' ' && *pCur != '\0')
|
|
{
|
|
*szName = *pCur;
|
|
szName = CharNext(szName);
|
|
pCur = CharNext(pCur);
|
|
}
|
|
|
|
*szName = '\0';
|
|
if(*pCur == '=')
|
|
{
|
|
bEqFound = true;
|
|
}
|
|
|
|
// Skip over seperator
|
|
pCur = CharNext(pCur);
|
|
|
|
// Skip Whitespace
|
|
while(*pCur == ' ')
|
|
{
|
|
pCur = CharNext(pCur);
|
|
}
|
|
|
|
// If we have not found the equal sign separator, we have to make sure to skip it...
|
|
if(!bEqFound && ('=' == *pCur))
|
|
{
|
|
// Skip over the equal sign
|
|
pCur = CharNext(pCur);
|
|
|
|
// Skip Whitespace
|
|
while(*pCur == ' ')
|
|
{
|
|
pCur = CharNext(pCur);
|
|
}
|
|
}
|
|
|
|
// Read the value
|
|
while( *pCur != ' ' && *pCur != '\0')
|
|
{
|
|
if(*pCur == ',')
|
|
{
|
|
if(*CharNext(pCur) == ',')
|
|
{
|
|
pCur = CharNext(pCur);
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
*szValue = *pCur;
|
|
szValue = CharNext(szValue);
|
|
pCur = CharNext(pCur);
|
|
}
|
|
|
|
*szValue = '\0';
|
|
|
|
// Skip over last seperator
|
|
pCur = CharNext(pCur);
|
|
|
|
// Skip Whitespace
|
|
while(*pCur == ' ')
|
|
{
|
|
pCur = CharNext(pCur);
|
|
}
|
|
|
|
*ppszInitString = pCur;
|
|
hr = S_OK;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// IPersistStreamInit
|
|
STDMETHODIMP CNetMeetingObj::Load(LPSTREAM pStm)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if(pStm)
|
|
{
|
|
STATSTG stat;
|
|
pStm->Stat(&stat, 0);
|
|
BSTR pb = SysAllocStringLen(NULL, stat.cbSize.LowPart);
|
|
if(pb)
|
|
{
|
|
ULONG cbRead;
|
|
|
|
hr = pStm->Read(pb, stat.cbSize.LowPart, &cbRead);
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
TCHAR szName[MAX_PATH];
|
|
TCHAR szValue[MAX_PATH];
|
|
|
|
LPTSTR lpszName;
|
|
hr = BSTR_to_LPTSTR (&lpszName, pb);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
LPCTSTR pszInitString = lpszName;
|
|
|
|
while(SUCCEEDED(_ParseInitString(&pszInitString, szName, szValue)))
|
|
{
|
|
if(!lstrcmpi(szName, _T("mode")))
|
|
{
|
|
_SetMode(szValue);
|
|
}
|
|
}
|
|
|
|
delete (lpszName);
|
|
}
|
|
|
|
}
|
|
|
|
SysFreeString(pb);
|
|
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
// INetMeeting_Events_Enabled
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
// IProvideClassInfo2
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
STDMETHODIMP CNetMeetingObj::GetClassInfo(ITypeInfo** pptinfo)
|
|
{
|
|
DBGENTRY(CNetMeetingObj::GetClassInfo);
|
|
|
|
CComPtr<IMarshalableTI> spmti;
|
|
HRESULT hr = CoCreateInstance(CLSID_MarshalableTI, NULL, CLSCTX_INPROC, IID_IMarshalableTI, reinterpret_cast<void**>(&spmti));
|
|
if( SUCCEEDED( hr ) )
|
|
{
|
|
if( SUCCEEDED( hr = spmti->Create(CLSID_NetMeeting, LIBID_NetMeetingLib, LANG_NEUTRAL, 1, 0) ) )
|
|
{
|
|
hr = spmti->QueryInterface(IID_ITypeInfo, reinterpret_cast<void**>(pptinfo));
|
|
}
|
|
}
|
|
|
|
DBGEXIT_HR(CNetMeetingObj::GetClassInfo,hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
// Helpers
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
//static
|
|
void CNetMeetingObj::Broadcast_ConferenceStarted()
|
|
{
|
|
DBGENTRY(CNetMeetingObj::Broadcast_ConferenceStarted);
|
|
|
|
if(ms_pNetMeetingObjList)
|
|
{
|
|
for(int i = 0; i < ms_pNetMeetingObjList->GetSize(); ++i)
|
|
{
|
|
(*ms_pNetMeetingObjList)[i]->Fire_ConferenceStarted();
|
|
}
|
|
}
|
|
|
|
DBGEXIT(CNetMeetingObj::Broadcast_ConferenceStarted);
|
|
}
|
|
|
|
//static
|
|
void CNetMeetingObj::Broadcast_ConferenceEnded()
|
|
{
|
|
DBGENTRY(CNetMeetingObj::Broadcast_ConferenceEnded);
|
|
|
|
if(ms_pNetMeetingObjList)
|
|
{
|
|
for(int i = 0; i < ms_pNetMeetingObjList->GetSize(); ++i)
|
|
{
|
|
(*ms_pNetMeetingObjList)[i]->Fire_ConferenceEnded();
|
|
}
|
|
}
|
|
|
|
DBGEXIT(CNetMeetingObj::Broadcast_ConferenceEnded);
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////////////
|