Leaked source code of windows server 2003
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

  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. USES_RES2T
  91. TCHAR res1[RES_CH_MAX];
  92. RES2T(IDS_CONTAINER_GOING_AWAY_BUT_ACVITE_CONFERENCE);
  93. COPY_RES2T(res1);
  94. int iRet = ::MessageBox(m_hWnd,
  95. res1,
  96. RES2T(IDS_MSGBOX_TITLE),
  97. MB_SETFOREGROUND | MB_YESNO | MB_ICONQUESTION);
  98. if(IDNO == iRet)
  99. {
  100. UnDock();
  101. }
  102. else
  103. {
  104. // This means that the user wants to close the conference
  105. ASSERT(g_pConfRoom);
  106. if(g_pConfRoom)
  107. {
  108. g_pConfRoom->LeaveConference();
  109. }
  110. }
  111. }
  112. }
  113. else
  114. {
  115. ASSERT(g_pConfRoom);
  116. if(g_pConfRoom)
  117. {
  118. // Bring the window to the front
  119. g_pConfRoom->BringToFront();
  120. }
  121. }
  122. return 0;
  123. }
  124. HRESULT CNetMeetingObj::FinalConstruct()
  125. {
  126. HRESULT hr = S_OK;
  127. if(!g_pInternalNmManager)
  128. {
  129. if(!CheckRemoteControlService())
  130. {
  131. return E_FAIL;
  132. }
  133. hr = InitConfExe(FALSE);
  134. }
  135. return hr;
  136. }
  137. //static
  138. HRESULT CNetMeetingObj::InitSDK()
  139. {
  140. DBGENTRY(CNetMeetingObj::InitSDK);
  141. HRESULT hr = S_OK;
  142. ASSERT(NULL == ms_pNetMeetingObjList);
  143. hr = (ms_pNetMeetingObjList = new CSimpleArray<CNetMeetingObj*>) ? S_OK : E_OUTOFMEMORY;
  144. DBGEXIT_HR(CNetMeetingObj::InitSDK,hr);
  145. return hr;
  146. }
  147. //static
  148. void CNetMeetingObj::CleanupSDK()
  149. {
  150. DBGENTRY(CNetMeetingObj::CleanupSDK);
  151. if(ms_pNetMeetingObjList)
  152. {
  153. delete ms_pNetMeetingObjList;
  154. }
  155. DBGEXIT(CNetMeetingObj::CleanupSDK);
  156. }
  157. /////////////////////////////////////////////////////////////////////////////
  158. // CComControlBase
  159. /////////////////////////////////////////////////////////////////////////////
  160. HWND CNetMeetingObj::CreateControlWindow(HWND hWndParent, RECT& rcPos)
  161. {
  162. DBGENTRY(CNetMeetingObj::CreateControlWindow);
  163. Create(hWndParent, rcPos);
  164. if(m_hWnd)
  165. {
  166. m_pMainView = new CMainUI;
  167. if(m_pMainView)
  168. {
  169. m_pMainView->Create(m_hWnd, g_pConfRoom, m_CreateMode, true);
  170. RECT rcClient = {0, 0, 0, 0};
  171. GetClientRect(&rcClient);
  172. ::SetWindowPos(m_pMainView->GetWindow(), NULL, 0, 0, rcClient.right, rcClient.bottom, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  173. ShowWindow(TRUE);
  174. }
  175. else
  176. {
  177. ERROR_OUT(("Out of memory, new CMainUI failed"));
  178. }
  179. }
  180. DBGEXIT(CNetMeetingObj::CreateControlWindow);
  181. return m_hWnd;
  182. }
  183. /////////////////////////////////////////////////////////////////////////////
  184. // INetMeeting
  185. /////////////////////////////////////////////////////////////////////////////
  186. STDMETHODIMP CNetMeetingObj::Version(long *pdwVersion)
  187. {
  188. DBGENTRY(CNetMeetingObj::Version);
  189. HRESULT hr = E_POINTER;
  190. if(pdwVersion)
  191. {
  192. *pdwVersion = VER_PRODUCTVERSION_DW;
  193. hr = S_OK;
  194. }
  195. DBGEXIT_HR(CNetMeetingObj::Version,hr);
  196. return hr;
  197. }
  198. STDMETHODIMP CNetMeetingObj::UnDock()
  199. {
  200. DBGENTRY(CNetMeetingObj::UnDock);
  201. HRESULT hr = S_OK;
  202. ::CreateConfRoomWindow();
  203. DBGEXIT_HR(CNetMeetingObj::UnDock,hr);
  204. return hr;
  205. }
  206. STDMETHODIMP CNetMeetingObj::IsInConference(BOOL *pbInConference)
  207. {
  208. DBGENTRY(CNetMeetingObj::IsInConference);
  209. HRESULT hr = S_OK;
  210. *pbInConference = FIsConferenceActive();
  211. DBGEXIT_HR(CNetMeetingObj::IsInConference,hr);
  212. return hr;
  213. }
  214. STDMETHODIMP CNetMeetingObj::CallTo(BSTR bstrCallToString)
  215. {
  216. DBGENTRY( CNetMeetingObj::CallTo );
  217. HRESULT hr;
  218. ASSERT( g_pCCallto != NULL );
  219. LPTSTR szName;
  220. hr = BSTR_to_LPTSTR (&szName, bstrCallToString);
  221. if (SUCCEEDED(hr))
  222. {
  223. if(CCallto::DoUserValidation(szName))
  224. {
  225. hr = g_pCCallto->Callto( bstrCallToString ?
  226. szName:
  227. g_cszEmpty, // pointer to the callto url to try to place the call with...
  228. NULL, // pointer to the display name to use...
  229. NM_ADDR_CALLTO, // callto type to resolve this callto as...
  230. false, // the pszCallto parameter is to be interpreted as a pre-unescaped addressing component vs a full callto...
  231. NULL, // security preference, NULL for none. must be "compatible" with secure param if present...
  232. false, // whether or not save in mru...
  233. true, // whether or not to perform user interaction on errors...
  234. NULL, // if bUIEnabled is true this is the window to parent error/status windows to...
  235. NULL ); // out pointer to INmCall * to receive INmCall * generated by placing call...
  236. }
  237. delete (szName);
  238. }
  239. DBGEXIT_HR(CNetMeetingObj::CallTo,hr);
  240. return( S_OK );
  241. }
  242. STDMETHODIMP CNetMeetingObj::LeaveConference()
  243. {
  244. DBGENTRY(CNetMeetingObj::HangUp);
  245. HRESULT hr = S_OK;
  246. CConfRoom::HangUp(FALSE);
  247. DBGEXIT_HR(CNetMeetingObj::HangUp,hr);
  248. return hr;
  249. }
  250. //////////////////////////////////////////////////////////////////////////////////////
  251. // IPersistPropertyBag
  252. //////////////////////////////////////////////////////////////////////////////////////
  253. struct CreateModeMapEntry
  254. {
  255. LPCTSTR szName;
  256. CMainUI::CreateViewMode mode;
  257. };
  258. static CreateModeMapEntry s_CreateModeMap[] =
  259. {
  260. // Note: These are compared with lstrcmpi
  261. { _T("Full"), CMainUI::CreateFull },
  262. { _T("DataOnly"), CMainUI::CreateDataOnly },
  263. { _T("PreviewOnly"), CMainUI::CreatePreviewOnly },
  264. { _T("RemoteOnly"), CMainUI::CreateRemoteOnly },
  265. { _T("PreviewNoPause"), CMainUI::CreatePreviewNoPause },
  266. { _T("RemoteNoPause"), CMainUI::CreateRemoteNoPause },
  267. { _T("Telephone"), CMainUI::CreateTelephone },
  268. };
  269. void CNetMeetingObj::_SetMode(LPCTSTR pszMode)
  270. {
  271. ULONG nEntries = ARRAY_ELEMENTS(s_CreateModeMap);
  272. for(ULONG i = 0; i < nEntries; ++i)
  273. {
  274. if(!lstrcmpi(s_CreateModeMap[i].szName, pszMode))
  275. {
  276. m_CreateMode = s_CreateModeMap[i].mode;
  277. SIZE sizehm;
  278. AtlPixelToHiMetric(&s_CreateModeSizeMap[m_CreateMode], &m_sizeNatural);
  279. m_sizeExtent = m_sizeNatural;
  280. break;
  281. }
  282. }
  283. //Allow these modes to be sized
  284. if (CMainUI::CreatePreviewNoPause == m_CreateMode
  285. || CMainUI::CreateRemoteNoPause == m_CreateMode
  286. )
  287. {
  288. m_bAutoSize = false;
  289. }
  290. }
  291. STDMETHODIMP CNetMeetingObj::Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog)
  292. {
  293. CComVariant var;
  294. var.vt = VT_BSTR;
  295. HRESULT hr = pPropBag->Read(L"MODE", &var, pErrorLog);
  296. if(SUCCEEDED(hr))
  297. {
  298. if(var.vt == VT_BSTR)
  299. {
  300. LPTSTR szName;
  301. hr = BSTR_to_LPTSTR (&szName, var.bstrVal);
  302. if (SUCCEEDED(hr))
  303. {
  304. _SetMode(szName);
  305. delete (szName);
  306. }
  307. }
  308. }
  309. return IPersistPropertyBagImpl<CNetMeetingObj>::Load(pPropBag, pErrorLog);
  310. }
  311. STDMETHODIMP CNetMeetingObj::_ParseInitString(LPCTSTR* ppszInitString, LPTSTR szName, LPTSTR szValue)
  312. {
  313. HRESULT hr = E_FAIL;
  314. if(**ppszInitString)
  315. {
  316. // First read the name
  317. const TCHAR* pCur = *ppszInitString;
  318. // Skip Whitespace
  319. while(*pCur == ' ')
  320. {
  321. pCur = CharNext(pCur);
  322. }
  323. bool bEqFound = false;
  324. while( *pCur != '=' && *pCur != ' ' && *pCur != '\0')
  325. {
  326. *szName = *pCur;
  327. szName = CharNext(szName);
  328. pCur = CharNext(pCur);
  329. }
  330. *szName = '\0';
  331. if(*pCur == '=')
  332. {
  333. bEqFound = true;
  334. }
  335. // Skip over seperator
  336. pCur = CharNext(pCur);
  337. // Skip Whitespace
  338. while(*pCur == ' ')
  339. {
  340. pCur = CharNext(pCur);
  341. }
  342. // If we have not found the equal sign separator, we have to make sure to skip it...
  343. if(!bEqFound && ('=' == *pCur))
  344. {
  345. // Skip over the equal sign
  346. pCur = CharNext(pCur);
  347. // Skip Whitespace
  348. while(*pCur == ' ')
  349. {
  350. pCur = CharNext(pCur);
  351. }
  352. }
  353. // Read the value
  354. while( *pCur != ' ' && *pCur != '\0')
  355. {
  356. if(*pCur == ',')
  357. {
  358. if(*CharNext(pCur) == ',')
  359. {
  360. pCur = CharNext(pCur);
  361. }
  362. else
  363. {
  364. break;
  365. }
  366. }
  367. *szValue = *pCur;
  368. szValue = CharNext(szValue);
  369. pCur = CharNext(pCur);
  370. }
  371. *szValue = '\0';
  372. // Skip over last seperator
  373. pCur = CharNext(pCur);
  374. // Skip Whitespace
  375. while(*pCur == ' ')
  376. {
  377. pCur = CharNext(pCur);
  378. }
  379. *ppszInitString = pCur;
  380. hr = S_OK;
  381. }
  382. return hr;
  383. }
  384. // IPersistStreamInit
  385. STDMETHODIMP CNetMeetingObj::Load(LPSTREAM pStm)
  386. {
  387. HRESULT hr = E_FAIL;
  388. if(pStm)
  389. {
  390. STATSTG stat;
  391. pStm->Stat(&stat, 0);
  392. BSTR pb = SysAllocStringLen(NULL, stat.cbSize.LowPart);
  393. if(pb)
  394. {
  395. ULONG cbRead;
  396. hr = pStm->Read(pb, stat.cbSize.LowPart, &cbRead);
  397. if(SUCCEEDED(hr))
  398. {
  399. TCHAR szName[MAX_PATH];
  400. TCHAR szValue[MAX_PATH];
  401. LPTSTR lpszName;
  402. hr = BSTR_to_LPTSTR (&lpszName, pb);
  403. if (SUCCEEDED(hr))
  404. {
  405. LPCTSTR pszInitString = lpszName;
  406. while(SUCCEEDED(_ParseInitString(&pszInitString, szName, szValue)))
  407. {
  408. if(!lstrcmpi(szName, _T("mode")))
  409. {
  410. _SetMode(szValue);
  411. }
  412. }
  413. delete (lpszName);
  414. }
  415. }
  416. SysFreeString(pb);
  417. }
  418. }
  419. return hr;
  420. }
  421. //////////////////////////////////////////////////////////////////////////////////////
  422. //////////////////////////////////////////////////////////////////////////////////////
  423. //////////////////////////////////////////////////////////////////////////////////////
  424. //////////////////////////////////////////////////////////////////////////////////////
  425. //////////////////////////////////////////////////////////////////////////////////////
  426. // INetMeeting_Events_Enabled
  427. //////////////////////////////////////////////////////////////////////////////////////
  428. // IProvideClassInfo2
  429. //////////////////////////////////////////////////////////////////////////////////////
  430. STDMETHODIMP CNetMeetingObj::GetClassInfo(ITypeInfo** pptinfo)
  431. {
  432. DBGENTRY(CNetMeetingObj::GetClassInfo);
  433. CComPtr<IMarshalableTI> spmti;
  434. HRESULT hr = CoCreateInstance(CLSID_MarshalableTI, NULL, CLSCTX_INPROC, IID_IMarshalableTI, reinterpret_cast<void**>(&spmti));
  435. if( SUCCEEDED( hr ) )
  436. {
  437. if( SUCCEEDED( hr = spmti->Create(CLSID_NetMeeting, LIBID_NetMeetingLib, LANG_NEUTRAL, 1, 0) ) )
  438. {
  439. hr = spmti->QueryInterface(IID_ITypeInfo, reinterpret_cast<void**>(pptinfo));
  440. }
  441. }
  442. DBGEXIT_HR(CNetMeetingObj::GetClassInfo,hr);
  443. return hr;
  444. }
  445. //////////////////////////////////////////////////////////////////////////////////////
  446. // Helpers
  447. //////////////////////////////////////////////////////////////////////////////////////
  448. //static
  449. void CNetMeetingObj::Broadcast_ConferenceStarted()
  450. {
  451. DBGENTRY(CNetMeetingObj::Broadcast_ConferenceStarted);
  452. if(ms_pNetMeetingObjList)
  453. {
  454. for(int i = 0; i < ms_pNetMeetingObjList->GetSize(); ++i)
  455. {
  456. (*ms_pNetMeetingObjList)[i]->Fire_ConferenceStarted();
  457. }
  458. }
  459. DBGEXIT(CNetMeetingObj::Broadcast_ConferenceStarted);
  460. }
  461. //static
  462. void CNetMeetingObj::Broadcast_ConferenceEnded()
  463. {
  464. DBGENTRY(CNetMeetingObj::Broadcast_ConferenceEnded);
  465. if(ms_pNetMeetingObjList)
  466. {
  467. for(int i = 0; i < ms_pNetMeetingObjList->GetSize(); ++i)
  468. {
  469. (*ms_pNetMeetingObjList)[i]->Fire_ConferenceEnded();
  470. }
  471. }
  472. DBGEXIT(CNetMeetingObj::Broadcast_ConferenceEnded);
  473. }
  474. //////////////////////////////////////////////////////////////////////////////////////
  475. //////////////////////////////////////////////////////////////////////////////////////
  476. //////////////////////////////////////////////////////////////////////////////////////
  477. //////////////////////////////////////////////////////////////////////////////////////