Source code of Windows XP (NT5)
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.

583 lines
13 KiB

  1. #include "precomp.h"
  2. #include "NetMeeting.h"
  3. #include "mslablti.h"
  4. #include "nameres.h"
  5. #include "conf.h"
  6. #include "ConfRoom.h"
  7. #include "call.h"
  8. #include "conf.h"
  9. #include "Callto.h"
  10. #include "version.h"
  11. // NetMeeting SDK includes
  12. #include "SdkInternal.h"
  13. #include "NmEnum.h"
  14. #include "NmMember.h"
  15. #include "NmManager.h"
  16. #include "NmConference.h"
  17. #include "NmCall.h"
  18. #include "SDKWindow.h"
  19. #include "NmApp.h"
  20. //////////////////////////////////////////
  21. // Static Data
  22. //////////////////////////////////////////
  23. /*static*/ CSimpleArray<CNetMeetingObj*>* CNetMeetingObj::ms_pNetMeetingObjList = NULL;
  24. ///////////////////////////////////////////////////////////////////////////
  25. // Construction / Destruction
  26. /////////////////////////////////////////////////////////////////////////////
  27. static SIZE s_CreateModeSizeMap[] =
  28. {
  29. { 244, 410 }, // CMainUI::CreateFull
  30. { 244, 158 }, // CMainUI::CreateDataOnly
  31. { 196, 200 }, // CMainUI::CreatePreviewOnly
  32. { 196, 200 }, // CMainUI::CreateRemoteOnly
  33. { 180, 148 }, // CMainUI::CreatePreviewNoPause
  34. { 180, 148 }, // CMainUI::CreateRemoteNoPause
  35. { 240, 318 }, // CMainUI::CreateTelephone
  36. };
  37. CNetMeetingObj::CNetMeetingObj()
  38. : m_pMainView(NULL),
  39. m_CreateMode(CMainUI::CreateFull)
  40. {
  41. DBGENTRY(CNetMeetingObj::CNetMeetingObj);
  42. m_bAutoSize = true;
  43. m_bDrawFromNatural = true;
  44. m_bWindowOnly = true;
  45. SIZE sizehm;
  46. AtlPixelToHiMetric(&s_CreateModeSizeMap[m_CreateMode], &m_sizeNatural);
  47. m_sizeExtent = m_sizeNatural;
  48. CNetMeetingObj* p = const_cast<CNetMeetingObj*>(this);
  49. ms_pNetMeetingObjList->Add(p);
  50. DBGEXIT(CNetMeetingObj::CNetMeetingObj);
  51. }
  52. CNetMeetingObj::~CNetMeetingObj()
  53. {
  54. DBGENTRY(CNetMeetingObj::~CNetMeetingObj);
  55. if(m_pMainView)
  56. {
  57. m_pMainView->Release();
  58. m_pMainView = NULL;
  59. }
  60. CNetMeetingObj* p = const_cast<CNetMeetingObj*>(this);
  61. ms_pNetMeetingObjList->Remove(p);
  62. // If we are the last guy on the block, we should delay unload
  63. if(0 == _Module.GetLockCount())
  64. {
  65. _Module.Lock();
  66. CSDKWindow::PostDelayModuleUnlock();
  67. }
  68. DBGEXIT(CNetMeetingObj::~CNetMeetingObj);
  69. }
  70. LRESULT CNetMeetingObj::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  71. {
  72. if(SIZE_MINIMIZED != wParam)
  73. {
  74. if(m_pMainView)
  75. {
  76. int nWidth = LOWORD(lParam); // width of client area
  77. int nHeight = HIWORD(lParam); // height of client area
  78. ::SetWindowPos(m_pMainView->GetWindow(), NULL, 0, 0, nWidth, nHeight, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  79. }
  80. }
  81. return 0;
  82. }
  83. LRESULT CNetMeetingObj::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  84. {
  85. BOOL bInConference;
  86. if(!_Module.IsUIVisible())
  87. {
  88. if(SUCCEEDED(IsInConference(&bInConference)) && bInConference)
  89. {
  90. int iRet = ::MessageBox(m_hWnd,
  91. RES2T(IDS_CONTAINER_GOING_AWAY_BUT_ACVITE_CONFERENCE),
  92. RES2T(IDS_MSGBOX_TITLE),
  93. MB_SETFOREGROUND | MB_YESNO | MB_ICONQUESTION);
  94. if(IDNO == iRet)
  95. {
  96. UnDock();
  97. }
  98. else
  99. {
  100. // This means that the user wants to close the conference
  101. ASSERT(g_pConfRoom);
  102. if(g_pConfRoom)
  103. {
  104. g_pConfRoom->LeaveConference();
  105. }
  106. }
  107. }
  108. }
  109. else
  110. {
  111. ASSERT(g_pConfRoom);
  112. if(g_pConfRoom)
  113. {
  114. // Bring the window to the front
  115. g_pConfRoom->BringToFront();
  116. }
  117. }
  118. return 0;
  119. }
  120. HRESULT CNetMeetingObj::FinalConstruct()
  121. {
  122. HRESULT hr = S_OK;
  123. if(!g_pInternalNmManager)
  124. {
  125. if(!CheckRemoteControlService())
  126. {
  127. return E_FAIL;
  128. }
  129. hr = InitConfExe(FALSE);
  130. }
  131. return hr;
  132. }
  133. //static
  134. HRESULT CNetMeetingObj::InitSDK()
  135. {
  136. DBGENTRY(CNetMeetingObj::InitSDK);
  137. HRESULT hr = S_OK;
  138. ASSERT(NULL == ms_pNetMeetingObjList);
  139. hr = (ms_pNetMeetingObjList = new CSimpleArray<CNetMeetingObj*>) ? S_OK : E_OUTOFMEMORY;
  140. DBGEXIT_HR(CNetMeetingObj::InitSDK,hr);
  141. return hr;
  142. }
  143. //static
  144. void CNetMeetingObj::CleanupSDK()
  145. {
  146. DBGENTRY(CNetMeetingObj::CleanupSDK);
  147. if(ms_pNetMeetingObjList)
  148. {
  149. delete ms_pNetMeetingObjList;
  150. }
  151. DBGEXIT(CNetMeetingObj::CleanupSDK);
  152. }
  153. /////////////////////////////////////////////////////////////////////////////
  154. // CComControlBase
  155. /////////////////////////////////////////////////////////////////////////////
  156. HWND CNetMeetingObj::CreateControlWindow(HWND hWndParent, RECT& rcPos)
  157. {
  158. DBGENTRY(CNetMeetingObj::CreateControlWindow);
  159. Create(hWndParent, rcPos);
  160. if(m_hWnd)
  161. {
  162. m_pMainView = new CMainUI;
  163. if(m_pMainView)
  164. {
  165. m_pMainView->Create(m_hWnd, g_pConfRoom, m_CreateMode, true);
  166. RECT rcClient = {0, 0, 0, 0};
  167. GetClientRect(&rcClient);
  168. ::SetWindowPos(m_pMainView->GetWindow(), NULL, 0, 0, rcClient.right, rcClient.bottom, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  169. ShowWindow(TRUE);
  170. }
  171. else
  172. {
  173. ERROR_OUT(("Out of memory, new CMainUI failed"));
  174. }
  175. }
  176. DBGEXIT(CNetMeetingObj::CreateControlWindow);
  177. return m_hWnd;
  178. }
  179. /////////////////////////////////////////////////////////////////////////////
  180. // INetMeeting
  181. /////////////////////////////////////////////////////////////////////////////
  182. STDMETHODIMP CNetMeetingObj::Version(long *pdwVersion)
  183. {
  184. DBGENTRY(CNetMeetingObj::Version);
  185. HRESULT hr = E_POINTER;
  186. if(pdwVersion)
  187. {
  188. *pdwVersion = VER_PRODUCTVERSION_DW;
  189. hr = S_OK;
  190. }
  191. DBGEXIT_HR(CNetMeetingObj::Version,hr);
  192. return hr;
  193. }
  194. STDMETHODIMP CNetMeetingObj::UnDock()
  195. {
  196. DBGENTRY(CNetMeetingObj::UnDock);
  197. HRESULT hr = S_OK;
  198. ::CreateConfRoomWindow();
  199. DBGEXIT_HR(CNetMeetingObj::UnDock,hr);
  200. return hr;
  201. }
  202. STDMETHODIMP CNetMeetingObj::IsInConference(BOOL *pbInConference)
  203. {
  204. DBGENTRY(CNetMeetingObj::IsInConference);
  205. HRESULT hr = S_OK;
  206. *pbInConference = FIsConferenceActive();
  207. DBGEXIT_HR(CNetMeetingObj::IsInConference,hr);
  208. return hr;
  209. }
  210. STDMETHODIMP CNetMeetingObj::CallTo(BSTR bstrCallToString)
  211. {
  212. DBGENTRY( CNetMeetingObj::CallTo );
  213. USES_CONVERSION;
  214. HRESULT hr;
  215. const TCHAR *pszCallto = bstrCallToString ? OLE2T( bstrCallToString ) : g_cszEmpty;
  216. ASSERT( g_pCCallto != NULL );
  217. if(CCallto::DoUserValidation(pszCallto))
  218. {
  219. hr = g_pCCallto->Callto( pszCallto, // pointer to the callto url to try to place the call with...
  220. NULL, // pointer to the display name to use...
  221. NM_ADDR_CALLTO, // callto type to resolve this callto as...
  222. false, // the pszCallto parameter is to be interpreted as a pre-unescaped addressing component vs a full callto...
  223. NULL, // security preference, NULL for none. must be "compatible" with secure param if present...
  224. false, // whether or not save in mru...
  225. true, // whether or not to perform user interaction on errors...
  226. NULL, // if bUIEnabled is true this is the window to parent error/status windows to...
  227. NULL ); // out pointer to INmCall * to receive INmCall * generated by placing call...
  228. }
  229. DBGEXIT_HR(CNetMeetingObj::CallTo,hr);
  230. return( S_OK );
  231. }
  232. STDMETHODIMP CNetMeetingObj::LeaveConference()
  233. {
  234. DBGENTRY(CNetMeetingObj::HangUp);
  235. HRESULT hr = S_OK;
  236. CConfRoom::HangUp(FALSE);
  237. DBGEXIT_HR(CNetMeetingObj::HangUp,hr);
  238. return hr;
  239. }
  240. //////////////////////////////////////////////////////////////////////////////////////
  241. // IPersistPropertyBag
  242. //////////////////////////////////////////////////////////////////////////////////////
  243. struct CreateModeMapEntry
  244. {
  245. LPCTSTR szName;
  246. CMainUI::CreateViewMode mode;
  247. };
  248. static CreateModeMapEntry s_CreateModeMap[] =
  249. {
  250. // Note: These are compared with lstrcmpi
  251. { _T("Full"), CMainUI::CreateFull },
  252. { _T("DataOnly"), CMainUI::CreateDataOnly },
  253. { _T("PreviewOnly"), CMainUI::CreatePreviewOnly },
  254. { _T("RemoteOnly"), CMainUI::CreateRemoteOnly },
  255. { _T("PreviewNoPause"), CMainUI::CreatePreviewNoPause },
  256. { _T("RemoteNoPause"), CMainUI::CreateRemoteNoPause },
  257. { _T("Telephone"), CMainUI::CreateTelephone },
  258. };
  259. void CNetMeetingObj::_SetMode(LPCTSTR pszMode)
  260. {
  261. ULONG nEntries = ARRAY_ELEMENTS(s_CreateModeMap);
  262. for(ULONG i = 0; i < nEntries; ++i)
  263. {
  264. if(!lstrcmpi(s_CreateModeMap[i].szName, pszMode))
  265. {
  266. m_CreateMode = s_CreateModeMap[i].mode;
  267. SIZE sizehm;
  268. AtlPixelToHiMetric(&s_CreateModeSizeMap[m_CreateMode], &m_sizeNatural);
  269. m_sizeExtent = m_sizeNatural;
  270. break;
  271. }
  272. }
  273. //Allow these modes to be sized
  274. if (CMainUI::CreatePreviewNoPause == m_CreateMode
  275. || CMainUI::CreateRemoteNoPause == m_CreateMode
  276. )
  277. {
  278. m_bAutoSize = false;
  279. }
  280. }
  281. STDMETHODIMP CNetMeetingObj::Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog)
  282. {
  283. CComVariant var;
  284. var.vt = VT_BSTR;
  285. HRESULT hr = pPropBag->Read(L"MODE", &var, pErrorLog);
  286. if(SUCCEEDED(hr))
  287. {
  288. if(var.vt == VT_BSTR)
  289. {
  290. USES_CONVERSION;
  291. LPCTSTR pszMode = OLE2T(var.bstrVal);
  292. _SetMode(pszMode);
  293. }
  294. }
  295. return IPersistPropertyBagImpl<CNetMeetingObj>::Load(pPropBag, pErrorLog);
  296. }
  297. STDMETHODIMP CNetMeetingObj::_ParseInitString(LPCTSTR* ppszInitString, LPTSTR szName, LPTSTR szValue)
  298. {
  299. HRESULT hr = E_FAIL;
  300. if(**ppszInitString)
  301. {
  302. // First read the name
  303. const TCHAR* pCur = *ppszInitString;
  304. // Skip Whitespace
  305. while(*pCur == ' ')
  306. {
  307. pCur = CharNext(pCur);
  308. }
  309. bool bEqFound = false;
  310. while( *pCur != '=' && *pCur != ' ' && *pCur != '\0')
  311. {
  312. *szName = *pCur;
  313. szName = CharNext(szName);
  314. pCur = CharNext(pCur);
  315. }
  316. *szName = '\0';
  317. if(*pCur == '=')
  318. {
  319. bEqFound = true;
  320. }
  321. // Skip over seperator
  322. pCur = CharNext(pCur);
  323. // Skip Whitespace
  324. while(*pCur == ' ')
  325. {
  326. pCur = CharNext(pCur);
  327. }
  328. // If we have not found the equal sign separator, we have to make sure to skip it...
  329. if(!bEqFound && ('=' == *pCur))
  330. {
  331. // Skip over the equal sign
  332. pCur = CharNext(pCur);
  333. // Skip Whitespace
  334. while(*pCur == ' ')
  335. {
  336. pCur = CharNext(pCur);
  337. }
  338. }
  339. // Read the value
  340. while( *pCur != ' ' && *pCur != '\0')
  341. {
  342. if(*pCur == ',')
  343. {
  344. if(*CharNext(pCur) == ',')
  345. {
  346. pCur = CharNext(pCur);
  347. }
  348. else
  349. {
  350. break;
  351. }
  352. }
  353. *szValue = *pCur;
  354. szValue = CharNext(szValue);
  355. pCur = CharNext(pCur);
  356. }
  357. *szValue = '\0';
  358. // Skip over last seperator
  359. pCur = CharNext(pCur);
  360. // Skip Whitespace
  361. while(*pCur == ' ')
  362. {
  363. pCur = CharNext(pCur);
  364. }
  365. *ppszInitString = pCur;
  366. hr = S_OK;
  367. }
  368. return hr;
  369. }
  370. // IPersistStreamInit
  371. STDMETHODIMP CNetMeetingObj::Load(LPSTREAM pStm)
  372. {
  373. HRESULT hr = E_FAIL;
  374. if(pStm)
  375. {
  376. STATSTG stat;
  377. pStm->Stat(&stat, 0);
  378. BYTE* pb = new BYTE[stat.cbSize.LowPart];
  379. if(pb)
  380. {
  381. USES_CONVERSION;
  382. ULONG cbRead;
  383. hr = pStm->Read(pb, stat.cbSize.LowPart, &cbRead);
  384. if(SUCCEEDED(hr))
  385. {
  386. TCHAR szName[MAX_PATH];
  387. TCHAR szValue[MAX_PATH];
  388. LPCTSTR pszInitString = OLE2T((OLECHAR*)pb);
  389. while(SUCCEEDED(_ParseInitString(&pszInitString, szName, szValue)))
  390. {
  391. if(!lstrcmpi(szName, _T("mode")))
  392. {
  393. _SetMode(szValue);
  394. }
  395. }
  396. }
  397. delete pb;
  398. }
  399. }
  400. return hr;
  401. }
  402. //////////////////////////////////////////////////////////////////////////////////////
  403. //////////////////////////////////////////////////////////////////////////////////////
  404. //////////////////////////////////////////////////////////////////////////////////////
  405. //////////////////////////////////////////////////////////////////////////////////////
  406. //////////////////////////////////////////////////////////////////////////////////////
  407. // INetMeeting_Events_Enabled
  408. //////////////////////////////////////////////////////////////////////////////////////
  409. // IProvideClassInfo2
  410. //////////////////////////////////////////////////////////////////////////////////////
  411. STDMETHODIMP CNetMeetingObj::GetClassInfo(ITypeInfo** pptinfo)
  412. {
  413. DBGENTRY(CNetMeetingObj::GetClassInfo);
  414. CComPtr<IMarshalableTI> spmti;
  415. HRESULT hr = CoCreateInstance(CLSID_MarshalableTI, NULL, CLSCTX_INPROC, IID_IMarshalableTI, reinterpret_cast<void**>(&spmti));
  416. if( SUCCEEDED( hr ) )
  417. {
  418. if( SUCCEEDED( hr = spmti->Create(CLSID_NetMeeting, LIBID_NetMeetingLib, LANG_NEUTRAL, 1, 0) ) )
  419. {
  420. hr = spmti->QueryInterface(IID_ITypeInfo, reinterpret_cast<void**>(pptinfo));
  421. }
  422. }
  423. DBGEXIT_HR(CNetMeetingObj::GetClassInfo,hr);
  424. return hr;
  425. }
  426. //////////////////////////////////////////////////////////////////////////////////////
  427. // Helpers
  428. //////////////////////////////////////////////////////////////////////////////////////
  429. //static
  430. void CNetMeetingObj::Broadcast_ConferenceStarted()
  431. {
  432. DBGENTRY(CNetMeetingObj::Broadcast_ConferenceStarted);
  433. if(ms_pNetMeetingObjList)
  434. {
  435. for(int i = 0; i < ms_pNetMeetingObjList->GetSize(); ++i)
  436. {
  437. (*ms_pNetMeetingObjList)[i]->Fire_ConferenceStarted();
  438. }
  439. }
  440. DBGEXIT(CNetMeetingObj::Broadcast_ConferenceStarted);
  441. }
  442. //static
  443. void CNetMeetingObj::Broadcast_ConferenceEnded()
  444. {
  445. DBGENTRY(CNetMeetingObj::Broadcast_ConferenceEnded);
  446. if(ms_pNetMeetingObjList)
  447. {
  448. for(int i = 0; i < ms_pNetMeetingObjList->GetSize(); ++i)
  449. {
  450. (*ms_pNetMeetingObjList)[i]->Fire_ConferenceEnded();
  451. }
  452. }
  453. DBGEXIT(CNetMeetingObj::Broadcast_ConferenceEnded);
  454. }
  455. //////////////////////////////////////////////////////////////////////////////////////
  456. //////////////////////////////////////////////////////////////////////////////////////
  457. //////////////////////////////////////////////////////////////////////////////////////
  458. //////////////////////////////////////////////////////////////////////////////////////