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.

3211 lines
77 KiB

  1. // File: iconf.cpp
  2. #include "precomp.h"
  3. #include "version.h"
  4. #include "ichnlaud.h"
  5. #include "ichnlvid.h"
  6. #include "ichnldat.h"
  7. #include "rostinfo.h"
  8. #include "imanager.h"
  9. #include "isysinfo.h"
  10. #include "imstream.h"
  11. #include "medialst.h"
  12. #include <tsecctrl.h>
  13. typedef CEnumNmX<IEnumNmChannel, &IID_IEnumNmChannel, INmChannel, INmChannel> CEnumNmChannel;
  14. // BUGBUG:
  15. // This is defined as 128 because the RNC_ROSTER structure has the
  16. // same limitation. Investigate what the appropriate number is.
  17. const int MAX_CALLER_NAME = 128;
  18. static const WCHAR _szConferenceNameDefault[] = L"Personal Conference";
  19. static HRESULT OnNotifyStateChanged(IUnknown *pConfNotify, PVOID pv, REFIID riid);
  20. static HRESULT OnNotifyMemberAdded(IUnknown *pConfNotify, PVOID pv, REFIID riid);
  21. static HRESULT OnNotifyMemberUpdated(IUnknown *pConfNotify, PVOID pv, REFIID riid);
  22. static HRESULT OnNotifyMemberRemoved(IUnknown *pConfNotify, PVOID pv, REFIID riid);
  23. static HRESULT OnNotifyChannelAdded(IUnknown *pConfNotify, PVOID pv, REFIID riid);
  24. static HRESULT OnNotifyChannelUpdated(IUnknown *pConfNotify, PVOID pv, REFIID riid);
  25. static HRESULT OnNotifyChannelRemoved(IUnknown *pConfNotify, PVOID pv, REFIID riid);
  26. static HRESULT OnNotifyNmUI(IUnknown *pConfNotify, PVOID pv, REFIID riid);
  27. static HRESULT OnNotifyStreamEvent(IUnknown *pConfNotify, PVOID pv, REFIID riid);
  28. static DWORD PF_VER_FromDw(DWORD dw);
  29. static DWORD PF_VER_FromUserData(ROSTER_DATA_HANDLE hUserData);
  30. static const IID * g_apiidCP[] =
  31. {
  32. {&IID_INmConferenceNotify},
  33. {&IID_INmConferenceNotify2}
  34. };
  35. struct StreamEventInfo
  36. {
  37. INmChannel *pChannel;
  38. NM_STREAMEVENT uEventCode;
  39. UINT uSubCode;
  40. };
  41. class CUserDataOut
  42. {
  43. private:
  44. int m_nEntries;
  45. PUSERDATAINFO m_pudi;
  46. CRosterInfo m_ri;
  47. PBYTE m_pbSecurity;
  48. public:
  49. CUserDataOut(BOOL fSecure, BSTR bstrUserString);
  50. ~CUserDataOut()
  51. {
  52. delete [] m_pbSecurity;
  53. delete [] m_pudi;
  54. }
  55. PUSERDATAINFO Data() { return m_pudi; }
  56. int Entries() { return m_nEntries; }
  57. };
  58. CUserDataOut::CUserDataOut(BOOL fSecure, BSTR bstrUserString) :
  59. m_nEntries(0),
  60. m_pudi(NULL),
  61. m_pbSecurity(NULL)
  62. {
  63. COprahNCUI *pOprahNCUI = COprahNCUI::GetInstance();
  64. if (NULL != pOprahNCUI)
  65. {
  66. BOOL fULSNameValid = FALSE;
  67. ULONG cbSecurity = 0;
  68. ULONG cbUserString = 0;
  69. if (fULSNameValid = pOprahNCUI->GetULSName(&m_ri))
  70. m_nEntries++;
  71. DWORD dwResult;
  72. if ( fSecure )
  73. {
  74. if (cbSecurity =
  75. pOprahNCUI->GetAuthenticatedName(&m_pbSecurity)) {
  76. m_nEntries++;
  77. }
  78. }
  79. if (bstrUserString)
  80. {
  81. if (cbUserString = SysStringByteLen(bstrUserString))
  82. {
  83. m_nEntries++;
  84. }
  85. }
  86. // only add the LocalNodeId to the call user data if H323 is enabled
  87. if (pOprahNCUI->IsH323Enabled())
  88. {
  89. m_nEntries++;
  90. }
  91. m_pudi = new USERDATAINFO[m_nEntries];
  92. if (m_pudi != NULL)
  93. {
  94. m_nEntries = 0;
  95. if (fULSNameValid)
  96. {
  97. m_pudi[m_nEntries].pData = NULL;
  98. m_pudi[m_nEntries].pGUID = (PGUID) &g_csguidRostInfo;
  99. m_ri.Save(&(m_pudi[m_nEntries].pData), &(m_pudi[m_nEntries].cbData));
  100. m_nEntries++;
  101. }
  102. if (cbSecurity > 0) {
  103. m_pudi[m_nEntries].pData = m_pbSecurity;
  104. m_pudi[m_nEntries].cbData = cbSecurity;
  105. m_pudi[m_nEntries].pGUID = (PGUID) &g_csguidSecurity;
  106. m_nEntries++;
  107. }
  108. if (cbUserString > 0) {
  109. m_pudi[m_nEntries].pData = bstrUserString;
  110. m_pudi[m_nEntries].cbData = cbUserString;
  111. m_pudi[m_nEntries].pGUID = (PGUID) &g_csguidUserString;
  112. m_nEntries++;
  113. }
  114. // only add the LocalNodeId to the call user data if H323 is enabled
  115. if (pOprahNCUI->IsH323Enabled())
  116. {
  117. m_pudi[m_nEntries].pData = &g_guidLocalNodeId;
  118. m_pudi[m_nEntries].cbData = sizeof(g_guidLocalNodeId);
  119. m_pudi[m_nEntries].pGUID = (PGUID) &g_csguidNodeIdTag;
  120. m_nEntries++;
  121. }
  122. }
  123. }
  124. }
  125. CConfObject::CConfObject() :
  126. CConnectionPointContainer(g_apiidCP, ARRAY_ELEMENTS(g_apiidCP)),
  127. m_hConf (NULL),
  128. m_csState (CS_UNINITIALIZED),
  129. m_fConferenceCreated(FALSE),
  130. m_bstrConfName (NULL),
  131. m_bstrConfPassword (NULL),
  132. m_pbConfHashedPassword (NULL),
  133. m_cbConfHashedPassword (0),
  134. m_fServerMode (FALSE),
  135. m_uDataMembers (0),
  136. m_uMembers (0),
  137. m_uH323Endpoints (0),
  138. m_ourNodeID (0),
  139. m_pMemberLocal (NULL),
  140. m_uGCCConferenceID (0),
  141. m_pChannelAudioLocal(NULL),
  142. m_pChannelVideoLocal(NULL),
  143. m_pChannelAudioRemote(NULL),
  144. m_pChannelVideoRemote(NULL),
  145. m_fSecure (FALSE),
  146. m_attendeePermissions (NM_PERMIT_ALL),
  147. m_maxParticipants (-1),
  148. m_cRef (1)
  149. {
  150. DebugEntry(CConfObject::CConfObject);
  151. DebugExitVOID(CConfObject::CConfObject);
  152. }
  153. CConfObject::~CConfObject()
  154. {
  155. DebugEntry(CConfObject::~CConfObject);
  156. // Empty the participant list:
  157. while (!m_MemberList.IsEmpty())
  158. {
  159. CNmMember * pMember = (CNmMember *) m_MemberList.RemoveHead();
  160. // Shouldn't have any NULL entries:
  161. ASSERT(pMember);
  162. pMember->Release();
  163. }
  164. _EraseDataChannelGUIDS();
  165. SysFreeString(m_bstrConfName);
  166. SysFreeString(m_bstrConfPassword);
  167. delete []m_pbConfHashedPassword;
  168. DebugExitVOID(CConfObject::~CConfObject);
  169. }
  170. VOID CConfObject::SetConfName(BSTR bstr)
  171. {
  172. SysFreeString(m_bstrConfName);
  173. m_bstrConfName = SysAllocString(bstr);
  174. }
  175. VOID CConfObject::SetConfPassword(BSTR bstr)
  176. {
  177. ASSERT (NULL == m_pbConfHashedPassword);
  178. SysFreeString(m_bstrConfPassword);
  179. m_bstrConfPassword = SysAllocString(bstr);
  180. }
  181. VOID CConfObject::SetConfHashedPassword(BSTR bstr)
  182. {
  183. int cch = 0;
  184. ASSERT (NULL == m_bstrConfPassword);
  185. delete []m_pbConfHashedPassword;
  186. m_pbConfHashedPassword = NULL;
  187. if (NULL == bstr) return;
  188. cch = SysStringByteLen(bstr);
  189. m_pbConfHashedPassword = (PBYTE) new BYTE[cch];
  190. if (NULL == m_pbConfHashedPassword) {
  191. ERROR_OUT(("CConfObject::SetConfHashedPassword() - Out of merory."));
  192. return;
  193. }
  194. memcpy(m_pbConfHashedPassword, bstr, cch);
  195. m_cbConfHashedPassword = cch;
  196. }
  197. VOID CConfObject::SetConfSecurity(BOOL fSecure)
  198. {
  199. NM_CONFERENCE_STATE NmState;
  200. m_fSecure = fSecure;
  201. // Force update of the status icon to reflect security
  202. GetState(&NmState);
  203. NotifySink((PVOID) NmState, OnNotifyStateChanged);
  204. }
  205. VOID CConfObject::SetConfAttendeePermissions(NM30_MTG_PERMISSIONS attendeePermissions)
  206. {
  207. m_attendeePermissions = attendeePermissions;
  208. }
  209. VOID CConfObject::SetConfMaxParticipants(UINT maxParticipants)
  210. {
  211. m_maxParticipants = maxParticipants;
  212. }
  213. HRESULT CConfObject::CreateConference(void)
  214. {
  215. DebugEntry(CConfObject::CreateConference);
  216. HRESULT nsRet = E_FAIL;
  217. switch (m_csState)
  218. {
  219. case CS_UNINITIALIZED:
  220. case CS_TERMINATED:
  221. {
  222. if ((NULL == m_bstrConfName) || (0 == *m_bstrConfName))
  223. {
  224. m_bstrConfName = SysAllocString(_szConferenceNameDefault);
  225. }
  226. TRACE_OUT(("CConfObject:CreateConference [%ls]", m_bstrConfName));
  227. ASSERT(g_pNodeController);
  228. ASSERT(NULL == m_hConf);
  229. nsRet = g_pNodeController->CreateConference(
  230. m_bstrConfName,
  231. m_bstrConfPassword,
  232. m_pbConfHashedPassword,
  233. m_cbConfHashedPassword,
  234. m_fSecure,
  235. &m_hConf);
  236. if (0 == nsRet)
  237. {
  238. SetT120State(CS_CREATING);
  239. }
  240. else
  241. {
  242. m_hConf = NULL;
  243. }
  244. break;
  245. }
  246. default:
  247. {
  248. WARNING_OUT(("CConfObject: Can't create - bad state"));
  249. nsRet = E_FAIL;
  250. }
  251. }
  252. DebugExitINT(CConfObject::CreateConference, nsRet);
  253. return nsRet;
  254. }
  255. HRESULT CConfObject::JoinConference( LPCWSTR pcwszConferenceName,
  256. LPCWSTR pcwszPassword,
  257. LPCSTR pcszAddress,
  258. BSTR bstrUserString,
  259. BOOL fRetry)
  260. {
  261. DebugEntry(CConfObject::JoinConference);
  262. HRESULT nsRet = E_FAIL;
  263. switch (m_csState)
  264. {
  265. case CS_COMING_UP:
  266. {
  267. if (!fRetry)
  268. {
  269. break;
  270. }
  271. // fall through if this is another attempt to join
  272. }
  273. case CS_UNINITIALIZED:
  274. case CS_TERMINATED:
  275. {
  276. TRACE_OUT(("CConfObject: Joining conference..."));
  277. CUserDataOut userData(m_fSecure, bstrUserString);
  278. ASSERT(g_pNodeController);
  279. nsRet = g_pNodeController->JoinConference(pcwszConferenceName,
  280. pcwszPassword,
  281. pcszAddress,
  282. m_fSecure,
  283. userData.Data(),
  284. userData.Entries(),
  285. &m_hConf);
  286. if (0 == nsRet)
  287. {
  288. SetT120State(CS_COMING_UP);
  289. }
  290. else
  291. {
  292. m_hConf = NULL;
  293. }
  294. break;
  295. }
  296. case CS_GOING_DOWN:
  297. default:
  298. {
  299. WARNING_OUT(("CConfObject: Can't join - bad state"));
  300. // BUGBUG: define return values
  301. nsRet = S_FALSE;
  302. }
  303. }
  304. DebugExitINT(CConfObject::JoinConference, nsRet);
  305. return nsRet;
  306. }
  307. HRESULT CConfObject::InviteConference( LPCSTR Address,
  308. BSTR bstrUserString,
  309. REQUEST_HANDLE *phRequest )
  310. {
  311. DebugEntry(CConfObject::InviteConference);
  312. HRESULT nsRet = E_FAIL;
  313. ASSERT(phRequest);
  314. switch (m_csState)
  315. {
  316. case CS_RUNNING:
  317. {
  318. TRACE_OUT(("CConfObject: Inviting conference..."));
  319. CUserDataOut userData(m_fSecure, bstrUserString);
  320. ASSERT(g_pNodeController);
  321. ASSERT(m_hConf);
  322. m_hConf->SetSecurity(m_fSecure);
  323. nsRet = m_hConf->Invite(Address,
  324. userData.Data(),
  325. userData.Entries(),
  326. phRequest);
  327. break;
  328. }
  329. default:
  330. {
  331. WARNING_OUT(("CConfObject: Can't invite - bad state"));
  332. nsRet = E_FAIL;
  333. }
  334. }
  335. DebugExitINT(CConfObject::InviteConference, nsRet);
  336. return nsRet;
  337. }
  338. HRESULT CConfObject::LeaveConference(BOOL fForceLeave)
  339. {
  340. DebugEntry(CConfObject::LeaveConference);
  341. HRESULT nsRet = E_FAIL;
  342. REQUEST_HANDLE hReq = NULL;
  343. switch (m_csState)
  344. {
  345. case CS_GOING_DOWN:
  346. {
  347. // we're already going down
  348. nsRet = S_OK;
  349. break;
  350. }
  351. case CS_COMING_UP:
  352. case CS_RUNNING:
  353. {
  354. if (FALSE == fForceLeave)
  355. {
  356. COprahNCUI *pOprahNCUI = COprahNCUI::GetInstance();
  357. if (NULL != pOprahNCUI)
  358. {
  359. int nNodes = pOprahNCUI->GetOutgoingCallCount();
  360. if (m_fServerMode || (nNodes > 1) || (m_uDataMembers > 1))
  361. {
  362. // We are either in the process of calling another node
  363. // or we have other people in our conference roster
  364. TRACE_OUT(("CConfObject: Not leaving (there are other nodes)"));
  365. break;
  366. }
  367. }
  368. }
  369. TRACE_OUT(("CConfObject: Leaving conference..."));
  370. ASSERT(g_pNodeController);
  371. ASSERT(m_hConf);
  372. SetT120State(CS_GOING_DOWN);
  373. nsRet = m_hConf->Leave();
  374. break;
  375. }
  376. default:
  377. {
  378. WARNING_OUT(("CConfObject: Can't leave - bad state"));
  379. break;
  380. }
  381. }
  382. DebugExitINT(CConfObject::LeaveConference, nsRet);
  383. return nsRet;
  384. }
  385. BOOL CConfObject::OnT120Invite(CONF_HANDLE hConference, BOOL fSecure)
  386. {
  387. DebugEntry(CConfObject::OnT120Invite);
  388. BOOL bRet = FALSE;
  389. switch (m_csState)
  390. {
  391. case CS_UNINITIALIZED:
  392. case CS_TERMINATED:
  393. {
  394. TRACE_OUT(("CConfObject: Accepting a conference invitation..."));
  395. ASSERT(g_pNodeController);
  396. ASSERT(NULL == m_hConf);
  397. m_hConf = hConference;
  398. m_fSecure = fSecure;
  399. hConference->SetSecurity(m_fSecure);
  400. // WORKITEM need to issue INmManagerNotify::ConferenceCreated()
  401. SetT120State(CS_COMING_UP);
  402. bRet = TRUE;
  403. break;
  404. }
  405. default:
  406. {
  407. WARNING_OUT(("CConfObject: Can't accept invite - bad state"));
  408. }
  409. }
  410. DebugExitBOOL(CConfObject::OnT120Invite, bRet);
  411. return bRet;
  412. }
  413. BOOL CConfObject::OnRosterChanged(PNC_ROSTER pRoster)
  414. {
  415. DebugEntry(CConfObject::OnRosterChanged);
  416. BOOL bRet = TRUE;
  417. int i;
  418. // REVIEW: Could these be done more efficiently?
  419. if (NULL != pRoster)
  420. {
  421. #ifdef DEBUG
  422. TRACE_OUT(("Data Roster Dump: for conference ID = %d", pRoster->uConferenceID));
  423. for (i = 0; i < (int) pRoster->uNumNodes; i++)
  424. {
  425. TRACE_OUT(( "\tID:%d\tName:%ls",
  426. pRoster->nodes[i].uNodeID,
  427. pRoster->nodes[i].pwszNodeName));
  428. ASSERT(g_pNodeController);
  429. UINT cbData;
  430. PVOID pData;
  431. if (NOERROR == g_pNodeController->GetUserData(
  432. pRoster->nodes[i].hUserData,
  433. (GUID*) &g_csguidRostInfo,
  434. &cbData,
  435. &pData))
  436. {
  437. CRosterInfo ri;
  438. ri.Load(pData);
  439. ri.Dump();
  440. }
  441. }
  442. #endif // DEBUG
  443. UINT nExistingParts = 0;
  444. // Allocate an array of markers:
  445. UINT uRosterNodes = pRoster->uNumNodes;
  446. LPBOOL pMarkArray = new BOOL[uRosterNodes];
  447. m_ourNodeID = pRoster->uLocalNodeID;
  448. m_uGCCConferenceID = pRoster->uConferenceID;
  449. if (NULL != pRoster->pwszConferenceName)
  450. {
  451. SysFreeString(m_bstrConfName);
  452. m_bstrConfName = SysAllocString(pRoster->pwszConferenceName);
  453. }
  454. if (NULL != pMarkArray)
  455. {
  456. // Zero out the array:
  457. for (UINT iNode = 0; iNode < uRosterNodes; iNode++)
  458. {
  459. pMarkArray[iNode] = FALSE;
  460. }
  461. // For all participants still in the roster,
  462. // clear out the reserved flags and
  463. // copy in new UserInfo
  464. POSITION pos = m_MemberList.GetHeadPosition();
  465. // lous: Preserve previous pos so we can check list integrity
  466. POSITION prevpos = pos;
  467. while (NULL != pos)
  468. {
  469. CNmMember * pMember = (CNmMember *) m_MemberList.GetNext(pos);
  470. ASSERT(pMember);
  471. pMember->RemovePf(PF_RESERVED);
  472. UINT uNodeID = INVALID_GCCID;
  473. if (PF_T120 & pMember->GetDwFlags())
  474. {
  475. uNodeID = pMember->GetGCCID();
  476. }
  477. for (UINT uNode = 0; uNode < uRosterNodes; uNode++)
  478. {
  479. if (uNodeID == pRoster->nodes[uNode].uNodeID)
  480. {
  481. nExistingParts++;
  482. pMarkArray[uNode] = TRUE; // mark this node as "existing member"
  483. ResetDataMember(pMember, pRoster->nodes[uNode].hUserData);
  484. // lou: Check pos to make sure we didn't just wipe out the end of
  485. // the list in ResetDataMember.
  486. if (NULL == prevpos->pNext)
  487. {
  488. pos = NULL;
  489. }
  490. break;
  491. }
  492. }
  493. // lou: Store previous pos so we can check list integrity.
  494. prevpos = pos;
  495. }
  496. RemoveOldDataMembers(m_uDataMembers - nExistingParts);
  497. if (pRoster->uNumNodes > nExistingParts)
  498. {
  499. #ifdef _DEBUG
  500. UINT nAdded = 0;
  501. #endif // _DEBUG
  502. // At least one participant joined:
  503. // find the new participant(s)
  504. for (UINT uNode = 0; uNode < uRosterNodes; uNode++)
  505. {
  506. if (FALSE == pMarkArray[uNode]) // a new participant?
  507. {
  508. BOOL fLocal = FALSE;
  509. CNmMember * pMember = NULL;
  510. PVOID pvUserInfo;
  511. UINT cbUserInfo;
  512. ASSERT(g_pNodeController);
  513. if (NOERROR != g_pNodeController->GetUserData(
  514. pRoster->nodes[uNode].hUserData,
  515. (GUID*) &g_csguidRostInfo,
  516. &cbUserInfo,
  517. &pvUserInfo))
  518. {
  519. pvUserInfo = NULL;
  520. cbUserInfo = 0;
  521. }
  522. UINT uCaps;
  523. UINT cbCaps;
  524. PVOID pvCaps;
  525. if (NOERROR != g_pNodeController->GetUserData(
  526. pRoster->nodes[uNode].hUserData,
  527. (GUID*) &g_csguidRosterCaps,
  528. &cbCaps,
  529. &pvCaps))
  530. {
  531. uCaps = 0;
  532. }
  533. else
  534. {
  535. ASSERT(pvCaps && (sizeof(uCaps) == cbCaps));
  536. uCaps = *((PUINT)pvCaps);
  537. }
  538. PGUID pguidNodeId;
  539. UINT cbNodeId;
  540. if (NOERROR != g_pNodeController->GetUserData(
  541. pRoster->nodes[uNode].hUserData,
  542. (GUID*) &g_csguidNodeIdTag,
  543. &cbNodeId,
  544. (PVOID*) &pguidNodeId))
  545. {
  546. pguidNodeId = NULL;
  547. }
  548. else
  549. {
  550. if (sizeof(GUID) != cbNodeId)
  551. {
  552. pguidNodeId = NULL;
  553. }
  554. }
  555. if (m_ourNodeID == pRoster->nodes[uNode].uNodeID)
  556. {
  557. fLocal = TRUE;
  558. }
  559. REFGUID rguidNodeId = pguidNodeId ? *pguidNodeId : GUID_NULL;
  560. if (fLocal)
  561. {
  562. pMember = GetLocalMember();
  563. }
  564. else
  565. {
  566. pMember = MatchDataToH323Member(rguidNodeId, pRoster->nodes[uNode].uNodeID, pvUserInfo);
  567. }
  568. if(pMember)
  569. {
  570. AddDataToH323Member(pMember,
  571. pvUserInfo,
  572. cbUserInfo,
  573. uCaps,
  574. &pRoster->nodes[uNode]);
  575. #ifdef _DEBUG
  576. nAdded++; // a data participant was effectively added
  577. #endif // _DEBUG
  578. }
  579. else
  580. {
  581. pMember = CreateDataMember(
  582. fLocal,
  583. rguidNodeId,
  584. pvUserInfo,
  585. cbUserInfo,
  586. uCaps,
  587. &pRoster->nodes[uNode]);
  588. #ifdef _DEBUG
  589. if (NULL != pMember)
  590. {
  591. nAdded++;
  592. }
  593. #endif // _DEBUG
  594. AddMember(pMember, NULL);
  595. }
  596. }
  597. }
  598. // Validate that we did the right thing:
  599. ASSERT(nAdded == (uRosterNodes - nExistingParts));
  600. }
  601. delete [] pMarkArray;
  602. pMarkArray = NULL;
  603. }
  604. else
  605. {
  606. ERROR_OUT(("Couldn't allocate pMarkArray - no roster diff done"));
  607. }
  608. UINT uPrevDataMembers = m_uDataMembers;
  609. m_uDataMembers = pRoster->uNumNodes;
  610. // Check to decide if we should auto-terminate here..
  611. if ((1 == pRoster->uNumNodes) &&
  612. (uPrevDataMembers > 1) &&
  613. (1 == m_uDataMembers))
  614. {
  615. if (!m_fServerMode)
  616. {
  617. LeaveConference(FALSE); // don't force (we could be inviting)
  618. }
  619. }
  620. }
  621. else
  622. {
  623. WARNING_OUT(("NULL pRoster passed to CConfObject::OnRosterChanged!"));
  624. }
  625. DebugExitBOOL(CConfObject::OnRosterChanged, bRet);
  626. return bRet;
  627. }
  628. VOID CConfObject::AddMember(CNmMember * pMember, IH323Endpoint * pConnection)
  629. {
  630. DebugEntry(CConfObject::AddMember);
  631. if (NULL == pMember)
  632. {
  633. ERROR_OUT(("AddMember - null member!"));
  634. return;
  635. }
  636. NM_CONFERENCE_STATE oldNmState, newNmState;
  637. GetState(&oldNmState);
  638. m_MemberList.AddTail(pMember);
  639. if(pConnection)
  640. {
  641. pMember->AddH323Endpoint(pConnection);
  642. ++m_uH323Endpoints;
  643. CheckState(oldNmState);
  644. GetState(&oldNmState);
  645. }
  646. m_uMembers++;
  647. CheckState(oldNmState);
  648. NotifySink((INmMember *) pMember, OnNotifyMemberAdded);
  649. DebugExitVOID(CConfObject::AddMember);
  650. }
  651. VOID CConfObject::RemoveMember(POSITION pos)
  652. {
  653. DebugEntry(CConfObject::RemoveMember);
  654. NM_CONFERENCE_STATE oldNmState, newNmState;
  655. GetState(&oldNmState);
  656. CNmMember * pMember = (CNmMember *) m_MemberList.RemoveAt(pos);
  657. --m_uMembers;
  658. if (pMember->FLocal())
  659. {
  660. // this is the local node:
  661. m_pMemberLocal = NULL;
  662. }
  663. IH323Endpoint *pConnection = pMember->GetH323Endpoint();
  664. if(pConnection)
  665. {
  666. pMember->DeleteH323Endpoint(pConnection);
  667. --m_uH323Endpoints;
  668. }
  669. NotifySink((INmMember *) pMember, OnNotifyMemberRemoved);
  670. pMember->Release();
  671. CheckState(oldNmState);
  672. DebugExitVOID(CConfObject::RemoveMember);
  673. }
  674. BOOL CConfObject::OnConferenceEnded()
  675. {
  676. DebugEntry(CConfObject::OnConferenceEnded);
  677. BOOL bRet = TRUE;
  678. switch (m_csState)
  679. {
  680. case CS_GOING_DOWN:
  681. {
  682. TRACE_OUT(("ConfEnded received (from CS_GOING_DOWN)"));
  683. break;
  684. }
  685. case CS_RUNNING:
  686. {
  687. TRACE_OUT(("ConfEnded received (from CS_RUNNING)"));
  688. break;
  689. }
  690. case CS_COMING_UP:
  691. {
  692. TRACE_OUT(("ConfEnded received (from CS_COMING_UP)"));
  693. break;
  694. }
  695. default:
  696. {
  697. WARNING_OUT(("ConfEnded received (UNEXPECTED)"));
  698. }
  699. }
  700. if (NULL != m_hConf)
  701. {
  702. m_hConf->ReleaseInterface();
  703. m_hConf = NULL;
  704. }
  705. SetT120State(CS_TERMINATED);
  706. TRACE_OUT(("OnConferenceEnded(), num participants is %d", m_uMembers));
  707. // Empty the participant list:
  708. NC_ROSTER FakeRoster;
  709. ClearStruct(&FakeRoster);
  710. FakeRoster.uConferenceID = m_uGCCConferenceID;
  711. OnRosterChanged(&FakeRoster);
  712. ASSERT(0 == m_ourNodeID);
  713. ASSERT(0 == m_uDataMembers);
  714. // Reset member variables that pertain to a conference
  715. m_uGCCConferenceID = 0;
  716. m_fServerMode = FALSE;
  717. m_attendeePermissions = NM_PERMIT_ALL;
  718. m_maxParticipants = (UINT)-1;
  719. SysFreeString(m_bstrConfName);
  720. m_bstrConfName = NULL;
  721. SysFreeString(m_bstrConfPassword);
  722. m_bstrConfPassword = NULL;
  723. LeaveH323(TRUE /* fKeepAV */);
  724. DebugExitBOOL(CConfObject::OnConferenceEnded, bRet);
  725. return bRet;
  726. }
  727. BOOL CConfObject::OnConferenceStarted(CONF_HANDLE hConf, HRESULT hResult)
  728. {
  729. DebugEntry(CConfObject::OnConferenceStarted);
  730. BOOL bRet = TRUE;
  731. ASSERT(hConf == m_hConf);
  732. switch (m_csState)
  733. {
  734. case CS_CREATING:
  735. case CS_COMING_UP:
  736. {
  737. switch(hResult)
  738. {
  739. case S_OK:
  740. TRACE_OUT(("ConfStarted received -> now running"));
  741. SetT120State(CS_RUNNING);
  742. break;
  743. case UI_RC_INVALID_PASSWORD:
  744. // nop, don't mess with state
  745. // the conference is still coming up
  746. // the incoming call handler will deal with this
  747. break;
  748. default:
  749. SetT120State(CS_GOING_DOWN);
  750. TRACE_OUT(("ConfStarted failed"));
  751. break;
  752. }
  753. break;
  754. }
  755. default:
  756. {
  757. WARNING_OUT(("OnConferenceStarted received (UNEXPECTED)"));
  758. break;
  759. }
  760. }
  761. DebugExitBOOL(CConfObject::OnConferenceStarted, bRet);
  762. return bRet;
  763. }
  764. VOID CConfObject::OnH323ChannelChange(DWORD dwFlags, BOOL fIncoming, BOOL fOpen, ICommChannel *pIChannel)
  765. {
  766. CConfObject *pco = ::GetConfObject();
  767. IEnumNmMember *pEnumMember = NULL;
  768. ULONG cFetched;
  769. INmChannel *pINmChannel;
  770. DWORD dwMediaFlag;
  771. HRESULT hr;
  772. // find the INmChannel instance that would be associated with the
  773. // comm channel (pIChannel).
  774. // note the current issues with making this work for any number/type of
  775. // channels
  776. //
  777. // - CConfObject has 4 hardcoded instances of send/receive audio/video
  778. // - Those instances aren't yet associated with the ICommChannel instance
  779. // other than by media type and direction. For receive, new instances
  780. // could even be created dynamically as rx channel requests are
  781. // processed. For send, need to change CNmChannelAudio
  782. // and CNmChannelVideo to keep a reference to ICommChannel before
  783. // the channel open attempt occurs
  784. // - There is no base interface common to CNmChannelAudio
  785. // and CNmChannelVideo
  786. // - There is no internal interface on CNmMember
  787. //
  788. CNmMember *pMember = NULL;
  789. INmMember *pIMember = NULL;
  790. if (PF_MEDIA_AUDIO & dwFlags)
  791. {
  792. dwMediaFlag = PF_MEDIA_AUDIO;
  793. CNmChannelAudio *pChannelAudio;
  794. if (fIncoming)
  795. {
  796. pChannelAudio = m_pChannelAudioRemote;
  797. }
  798. else
  799. {
  800. pChannelAudio = m_pChannelAudioLocal;
  801. }
  802. if (NULL != pChannelAudio)
  803. {
  804. pINmChannel = (INmChannel *) pChannelAudio;
  805. if (fOpen)
  806. {
  807. pChannelAudio->CommChannelOpened(pIChannel);
  808. }
  809. else
  810. {
  811. pChannelAudio->CommChannelClosed();
  812. }
  813. // for every member associated with this channel, do the
  814. // member update thing
  815. hr = pChannelAudio->EnumMember(&pEnumMember);
  816. if(pEnumMember)
  817. {
  818. ASSERT(hr == S_OK);
  819. while(hr == S_OK)
  820. {
  821. pIMember = NULL;
  822. hr = pEnumMember->Next(1, &pIMember, &cFetched);
  823. if(!pIMember)
  824. {
  825. break;
  826. }
  827. else
  828. {
  829. ASSERT(hr == S_OK);
  830. // this cast is ugly, but necessary because there is no
  831. // real internal interface of CNmMember to query for.
  832. // When in Rome........
  833. pMember = (CNmMember *)pIMember;
  834. if (fOpen)
  835. {
  836. pMember->AddPf(dwMediaFlag);
  837. }
  838. else
  839. {
  840. pMember->RemovePf(dwMediaFlag);
  841. }
  842. // ugly - OnMemberUpdated() should be a base interface
  843. // method so that this code didn't have to be copied
  844. // for the video case
  845. pChannelAudio->OnMemberUpdated(pMember);
  846. pco->OnMemberUpdated(pMember);
  847. if (pMember->FLocal() && (NULL != m_hConf) && (CS_RUNNING == m_csState))
  848. {
  849. // m_hConf->UpdateUserData();
  850. }
  851. pMember->Release();
  852. }
  853. }
  854. pEnumMember->Release();
  855. }
  856. NotifySink(pINmChannel, OnNotifyChannelUpdated);
  857. }
  858. }
  859. else if (PF_MEDIA_VIDEO & dwFlags)
  860. {
  861. dwMediaFlag = PF_MEDIA_VIDEO;
  862. CNmChannelVideo *pChannelVideo;
  863. if (fIncoming)
  864. {
  865. pChannelVideo = m_pChannelVideoRemote;
  866. }
  867. else
  868. {
  869. pChannelVideo = m_pChannelVideoLocal;
  870. }
  871. if (NULL != pChannelVideo)
  872. {
  873. pINmChannel = (INmChannel *) pChannelVideo;
  874. if (fOpen)
  875. {
  876. pChannelVideo->CommChannelOpened(pIChannel);
  877. }
  878. else
  879. {
  880. pChannelVideo->CommChannelClosed();
  881. }
  882. // for every member associated with this channel, do the
  883. // member update thing
  884. hr = pChannelVideo->EnumMember(&pEnumMember);
  885. if(pEnumMember)
  886. {
  887. ASSERT(hr == S_OK);
  888. while(hr == S_OK)
  889. {
  890. pIMember = NULL;
  891. hr = pEnumMember->Next(1, &pIMember, &cFetched);
  892. if(!pIMember)
  893. {
  894. break;
  895. }
  896. else
  897. {
  898. ASSERT(hr == S_OK);
  899. // this cast is ugly, but necessary because there is no
  900. // real internal interface of CNmMember to query for.
  901. // When in Rome........
  902. pMember = (CNmMember *)pIMember;
  903. if (fOpen)
  904. {
  905. pMember->AddPf(dwMediaFlag);
  906. }
  907. else
  908. {
  909. pMember->RemovePf(dwMediaFlag);
  910. }
  911. // ugly - OnMemberUpdated() should be a base interface
  912. // method so that this code didn't have to be copied
  913. // from the audio case
  914. pChannelVideo->OnMemberUpdated(pMember);
  915. pco->OnMemberUpdated(pMember);
  916. if (pMember->FLocal() && (NULL != m_hConf) && (CS_RUNNING == m_csState))
  917. {
  918. // m_hConf->UpdateUserData();
  919. }
  920. pMember->Release();
  921. }
  922. }
  923. pEnumMember->Release();
  924. }
  925. NotifySink(pINmChannel, OnNotifyChannelUpdated);
  926. }
  927. }
  928. else
  929. ASSERT(0);
  930. }
  931. VOID CConfObject::OnAudioChannelStatus(ICommChannel *pIChannel, IH323Endpoint * lpConnection, DWORD dwStatus)
  932. {
  933. BOOL bIncoming = (pIChannel->IsSendChannel())? FALSE:TRUE;
  934. CNmChannelAudio *pChannelAudio;
  935. switch (dwStatus)
  936. {
  937. case CHANNEL_ACTIVE:
  938. if (bIncoming)
  939. {
  940. pChannelAudio = m_pChannelAudioRemote;
  941. }
  942. else
  943. {
  944. pChannelAudio = m_pChannelAudioLocal;
  945. }
  946. if (NULL != pChannelAudio)
  947. {
  948. pChannelAudio->CommChannelActive(pIChannel);
  949. }
  950. break;
  951. case CHANNEL_OPEN:
  952. OnH323ChannelChange(PF_MEDIA_AUDIO, bIncoming, TRUE, pIChannel);
  953. break;
  954. case CHANNEL_CLOSED:
  955. OnH323ChannelChange(PF_MEDIA_AUDIO, bIncoming, FALSE, pIChannel);
  956. break;
  957. default:
  958. return;
  959. }
  960. }
  961. VOID CConfObject::OnVideoChannelStatus(ICommChannel *pIChannel, IH323Endpoint * lpConnection, DWORD dwStatus)
  962. {
  963. BOOL bIncoming = (pIChannel->IsSendChannel())? FALSE:TRUE;
  964. CNmChannelVideo *pChannelVideo;
  965. switch (dwStatus)
  966. {
  967. case CHANNEL_ACTIVE:
  968. if (bIncoming)
  969. {
  970. pChannelVideo = m_pChannelVideoRemote;
  971. }
  972. else
  973. {
  974. pChannelVideo = m_pChannelVideoLocal;
  975. }
  976. if (NULL != pChannelVideo)
  977. {
  978. pChannelVideo->CommChannelActive(pIChannel);
  979. }
  980. break;
  981. case CHANNEL_OPEN:
  982. OnH323ChannelChange(PF_MEDIA_VIDEO, bIncoming, TRUE, pIChannel);
  983. break;
  984. case CHANNEL_CLOSED:
  985. OnH323ChannelChange(PF_MEDIA_VIDEO, bIncoming, FALSE, pIChannel);
  986. break;
  987. case CHANNEL_REJECTED:
  988. case CHANNEL_OPEN_ERROR:
  989. case CHANNEL_NO_CAPABILITY:
  990. if(bIncoming)
  991. {
  992. if (NULL != m_pChannelVideoRemote)
  993. {
  994. m_pChannelVideoRemote->CommChannelError(dwStatus);
  995. }
  996. }
  997. else
  998. {
  999. if (NULL != m_pChannelVideoLocal)
  1000. {
  1001. m_pChannelVideoLocal->CommChannelError(dwStatus);
  1002. }
  1003. }
  1004. break;
  1005. case CHANNEL_REMOTE_PAUSE_ON:
  1006. case CHANNEL_REMOTE_PAUSE_OFF:
  1007. if(bIncoming)
  1008. {
  1009. if (NULL != m_pChannelVideoRemote)
  1010. {
  1011. BOOL fPause = CHANNEL_REMOTE_PAUSE_ON == dwStatus;
  1012. m_pChannelVideoRemote->CommChannelRemotePaused(fPause);
  1013. }
  1014. }
  1015. else
  1016. {
  1017. if (NULL != m_pChannelVideoLocal)
  1018. {
  1019. BOOL fPause = CHANNEL_REMOTE_PAUSE_ON == dwStatus;
  1020. m_pChannelVideoLocal->CommChannelRemotePaused(fPause);
  1021. }
  1022. }
  1023. break;
  1024. default:
  1025. break;
  1026. }
  1027. }
  1028. VOID CConfObject::CreateMember(IH323Endpoint * pConnection, REFGUID rguidNode, UINT uNodeID)
  1029. {
  1030. ASSERT(g_pH323UI);
  1031. WCHAR wszRemoteName[MAX_CALLER_NAME];
  1032. if (FAILED(pConnection->GetRemoteUserName(wszRemoteName, MAX_CALLER_NAME)))
  1033. {
  1034. ERROR_OUT(("GetRemoteUserName() failed!"));
  1035. return;
  1036. }
  1037. // Add the local member
  1038. CNmMember * pMemberLocal = GetLocalMember();
  1039. if (NULL != pMemberLocal)
  1040. {
  1041. AddH323ToDataMember(pMemberLocal, NULL);
  1042. }
  1043. else
  1044. {
  1045. // We aren't already in the list, so add ourselves here:
  1046. BSTR bstrName = NULL;
  1047. COprahNCUI *pOprahNCUI = COprahNCUI::GetInstance();
  1048. if (NULL != pOprahNCUI)
  1049. {
  1050. bstrName = pOprahNCUI->GetUserName();
  1051. }
  1052. pMemberLocal = new CNmMember(bstrName, H323_GCCID_LOCAL,
  1053. PF_H323 | PF_LOCAL_NODE | PF_VER_CURRENT, 0, g_guidLocalNodeId, NULL, 0);
  1054. if (NULL != pMemberLocal)
  1055. {
  1056. AddMember(pMemberLocal, NULL);
  1057. ASSERT(NULL == m_pMemberLocal);
  1058. m_pMemberLocal = pMemberLocal;
  1059. }
  1060. }
  1061. // Add the remote member
  1062. CNmMember * pMemberRemote = MatchH323ToDataMembers(rguidNode, pConnection);
  1063. if (NULL != pMemberRemote)
  1064. {
  1065. AddH323ToDataMember(pMemberRemote, pConnection);
  1066. }
  1067. else
  1068. {
  1069. // BUGBUG: A version number should be added here, if possible
  1070. pMemberRemote = new CNmMember( wszRemoteName,
  1071. uNodeID,
  1072. PF_H323,
  1073. 0,
  1074. rguidNode,
  1075. NULL,
  1076. 0);
  1077. if (NULL != pMemberRemote)
  1078. {
  1079. AddMember(pMemberRemote, pConnection);
  1080. }
  1081. }
  1082. if (NULL != m_hConf && (CS_RUNNING == m_csState))
  1083. {
  1084. // m_hConf->UpdateUserData();
  1085. }
  1086. }
  1087. VOID CConfObject::OnH323Connected(IH323Endpoint * pConnection, DWORD dwFlags, BOOL fAddMember, REFGUID rguidNode)
  1088. {
  1089. HRESULT hr;
  1090. UINT ui;
  1091. ASSERT(NULL != pConnection);
  1092. // alloc and initialize media guids.
  1093. CMediaList MediaList;
  1094. GUID MediaType;
  1095. BOOL fEnableMedia;
  1096. COprahNCUI *pOprahNCUI = COprahNCUI::GetInstance();
  1097. if (NULL != pOprahNCUI)
  1098. {
  1099. MediaType = MEDIA_TYPE_H323VIDEO;
  1100. fEnableMedia = pOprahNCUI->IsSendVideoAllowed() && (dwFlags & CRPCF_VIDEO);
  1101. MediaList.EnableMedia(&MediaType, TRUE /*send */, fEnableMedia);
  1102. fEnableMedia = pOprahNCUI->IsReceiveVideoAllowed() && (dwFlags & CRPCF_VIDEO);
  1103. MediaList.EnableMedia(&MediaType, FALSE /* recv, NOT send */, fEnableMedia);
  1104. MediaType = MEDIA_TYPE_H323AUDIO;
  1105. fEnableMedia = pOprahNCUI->IsAudioAllowed() && (dwFlags & CRPCF_AUDIO);
  1106. MediaList.EnableMedia(&MediaType, TRUE /* send */, fEnableMedia);
  1107. MediaList.EnableMedia(&MediaType, FALSE /* recv, NOT send */, fEnableMedia);
  1108. MediaType = MEDIA_TYPE_H323_T120;
  1109. fEnableMedia = (dwFlags & CRPCF_DATA);
  1110. MediaList.EnableMedia(&MediaType, TRUE /* send */, fEnableMedia);
  1111. MediaList.EnableMedia(&MediaType, FALSE /* recv, NOT send */, fEnableMedia);
  1112. }
  1113. hr = MediaList.ResolveSendFormats(pConnection);
  1114. if(!(SUCCEEDED(hr)))
  1115. {
  1116. // Well, there is no way we can ever open any send channel. But It is a
  1117. // product requirement to keep the connection up just in case the other
  1118. // endpoint(s) ever wants to open a send video channel to this endpoint.
  1119. }
  1120. ICommChannel* pChannelT120 = CreateT120Channel(pConnection, &MediaList);
  1121. CreateAVChannels(pConnection, &MediaList);
  1122. if (pChannelT120)
  1123. {
  1124. OpenT120Channel(pConnection, &MediaList, pChannelT120);
  1125. // no need to hold onto the T120 channel
  1126. pChannelT120->Release();
  1127. }
  1128. OpenAVChannels(pConnection, &MediaList);
  1129. if (fAddMember)
  1130. {
  1131. CreateMember(pConnection, rguidNode, H323_GCCID_REMOTE);
  1132. if (dwFlags & (CRPCF_AUDIO | CRPCF_VIDEO))
  1133. {
  1134. CNmMember* pMemberLocal = GetLocalMember();
  1135. if (pMemberLocal)
  1136. {
  1137. AddMemberToAVChannels(pMemberLocal);
  1138. }
  1139. CNmMember* pMemberRemote = PMemberFromH323Endpoint(pConnection);
  1140. if (pMemberRemote)
  1141. {
  1142. AddMemberToAVChannels(pMemberRemote);
  1143. }
  1144. }
  1145. }
  1146. }
  1147. VOID CConfObject::OnH323Disconnected(IH323Endpoint * pConnection, BOOL fHasAV)
  1148. {
  1149. DebugEntry(CConfObject::OnH323Disconnected);
  1150. POSITION pos = m_MemberList.GetHeadPosition();
  1151. while (NULL != pos)
  1152. {
  1153. POSITION oldpos = pos;
  1154. CNmMember * pMember = (CNmMember *) m_MemberList.GetNext(pos);
  1155. ASSERT(pMember);
  1156. if (pMember->GetH323Endpoint() == pConnection)
  1157. {
  1158. if (fHasAV)
  1159. {
  1160. RemoveMemberFromAVChannels(pMember);
  1161. }
  1162. if (0 == (PF_T120 & pMember->GetDwFlags()))
  1163. {
  1164. // This is an H323 only participant, so remove now:
  1165. RemoveMember(oldpos);
  1166. }
  1167. else
  1168. {
  1169. RemoveH323FromDataMember(pMember, pConnection);
  1170. }
  1171. }
  1172. }
  1173. CNmMember *pLocalMember = GetLocalMember();
  1174. if (pLocalMember)
  1175. {
  1176. if (fHasAV)
  1177. {
  1178. RemoveMemberFromAVChannels(pLocalMember);
  1179. }
  1180. if (0 == m_uH323Endpoints)
  1181. {
  1182. if (0 == (PF_T120 & pLocalMember->GetDwFlags()))
  1183. {
  1184. // This is an H323 only participant, so remove now:
  1185. RemoveMember(pLocalMember);
  1186. }
  1187. else
  1188. {
  1189. RemoveH323FromDataMember(pLocalMember, NULL);
  1190. }
  1191. }
  1192. }
  1193. if (fHasAV)
  1194. {
  1195. DestroyAVChannels();
  1196. }
  1197. #ifdef REPORT_ALL_ERRORS
  1198. DWORD dwSummary;
  1199. dwSummary = pConnection->GetSummaryCode()
  1200. if(CCR_REMOTE_MEDIA_ERROR == dwSummary)
  1201. {
  1202. ::PostConfMsgBox(IDS_REMOTE_MEDIA_ERROR);
  1203. }
  1204. #endif
  1205. if ((NULL != m_hConf) && (CS_RUNNING == m_csState))
  1206. {
  1207. // m_hConf->UpdateUserData();
  1208. }
  1209. DebugExitVOID(CConfObject::OnH323Disconnected);
  1210. }
  1211. VOID CConfObject::OnT120Connected(IH323Endpoint * pConnection, UINT uNodeID)
  1212. {
  1213. CNmMember *pMember = PMemberFromH323Endpoint(pConnection);
  1214. if (pMember)
  1215. {
  1216. // save away the GCC id so that we can match this up when the member is added
  1217. pMember->SetGCCID(uNodeID);
  1218. }
  1219. else
  1220. {
  1221. CreateMember(pConnection, GUID_NULL, uNodeID);
  1222. }
  1223. }
  1224. // StoreAndVerifyMemberUserData
  1225. //
  1226. // Processes a member's user data and stores them for the GetUserData API call.
  1227. // If security data is among the user data, verification against the transport-level
  1228. // credentials is performed.
  1229. // Returns FALSE if security verification fails, TRUE otherwise.
  1230. BOOL StoreAndVerifyMemberUserData(CNmMember * pMember, ROSTER_DATA_HANDLE hData)
  1231. {
  1232. BOOL rc = TRUE;
  1233. BOOL fUserDataSet;
  1234. GCCNodeRecord * pRosterEntry = (GCCNodeRecord *)hData;
  1235. GCCUserData ** ppUserData = pRosterEntry->user_data_list;
  1236. for (int i = 0; i < pRosterEntry->number_of_user_data_members; i++)
  1237. {
  1238. fUserDataSet = FALSE;
  1239. /* Always False if ((int)ppUserData[i]->octet_string->length - sizeof(GUID) < 0)
  1240. {
  1241. WARNING_OUT(("StoreAndVerifyMemberUserData: bad user data"));
  1242. rc = FALSE;
  1243. break;
  1244. }*/
  1245. if (!pMember->FLocal() && 0 == CompareGuid((GUID *)ppUserData[i]->octet_string->value,(GUID *)&g_csguidSecurity))
  1246. {
  1247. PBYTE pb = NULL;
  1248. ULONG cb = 0;
  1249. if (pMember->GetSecurityData(&pb,&cb))
  1250. {
  1251. //
  1252. // Check to make sure that the current user data matches
  1253. // the transport security data.
  1254. //
  1255. if (memcmp(pb,ppUserData[i]->octet_string->value + sizeof(GUID),
  1256. ppUserData[i]->octet_string->length - sizeof(GUID) - 1))
  1257. {
  1258. //
  1259. // This should NOT happen. Either there is a bug
  1260. // in the security code (credentials failed up update
  1261. // in the transport or the like), or someone is trying
  1262. // to deceive us.
  1263. ERROR_OUT(("SECURITYDATA MISMATCH"));
  1264. fUserDataSet = TRUE; // so we don't do it below.
  1265. rc = FALSE;
  1266. }
  1267. }
  1268. else {
  1269. WARNING_OUT(("StoreAndVerifyMemberUserData: failed to get security data"));
  1270. rc = FALSE;
  1271. }
  1272. CoTaskMemFree(pb);
  1273. }
  1274. if ( FALSE == fUserDataSet )
  1275. {
  1276. pMember->SetUserData(*(GUID *)ppUserData[i]->octet_string->value,
  1277. (BYTE *)ppUserData[i]->octet_string->value + sizeof(GUID),
  1278. ppUserData[i]->octet_string->length - sizeof(GUID));
  1279. }
  1280. }
  1281. return rc;
  1282. }
  1283. VOID CConfObject::ResetDataMember( CNmMember * pMember,
  1284. ROSTER_DATA_HANDLE hData)
  1285. {
  1286. DebugEntry(CConfObject::ResetDataMember);
  1287. pMember->AddPf(PF_RESERVED);
  1288. pMember->SetUserInfo(NULL, 0);
  1289. UINT cbData;
  1290. PVOID pData;
  1291. ASSERT(g_pNodeController);
  1292. if (NOERROR == g_pNodeController->GetUserData(
  1293. hData,
  1294. (GUID*) &g_csguidRostInfo,
  1295. &cbData,
  1296. &pData))
  1297. {
  1298. pMember->SetUserInfo(pData, cbData);
  1299. }
  1300. UINT cbCaps;
  1301. PVOID pvCaps;
  1302. if (NOERROR != g_pNodeController->GetUserData(
  1303. hData,
  1304. (GUID*) &g_csguidRosterCaps,
  1305. &cbCaps,
  1306. &pvCaps))
  1307. {
  1308. WARNING_OUT(("roster update is missing caps information"));
  1309. }
  1310. else
  1311. {
  1312. ASSERT(NULL != pvCaps);
  1313. ASSERT(sizeof(ULONG) == cbCaps);
  1314. pMember->SetCaps( *((PULONG)pvCaps) );
  1315. }
  1316. if (StoreAndVerifyMemberUserData(pMember, hData) == FALSE) {
  1317. // Need to disconnect the conference in this case.
  1318. WARNING_OUT(("ResetDataMember Security Warning: Authentication data could not be verified."));
  1319. }
  1320. NotifySink((INmMember *) pMember, OnNotifyMemberUpdated);
  1321. DebugExitVOID(CConfObject::ResetDataMember);
  1322. }
  1323. VOID CConfObject::RemoveOldDataMembers(int nExpected)
  1324. {
  1325. DebugEntry(CConfObject::RemoveOldDataMembers);
  1326. #ifdef _DEBUG
  1327. int nRemoved = 0;
  1328. #endif // _DEBUG
  1329. ASSERT(nExpected >= 0);
  1330. if (nExpected > 0)
  1331. {
  1332. // At least one participant left:
  1333. POSITION pos = m_MemberList.GetHeadPosition();
  1334. while (NULL != pos)
  1335. {
  1336. POSITION oldpos = pos;
  1337. CNmMember * pMember = (CNmMember *) m_MemberList.GetNext(pos);
  1338. ASSERT(pMember);
  1339. DWORD dwFlags = pMember->GetDwFlags();
  1340. if (!(PF_RESERVED & dwFlags))
  1341. {
  1342. // This one is not in the data call:
  1343. TRACE_OUT(("CConfObject Roster: %ls (%d) has left.",
  1344. pMember->GetName(), pMember->GetGCCID()));
  1345. #ifdef _DEBUG
  1346. if (dwFlags & PF_T120)
  1347. {
  1348. nRemoved++;
  1349. }
  1350. #endif // _DEBUG
  1351. if (0 == (dwFlags & PF_H323))
  1352. {
  1353. // If they were data only, then remove:
  1354. RemoveMember(oldpos);
  1355. }
  1356. else
  1357. {
  1358. pMember->RemovePf(PF_DATA_ALL);
  1359. pMember->SetGCCID(pMember->FLocal() ? H323_GCCID_LOCAL : H323_GCCID_REMOTE);
  1360. pMember->SetGccIdParent(INVALID_GCCID);
  1361. pMember->SetCaps(0);
  1362. pMember->SetUserInfo(NULL, 0);
  1363. NotifySink((INmMember *) pMember, OnNotifyMemberUpdated);
  1364. }
  1365. }
  1366. }
  1367. // Validate that we did the right thing:
  1368. ASSERT(nRemoved == nExpected);
  1369. }
  1370. DebugExitVOID(CConfObject::RemoveOldDataMembers);
  1371. }
  1372. CNmMember *CConfObject::MatchDataToH323Member( REFGUID rguidNode,
  1373. UINT uNodeId,
  1374. PVOID pvUserInfo)
  1375. {
  1376. DebugEntry(CConfObject::MatchDataToH323Member);
  1377. CNmMember *pMemberRet = NULL;
  1378. BOOL bRet = FALSE;
  1379. if (GUID_NULL != rguidNode)
  1380. {
  1381. // try matching up guids
  1382. pMemberRet = PMemberFromNodeGuid(rguidNode);
  1383. }
  1384. if (NULL == pMemberRet)
  1385. {
  1386. // try matching up node ids
  1387. pMemberRet = PMemberFromGCCID(uNodeId);
  1388. }
  1389. if ((NULL == pMemberRet) && pvUserInfo)
  1390. {
  1391. // All else failed try mathcing IP addresses
  1392. CRosterInfo ri;
  1393. if(SUCCEEDED(ri.Load(pvUserInfo)))
  1394. {
  1395. POSITION pos = m_MemberList.GetHeadPosition();
  1396. while (NULL != pos)
  1397. {
  1398. SOCKADDR_IN sin;
  1399. CNmMember * pMember = (CNmMember *) m_MemberList.GetNext(pos);
  1400. IH323Endpoint * pConnection = pMember->GetH323Endpoint();
  1401. if (pConnection && (S_OK == pConnection->GetRemoteUserAddr(&sin)))
  1402. {
  1403. TCHAR szAudioIP[MAX_PATH];
  1404. TCHAR szDataIP[MAX_PATH];
  1405. HROSTINFO hRI = NULL;
  1406. // BUGBUG: UNICODE issues?
  1407. lstrcpyn(szAudioIP, inet_ntoa(sin.sin_addr), CCHMAX(szAudioIP));
  1408. while (SUCCEEDED(ri.ExtractItem(&hRI,
  1409. g_cwszIPTag,
  1410. szDataIP,
  1411. CCHMAX(szDataIP))))
  1412. {
  1413. TRACE_OUT(("Comparing data IP \"%s\" with "
  1414. "audio IP \"%s\"", szDataIP, szAudioIP));
  1415. if (0 == lstrcmp(szDataIP, szAudioIP))
  1416. {
  1417. pMemberRet = pMember;
  1418. break; // out of outer while loop
  1419. }
  1420. }
  1421. }
  1422. }
  1423. }
  1424. }
  1425. DebugExitPVOID(CConfObject::MatchDataToH323Member, pMemberRet);
  1426. return pMemberRet;
  1427. }
  1428. VOID CConfObject::AddDataToH323Member( CNmMember * pMember,
  1429. PVOID pvUserInfo,
  1430. UINT cbUserInfo,
  1431. UINT uCaps,
  1432. NC_ROSTER_NODE_ENTRY* pRosterNode)
  1433. {
  1434. DebugEntry(CConfObject::AddDataToH323Member);
  1435. ASSERT(pMember);
  1436. ASSERT(NULL != pRosterNode);
  1437. DWORD dwFlags = pMember->GetDwFlags();
  1438. ASSERT(0 == ((PF_MEDIA_DATA | PF_T120) & dwFlags));
  1439. dwFlags |= (PF_T120 | PF_MEDIA_DATA | PF_CA_DETACHED);
  1440. // Add version information
  1441. dwFlags = (dwFlags & ~PF_VER_MASK) |
  1442. PF_VER_FromUserData(pRosterNode->hUserData);
  1443. pMember->SetDwFlags(dwFlags);
  1444. pMember->SetGCCID(pRosterNode->uNodeID);
  1445. pMember->SetGccIdParent(pRosterNode->uSuperiorNodeID);
  1446. ASSERT(0 == pMember->GetCaps());
  1447. pMember->SetCaps(uCaps);
  1448. pMember->SetUserInfo(pvUserInfo, cbUserInfo);
  1449. NotifySink((INmMember *) pMember, OnNotifyMemberUpdated);
  1450. ROSTER_DATA_HANDLE hData = pRosterNode->hUserData;
  1451. if (StoreAndVerifyMemberUserData(pMember, hData) == FALSE) {
  1452. // Need to disconnect the conference in this case.
  1453. WARNING_OUT(("AddDataToH323Member Security Warning: Authentication data could not be verified."));
  1454. }
  1455. DebugExitVOID(CConfObject::AddDataToH323Member);
  1456. }
  1457. CNmMember * CConfObject::CreateDataMember(BOOL fLocal,
  1458. REFGUID rguidNode,
  1459. PVOID pvUserInfo,
  1460. UINT cbUserInfo,
  1461. UINT uCaps,
  1462. NC_ROSTER_NODE_ENTRY* pRosterNode)
  1463. {
  1464. DebugEntry(CConfObject::CreateDataMember);
  1465. ASSERT(NULL != pRosterNode);
  1466. DWORD dwFlags = PF_T120 | PF_MEDIA_DATA | PF_CA_DETACHED;
  1467. if (fLocal)
  1468. {
  1469. dwFlags |= (PF_LOCAL_NODE | PF_VER_CURRENT);
  1470. }
  1471. if (pRosterNode->fMCU)
  1472. {
  1473. dwFlags |= PF_T120_MCU;
  1474. }
  1475. if (0 != cbUserInfo)
  1476. {
  1477. dwFlags = (dwFlags & ~PF_VER_MASK)
  1478. | PF_VER_FromUserData(pRosterNode->hUserData);
  1479. }
  1480. CNmMember * pMember = new CNmMember(pRosterNode->pwszNodeName,
  1481. pRosterNode->uNodeID,
  1482. dwFlags,
  1483. uCaps,
  1484. rguidNode,
  1485. pvUserInfo,
  1486. cbUserInfo);
  1487. if (NULL != pMember)
  1488. {
  1489. pMember->SetGccIdParent(pRosterNode->uSuperiorNodeID);
  1490. if (fLocal)
  1491. {
  1492. ASSERT(NULL == m_pMemberLocal);
  1493. m_pMemberLocal = pMember;
  1494. }
  1495. }
  1496. ROSTER_DATA_HANDLE hData = pRosterNode->hUserData;
  1497. if (StoreAndVerifyMemberUserData(pMember, hData) == FALSE) {
  1498. // Need to disconnect the conference in this case.
  1499. WARNING_OUT(("CreateDataMember Security Warning: Authentication data could not be verified."));
  1500. }
  1501. TRACE_OUT(("CConfObject Roster: %ls (%d) has joined.", pRosterNode->pwszNodeName, pRosterNode->uNodeID));
  1502. DebugExitPVOID(CConfObject::CreateDataMember, pMember);
  1503. return pMember;
  1504. }
  1505. CNmMember * CConfObject::MatchH323ToDataMembers(REFGUID rguidNodeId,
  1506. IH323Endpoint * pConnection)
  1507. {
  1508. DebugEntry(CConfObject::MatchH323ToDataMembers);
  1509. CNmMember * pMemberRet = NULL;
  1510. // This is currently called only by OnH323Connected(). Terminal label isn't assigned yet.
  1511. // so there is no need yet to INSERT SEARCH FOR MATCHING TERMINAL LABEL HERE
  1512. if (GUID_NULL != rguidNodeId)
  1513. {
  1514. pMemberRet = PMemberFromNodeGuid(rguidNodeId);
  1515. }
  1516. else
  1517. {
  1518. SOCKADDR_IN sin;
  1519. if (S_OK == pConnection->GetRemoteUserAddr(&sin))
  1520. {
  1521. TCHAR szAudioIP[MAX_PATH];
  1522. lstrcpyn(szAudioIP, inet_ntoa(sin.sin_addr), CCHMAX(szAudioIP));
  1523. POSITION pos = m_MemberList.GetHeadPosition();
  1524. while (NULL != pos)
  1525. {
  1526. CNmMember * pMember = (CNmMember *) m_MemberList.GetNext(pos);
  1527. // need to try to match IP addresses
  1528. // this is how things were done in NM2.11 and earlier
  1529. TCHAR szDataIP[MAX_PATH];
  1530. HROSTINFO hRI = NULL;
  1531. CRosterInfo ri;
  1532. if (SUCCEEDED(ri.Load(pMember->GetUserInfo())) )
  1533. {
  1534. while (SUCCEEDED(ri.ExtractItem(&hRI,
  1535. g_cwszIPTag,
  1536. szDataIP,
  1537. CCHMAX(szDataIP))))
  1538. {
  1539. TRACE_OUT(("Comparing data IP \"%s\" with "
  1540. "h323 IP \"%s\"", szDataIP, szAudioIP));
  1541. if (0 == lstrcmp(szDataIP, szAudioIP))
  1542. {
  1543. // close enough
  1544. return pMember;
  1545. }
  1546. }
  1547. }
  1548. }
  1549. }
  1550. }
  1551. DebugExitPVOID(CConfObject::MatchH323ToDataMembers, pMemberRet);
  1552. return pMemberRet;
  1553. }
  1554. VOID CConfObject::AddMemberToAVChannels(CNmMember *pMember)
  1555. {
  1556. CNmChannelAudio *pChannelAudio;
  1557. CNmChannelVideo *pChannelVideo;
  1558. if (pMember->FLocal())
  1559. {
  1560. pChannelAudio = m_pChannelAudioLocal;
  1561. pChannelVideo = m_pChannelVideoLocal;
  1562. }
  1563. else
  1564. {
  1565. pChannelAudio = m_pChannelAudioRemote;
  1566. pChannelVideo = m_pChannelVideoRemote;
  1567. }
  1568. if (pChannelAudio)
  1569. {
  1570. pChannelAudio->OnMemberAdded(pMember);
  1571. // set media flags if channel is open
  1572. if(S_OK == pChannelAudio->IsActive())
  1573. {
  1574. pMember->AddPf(PF_MEDIA_AUDIO);
  1575. pChannelAudio->OnMemberUpdated(pMember);
  1576. OnMemberUpdated(pMember);
  1577. }
  1578. }
  1579. if (pChannelVideo)
  1580. {
  1581. pChannelVideo->OnMemberAdded(pMember);
  1582. // set media flags if channel is open
  1583. if(S_OK == pChannelVideo->IsActive())
  1584. {
  1585. pMember->AddPf(PF_MEDIA_VIDEO);
  1586. pChannelVideo->OnMemberUpdated(pMember);
  1587. OnMemberUpdated(pMember);
  1588. }
  1589. }
  1590. }
  1591. VOID CConfObject::RemoveMemberFromAVChannels(CNmMember *pMember)
  1592. {
  1593. CNmChannelAudio *pChannelAudio;
  1594. CNmChannelVideo *pChannelVideo;
  1595. if (pMember->FLocal())
  1596. {
  1597. pChannelAudio = m_pChannelAudioLocal;
  1598. pChannelVideo = m_pChannelVideoLocal;
  1599. }
  1600. else
  1601. {
  1602. pChannelAudio = m_pChannelAudioRemote;
  1603. pChannelVideo = m_pChannelVideoRemote;
  1604. }
  1605. if ((NULL != pChannelVideo) && (PF_MEDIA_VIDEO & pMember->GetDwFlags()))
  1606. {
  1607. pMember->RemovePf(PF_MEDIA_VIDEO);
  1608. pChannelVideo->OnMemberRemoved(pMember);
  1609. OnMemberUpdated(pMember);
  1610. }
  1611. if ((NULL != pChannelAudio) && (PF_MEDIA_AUDIO & pMember->GetDwFlags()))
  1612. {
  1613. pMember->RemovePf(PF_MEDIA_AUDIO);
  1614. pChannelAudio->OnMemberRemoved(pMember);
  1615. OnMemberUpdated(pMember);
  1616. }
  1617. }
  1618. /* C R E A T E A V C H A N N E L S */
  1619. /*-------------------------------------------------------------------------
  1620. %%Function: CreateAVChannels
  1621. Create AV channels.
  1622. -------------------------------------------------------------------------*/
  1623. VOID CConfObject::CreateAVChannels(IH323Endpoint * pConnection, CMediaList* pMediaList)
  1624. {
  1625. HRESULT hr;
  1626. GUID MediaGuid;
  1627. ICommChannel *pCommChannel = NULL;
  1628. MediaGuid = MEDIA_TYPE_H323AUDIO;
  1629. if (pMediaList->IsInSendList(&MediaGuid))
  1630. {
  1631. m_pChannelAudioLocal = new CNmChannelAudio(FALSE /* fIncoming */);
  1632. if (NULL != m_pChannelAudioLocal)
  1633. {
  1634. hr = pConnection->CreateCommChannel(&MediaGuid, &pCommChannel, TRUE /* fSend*/);
  1635. ASSERT(SUCCEEDED(hr) && (NULL != pCommChannel));
  1636. //if(SUCCEEDED(hr) && (NULL != pCommChannel))
  1637. {
  1638. NotifySink((INmChannel *) m_pChannelAudioLocal, OnNotifyChannelAdded);
  1639. m_pChannelAudioLocal->OnConnected(pConnection, pCommChannel);
  1640. hr = pCommChannel->EnableOpen(TRUE);
  1641. ASSERT(SUCCEEDED(hr));
  1642. }
  1643. pCommChannel->Release();
  1644. pCommChannel = NULL; // bug detection that can be removed later
  1645. }
  1646. }
  1647. if (pMediaList->IsInRecvList(&MediaGuid))
  1648. {
  1649. m_pChannelAudioRemote = new CNmChannelAudio(TRUE /* fIncoming */);
  1650. if (NULL != m_pChannelAudioRemote)
  1651. {
  1652. hr = pConnection->CreateCommChannel(&MediaGuid, &pCommChannel, FALSE /* fSend*/);
  1653. ASSERT(SUCCEEDED(hr) && (NULL != pCommChannel));
  1654. //if(SUCCEEDED(hr) && (NULL != pCommChannel))
  1655. {
  1656. NotifySink((INmChannel *) m_pChannelAudioRemote, OnNotifyChannelAdded);
  1657. m_pChannelAudioRemote->OnConnected(pConnection, pCommChannel);
  1658. hr = pCommChannel->EnableOpen(TRUE);
  1659. ASSERT(SUCCEEDED(hr));
  1660. }
  1661. pCommChannel->Release();
  1662. pCommChannel = NULL; // bug detection that can be removed later
  1663. }
  1664. }
  1665. MediaGuid = MEDIA_TYPE_H323VIDEO; // now doing video channels
  1666. if (pMediaList->IsInSendList(&MediaGuid))
  1667. {
  1668. m_pChannelVideoLocal = CNmChannelVideo::CreateChannel(FALSE /* fIncoming */);
  1669. if (NULL != m_pChannelVideoLocal)
  1670. {
  1671. BOOL fCreated = FALSE;
  1672. // check for previous existence of preview stream/preview channel
  1673. if(NULL == (pCommChannel= m_pChannelVideoLocal->GetPreviewCommChannel()))
  1674. {
  1675. hr = pConnection->CreateCommChannel(&MediaGuid, &pCommChannel, TRUE /* fSend*/);
  1676. ASSERT(SUCCEEDED(hr) && (NULL != pCommChannel));
  1677. fCreated = TRUE;
  1678. }
  1679. else
  1680. {
  1681. pCommChannel->SetAdviseInterface(m_pIH323ConfAdvise);
  1682. }
  1683. //if(SUCCEEDED(hr) && (NULL != pCommChannel))
  1684. {
  1685. NotifySink((INmChannel *) m_pChannelVideoLocal, OnNotifyChannelAdded);
  1686. m_pChannelVideoLocal->OnConnected(pConnection, pCommChannel);
  1687. hr = pCommChannel->EnableOpen(TRUE);
  1688. ASSERT(SUCCEEDED(hr));
  1689. }
  1690. if (fCreated)
  1691. pCommChannel->Release();
  1692. pCommChannel = NULL; // bug detection that can be removed later
  1693. }
  1694. }
  1695. if (pMediaList->IsInRecvList(&MediaGuid))
  1696. {
  1697. m_pChannelVideoRemote = CNmChannelVideo::CreateChannel(TRUE /* fIncoming */);
  1698. if (NULL != m_pChannelVideoRemote)
  1699. {
  1700. BOOL fCreated = FALSE;
  1701. // check for previous existence of preview stream/preview channel
  1702. if(NULL == (pCommChannel= m_pChannelVideoRemote->GetCommChannel()))
  1703. {
  1704. hr = pConnection->CreateCommChannel(&MediaGuid, &pCommChannel, FALSE /* fSend*/);
  1705. fCreated = TRUE;
  1706. }
  1707. else
  1708. {
  1709. pCommChannel->SetAdviseInterface(m_pIH323ConfAdvise);
  1710. }
  1711. ASSERT(SUCCEEDED(hr) && (NULL != pCommChannel));
  1712. //if(SUCCEEDED(hr) && (NULL != pCommChannel))
  1713. {
  1714. NotifySink((INmChannel *) m_pChannelVideoRemote, OnNotifyChannelAdded);
  1715. m_pChannelVideoRemote->OnConnected(pConnection, pCommChannel);
  1716. hr = pCommChannel->EnableOpen(TRUE);
  1717. ASSERT(SUCCEEDED(hr));
  1718. }
  1719. if (fCreated)
  1720. pCommChannel->Release();
  1721. }
  1722. }
  1723. }
  1724. /* O P E N A V C H A N N E L S */
  1725. /*-------------------------------------------------------------------------
  1726. %%Function: OpenAVChannels
  1727. Open AV channels.
  1728. -------------------------------------------------------------------------*/
  1729. VOID CConfObject::OpenAVChannels(IH323Endpoint * pConnection, CMediaList* pMediaList)
  1730. {
  1731. MEDIA_FORMAT_ID idLocal;
  1732. if(m_pChannelAudioLocal)
  1733. {
  1734. if (pMediaList->GetSendFormatLocalID(MEDIA_TYPE_H323AUDIO, &idLocal))
  1735. {
  1736. m_pChannelAudioLocal->SetFormat(idLocal);
  1737. // open only if a valid negotiated format exists.
  1738. // it won't hurt to always call the Open() method, but there is
  1739. // no need to. This will and should probably change. Calling
  1740. // this with INVALID_MEDIA_FORMAT results in a call to the event
  1741. // handler for the channel, notifying the upper layer(s) that the
  1742. // channel could not be opened due to no compatible caps. User
  1743. // feedback could be much improved if it took advantage of this.
  1744. if(idLocal != INVALID_MEDIA_FORMAT)
  1745. {
  1746. m_pChannelAudioLocal->Open();
  1747. }
  1748. }
  1749. }
  1750. if(m_pChannelVideoLocal)
  1751. {
  1752. if (pMediaList->GetSendFormatLocalID(MEDIA_TYPE_H323VIDEO, &idLocal))
  1753. {
  1754. m_pChannelVideoLocal->SetFormat(idLocal);
  1755. if(m_pChannelVideoLocal->IsPreviewEnabled())
  1756. {
  1757. // open only if a valid negotiated format exists. see comments
  1758. // in the MEDIA_TYPE_H323AUDIO case above
  1759. if(idLocal != INVALID_MEDIA_FORMAT)
  1760. {
  1761. m_pChannelVideoLocal->Open();
  1762. }
  1763. }
  1764. }
  1765. }
  1766. }
  1767. ICommChannel* CConfObject::CreateT120Channel(IH323Endpoint * pConnection, CMediaList* pMediaList)
  1768. {
  1769. ICommChannel *pChannelT120 = NULL;
  1770. // create a T.120 channel stub
  1771. GUID MediaGuid = MEDIA_TYPE_H323_T120;
  1772. if (pMediaList->IsInSendList(&MediaGuid))
  1773. {
  1774. HRESULT hr = pConnection->CreateCommChannel(&MediaGuid, &pChannelT120, TRUE /* fSend*/);
  1775. if(SUCCEEDED(hr))
  1776. {
  1777. ASSERT(NULL != pChannelT120);
  1778. hr = pChannelT120->EnableOpen(TRUE);
  1779. ASSERT(SUCCEEDED(hr));
  1780. }
  1781. }
  1782. return pChannelT120;
  1783. }
  1784. VOID CConfObject::OpenT120Channel(IH323Endpoint * pConnection, CMediaList* pMediaList, ICommChannel* pChannelT120)
  1785. {
  1786. if(pChannelT120)
  1787. {
  1788. MEDIA_FORMAT_ID idLocal;
  1789. if (pMediaList->GetSendFormatLocalID(MEDIA_TYPE_H323_T120, &idLocal))
  1790. {
  1791. // T.120 channels are different. Always call the Open() method
  1792. // If there are no common T.120 capabilities. This lets the
  1793. // channel event handler know of the absence of remote T.120
  1794. // caps.
  1795. // The T.120 call side of things is tied into the T.120 channel
  1796. // event handler.
  1797. pChannelT120->Open(idLocal, pConnection);
  1798. }
  1799. }
  1800. }
  1801. /* D E S T R O Y A V C H A N N E L S */
  1802. /*-------------------------------------------------------------------------
  1803. %%Function: DestroyAVChannels
  1804. Destroy AV channels.
  1805. -------------------------------------------------------------------------*/
  1806. VOID CConfObject::DestroyAVChannels()
  1807. {
  1808. if (NULL != m_pChannelAudioLocal)
  1809. {
  1810. NotifySink((INmChannel *) m_pChannelAudioLocal, OnNotifyChannelRemoved);
  1811. m_pChannelAudioLocal->Release();
  1812. m_pChannelAudioLocal = NULL;
  1813. }
  1814. if (NULL != m_pChannelAudioRemote)
  1815. {
  1816. NotifySink((INmChannel *) m_pChannelAudioRemote, OnNotifyChannelRemoved);
  1817. m_pChannelAudioRemote->Release();
  1818. m_pChannelAudioRemote = NULL;
  1819. }
  1820. if (NULL != m_pChannelVideoLocal)
  1821. {
  1822. m_pChannelVideoLocal->OnDisconnected();
  1823. NotifySink((INmChannel *) m_pChannelVideoLocal, OnNotifyChannelRemoved);
  1824. m_pChannelVideoLocal->Release();
  1825. m_pChannelVideoLocal = NULL;
  1826. }
  1827. if (NULL != m_pChannelVideoRemote)
  1828. {
  1829. m_pChannelVideoRemote->OnDisconnected();
  1830. NotifySink((INmChannel *) m_pChannelVideoRemote, OnNotifyChannelRemoved);
  1831. m_pChannelVideoRemote->Release();
  1832. m_pChannelVideoRemote = NULL;
  1833. }
  1834. }
  1835. HRESULT CConfObject::GetMediaChannel (GUID *pmediaID,BOOL bSendDirection, IMediaChannel **ppI)
  1836. {
  1837. *ppI = NULL;
  1838. if (*pmediaID == MEDIA_TYPE_H323AUDIO)
  1839. {
  1840. CNmChannelAudio *pAudChan = (bSendDirection ? m_pChannelAudioLocal : m_pChannelAudioRemote);
  1841. *ppI = (pAudChan ? pAudChan->GetMediaChannelInterface() : NULL);
  1842. }
  1843. else if (*pmediaID == MEDIA_TYPE_H323VIDEO)
  1844. {
  1845. CNmChannelVideo *pVidChan = (bSendDirection ? m_pChannelVideoLocal : m_pChannelVideoRemote);
  1846. *ppI = (pVidChan ? pVidChan->GetMediaChannelInterface() : NULL);
  1847. }
  1848. return (*ppI == NULL ? E_NOINTERFACE : S_OK);
  1849. }
  1850. VOID CConfObject::AddH323ToDataMember(CNmMember * pMember, IH323Endpoint * pConnection)
  1851. {
  1852. DebugEntry(CConfObject::AddH323ToDataMember);
  1853. // Add the H323 flag bit to the member:
  1854. pMember->AddPf(PF_H323);
  1855. if (pConnection)
  1856. {
  1857. ASSERT(NULL == pMember->GetH323Endpoint());
  1858. pMember->AddH323Endpoint(pConnection);
  1859. ++m_uH323Endpoints;
  1860. }
  1861. DebugExitVOID(CConfObject::AddH323ToDataMember);
  1862. }
  1863. VOID CConfObject::RemoveH323FromDataMember(CNmMember * pMember, IH323Endpoint * pConnection)
  1864. {
  1865. DebugEntry(CConfObject::RemoveH323FromDataMember);
  1866. // Remove the H323 flag from the member:
  1867. pMember->RemovePf(PF_H323);
  1868. if (pConnection)
  1869. {
  1870. pMember->DeleteH323Endpoint(pConnection);
  1871. --m_uH323Endpoints;
  1872. }
  1873. DebugExitVOID(CConfObject::RemoveH323FromDataMember);
  1874. }
  1875. VOID CConfObject::OnMemberUpdated(INmMember *pMember)
  1876. {
  1877. NotifySink(pMember, OnNotifyMemberUpdated);
  1878. }
  1879. VOID CConfObject::OnChannelUpdated(INmChannel *pChannel)
  1880. {
  1881. NotifySink(pChannel, OnNotifyChannelUpdated);
  1882. }
  1883. VOID CConfObject::SetT120State(CONFSTATE state)
  1884. {
  1885. NM_CONFERENCE_STATE oldNmState;
  1886. GetState(&oldNmState);
  1887. m_csState = state;
  1888. if ( state == CS_TERMINATED )
  1889. m_fSecure = FALSE; // Reset secure flag
  1890. CheckState(oldNmState);
  1891. }
  1892. VOID CConfObject::CheckState(NM_CONFERENCE_STATE oldNmState)
  1893. {
  1894. NM_CONFERENCE_STATE newNmState;
  1895. GetState(&newNmState);
  1896. if (oldNmState != newNmState)
  1897. {
  1898. NotifySink((PVOID) newNmState, OnNotifyStateChanged);
  1899. if (NM_CONFERENCE_IDLE == newNmState)
  1900. {
  1901. _EraseDataChannelGUIDS();
  1902. m_fConferenceCreated = FALSE;
  1903. }
  1904. }
  1905. }
  1906. void CConfObject::RemoveDataChannelGUID(REFGUID rguid)
  1907. {
  1908. POSITION pCur = m_DataChannelGUIDS.GetHeadPosition();
  1909. POSITION pNext = pCur;
  1910. while(pCur)
  1911. {
  1912. GUID* pG = reinterpret_cast<GUID*>(m_DataChannelGUIDS.GetNext(pNext));
  1913. if(*pG == rguid)
  1914. {
  1915. m_DataChannelGUIDS.RemoveAt(pCur);
  1916. }
  1917. pCur = pNext;
  1918. }
  1919. }
  1920. void CConfObject::_EraseDataChannelGUIDS(void)
  1921. {
  1922. POSITION pCur = m_DataChannelGUIDS.GetHeadPosition();
  1923. while(pCur)
  1924. {
  1925. GUID* pG = reinterpret_cast<GUID*>(m_DataChannelGUIDS.GetNext(pCur));
  1926. delete pG;
  1927. }
  1928. m_DataChannelGUIDS.EmptyList();
  1929. }
  1930. ULONG CConfObject::AddRef(void)
  1931. {
  1932. return ++m_cRef;
  1933. }
  1934. ULONG CConfObject::Release(void)
  1935. {
  1936. ASSERT(m_cRef > 0);
  1937. if (m_cRef > 0)
  1938. {
  1939. m_cRef--;
  1940. }
  1941. ULONG cRef = m_cRef;
  1942. if (0 == cRef)
  1943. {
  1944. delete this;
  1945. }
  1946. return cRef;
  1947. }
  1948. HRESULT STDMETHODCALLTYPE CConfObject::QueryInterface(REFIID riid, PVOID *ppv)
  1949. {
  1950. HRESULT hr = S_OK;
  1951. if((riid == IID_INmConference2) || (riid == IID_INmConference) || (riid == IID_IUnknown))
  1952. {
  1953. *ppv = (INmConference2 *)this;
  1954. ApiDebugMsg(("CConfObject::QueryInterface()"));
  1955. }
  1956. else if (riid == IID_IConnectionPointContainer)
  1957. {
  1958. *ppv = (IConnectionPointContainer *) this;
  1959. ApiDebugMsg(("CConfObject::QueryInterface(): Returning IConnectionPointContainer."));
  1960. }
  1961. else
  1962. {
  1963. hr = E_NOINTERFACE;
  1964. *ppv = NULL;
  1965. ApiDebugMsg(("CConfObject::QueryInterface(): Called on unknown interface."));
  1966. }
  1967. if (S_OK == hr)
  1968. {
  1969. AddRef();
  1970. }
  1971. return hr;
  1972. }
  1973. HRESULT CConfObject::GetName(BSTR *pbstrName)
  1974. {
  1975. HRESULT hr = E_POINTER;
  1976. if (NULL != pbstrName)
  1977. {
  1978. *pbstrName = SysAllocString(m_bstrConfName);
  1979. hr = *pbstrName ? S_OK : E_FAIL;
  1980. }
  1981. return hr;
  1982. }
  1983. HRESULT CConfObject::GetID(ULONG *puID)
  1984. {
  1985. HRESULT hr = E_POINTER;
  1986. if (NULL != puID)
  1987. {
  1988. *puID = m_uGCCConferenceID;
  1989. hr = S_OK;
  1990. }
  1991. return hr;
  1992. }
  1993. HRESULT CConfObject::GetState(NM_CONFERENCE_STATE *pState)
  1994. {
  1995. HRESULT hr = E_POINTER;
  1996. if (NULL != pState)
  1997. {
  1998. hr = S_OK;
  1999. switch (m_csState)
  2000. {
  2001. // Note: All states are valid (at least, for now)
  2002. case CS_CREATING:
  2003. case CS_UNINITIALIZED:
  2004. case CS_TERMINATED:
  2005. if (0 == m_uH323Endpoints)
  2006. {
  2007. *pState = NM_CONFERENCE_IDLE;
  2008. break;
  2009. }
  2010. //////////////////////////////////////////////////////////////////////////
  2011. //////////////////////////////////////////////////////////////////////////
  2012. //////////////////////////////////////////////////////////////////////////
  2013. //////////////////////////////////////////////////////////////////////////
  2014. //////////////////////////////////////////////////////////////////////////
  2015. //////////////////////////////////////////////////////////////////////////
  2016. //////////////////////////////////////////////////////////////////////////
  2017. //////////////////////////////////////////////////////////////////////////
  2018. // else fall through !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  2019. //////////////////////////////////////////////////////////////////////////
  2020. case CS_COMING_UP:
  2021. case CS_GOING_DOWN:
  2022. case CS_RUNNING:
  2023. if (m_uMembers < 2)
  2024. {
  2025. if (m_fServerMode)
  2026. {
  2027. *pState = NM_CONFERENCE_WAITING;
  2028. }
  2029. else
  2030. {
  2031. *pState = NM_CONFERENCE_INITIALIZING;
  2032. }
  2033. }
  2034. else
  2035. {
  2036. *pState = NM_CONFERENCE_ACTIVE;
  2037. }
  2038. break;
  2039. default:
  2040. hr = E_FAIL;
  2041. break;
  2042. }
  2043. }
  2044. return hr;
  2045. }
  2046. HRESULT CConfObject::GetNmchCaps(ULONG *puchCaps)
  2047. {
  2048. HRESULT hr = E_POINTER;
  2049. // BUGBUG: this returns secure cap only, used to be NOTIMPL
  2050. if (NULL != puchCaps)
  2051. {
  2052. *puchCaps = m_fSecure ? NMCH_SECURE : 0;
  2053. hr = S_OK;
  2054. }
  2055. return hr;
  2056. }
  2057. HRESULT CConfObject::GetTopProvider(INmMember **ppMember)
  2058. {
  2059. CNmMember *pMemberRet = NULL;
  2060. HRESULT hr = E_POINTER;
  2061. if (NULL != ppMember)
  2062. {
  2063. POSITION pos = m_MemberList.GetHeadPosition();
  2064. while (NULL != pos)
  2065. {
  2066. CNmMember *pMember = (CNmMember *) m_MemberList.GetNext(pos);
  2067. ASSERT(pMember);
  2068. if (pMember->FTopProvider())
  2069. {
  2070. // We have found the top provider
  2071. pMemberRet = pMember;
  2072. break;
  2073. }
  2074. }
  2075. *ppMember = pMemberRet;
  2076. hr = (NULL != pMemberRet) ? S_OK : S_FALSE;
  2077. }
  2078. return hr;
  2079. }
  2080. HRESULT CConfObject::EnumMember(IEnumNmMember **ppEnum)
  2081. {
  2082. HRESULT hr = E_POINTER;
  2083. if (NULL != ppEnum)
  2084. {
  2085. *ppEnum = new CEnumNmMember(&m_MemberList, m_uMembers);
  2086. hr = (NULL != *ppEnum) ? S_OK : E_OUTOFMEMORY;
  2087. }
  2088. return hr;
  2089. }
  2090. HRESULT CConfObject::GetMemberCount(ULONG *puCount)
  2091. {
  2092. HRESULT hr = E_POINTER;
  2093. if (NULL != puCount)
  2094. {
  2095. *puCount = m_uMembers;
  2096. hr = S_OK;
  2097. }
  2098. return hr;
  2099. }
  2100. HRESULT CConfObject::EnumChannel(IEnumNmChannel **ppEnum)
  2101. {
  2102. HRESULT hr = E_POINTER;
  2103. if (NULL != ppEnum)
  2104. {
  2105. COBLIST ChannelList;
  2106. ULONG cChannels = 0;
  2107. if (NULL != m_pChannelAudioLocal)
  2108. {
  2109. ChannelList.AddTail(m_pChannelAudioLocal);
  2110. ++cChannels;
  2111. }
  2112. if (NULL != m_pChannelAudioRemote)
  2113. {
  2114. ChannelList.AddTail(m_pChannelAudioRemote);
  2115. ++cChannels;
  2116. }
  2117. if (NULL != m_pChannelVideoLocal)
  2118. {
  2119. ChannelList.AddTail(m_pChannelVideoLocal);
  2120. ++cChannels;
  2121. }
  2122. if (NULL != m_pChannelVideoRemote)
  2123. {
  2124. ChannelList.AddTail(m_pChannelVideoRemote);
  2125. ++cChannels;
  2126. }
  2127. *ppEnum = new CEnumNmChannel(&ChannelList, cChannels);
  2128. hr = (NULL != ppEnum) ? S_OK : E_OUTOFMEMORY;
  2129. ChannelList.EmptyList();
  2130. }
  2131. return hr;
  2132. }
  2133. HRESULT CConfObject::GetChannelCount(ULONG *puCount)
  2134. {
  2135. HRESULT hr = E_POINTER;
  2136. if (NULL != puCount)
  2137. {
  2138. ULONG cChannels = 0;
  2139. if (NULL != m_pChannelAudioLocal)
  2140. {
  2141. ++cChannels;
  2142. }
  2143. if (NULL != m_pChannelAudioRemote)
  2144. {
  2145. ++cChannels;
  2146. }
  2147. if (NULL != m_pChannelVideoLocal)
  2148. {
  2149. ++cChannels;
  2150. }
  2151. if (NULL != m_pChannelVideoRemote)
  2152. {
  2153. ++cChannels;
  2154. }
  2155. *puCount = cChannels;
  2156. hr = S_OK;
  2157. }
  2158. return hr;
  2159. }
  2160. /* P M E M B E R L O C A L */
  2161. /*-------------------------------------------------------------------------
  2162. %%Function: PMemberLocal
  2163. -------------------------------------------------------------------------*/
  2164. CNmMember * PMemberLocal(COBLIST *pList)
  2165. {
  2166. if (NULL != pList)
  2167. {
  2168. POSITION posCurr;
  2169. POSITION pos = pList->GetHeadPosition();
  2170. while (NULL != pos)
  2171. {
  2172. posCurr = pos;
  2173. CNmMember * pMember = (CNmMember *) pList->GetNext(pos);
  2174. ASSERT(NULL != pMember);
  2175. if (pMember->FLocal())
  2176. return pMember;
  2177. }
  2178. }
  2179. return NULL;
  2180. }
  2181. HRESULT STDMETHODCALLTYPE CConfObject::CreateDataChannelEx(INmChannelData **ppChannel, REFGUID rguid, BYTE * pER)
  2182. {
  2183. if (NULL != ppChannel)
  2184. {
  2185. if (IsBadWritePtr(ppChannel, sizeof(LPVOID)))
  2186. return E_POINTER;
  2187. *ppChannel = NULL;
  2188. }
  2189. if (GUID_NULL == rguid)
  2190. {
  2191. WARNING_OUT(("CreateDataChannel: Null guid"));
  2192. return E_INVALIDARG;
  2193. }
  2194. { // Make sure we're in a data conference
  2195. CNmMember * pMember = PMemberLocal(&m_MemberList);
  2196. if (NULL == pMember)
  2197. return E_FAIL;
  2198. // Data must be available
  2199. if (!FValidGccId(pMember->GetGCCID()))
  2200. return NM_E_NO_T120_CONFERENCE;
  2201. }
  2202. // Make sure the data channel has not already been created
  2203. GUID g = rguid;
  2204. POSITION pCur = m_DataChannelGUIDS.GetHeadPosition();
  2205. while(pCur)
  2206. {
  2207. GUID* pG = reinterpret_cast<GUID*>(m_DataChannelGUIDS.GetNext(pCur));
  2208. if(*pG == rguid)
  2209. {
  2210. return NM_E_CHANNEL_ALREADY_EXISTS;
  2211. }
  2212. }
  2213. CNmChannelData * pChannel = new CNmChannelData(this, rguid, (PGCCEnrollRequest) pER);
  2214. if (NULL == pChannel)
  2215. {
  2216. WARNING_OUT(("CreateChannelData: Unable to create data channel"));
  2217. return E_OUTOFMEMORY;
  2218. }
  2219. HRESULT hr = pChannel->OpenConnection();
  2220. if (FAILED(hr))
  2221. {
  2222. ERROR_OUT(("CreateDataChannel: Unable to set guid / create T.120 channels"));
  2223. // Failed to create T.120 data channels
  2224. delete pChannel;
  2225. *ppChannel = NULL;
  2226. return hr;
  2227. }
  2228. GUID* pG = new GUID;
  2229. *pG = g;
  2230. m_DataChannelGUIDS.AddTail(pG);
  2231. NotifySink((INmChannel *) pChannel, OnNotifyChannelAdded);
  2232. TRACE_OUT(("CreateChannelData: Created data channel %08X", pChannel));
  2233. // Now we are active
  2234. NotifySink((INmChannel*) pChannel, OnNotifyChannelUpdated);
  2235. if (NULL != ppChannel)
  2236. {
  2237. *ppChannel = (INmChannelData *)pChannel;
  2238. // pChannel->AddRef(); // Caller needs to release the initial lock
  2239. }
  2240. else
  2241. {
  2242. pChannel->Release(); // No one is watching this channel? - free it now
  2243. }
  2244. return S_OK;
  2245. }
  2246. HRESULT STDMETHODCALLTYPE CConfObject::CreateDataChannel(INmChannelData **ppChannel, REFGUID rguid)
  2247. {
  2248. return CreateDataChannelEx(ppChannel, rguid, NULL);
  2249. }
  2250. HRESULT CConfObject::IsHosting(void)
  2251. {
  2252. return m_fServerMode ? S_OK : S_FALSE;
  2253. }
  2254. HRESULT CConfObject::Host(void)
  2255. {
  2256. HRESULT hr = E_FAIL;
  2257. if (m_fServerMode || IsConferenceActive())
  2258. {
  2259. WARNING_OUT(("Conference already exists!"));
  2260. // ncsRet = UI_RC_CONFERENCE_ALREADY_EXISTS;
  2261. }
  2262. else
  2263. {
  2264. HRESULT ncsRet = CreateConference();
  2265. if (S_OK == ncsRet)
  2266. {
  2267. // The only success case:
  2268. TRACE_OUT(("Create local issued successfully"));
  2269. m_fServerMode = TRUE;
  2270. hr = S_OK;
  2271. }
  2272. else
  2273. {
  2274. // UI?
  2275. WARNING_OUT(("Create local failed!"));
  2276. }
  2277. }
  2278. return hr;
  2279. }
  2280. HRESULT CConfObject::Leave(void)
  2281. {
  2282. DebugEntry(CConfObject::Leave);
  2283. COprahNCUI *pOprahNCUI = COprahNCUI::GetInstance();
  2284. if (NULL != pOprahNCUI)
  2285. {
  2286. pOprahNCUI->CancelCalls();
  2287. }
  2288. HRESULT hr = S_OK;
  2289. switch (m_csState)
  2290. {
  2291. case CS_GOING_DOWN:
  2292. // we are already exiting
  2293. break;
  2294. case CS_COMING_UP:
  2295. case CS_RUNNING:
  2296. {
  2297. SetT120State(CS_GOING_DOWN);
  2298. ASSERT(m_hConf);
  2299. TRACE_OUT(("Calling IDataConference::Leave"));
  2300. hr = m_hConf->Leave();
  2301. if (FAILED(hr))
  2302. {
  2303. WARNING_OUT(("IDataConference::Leave failed"));
  2304. }
  2305. break;
  2306. }
  2307. default:
  2308. hr = E_FAIL;
  2309. break;
  2310. }
  2311. if(FAILED(LeaveH323(FALSE /* fKeepAV */ )))
  2312. {
  2313. // overwrite return value.... I guess this error is as good as any error
  2314. hr = E_FAIL;
  2315. }
  2316. DebugExitHRESULT(CConfObject::Leave, hr);
  2317. return hr;
  2318. }
  2319. HRESULT CConfObject::LeaveH323(BOOL fKeepAV)
  2320. {
  2321. HRESULT hrRet = S_OK;
  2322. POSITION pos = m_MemberList.GetHeadPosition();
  2323. while (NULL != pos && !m_MemberList.IsEmpty())
  2324. {
  2325. CNmMember * pMember = (CNmMember *) m_MemberList.GetNext(pos);
  2326. ASSERT(pMember);
  2327. HRESULT hr;
  2328. DWORD dwFlags = pMember->GetDwFlags();
  2329. IH323Endpoint * pConnection = pMember->GetH323Endpoint();
  2330. if(pConnection)
  2331. {
  2332. if (!fKeepAV || !((PF_MEDIA_AUDIO | PF_MEDIA_VIDEO) & dwFlags))
  2333. {
  2334. ConnectStateType state = CLS_Idle;
  2335. hr = pConnection->GetState(&state);
  2336. if (SUCCEEDED(hr))
  2337. {
  2338. if(state != CLS_Idle)
  2339. {
  2340. ASSERT(dwFlags & PF_H323);
  2341. hr = pConnection->Disconnect();
  2342. if (SUCCEEDED(hr))
  2343. {
  2344. TRACE_OUT(("pConnection->Disconnect() succeeded!"));
  2345. }
  2346. else
  2347. {
  2348. hrRet = E_FAIL;
  2349. WARNING_OUT(("pConnection->Disconnect() failed!"));
  2350. }
  2351. }
  2352. }
  2353. else
  2354. {
  2355. hrRet = E_FAIL;
  2356. }
  2357. }
  2358. }
  2359. }
  2360. return hrRet;
  2361. }
  2362. HRESULT CConfObject::LaunchRemote(REFGUID rguid, INmMember *pMember)
  2363. {
  2364. DWORD dwUserId = 0;
  2365. if(m_hConf)
  2366. {
  2367. if (NULL != pMember)
  2368. {
  2369. dwUserId = ((CNmMember*)pMember)->GetGCCID();
  2370. }
  2371. ASSERT(g_pNodeController);
  2372. ASSERT(m_hConf);
  2373. HRESULT nsRet = m_hConf->LaunchGuid(&rguid,
  2374. (PUINT) &dwUserId, (0 == dwUserId) ? 0 : 1);
  2375. return (S_OK == nsRet) ? S_OK : E_FAIL;
  2376. }
  2377. return NM_E_NO_T120_CONFERENCE;
  2378. }
  2379. STDMETHODIMP CConfObject::DisconnectAV(INmMember *pMember)
  2380. {
  2381. return E_FAIL;
  2382. }
  2383. /****************************************************************************
  2384. *
  2385. * CLASS: CConfObject
  2386. *
  2387. * FUNCTION: ConnectAV(LPCTSTR, LPCTSTR)
  2388. *
  2389. * PURPOSE: Switches Audio and Video to a new person (given an IP address)
  2390. *
  2391. ****************************************************************************/
  2392. STDMETHODIMP CConfObject::ConnectAV(INmMember *pMember)
  2393. {
  2394. DebugEntry(CConfRoom::SwitchAV);
  2395. HRESULT hr = E_FAIL;
  2396. DebugExitHRESULT(CConfRoom::SwitchAV, hr);
  2397. return hr;
  2398. }
  2399. /****************************************************************************
  2400. *
  2401. * CLASS: CConfObject
  2402. *
  2403. * FUNCTION: GetConferenceHandle(DWORD *)
  2404. *
  2405. * PURPOSE: Gets the T120 conference handle
  2406. *
  2407. ****************************************************************************/
  2408. STDMETHODIMP CConfObject::GetConferenceHandle(DWORD_PTR *pdwHandle)
  2409. {
  2410. HRESULT hr = E_FAIL;
  2411. if (NULL != pdwHandle)
  2412. {
  2413. CONF_HANDLE hConf = GetConfHandle();
  2414. *pdwHandle = (DWORD_PTR)hConf;
  2415. hr = S_OK;
  2416. }
  2417. return hr;
  2418. }
  2419. /* O N N O T I F Y S T A T E C H A N G E D */
  2420. /*-------------------------------------------------------------------------
  2421. %%Function: OnNotifyStateChanged
  2422. -------------------------------------------------------------------------*/
  2423. HRESULT OnNotifyStateChanged(IUnknown *pConfNotify, PVOID pv, REFIID riid)
  2424. {
  2425. ASSERT(NULL != pConfNotify);
  2426. ((INmConferenceNotify*)pConfNotify)->StateChanged((NM_CONFERENCE_STATE)((DWORD_PTR)pv));
  2427. return S_OK;
  2428. }
  2429. /* O N N O T I F Y M E M B E R A D D E D */
  2430. /*-------------------------------------------------------------------------
  2431. %%Function: OnNotifyMemberAdded
  2432. -------------------------------------------------------------------------*/
  2433. HRESULT OnNotifyMemberAdded(IUnknown *pConfNotify, PVOID pv, REFIID riid)
  2434. {
  2435. ASSERT(NULL != pConfNotify);
  2436. ((INmConferenceNotify*)pConfNotify)->MemberChanged(NM_MEMBER_ADDED, (INmMember *) pv);
  2437. return S_OK;
  2438. }
  2439. /* O N N O T I F Y M E M B E R U P D A T E D */
  2440. /*-------------------------------------------------------------------------
  2441. %%Function: OnNotifyMemberUpdated
  2442. -------------------------------------------------------------------------*/
  2443. HRESULT OnNotifyMemberUpdated(IUnknown *pConfNotify, PVOID pv, REFIID riid)
  2444. {
  2445. ASSERT(NULL != pConfNotify);
  2446. ((INmConferenceNotify*)pConfNotify)->MemberChanged(NM_MEMBER_UPDATED, (INmMember *) pv);
  2447. return S_OK;
  2448. }
  2449. /* O N N O T I F Y M E M B E R R E M O V E D */
  2450. /*-------------------------------------------------------------------------
  2451. %%Function: OnNotifyMemberRemoved
  2452. -------------------------------------------------------------------------*/
  2453. HRESULT OnNotifyMemberRemoved(IUnknown *pConfNotify, PVOID pv, REFIID riid)
  2454. {
  2455. ASSERT(NULL != pConfNotify);
  2456. ((INmConferenceNotify*)pConfNotify)->MemberChanged(NM_MEMBER_REMOVED, (INmMember *) pv);
  2457. return S_OK;
  2458. }
  2459. /* O N N O T I F Y C H A N N E L A D D E D */
  2460. /*-------------------------------------------------------------------------
  2461. %%Function: OnNotifyChannelAdded
  2462. -------------------------------------------------------------------------*/
  2463. HRESULT OnNotifyChannelAdded(IUnknown *pConfNotify, PVOID pv, REFIID riid)
  2464. {
  2465. ASSERT(NULL != pConfNotify);
  2466. ((INmConferenceNotify*)pConfNotify)->ChannelChanged(NM_CHANNEL_ADDED, (INmChannel *) pv);
  2467. return S_OK;
  2468. }
  2469. /* O N N O T I F Y C H A N N E L U P D A T E D */
  2470. /*-------------------------------------------------------------------------
  2471. %%Function: OnNotifyChannelUpdated
  2472. -------------------------------------------------------------------------*/
  2473. HRESULT OnNotifyChannelUpdated(IUnknown *pConfNotify, PVOID pv, REFIID riid)
  2474. {
  2475. ASSERT(NULL != pConfNotify);
  2476. ((INmConferenceNotify*)pConfNotify)->ChannelChanged(NM_CHANNEL_UPDATED, (INmChannel *) pv);
  2477. return S_OK;
  2478. }
  2479. /* O N N O T I F Y C H A N N E L R E M O V E D */
  2480. /*-------------------------------------------------------------------------
  2481. %%Function: OnNotifyChannelRemoved
  2482. -------------------------------------------------------------------------*/
  2483. HRESULT OnNotifyChannelRemoved(IUnknown *pConfNotify, PVOID pv, REFIID riid)
  2484. {
  2485. ASSERT(NULL != pConfNotify);
  2486. ((INmConferenceNotify*)pConfNotify)->ChannelChanged(NM_CHANNEL_REMOVED, (INmChannel *) pv);
  2487. return S_OK;
  2488. }
  2489. HRESULT OnNotifyStreamEvent(IUnknown *pConfNotify, PVOID pv, REFIID riid)
  2490. {
  2491. StreamEventInfo *pInfo = (StreamEventInfo*)pv;
  2492. ASSERT(NULL != pConfNotify);
  2493. HRESULT hr;
  2494. if (riid != IID_INmConferenceNotify2)
  2495. return E_NOINTERFACE;
  2496. ((INmConferenceNotify2*)pConfNotify)->StreamEvent(pInfo->uEventCode, pInfo->uSubCode, pInfo->pChannel);
  2497. return S_OK;
  2498. }
  2499. /* O N N O T I F Y N M U I */
  2500. /*-------------------------------------------------------------------------
  2501. %%Function: OnNotifyNmUI
  2502. -------------------------------------------------------------------------*/
  2503. HRESULT OnNotifyNmUI(IUnknown *pConfNotify, PVOID pv, REFIID riid)
  2504. {
  2505. ASSERT(NULL != pConfNotify);
  2506. ((INmConferenceNotify*)pConfNotify)->NmUI((CONFN)((DWORD_PTR)pv));
  2507. return S_OK;
  2508. }
  2509. /* G E T C O N F O B J E C T */
  2510. /*-------------------------------------------------------------------------
  2511. %%Function: GetConfObject
  2512. Global function to get the conference object
  2513. -------------------------------------------------------------------------*/
  2514. CConfObject * GetConfObject(void)
  2515. {
  2516. COprahNCUI *pOprahNCUI = COprahNCUI::GetInstance();
  2517. if (NULL != pOprahNCUI)
  2518. {
  2519. return pOprahNCUI->GetConfObject();
  2520. }
  2521. return NULL;
  2522. }
  2523. /* G E T C O N F E R E N C E */
  2524. /*-------------------------------------------------------------------------
  2525. %%Function: GetConference
  2526. Global function to get the INmConference interface to the conf object
  2527. -------------------------------------------------------------------------*/
  2528. HRESULT GetConference(INmConference **ppConference)
  2529. {
  2530. HRESULT hr = E_POINTER;
  2531. if (NULL != ppConference)
  2532. {
  2533. hr = E_FAIL;
  2534. INmConference *pConference = GetConfObject();
  2535. if (NULL != pConference)
  2536. {
  2537. pConference->AddRef();
  2538. hr = S_OK;
  2539. }
  2540. *ppConference = pConference;
  2541. }
  2542. return hr;
  2543. }
  2544. /* G E T M E M B E R L I S T */
  2545. /*-------------------------------------------------------------------------
  2546. %%Function: GetMemberList
  2547. Global function to get the member list
  2548. -------------------------------------------------------------------------*/
  2549. COBLIST * GetMemberList(void)
  2550. {
  2551. CConfObject* pco = ::GetConfObject();
  2552. if (NULL == pco)
  2553. return NULL;
  2554. return pco->GetMemberList();
  2555. }
  2556. /* P F _ V E R _ F R O M D W */
  2557. /*-------------------------------------------------------------------------
  2558. %%Function: PF_VER_FromDw
  2559. -------------------------------------------------------------------------*/
  2560. DWORD PF_VER_FromDw(DWORD dw)
  2561. {
  2562. if (DWVERSION_NM_1 == dw)
  2563. return PF_VER_NM_1;
  2564. if ((DWVERSION_NM_2b2 <= dw) && (DWVERSION_NM_2 >= dw))
  2565. return PF_VER_NM_2;
  2566. if ((DWVERSION_NM_3a1 <= dw) && (DWVERSION_NM_3max >= dw))
  2567. return PF_VER_NM_3;
  2568. if ((DWVERSION_NM_4a1 <= dw) && (DWVERSION_NM_CURRENT >= dw))
  2569. return PF_VER_NM_4;
  2570. if (dw > DWVERSION_NM_CURRENT)
  2571. return PF_VER_FUTURE;
  2572. return PF_VER_UNKNOWN;
  2573. }
  2574. /* P F _ V E R _ F R O M U S E R D A T A */
  2575. /*-------------------------------------------------------------------------
  2576. %%Function: PV_VER_FromUserData
  2577. -------------------------------------------------------------------------*/
  2578. DWORD PF_VER_FromUserData(ROSTER_DATA_HANDLE hUserData)
  2579. {
  2580. UINT cb;
  2581. PT120PRODUCTVERSION pVersion;
  2582. PVOID pv;
  2583. static const GUID g_csguidVerInfo = GUID_VERSION;
  2584. ASSERT(NULL != g_pNodeController);
  2585. if (NULL == hUserData)
  2586. return PF_VER_UNKNOWN; // not NetMeeting
  2587. // Try to find the T.120 Product Version guid
  2588. if ((NOERROR == g_pNodeController->GetUserData(hUserData,
  2589. &g_csguidVerInfo, &cb, (PVOID *) &pVersion))
  2590. && (cb < sizeof(T120PRODUCTVERSION)) )
  2591. {
  2592. return PF_VER_FromDw(pVersion->dwVersion);
  2593. }
  2594. // Try to extract the build number from the hex string for VER_PRODUCTVERSION_DW
  2595. if ((NOERROR == g_pNodeController->GetUserData(hUserData,
  2596. (GUID *) &g_csguidRostInfo, &cb, &pv)))
  2597. {
  2598. CRosterInfo ri;
  2599. ri.Load(pv);
  2600. TCHAR szVersion[MAX_PATH];
  2601. if (SUCCEEDED(ri.ExtractItem(NULL,
  2602. g_cwszVerTag, szVersion, CCHMAX(szVersion))))
  2603. {
  2604. return PF_VER_FromDw(DwFromHex(szVersion));
  2605. }
  2606. }
  2607. return PF_VER_NM_1; // Must be at least NetMeeting 1.0
  2608. }
  2609. DWORD CConfObject::GetDwUserIdLocal(void)
  2610. {
  2611. CNmMember * pMemberLocal = GetLocalMember();
  2612. if (NULL != pMemberLocal)
  2613. {
  2614. return pMemberLocal->GetGCCID();
  2615. }
  2616. return 0;
  2617. }
  2618. CNmMember * CConfObject::PMemberFromGCCID(UINT uNodeID)
  2619. {
  2620. COBLIST* pMemberList = ::GetMemberList();
  2621. if (NULL != pMemberList)
  2622. {
  2623. POSITION pos = pMemberList->GetHeadPosition();
  2624. while (pos)
  2625. {
  2626. CNmMember * pMember = (CNmMember *) pMemberList->GetNext(pos);
  2627. ASSERT(NULL != pMember);
  2628. if (uNodeID == pMember->GetGCCID())
  2629. {
  2630. return pMember;
  2631. }
  2632. }
  2633. }
  2634. return NULL;
  2635. }
  2636. CNmMember * CConfObject::PMemberFromNodeGuid(REFGUID rguidNode)
  2637. {
  2638. POSITION pos = m_MemberList.GetHeadPosition();
  2639. while (NULL != pos)
  2640. {
  2641. CNmMember * pMember = (CNmMember *) m_MemberList.GetNext(pos);
  2642. if (pMember->GetNodeGuid() == rguidNode)
  2643. {
  2644. return pMember;
  2645. }
  2646. }
  2647. return NULL;
  2648. }
  2649. CNmMember * CConfObject::PMemberFromH323Endpoint(IH323Endpoint * pConnection)
  2650. {
  2651. COBLIST* pMemberList = ::GetMemberList();
  2652. if (NULL != pMemberList)
  2653. {
  2654. POSITION pos = pMemberList->GetHeadPosition();
  2655. while (pos)
  2656. {
  2657. CNmMember * pMember = (CNmMember *) pMemberList->GetNext(pos);
  2658. ASSERT(NULL != pMember);
  2659. if (pConnection == pMember->GetH323Endpoint())
  2660. {
  2661. return pMember;
  2662. }
  2663. }
  2664. }
  2665. return NULL;
  2666. }
  2667. CNmMember * CConfObject::PDataMemberFromName(PCWSTR pwszName)
  2668. {
  2669. POSITION pos = m_MemberList.GetHeadPosition();
  2670. while (NULL != pos)
  2671. {
  2672. CNmMember * pMember = (CNmMember *) m_MemberList.GetNext(pos);
  2673. if(pMember->FHasData())
  2674. {
  2675. if (0 == UnicodeCompare(pwszName, pMember->GetName()))
  2676. {
  2677. return pMember;
  2678. }
  2679. }
  2680. }
  2681. return NULL;
  2682. }
  2683. // IStreamEventNotify method
  2684. // get called whenever a major event on the stream occurs
  2685. HRESULT __stdcall CConfObject::EventNotification(UINT uDirection, UINT uMediaType, UINT uEventCode, UINT uSubCode)
  2686. {
  2687. CNmChannelAudio *pChannel = NULL;
  2688. ULONG uStatus = 0;
  2689. StreamEventInfo seInfo;
  2690. if (uMediaType == MCF_AUDIO)
  2691. {
  2692. if (uDirection == MCF_SEND)
  2693. {
  2694. pChannel = m_pChannelAudioLocal;
  2695. }
  2696. else if (uDirection == MCF_RECV)
  2697. {
  2698. pChannel = m_pChannelAudioRemote;
  2699. }
  2700. }
  2701. if (pChannel)
  2702. {
  2703. // If we get a device failure notification,
  2704. // do a quick check to see if the device is indeed
  2705. // jammed. The device may have opened by the time we
  2706. // got this notification
  2707. seInfo.pChannel = pChannel;
  2708. seInfo.uSubCode = uSubCode;
  2709. switch (uEventCode)
  2710. {
  2711. case STREAM_EVENT_DEVICE_FAILURE:
  2712. {
  2713. seInfo.uEventCode = (NM_STREAMEVENT)NM_STREAMEVENT_DEVICE_FAILURE;
  2714. NotifySink((void*)&seInfo, OnNotifyStreamEvent);
  2715. break;
  2716. }
  2717. case STREAM_EVENT_DEVICE_OPEN:
  2718. {
  2719. seInfo.uEventCode = (NM_STREAMEVENT)NM_STREAMEVENT_DEVICE_OPENED;
  2720. NotifySink((void*)&seInfo, OnNotifyStreamEvent);
  2721. break;
  2722. }
  2723. default:
  2724. {
  2725. break;
  2726. }
  2727. }
  2728. }
  2729. else
  2730. {
  2731. return E_FAIL;
  2732. }
  2733. return S_OK;
  2734. }