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.

1307 lines
26 KiB

  1. // File: iconf.cpp
  2. #include "precomp.h"
  3. #include "version.h"
  4. #include "imanager.h"
  5. // BUGBUG:
  6. // This is defined as 128 because the RNC_ROSTER structure has the
  7. // same limitation. Investigate what the appropriate number is.
  8. const int MAX_CALLER_NAME = 128;
  9. static const WCHAR _szConferenceNameDefault[] = L"Personal Conference";
  10. static HRESULT OnNotifyStateChanged(IUnknown *pConfNotify, PVOID pv, REFIID riid);
  11. static HRESULT OnNotifyMemberAdded(IUnknown *pConfNotify, PVOID pv, REFIID riid);
  12. static HRESULT OnNotifyMemberUpdated(IUnknown *pConfNotify, PVOID pv, REFIID riid);
  13. static HRESULT OnNotifyMemberRemoved(IUnknown *pConfNotify, PVOID pv, REFIID riid);
  14. static HRESULT OnNotifyNmUI(IUnknown *pConfNotify, PVOID pv, REFIID riid);
  15. static const IID * g_apiidCP[] =
  16. {
  17. {&IID_INmConferenceNotify}
  18. };
  19. CConfObject::CConfObject() :
  20. CConnectionPointContainer(g_apiidCP, ARRAY_ELEMENTS(g_apiidCP)),
  21. m_hConf (NULL),
  22. m_csState (CS_UNINITIALIZED),
  23. m_fConferenceCreated(FALSE),
  24. m_bstrConfName (NULL),
  25. m_fServerMode (FALSE),
  26. m_uMembers (0),
  27. m_ourNodeID (0),
  28. m_pMemberLocal (NULL),
  29. m_uGCCConferenceID (0),
  30. m_fSecure (FALSE),
  31. m_cRef (1)
  32. {
  33. DebugEntry(CConfObject::CConfObject);
  34. DebugExitVOID(CConfObject::CConfObject);
  35. }
  36. CConfObject::~CConfObject()
  37. {
  38. DebugEntry(CConfObject::~CConfObject);
  39. // Empty the participant list:
  40. while (!m_MemberList.IsEmpty())
  41. {
  42. CNmMember * pMember = (CNmMember *) m_MemberList.RemoveHead();
  43. // Shouldn't have any NULL entries:
  44. ASSERT(pMember);
  45. pMember->Release();
  46. }
  47. SysFreeString(m_bstrConfName);
  48. DebugExitVOID(CConfObject::~CConfObject);
  49. }
  50. VOID CConfObject::SetConfName(BSTR bstr)
  51. {
  52. SysFreeString(m_bstrConfName);
  53. m_bstrConfName = SysAllocString(bstr);
  54. }
  55. VOID CConfObject::SetConfSecurity(BOOL fSecure)
  56. {
  57. NM_CONFERENCE_STATE NmState;
  58. m_fSecure = fSecure;
  59. // Force update of the status icon to reflect security
  60. GetState(&NmState);
  61. NotifySink((PVOID) NmState, OnNotifyStateChanged);
  62. }
  63. HRESULT CConfObject::CreateConference(void)
  64. {
  65. DebugEntry(CConfObject::CreateConference);
  66. HRESULT nsRet = E_FAIL;
  67. switch (m_csState)
  68. {
  69. case CS_UNINITIALIZED:
  70. case CS_TERMINATED:
  71. {
  72. if ((NULL == m_bstrConfName) || (0 == *m_bstrConfName))
  73. {
  74. m_bstrConfName = SysAllocString(_szConferenceNameDefault);
  75. }
  76. TRACE_OUT(("CConfObject:CreateConference [%ls]", m_bstrConfName));
  77. ASSERT(g_pNodeController);
  78. ASSERT(NULL == m_hConf);
  79. nsRet = g_pNodeController->CreateConference(
  80. m_bstrConfName,
  81. NULL,
  82. NULL,
  83. 0,
  84. m_fSecure,
  85. &m_hConf);
  86. if (0 == nsRet)
  87. {
  88. SetT120State(CS_CREATING);
  89. }
  90. else
  91. {
  92. m_hConf = NULL;
  93. }
  94. break;
  95. }
  96. default:
  97. {
  98. WARNING_OUT(("CConfObject: Can't create - bad state"));
  99. nsRet = E_FAIL;
  100. }
  101. }
  102. DebugExitINT(CConfObject::CreateConference, nsRet);
  103. return nsRet;
  104. }
  105. HRESULT CConfObject::JoinConference( LPCWSTR pcwszConferenceName,
  106. LPCWSTR pcwszPassword,
  107. LPCSTR pcszAddress,
  108. BOOL fRetry)
  109. {
  110. DebugEntry(CConfObject::JoinConference);
  111. HRESULT nsRet = E_FAIL;
  112. switch (m_csState)
  113. {
  114. case CS_COMING_UP:
  115. {
  116. if (!fRetry)
  117. {
  118. break;
  119. }
  120. // fall through if this is another attempt to join
  121. }
  122. case CS_UNINITIALIZED:
  123. case CS_TERMINATED:
  124. {
  125. TRACE_OUT(("CConfObject: Joining conference..."));
  126. ASSERT(g_pNodeController);
  127. nsRet = g_pNodeController->JoinConference(pcwszConferenceName,
  128. pcwszPassword,
  129. pcszAddress,
  130. m_fSecure,
  131. &m_hConf);
  132. if (0 == nsRet)
  133. {
  134. SetT120State(CS_COMING_UP);
  135. }
  136. else
  137. {
  138. m_hConf = NULL;
  139. }
  140. break;
  141. }
  142. case CS_GOING_DOWN:
  143. default:
  144. {
  145. WARNING_OUT(("CConfObject: Can't join - bad state"));
  146. // BUGBUG: define return values
  147. nsRet = 1;
  148. }
  149. }
  150. DebugExitINT(CConfObject::JoinConference, nsRet);
  151. return nsRet;
  152. }
  153. HRESULT CConfObject::InviteConference( LPCSTR Address,
  154. REQUEST_HANDLE *phRequest )
  155. {
  156. DebugEntry(CConfObject::InviteConference);
  157. HRESULT nsRet = E_FAIL;
  158. ASSERT(phRequest);
  159. switch (m_csState)
  160. {
  161. case CS_RUNNING:
  162. {
  163. TRACE_OUT(("CConfObject: Inviting conference..."));
  164. ASSERT(g_pNodeController);
  165. ASSERT(m_hConf);
  166. m_hConf->SetSecurity(m_fSecure);
  167. nsRet = m_hConf->Invite(Address,
  168. phRequest);
  169. break;
  170. }
  171. default:
  172. {
  173. WARNING_OUT(("CConfObject: Can't invite - bad state"));
  174. nsRet = E_FAIL;
  175. }
  176. }
  177. DebugExitINT(CConfObject::InviteConference, nsRet);
  178. return nsRet;
  179. }
  180. HRESULT CConfObject::LeaveConference(BOOL fForceLeave)
  181. {
  182. DebugEntry(CConfObject::LeaveConference);
  183. HRESULT nsRet = E_FAIL;
  184. REQUEST_HANDLE hReq = NULL;
  185. switch (m_csState)
  186. {
  187. case CS_GOING_DOWN:
  188. {
  189. // we're already going down
  190. nsRet = S_OK;
  191. break;
  192. }
  193. case CS_COMING_UP:
  194. case CS_RUNNING:
  195. {
  196. if (FALSE == fForceLeave)
  197. {
  198. COprahNCUI *pOprahNCUI = COprahNCUI::GetInstance();
  199. if (NULL != pOprahNCUI)
  200. {
  201. int nNodes = pOprahNCUI->GetOutgoingCallCount();
  202. if (m_fServerMode || (nNodes > 1) || (m_uMembers > 1))
  203. {
  204. // We are either in the process of calling another node
  205. // or we have other people in our conference roster
  206. TRACE_OUT(("CConfObject: Not leaving (there are other nodes)"));
  207. break;
  208. }
  209. }
  210. }
  211. TRACE_OUT(("CConfObject: Leaving conference..."));
  212. ASSERT(g_pNodeController);
  213. ASSERT(m_hConf);
  214. SetT120State(CS_GOING_DOWN);
  215. nsRet = m_hConf->Leave();
  216. break;
  217. }
  218. default:
  219. {
  220. WARNING_OUT(("CConfObject: Can't leave - bad state"));
  221. break;
  222. }
  223. }
  224. DebugExitINT(CConfObject::LeaveConference, nsRet);
  225. return nsRet;
  226. }
  227. BOOL CConfObject::OnT120Invite(CONF_HANDLE hConference, BOOL fSecure)
  228. {
  229. DebugEntry(CConfObject::OnT120Invite);
  230. BOOL bRet = FALSE;
  231. switch (m_csState)
  232. {
  233. case CS_UNINITIALIZED:
  234. case CS_TERMINATED:
  235. {
  236. TRACE_OUT(("CConfObject: Accepting a conference invitation..."));
  237. ASSERT(g_pNodeController);
  238. ASSERT(NULL == m_hConf);
  239. m_hConf = hConference;
  240. m_fSecure = fSecure;
  241. hConference->SetSecurity(m_fSecure);
  242. // WORKITEM need to issue INmManagerNotify::ConferenceCreated()
  243. SetT120State(CS_COMING_UP);
  244. bRet = TRUE;
  245. break;
  246. }
  247. default:
  248. {
  249. WARNING_OUT(("CConfObject: Can't accept invite - bad state"));
  250. }
  251. }
  252. DebugExitBOOL(CConfObject::OnT120Invite, bRet);
  253. return bRet;
  254. }
  255. BOOL CConfObject::OnRosterChanged(PNC_ROSTER pRoster)
  256. {
  257. DebugEntry(CConfObject::OnRosterChanged);
  258. BOOL bRet = TRUE;
  259. int i;
  260. // REVIEW: Could these be done more efficiently?
  261. if (NULL != pRoster)
  262. {
  263. UINT nExistingParts = 0;
  264. // Allocate an array of markers:
  265. UINT uRosterNodes = pRoster->uNumNodes;
  266. LPBOOL pMarkArray = new BOOL[uRosterNodes];
  267. m_ourNodeID = pRoster->uLocalNodeID;
  268. m_uGCCConferenceID = pRoster->uConferenceID;
  269. if (NULL != pRoster->pwszConferenceName)
  270. {
  271. SysFreeString(m_bstrConfName);
  272. m_bstrConfName = SysAllocString(pRoster->pwszConferenceName);
  273. }
  274. if (NULL != pMarkArray)
  275. {
  276. // Zero out the array:
  277. for (UINT i = 0; i < uRosterNodes; i++)
  278. {
  279. pMarkArray[i] = FALSE;
  280. }
  281. // For all participants still in the roster,
  282. // clear out the reserved flags and
  283. // copy in new UserInfo
  284. POSITION pos = m_MemberList.GetHeadPosition();
  285. while (NULL != pos)
  286. {
  287. CNmMember * pMember = (CNmMember *) m_MemberList.GetNext(pos);
  288. ASSERT(pMember);
  289. pMember->RemovePf(PF_INCONFERENCE);
  290. for (UINT uNode = 0; uNode < uRosterNodes; uNode++)
  291. {
  292. if (pMember->GetGCCID() == pRoster->nodes[uNode].uNodeID)
  293. {
  294. nExistingParts++;
  295. pMarkArray[uNode] = TRUE; // mark this node as "existing member"
  296. pMember->AddPf(PF_INCONFERENCE);
  297. break;
  298. }
  299. }
  300. }
  301. RemoveOldMembers(m_uMembers - nExistingParts);
  302. if (pRoster->uNumNodes > nExistingParts)
  303. {
  304. #ifdef _DEBUG
  305. UINT nAdded = 0;
  306. #endif // _DEBUG
  307. // At least one participant joined:
  308. // find the new participant(s)
  309. for (UINT uNode = 0; uNode < uRosterNodes; uNode++)
  310. {
  311. if (FALSE == pMarkArray[uNode]) // a new participant?
  312. {
  313. BOOL fLocal = FALSE;
  314. CNmMember * pMember = NULL;
  315. if (m_ourNodeID == pRoster->nodes[uNode].uNodeID)
  316. {
  317. fLocal = TRUE;
  318. }
  319. if (fLocal)
  320. {
  321. pMember = GetLocalMember();
  322. }
  323. else
  324. {
  325. pMember = NULL;
  326. }
  327. if(pMember)
  328. {
  329. #ifdef _DEBUG
  330. nAdded++; // a data participant was effectively added
  331. #endif // _DEBUG
  332. }
  333. else
  334. {
  335. pMember = CreateMember(
  336. fLocal,
  337. 0,
  338. &pRoster->nodes[uNode]);
  339. #ifdef _DEBUG
  340. if (NULL != pMember)
  341. {
  342. nAdded++;
  343. }
  344. #endif // _DEBUG
  345. AddMember(pMember);
  346. }
  347. }
  348. }
  349. // Validate that we did the right thing:
  350. ASSERT(nAdded == (uRosterNodes - nExistingParts));
  351. }
  352. delete pMarkArray;
  353. pMarkArray = NULL;
  354. }
  355. else
  356. {
  357. ERROR_OUT(("Couldn't allocate pMarkArray - no roster diff done"));
  358. }
  359. // Check to decide if we should auto-terminate here..
  360. if ((1 == pRoster->uNumNodes) &&
  361. (m_uMembers > 1))
  362. {
  363. if (!m_fServerMode)
  364. {
  365. LeaveConference(FALSE); // don't force (we could be inviting)
  366. }
  367. }
  368. }
  369. else
  370. {
  371. WARNING_OUT(("NULL pRoster passed to CConfObject::OnRosterChanged!"));
  372. }
  373. DebugExitBOOL(CConfObject::OnRosterChanged, bRet);
  374. return bRet;
  375. }
  376. VOID CConfObject::AddMember(CNmMember * pMember)
  377. {
  378. DebugEntry(CConfObject::AddMember);
  379. if (NULL == pMember)
  380. {
  381. ERROR_OUT(("AddMember - null member!"));
  382. goto Done;
  383. }
  384. NM_CONFERENCE_STATE oldNmState, newNmState;
  385. GetState(&oldNmState);
  386. m_MemberList.AddTail(pMember);
  387. m_uMembers++;
  388. CheckState(oldNmState);
  389. NotifySink((INmMember *) pMember, OnNotifyMemberAdded);
  390. Done:
  391. DebugExitVOID(CConfObject::AddMember);
  392. }
  393. VOID CConfObject::RemoveMember(POSITION pos)
  394. {
  395. DebugEntry(CConfObject::RemoveMember);
  396. NM_CONFERENCE_STATE oldNmState, newNmState;
  397. GetState(&oldNmState);
  398. CNmMember * pMember = (CNmMember *) m_MemberList.RemoveAt(pos);
  399. --m_uMembers;
  400. if (pMember->FLocal())
  401. {
  402. // this is the local node:
  403. m_pMemberLocal = NULL;
  404. }
  405. NotifySink((INmMember *) pMember, OnNotifyMemberRemoved);
  406. pMember->Release();
  407. // Sanity check:
  408. ASSERT((m_uMembers >= 0) &&
  409. (m_uMembers < 10000));
  410. CheckState(oldNmState);
  411. DebugExitVOID(CConfObject::RemoveMember);
  412. }
  413. BOOL CConfObject::OnConferenceEnded()
  414. {
  415. DebugEntry(CConfObject::OnConferenceEnded);
  416. BOOL bRet = TRUE;
  417. switch (m_csState)
  418. {
  419. case CS_GOING_DOWN:
  420. {
  421. TRACE_OUT(("ConfEnded received (from CS_GOING_DOWN)"));
  422. break;
  423. }
  424. case CS_RUNNING:
  425. {
  426. TRACE_OUT(("ConfEnded received (from CS_RUNNING)"));
  427. break;
  428. }
  429. case CS_COMING_UP:
  430. {
  431. TRACE_OUT(("ConfEnded received (from CS_COMING_UP)"));
  432. break;
  433. }
  434. default:
  435. {
  436. WARNING_OUT(("ConfEnded received (UNEXPECTED)"));
  437. }
  438. }
  439. if (NULL != m_hConf)
  440. {
  441. m_hConf->ReleaseInterface();
  442. m_hConf = NULL;
  443. }
  444. SetT120State(CS_TERMINATED);
  445. TRACE_OUT(("OnConferenceEnded(), num participants is %d", m_uMembers));
  446. // Empty the participant list:
  447. NC_ROSTER FakeRoster;
  448. ClearStruct(&FakeRoster);
  449. FakeRoster.uConferenceID = m_uGCCConferenceID;
  450. OnRosterChanged(&FakeRoster);
  451. ASSERT(0 == m_ourNodeID);
  452. ASSERT(0 == m_uMembers);
  453. // Reset member variables that pertain to a conference
  454. m_uGCCConferenceID = 0;
  455. m_fServerMode = FALSE;
  456. SysFreeString(m_bstrConfName);
  457. m_bstrConfName = NULL;
  458. DebugExitBOOL(CConfObject::OnConferenceEnded, bRet);
  459. return bRet;
  460. }
  461. BOOL CConfObject::OnConferenceStarted(CONF_HANDLE hConf, HRESULT hResult)
  462. {
  463. DebugEntry(CConfObject::OnConferenceStarted);
  464. BOOL bRet = TRUE;
  465. ASSERT(hConf == m_hConf);
  466. switch (m_csState)
  467. {
  468. case CS_CREATING:
  469. case CS_COMING_UP:
  470. {
  471. switch(hResult)
  472. {
  473. case S_OK:
  474. TRACE_OUT(("ConfStarted received -> now running"));
  475. SetT120State(CS_RUNNING);
  476. break;
  477. case UI_RC_INVALID_PASSWORD:
  478. // nop, don't mess with state
  479. // the conference is still coming up
  480. // the incoming call handler will deal with this
  481. break;
  482. default:
  483. SetT120State(CS_GOING_DOWN);
  484. TRACE_OUT(("ConfStarted failed"));
  485. break;
  486. }
  487. break;
  488. }
  489. default:
  490. {
  491. WARNING_OUT(("OnConferenceStarted received (UNEXPECTED)"));
  492. break;
  493. }
  494. }
  495. DebugExitBOOL(CConfObject::OnConferenceStarted, bRet);
  496. return bRet;
  497. }
  498. VOID CConfObject::RemoveOldMembers(int nExpected)
  499. {
  500. DebugEntry(CConfObject::RemoveOldMembers);
  501. #ifdef _DEBUG
  502. int nRemoved = 0;
  503. #endif // _DEBUG
  504. ASSERT(nExpected >= 0);
  505. if (nExpected > 0)
  506. {
  507. // At least one participant left:
  508. POSITION pos = m_MemberList.GetHeadPosition();
  509. while (NULL != pos)
  510. {
  511. POSITION oldpos = pos;
  512. CNmMember * pMember = (CNmMember *) m_MemberList.GetNext(pos);
  513. ASSERT(pMember);
  514. DWORD dwFlags = pMember->GetDwFlags();
  515. if (!(PF_INCONFERENCE & dwFlags))
  516. {
  517. // This one is not in the data call:
  518. TRACE_OUT(("CConfObject Roster: %ls (%d) has left.",
  519. pMember->GetName(), pMember->GetGCCID()));
  520. #ifdef _DEBUG
  521. nRemoved++;
  522. #endif // _DEBUG
  523. // If they were data only, then remove:
  524. RemoveMember(oldpos);
  525. }
  526. }
  527. // Validate that we did the right thing:
  528. ASSERT(nRemoved == nExpected);
  529. }
  530. DebugExitVOID(CConfObject::RemoveOldMembers);
  531. }
  532. CNmMember * CConfObject::CreateMember(BOOL fLocal,
  533. UINT uCaps,
  534. NC_ROSTER_NODE_ENTRY* pRosterNode)
  535. {
  536. DebugEntry(CConfObject::CreateMember);
  537. ASSERT(NULL != pRosterNode);
  538. DWORD dwFlags = 0;
  539. if (fLocal)
  540. {
  541. dwFlags |= PF_LOCAL_NODE;
  542. }
  543. if (pRosterNode->fMCU)
  544. {
  545. dwFlags |= PF_T120_MCU;
  546. }
  547. CNmMember * pMember = new CNmMember(pRosterNode->pwszNodeName,
  548. pRosterNode->uNodeID,
  549. dwFlags,
  550. uCaps);
  551. if (NULL != pMember)
  552. {
  553. pMember->SetGccIdParent(pRosterNode->uSuperiorNodeID);
  554. if (fLocal)
  555. {
  556. ASSERT(NULL == m_pMemberLocal);
  557. m_pMemberLocal = pMember;
  558. }
  559. }
  560. TRACE_OUT(("CConfObject Roster: %ls (%d) has joined.", pRosterNode->pwszNodeName, pRosterNode->uNodeID));
  561. DebugExitPVOID(CConfObject::CreateMember, pMember);
  562. return pMember;
  563. }
  564. VOID CConfObject::OnMemberUpdated(INmMember *pMember)
  565. {
  566. NotifySink(pMember, OnNotifyMemberUpdated);
  567. }
  568. VOID CConfObject::SetT120State(CONFSTATE state)
  569. {
  570. NM_CONFERENCE_STATE oldNmState;
  571. GetState(&oldNmState);
  572. m_csState = state;
  573. if ( state == CS_TERMINATED )
  574. m_fSecure = FALSE; // Reset secure flag
  575. CheckState(oldNmState);
  576. }
  577. VOID CConfObject::CheckState(NM_CONFERENCE_STATE oldNmState)
  578. {
  579. NM_CONFERENCE_STATE newNmState;
  580. GetState(&newNmState);
  581. if (oldNmState != newNmState)
  582. {
  583. NotifySink((PVOID) newNmState, OnNotifyStateChanged);
  584. if (NM_CONFERENCE_IDLE == newNmState)
  585. {
  586. m_fConferenceCreated = FALSE;
  587. }
  588. }
  589. }
  590. ULONG CConfObject::AddRef(void)
  591. {
  592. return ++m_cRef;
  593. }
  594. ULONG CConfObject::Release(void)
  595. {
  596. ASSERT(m_cRef > 0);
  597. if (m_cRef > 0)
  598. {
  599. m_cRef--;
  600. }
  601. ULONG cRef = m_cRef;
  602. if (0 == cRef)
  603. {
  604. delete this;
  605. }
  606. return cRef;
  607. }
  608. HRESULT STDMETHODCALLTYPE CConfObject::QueryInterface(REFIID riid, PVOID *ppv)
  609. {
  610. HRESULT hr = S_OK;
  611. if((riid == IID_INmConference) || (riid == IID_IUnknown))
  612. {
  613. *ppv = (INmConference *)this;
  614. TRACE_OUT(("CConfObject::QueryInterface()"));
  615. }
  616. else if (riid == IID_IConnectionPointContainer)
  617. {
  618. *ppv = (IConnectionPointContainer *) this;
  619. TRACE_OUT(("CConfObject::QueryInterface(): Returning IConnectionPointContainer."));
  620. }
  621. else
  622. {
  623. hr = E_NOINTERFACE;
  624. *ppv = NULL;
  625. TRACE_OUT(("CConfObject::QueryInterface(): Called on unknown interface."));
  626. }
  627. if (S_OK == hr)
  628. {
  629. AddRef();
  630. }
  631. return hr;
  632. }
  633. HRESULT CConfObject::GetName(BSTR *pbstrName)
  634. {
  635. HRESULT hr = E_POINTER;
  636. if (NULL != pbstrName)
  637. {
  638. *pbstrName = SysAllocString(m_bstrConfName);
  639. hr = *pbstrName ? S_OK : E_FAIL;
  640. }
  641. return hr;
  642. }
  643. HRESULT CConfObject::GetID(ULONG *puID)
  644. {
  645. HRESULT hr = E_POINTER;
  646. if (NULL != puID)
  647. {
  648. *puID = m_uGCCConferenceID;
  649. hr = S_OK;
  650. }
  651. return hr;
  652. }
  653. HRESULT CConfObject::GetState(NM_CONFERENCE_STATE *pState)
  654. {
  655. HRESULT hr = E_POINTER;
  656. if (NULL != pState)
  657. {
  658. hr = S_OK;
  659. switch (m_csState)
  660. {
  661. // Note: All states are valid (at least, for now)
  662. case CS_CREATING:
  663. case CS_UNINITIALIZED:
  664. case CS_TERMINATED:
  665. *pState = NM_CONFERENCE_IDLE;
  666. break;
  667. case CS_COMING_UP:
  668. case CS_GOING_DOWN:
  669. case CS_RUNNING:
  670. if (m_uMembers < 2)
  671. {
  672. if (m_fServerMode)
  673. {
  674. *pState = NM_CONFERENCE_WAITING;
  675. }
  676. else
  677. {
  678. *pState = NM_CONFERENCE_INITIALIZING;
  679. }
  680. }
  681. else
  682. {
  683. *pState = NM_CONFERENCE_ACTIVE;
  684. }
  685. break;
  686. default:
  687. hr = E_FAIL;
  688. break;
  689. }
  690. }
  691. return hr;
  692. }
  693. HRESULT CConfObject::GetTopProvider(INmMember **ppMember)
  694. {
  695. CNmMember *pMemberRet = NULL;
  696. HRESULT hr = E_POINTER;
  697. if (NULL != ppMember)
  698. {
  699. POSITION pos = m_MemberList.GetHeadPosition();
  700. while (NULL != pos)
  701. {
  702. CNmMember *pMember = (CNmMember *) m_MemberList.GetNext(pos);
  703. ASSERT(pMember);
  704. if (pMember->FTopProvider())
  705. {
  706. // We have found the top provider
  707. pMemberRet = pMember;
  708. break;
  709. }
  710. }
  711. *ppMember = pMemberRet;
  712. hr = (NULL != pMemberRet) ? S_OK : S_FALSE;
  713. }
  714. return hr;
  715. }
  716. HRESULT CConfObject::EnumMember(IEnumNmMember **ppEnum)
  717. {
  718. HRESULT hr = E_POINTER;
  719. if (NULL != ppEnum)
  720. {
  721. *ppEnum = new CEnumNmMember(&m_MemberList, m_uMembers);
  722. hr = (NULL != *ppEnum) ? S_OK : E_OUTOFMEMORY;
  723. }
  724. return hr;
  725. }
  726. HRESULT CConfObject::GetMemberCount(ULONG *puCount)
  727. {
  728. HRESULT hr = E_POINTER;
  729. if (NULL != puCount)
  730. {
  731. *puCount = m_uMembers;
  732. hr = S_OK;
  733. }
  734. return hr;
  735. }
  736. HRESULT CConfObject::FindMember(ULONG gccID, INmMember ** ppMember)
  737. {
  738. CNmMember * pMember;
  739. if (!ppMember)
  740. return E_POINTER;
  741. pMember = PMemberFromGCCID(gccID);
  742. if (pMember)
  743. {
  744. pMember->AddRef();
  745. }
  746. *ppMember = pMember;
  747. return S_OK;
  748. }
  749. /* P M E M B E R L O C A L */
  750. /*-------------------------------------------------------------------------
  751. %%Function: PMemberLocal
  752. -------------------------------------------------------------------------*/
  753. CNmMember * PMemberLocal(COBLIST *pList)
  754. {
  755. if (NULL != pList)
  756. {
  757. POSITION posCurr;
  758. POSITION pos = pList->GetHeadPosition();
  759. while (NULL != pos)
  760. {
  761. posCurr = pos;
  762. CNmMember * pMember = (CNmMember *) pList->GetNext(pos);
  763. ASSERT(NULL != pMember);
  764. if (pMember->FLocal())
  765. return pMember;
  766. }
  767. }
  768. return NULL;
  769. }
  770. STDMETHODIMP CConfObject::CreateDataChannel
  771. (
  772. INmChannelData ** ppChannel,
  773. REFGUID rguid
  774. )
  775. {
  776. HRESULT hr = E_FAIL;
  777. DebugEntry(CConfObject::CreateDataChannel);
  778. if (NULL != ppChannel)
  779. {
  780. if (IsBadWritePtr(ppChannel, sizeof(LPVOID)))
  781. return E_POINTER;
  782. *ppChannel = NULL;
  783. }
  784. if (GUID_NULL == rguid)
  785. {
  786. WARNING_OUT(("CreateDataChannel: Null guid"));
  787. return E_INVALIDARG;
  788. }
  789. // Make sure we're in a data conference
  790. CNmMember * pMember = PMemberLocal(&m_MemberList);
  791. if (NULL == pMember)
  792. {
  793. WARNING_OUT(("CreateDataChannel: No members yet"));
  794. return E_FAIL;
  795. }
  796. CNmChannelData * pChannel = new CNmChannelData(this, rguid);
  797. if (NULL == pChannel)
  798. {
  799. WARNING_OUT(("CreateDataChannel: Unable to create data channel"));
  800. return E_OUTOFMEMORY;
  801. }
  802. hr = pChannel->OpenConnection();
  803. if (FAILED(hr))
  804. {
  805. ERROR_OUT(("CreateDataChannel: Unable to set guid / create T.120 channels"));
  806. // Failed to create T.120 data channels
  807. delete pChannel;
  808. *ppChannel = NULL;
  809. return hr;
  810. }
  811. if (NULL != ppChannel)
  812. {
  813. *ppChannel = (INmChannelData *)pChannel;
  814. }
  815. else
  816. {
  817. pChannel->Release(); // No one is watching this channel? - free it now
  818. }
  819. hr = S_OK;
  820. DebugExitHRESULT(CConfObject::CreateDataChannel, hr);
  821. return hr;
  822. }
  823. HRESULT CConfObject::IsHosting(void)
  824. {
  825. return m_fServerMode ? S_OK : S_FALSE;
  826. }
  827. HRESULT CConfObject::Host(void)
  828. {
  829. HRESULT hr = E_FAIL;
  830. if (m_fServerMode || IsConferenceActive())
  831. {
  832. WARNING_OUT(("Conference already exists!"));
  833. // ncsRet = UI_RC_CONFERENCE_ALREADY_EXISTS;
  834. }
  835. else
  836. {
  837. HRESULT ncsRet = CreateConference();
  838. if (S_OK == ncsRet)
  839. {
  840. // The only success case:
  841. TRACE_OUT(("Create local issued successfully"));
  842. m_fServerMode = TRUE;
  843. hr = S_OK;
  844. }
  845. else
  846. {
  847. // UI?
  848. WARNING_OUT(("Create local failed!"));
  849. }
  850. }
  851. return hr;
  852. }
  853. HRESULT CConfObject::Leave(void)
  854. {
  855. DebugEntry(CConfObject::Leave);
  856. COprahNCUI *pOprahNCUI = COprahNCUI::GetInstance();
  857. if (NULL != pOprahNCUI)
  858. {
  859. pOprahNCUI->CancelCalls();
  860. }
  861. HRESULT hr = S_OK;
  862. switch (m_csState)
  863. {
  864. case CS_GOING_DOWN:
  865. // we are already exiting
  866. break;
  867. case CS_COMING_UP:
  868. case CS_RUNNING:
  869. {
  870. SetT120State(CS_GOING_DOWN);
  871. ASSERT(m_hConf);
  872. TRACE_OUT(("Calling IDataConference::Leave"));
  873. hr = m_hConf->Leave();
  874. if (FAILED(hr))
  875. {
  876. WARNING_OUT(("IDataConference::Leave failed"));
  877. }
  878. break;
  879. }
  880. default:
  881. hr = E_FAIL;
  882. break;
  883. }
  884. DebugExitHRESULT(CConfObject::Leave, hr);
  885. return hr;
  886. }
  887. HRESULT CConfObject::LaunchRemote(REFGUID rguid, INmMember *pMember)
  888. {
  889. DWORD dwUserId = 0;
  890. if(m_hConf)
  891. {
  892. if (NULL != pMember)
  893. {
  894. dwUserId = ((CNmMember*)pMember)->GetGCCID();
  895. }
  896. ASSERT(g_pNodeController);
  897. ASSERT(m_hConf);
  898. HRESULT nsRet = m_hConf->LaunchGuid(&rguid,
  899. (PUINT) &dwUserId, (0 == dwUserId) ? 0 : 1);
  900. return (S_OK == nsRet) ? S_OK : E_FAIL;
  901. }
  902. return NM_E_NO_T120_CONFERENCE;
  903. }
  904. /****************************************************************************
  905. *
  906. * CLASS: CConfObject
  907. *
  908. * FUNCTION: GetConferenceHandle(DWORD *)
  909. *
  910. * PURPOSE: Gets the T120 conference handle
  911. *
  912. ****************************************************************************/
  913. STDMETHODIMP CConfObject::GetConferenceHandle(DWORD_PTR *pdwHandle)
  914. {
  915. HRESULT hr = E_FAIL;
  916. if (NULL != pdwHandle)
  917. {
  918. CONF_HANDLE hConf = GetConfHandle();
  919. *pdwHandle = (DWORD_PTR)hConf;
  920. hr = S_OK;
  921. }
  922. return hr;
  923. }
  924. /* O N N O T I F Y S T A T E C H A N G E D */
  925. /*-------------------------------------------------------------------------
  926. %%Function: OnNotifyStateChanged
  927. -------------------------------------------------------------------------*/
  928. HRESULT OnNotifyStateChanged(IUnknown *pConfNotify, PVOID pv, REFIID riid)
  929. {
  930. ASSERT(NULL != pConfNotify);
  931. ((INmConferenceNotify*)pConfNotify)->StateChanged((NM_CONFERENCE_STATE)((DWORD_PTR)pv));
  932. return S_OK;
  933. }
  934. /* O N N O T I F Y M E M B E R A D D E D */
  935. /*-------------------------------------------------------------------------
  936. %%Function: OnNotifyMemberAdded
  937. -------------------------------------------------------------------------*/
  938. HRESULT OnNotifyMemberAdded(IUnknown *pConfNotify, PVOID pv, REFIID riid)
  939. {
  940. ASSERT(NULL != pConfNotify);
  941. ((INmConferenceNotify*)pConfNotify)->MemberChanged(NM_MEMBER_ADDED, (INmMember *) pv);
  942. return S_OK;
  943. }
  944. /* O N N O T I F Y M E M B E R U P D A T E D */
  945. /*-------------------------------------------------------------------------
  946. %%Function: OnNotifyMemberUpdated
  947. -------------------------------------------------------------------------*/
  948. HRESULT OnNotifyMemberUpdated(IUnknown *pConfNotify, PVOID pv, REFIID riid)
  949. {
  950. ASSERT(NULL != pConfNotify);
  951. ((INmConferenceNotify*)pConfNotify)->MemberChanged(NM_MEMBER_UPDATED, (INmMember *) pv);
  952. return S_OK;
  953. }
  954. /* O N N O T I F Y M E M B E R R E M O V E D */
  955. /*-------------------------------------------------------------------------
  956. %%Function: OnNotifyMemberRemoved
  957. -------------------------------------------------------------------------*/
  958. HRESULT OnNotifyMemberRemoved(IUnknown *pConfNotify, PVOID pv, REFIID riid)
  959. {
  960. ASSERT(NULL != pConfNotify);
  961. ((INmConferenceNotify*)pConfNotify)->MemberChanged(NM_MEMBER_REMOVED, (INmMember *) pv);
  962. return S_OK;
  963. }
  964. /* O N N O T I F Y N M U I */
  965. /*-------------------------------------------------------------------------
  966. %%Function: OnNotifyNmUI
  967. -------------------------------------------------------------------------*/
  968. HRESULT OnNotifyNmUI(IUnknown *pConfNotify, PVOID pv, REFIID riid)
  969. {
  970. ASSERT(NULL != pConfNotify);
  971. ((INmConferenceNotify*)pConfNotify)->NmUI((CONFN)((DWORD_PTR)pv));
  972. return S_OK;
  973. }
  974. /* G E T C O N F O B J E C T */
  975. /*-------------------------------------------------------------------------
  976. %%Function: GetConfObject
  977. Global function to get the conference object
  978. -------------------------------------------------------------------------*/
  979. CConfObject * GetConfObject(void)
  980. {
  981. COprahNCUI *pOprahNCUI = COprahNCUI::GetInstance();
  982. if (NULL != pOprahNCUI)
  983. {
  984. return pOprahNCUI->GetConfObject();
  985. }
  986. return NULL;
  987. }
  988. /* G E T C O N F E R E N C E */
  989. /*-------------------------------------------------------------------------
  990. %%Function: GetConference
  991. Global function to get the INmConference interface to the conf object
  992. -------------------------------------------------------------------------*/
  993. HRESULT GetConference(INmConference **ppConference)
  994. {
  995. HRESULT hr = E_POINTER;
  996. if (NULL != ppConference)
  997. {
  998. hr = E_FAIL;
  999. INmConference *pConference = GetConfObject();
  1000. if (NULL != pConference)
  1001. {
  1002. pConference->AddRef();
  1003. hr = S_OK;
  1004. }
  1005. *ppConference = pConference;
  1006. }
  1007. return hr;
  1008. }
  1009. /* G E T M E M B E R L I S T */
  1010. /*-------------------------------------------------------------------------
  1011. %%Function: GetMemberList
  1012. Global function to get the member list
  1013. -------------------------------------------------------------------------*/
  1014. COBLIST * GetMemberList(void)
  1015. {
  1016. CConfObject* pco = ::GetConfObject();
  1017. if (NULL == pco)
  1018. return NULL;
  1019. return pco->GetMemberList();
  1020. }
  1021. DWORD CConfObject::GetDwUserIdLocal(void)
  1022. {
  1023. CNmMember * pMemberLocal = GetLocalMember();
  1024. if (NULL != pMemberLocal)
  1025. {
  1026. return pMemberLocal->GetGCCID();
  1027. }
  1028. return 0;
  1029. }
  1030. CNmMember * CConfObject::PMemberFromGCCID(UINT uNodeID)
  1031. {
  1032. COBLIST* pMemberList = ::GetMemberList();
  1033. if (NULL != pMemberList)
  1034. {
  1035. POSITION pos = pMemberList->GetHeadPosition();
  1036. while (pos)
  1037. {
  1038. CNmMember * pMember = (CNmMember *) pMemberList->GetNext(pos);
  1039. ASSERT(NULL != pMember);
  1040. if (uNodeID == pMember->GetGCCID())
  1041. {
  1042. return pMember;
  1043. }
  1044. }
  1045. }
  1046. return NULL;
  1047. }
  1048. CNmMember * CConfObject::PMemberFromName(PCWSTR pwszName)
  1049. {
  1050. POSITION pos = m_MemberList.GetHeadPosition();
  1051. while (NULL != pos)
  1052. {
  1053. CNmMember * pMember = (CNmMember *) m_MemberList.GetNext(pos);
  1054. if (0 == UnicodeCompare(pwszName, pMember->GetName()))
  1055. {
  1056. return pMember;
  1057. }
  1058. }
  1059. return NULL;
  1060. }