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.

1791 lines
44 KiB

  1. // File: ichnldat.cpp
  2. //
  3. // INmChannelData
  4. //
  5. #include "precomp.h"
  6. #include <confguid.h>
  7. static const IID * g_apiidCP[] =
  8. {
  9. {&IID_INmChannelDataNotify}
  10. };
  11. #define CopyStruct(pDest, pSrc) CopyMemory(pDest, pSrc, sizeof(*(pDest)))
  12. #define MAX_NM_PEER 256 // Maximum number of NetMeeting Peer applications/users
  13. #ifdef DEBUG /* T.120 Debug utilities */
  14. LPCTSTR GetGccErrorString(GCCError uErr);
  15. LPCTSTR GetMcsErrorString(MCSError uErr);
  16. LPCTSTR GetGccResultString(UINT uErr);
  17. LPCTSTR GetMcsResultString(UINT uErr);
  18. #else
  19. #define GetGccErrorString(uErr) ""
  20. #define GetMcsErrorString(uErr) ""
  21. #define GetGccResultString(uErr) ""
  22. #define GetMcsResultString(uErr) ""
  23. #endif /* DEBUG */
  24. // code from nm\ui\conf\cuserdta.cpp:
  25. static unsigned char H221IDGUID[5] = {H221GUIDKEY0,
  26. H221GUIDKEY1,
  27. H221GUIDKEY2,
  28. H221GUIDKEY3,
  29. H221GUIDKEY4};
  30. extern VOID CreateH221AppKeyFromGuid(LPBYTE lpb, GUID * pguid);
  31. /* S E T A P P K E Y */
  32. /*----------------------------------------------------------------------------
  33. %%Function: SetAppKey
  34. Set the two pieces of an OctetString (the length and the data.)
  35. Note that the length always includes the terminating null character.
  36. ----------------------------------------------------------------------------*/
  37. VOID SetAppKey(LPOSTR pOct, LPBYTE lpb)
  38. {
  39. pOct->length = cbKeyApp;
  40. pOct->value = lpb;
  41. }
  42. /* C R E A T E A P P K E Y */
  43. /*----------------------------------------------------------------------------
  44. %%Function: CreateAppKey
  45. Given a guid and a userid, create the appropriate application key.
  46. The key is formated as:
  47. 0xB5 0x00 0x53 0x4C - Microsoft Object Identifier
  48. 0x01 - guid identifier
  49. <binary guid> - guid data
  50. <dword node id> - user node id
  51. ----------------------------------------------------------------------------*/
  52. VOID CreateAppKey(LPBYTE lpb, GUID * pguid, DWORD dwUserId)
  53. {
  54. CreateH221AppKeyFromGuid(lpb, pguid);
  55. CopyMemory(lpb + cbKeyApp - sizeof(DWORD), &dwUserId, sizeof(DWORD));
  56. #ifdef DEBUG
  57. TCHAR szGuid[LENGTH_SZGUID_FORMATTED];
  58. GuidToSz(pguid, szGuid);
  59. TRACE_OUT(("CreateAppKey: %s %08X", szGuid, dwUserId));
  60. #endif
  61. }
  62. /* P M E M B E R F R O M D W U S E R I D */
  63. /*-------------------------------------------------------------------------
  64. %%Function: PMemberFromDwUserId
  65. -------------------------------------------------------------------------*/
  66. CNmMember * PMemberFromDwUserId(DWORD dwUserId, COBLIST *pList)
  67. {
  68. if (NULL != pList)
  69. {
  70. POSITION posCurr;
  71. POSITION pos = pList->GetHeadPosition();
  72. while (NULL != pos)
  73. {
  74. posCurr = pos;
  75. CNmMember * pMember = (CNmMember *) pList->GetNext(pos);
  76. if (dwUserId == pMember->GetGCCID())
  77. {
  78. pMember->AddRef();
  79. return pMember;
  80. }
  81. }
  82. }
  83. return NULL;
  84. }
  85. /* A D D N O D E */
  86. /*-------------------------------------------------------------------------
  87. %%Function: AddNode
  88. Add a node to a list.
  89. Initializes the ObList, if necessary.
  90. Returns the position in the list or NULL if there was a problem.
  91. -------------------------------------------------------------------------*/
  92. POSITION AddNode(PVOID pv, COBLIST ** ppList)
  93. {
  94. ASSERT(NULL != ppList);
  95. if (NULL == *ppList)
  96. {
  97. *ppList = new COBLIST();
  98. if (NULL == *ppList)
  99. return NULL;
  100. }
  101. return (*ppList)->AddTail(pv);
  102. }
  103. /* R E M O V E N O D E */
  104. /*-------------------------------------------------------------------------
  105. %%Function: RemoveNode
  106. Remove a node from a list.
  107. Sets pPos to NULL
  108. -------------------------------------------------------------------------*/
  109. PVOID RemoveNodePos(POSITION * pPos, COBLIST *pList)
  110. {
  111. if ((NULL == pList) || (NULL == pPos))
  112. return NULL;
  113. PVOID pv = pList->RemoveAt(*pPos);
  114. *pPos = NULL;
  115. return pv;
  116. }
  117. /* R E M O V E N O D E */
  118. /*-------------------------------------------------------------------------
  119. %%Function: RemoveNode
  120. -------------------------------------------------------------------------*/
  121. VOID RemoveNode(PVOID pv, COBLIST * pList)
  122. {
  123. ASSERT(NULL != pv);
  124. if (NULL != pList)
  125. {
  126. POSITION pos = pList->GetPosition(pv);
  127. RemoveNodePos(&pos, pList);
  128. }
  129. }
  130. VOID CNmChannelData::InitCT120Channel(DWORD dwUserId)
  131. {
  132. m_dwUserId = dwUserId;
  133. m_gcc_conference_id = 0;
  134. m_gcc_pIAppSap = NULL;
  135. m_mcs_channel_id = 0;
  136. m_pmcs_sap = NULL;
  137. m_gcc_node_id = 0;
  138. m_scs = SCS_UNINITIALIZED;
  139. m_pGuid = PGuid();
  140. ASSERT((NULL != m_pGuid) && (GUID_NULL != *m_pGuid));
  141. CreateAppKey(m_keyApp, m_pGuid, 0);
  142. CreateAppKey(m_keyChannel, m_pGuid, dwUserId);
  143. // initialize other gcc & mcs stuff
  144. GCCObjectKey FAR * pObjKey;
  145. ClearStruct(&m_gcc_session_key);
  146. pObjKey = &(m_gcc_session_key.application_protocol_key);
  147. pObjKey->key_type = GCC_H221_NONSTANDARD_KEY;
  148. SetAppKey(&(pObjKey->h221_non_standard_id), m_keyApp);
  149. ASSERT(0 == m_gcc_session_key.session_id);
  150. ClearStruct(&m_gcc_registry_item);
  151. ClearStruct(&m_gcc_registry_key);
  152. CopyStruct(&m_gcc_registry_key.session_key, &m_gcc_session_key);
  153. SetAppKey(&m_gcc_registry_key.resource_id, m_keyApp);
  154. ClearStruct(&m_registry_item_Private);
  155. ClearStruct(&m_registry_key_Private);
  156. CopyStruct(&m_registry_key_Private.session_key, &m_gcc_session_key);
  157. SetAppKey(&m_registry_key_Private.resource_id, m_keyChannel);
  158. UpdateScState(SCS_UNINITIALIZED, 0);
  159. }
  160. /* C L O S E C H A N N E L */
  161. /*----------------------------------------------------------------------------
  162. %%Function: CloseChannel
  163. Close the channel.
  164. Note there are no confirm messages expected for any of the GCC/MCS calls.
  165. ----------------------------------------------------------------------------*/
  166. VOID CNmChannelData::CloseChannel(void)
  167. {
  168. GCCError gccError = GCC_NO_ERROR;
  169. MCSError mcsError = MCS_NO_ERROR;
  170. if (SCS_UNINITIALIZED == m_scs)
  171. {
  172. WARNING_OUT(("in CT120Channel::CloseChannel, m_scs is SCS_UNINITIALIZED, is this OK?"));
  173. return;
  174. }
  175. TRACE_OUT(("CT120Channel::CloseChannel %08X (userHandle=%p)", m_mcs_channel_id, m_pmcs_sap));
  176. m_scs = SCS_TERMINATING;
  177. if (0 != m_mcs_channel_id)
  178. {
  179. ASSERT (m_pmcs_sap);
  180. mcsError = m_pmcs_sap->ChannelLeave(m_mcs_channel_id);
  181. TRACE_OUT(("CT120Channel::CloseChannel: ChannelLeave %s", GetMcsErrorString(mcsError)));
  182. m_mcs_channel_id = 0;
  183. }
  184. if (NULL != m_pmcs_sap)
  185. {
  186. mcsError = m_pmcs_sap->ReleaseInterface();
  187. TRACE_OUT(("CT120Channel::CloseChannel: MCS ReleaseInterface %s", GetMcsErrorString(mcsError)));
  188. m_pmcs_sap = NULL;
  189. }
  190. if (NULL != m_gcc_pIAppSap)
  191. {
  192. m_gcc_pIAppSap->RegistryDeleteEntry(m_gcc_conference_id, &m_registry_key_Private);
  193. // ignore the above result
  194. m_gcc_pIAppSap->ReleaseInterface();
  195. TRACE_OUT(("CT120Channel::CloseChannel: GCCDeleteSap %s", GetGccErrorString(gccError)));
  196. m_gcc_pIAppSap = NULL;
  197. }
  198. m_scs = SCS_UNINITIALIZED;
  199. m_gcc_conference_id = 0;
  200. // make sure no one is around
  201. UpdateRoster(NULL, 0, FALSE, TRUE /* fRemove */);;
  202. }
  203. /* U P D A T E S C S T A T E */
  204. /*----------------------------------------------------------------------------
  205. %%Function: UpdateScState
  206. The system progresses from one state to another
  207. by making an GCC (or MCS) call that is guarenteed to
  208. produce a notification that calls this function.
  209. The calling process is released by UnBlockThread.
  210. ----------------------------------------------------------------------------*/
  211. VOID CNmChannelData::UpdateScState(SCSTATE scs, DWORD dwErr)
  212. {
  213. DBGENTRY(CNmChannelData::UpdateScState)
  214. if (m_scs != scs)
  215. {
  216. WARNING_OUT(("UpdateScState - invalid state transition (%d - %d)", m_scs, scs));
  217. dwErr = INVALID_T120_ERROR; // We should never get here
  218. }
  219. if (0 == dwErr)
  220. {
  221. switch (m_scs)
  222. {
  223. case SCS_UNINITIALIZED:
  224. dwErr = DoCreateSap();
  225. break;
  226. case SCS_CREATESAP:
  227. dwErr = DoAttach();
  228. break;
  229. case SCS_ATTACH:
  230. dwErr = DoEnroll();
  231. break;
  232. case SCS_ENROLL:
  233. dwErr = DoJoinPrivate();
  234. break;
  235. case SCS_JOIN_PRIVATE:
  236. dwErr = DoRegRetrieve();
  237. break;
  238. case SCS_REGRETRIEVE_NEW:
  239. dwErr = DoJoinNew();
  240. break;
  241. case SCS_REGRETRIEVE_EXISTS:
  242. dwErr = DoJoinOld();
  243. break;
  244. case SCS_JOIN_NEW:
  245. dwErr = DoRegChannel();
  246. break;
  247. case SCS_REGCHANNEL:
  248. case SCS_JOIN_OLD:
  249. dwErr = DoRegPrivate();
  250. break;
  251. case SCS_REGPRIVATE:
  252. TRACE_OUT((">>>>>>>>>>>UpdateScState: Complete"));
  253. m_scs = SCS_CONNECTED;
  254. NotifyChannelConnected();
  255. break;
  256. case SCS_CONNECTED:
  257. case SCS_REGRETRIEVE:
  258. // we should never be called when we're in these states
  259. // so, treat it as an error and fall thru to the default case
  260. default:
  261. dwErr = INVALID_T120_ERROR; // We should never get here
  262. break;
  263. }
  264. }
  265. TRACE_OUT(("UpdateScState: New state (%d) channelId=%04X", m_scs, GetMcsChannelId()));
  266. if (0 != dwErr)
  267. {
  268. WARNING_OUT(("UpdateScState: Err=%d", dwErr));
  269. CloseConnection();
  270. }
  271. DBGEXIT(CNmChannelData::UpdateScState)
  272. }
  273. DWORD CNmChannelData::DoCreateSap(void)
  274. {
  275. ASSERT(SCS_UNINITIALIZED == m_scs);
  276. m_scs = SCS_CREATESAP;
  277. GCCError gccError = GCC_CreateAppSap(&m_gcc_pIAppSap, this, NmGccMsgHandler);
  278. TRACE_OUT(("GCCCreateSap err=%s", GetGccErrorString(gccError)));
  279. return (DWORD) gccError;
  280. }
  281. DWORD CNmChannelData::DoAttach(void)
  282. {
  283. ASSERT(SCS_CREATESAP == m_scs);
  284. m_scs = SCS_ATTACH;
  285. MCSError mcsError = MCS_AttachRequest(&m_pmcs_sap,
  286. (DomainSelector) &m_gcc_conference_id,
  287. sizeof(m_gcc_conference_id),
  288. NmMcsMsgHandler,
  289. this,
  290. ATTACHMENT_DISCONNECT_IN_DATA_LOSS | ATTACHMENT_MCS_FREES_DATA_IND_BUFFER);
  291. // This generates an async MCS_ATTACH_USER_CONFIRM
  292. TRACE_OUT(("MCS_AttachRequest err=%s", GetMcsErrorString(mcsError)));
  293. return (DWORD) mcsError;
  294. }
  295. DWORD CNmChannelData::DoEnroll(void)
  296. {
  297. ASSERT(SCS_ATTACH == m_scs || SCS_JOIN_STATIC_CHANNEL);
  298. m_scs = SCS_ENROLL;
  299. GCCEnrollRequest er;
  300. GCCRequestTag nReqTag;
  301. if(m_pGCCER)
  302. {
  303. m_pGCCER->pSessionKey = &m_gcc_session_key;
  304. m_pGCCER->nUserID = m_mcs_sender_id;
  305. }
  306. else
  307. {
  308. // fill in enroll request structure
  309. ::ZeroMemory(&er, sizeof(er));
  310. er.pSessionKey = &m_gcc_session_key;
  311. er.fEnrollActively = TRUE;
  312. er.nUserID = m_mcs_sender_id;
  313. // er.fConductingCapabable = FALSE;
  314. er.nStartupChannelType = MCS_DYNAMIC_MULTICAST_CHANNEL;
  315. // er.cNonCollapsedCaps = 0;
  316. // er.apNonCollapsedCaps = NULL;
  317. // er.cCollapsedCaps = 0;
  318. // er.apCollapsedCaps = NULL;
  319. er.fEnroll = TRUE;
  320. }
  321. GCCError gccError = m_gcc_pIAppSap->AppEnroll(m_gcc_conference_id, m_pGCCER != NULL ? m_pGCCER : &er, &nReqTag);
  322. TRACE_OUT(("GCCApplicationEnrollRequest err=%s", GetGccErrorString(gccError)));
  323. if (GCC_NO_ERROR != gccError)
  324. {
  325. ERROR_OUT(("DoEnroll failed - WHY?"));
  326. }
  327. return (DWORD) gccError;
  328. }
  329. // Join the PRIVATE data channel (m_mcs_sender_id)
  330. DWORD CNmChannelData::DoJoinPrivate(void)
  331. {
  332. ASSERT(SCS_ENROLL == m_scs || SCS_ATTACH == m_scs);
  333. m_scs = SCS_JOIN_PRIVATE;
  334. MCSError mcsError = m_pmcs_sap->ChannelJoin(m_mcs_sender_id);
  335. // This generates an async MCS_CHANNEL_JOIN_CONFIRM
  336. TRACE_OUT(("MCSChannelJoinRequest (private) %04X, err=%s",
  337. m_mcs_sender_id, GetMcsErrorString(mcsError)));
  338. return (DWORD) mcsError;
  339. }
  340. DWORD CNmChannelData::DoRegRetrieve(void)
  341. {
  342. ASSERT(SCS_JOIN_PRIVATE == m_scs);
  343. m_scs = SCS_REGRETRIEVE;
  344. GCCError gccError = m_gcc_pIAppSap->RegistryRetrieveEntry(
  345. m_gcc_conference_id, &m_gcc_registry_key);
  346. // This generates an async GCC_RETRIEVE_ENTRY_CONFIRM
  347. TRACE_OUT(("GCCRegistryRetrieveEntryRequest err=%s", GetGccErrorString(gccError)));
  348. return (DWORD) gccError;
  349. }
  350. // Register the PUBLIC channel
  351. DWORD CNmChannelData::DoRegChannel(void)
  352. {
  353. ASSERT(SCS_JOIN_NEW == m_scs);
  354. m_scs = SCS_REGCHANNEL;
  355. GCCError gccError = m_gcc_pIAppSap->RegisterChannel(
  356. m_gcc_conference_id, &m_gcc_registry_key, m_mcs_channel_id);
  357. // This generates an async GCC_REGISTER_CHANNEL_CONFIRM
  358. TRACE_OUT(("GCCRegisterChannelRequest err=%s", GetGccErrorString(gccError)));
  359. return (DWORD) gccError;
  360. }
  361. DWORD CNmChannelData::DoJoinStatic(ChannelID staticChannel)
  362. {
  363. m_scs = SCS_JOIN_STATIC_CHANNEL;
  364. MCSError mcsError = m_pmcs_sap->ChannelJoin(staticChannel);
  365. // This generates an async MCS_CHANNEL_JOIN_CONFIRM
  366. TRACE_OUT(("MCSChannelJoinRequest %04X, err=%s",
  367. staticChannel, GetMcsErrorString(mcsError)));
  368. return (DWORD) mcsError;
  369. }
  370. DWORD CNmChannelData::DoJoin(SCSTATE scs)
  371. {
  372. m_scs = scs;
  373. MCSError mcsError = m_pmcs_sap->ChannelJoin(m_mcs_channel_id);
  374. // This generates an async MCS_CHANNEL_JOIN_CONFIRM
  375. TRACE_OUT(("MCSChannelJoinRequest %04X, err=%s",
  376. m_mcs_channel_id, GetMcsErrorString(mcsError)));
  377. return (DWORD) mcsError;
  378. }
  379. DWORD CNmChannelData::DoJoinNew(void)
  380. {
  381. ASSERT(0 == m_mcs_channel_id);
  382. ASSERT(SCS_REGRETRIEVE_NEW == m_scs);
  383. return DoJoin(SCS_JOIN_NEW);
  384. }
  385. DWORD CNmChannelData::DoJoinOld(void)
  386. {
  387. ASSERT(0 != m_mcs_channel_id);
  388. ASSERT(SCS_REGRETRIEVE_EXISTS == m_scs);
  389. return DoJoin(SCS_JOIN_OLD);
  390. }
  391. // Register the PRIVATE data channel. (m_mcs_sender_id)
  392. DWORD CNmChannelData::DoRegPrivate(void)
  393. {
  394. ASSERT(0 != m_mcs_sender_id);
  395. ASSERT((SCS_REGCHANNEL == m_scs) || (SCS_JOIN_OLD == m_scs));
  396. m_scs = SCS_REGPRIVATE;
  397. TRACE_OUT(("DoRegPrivate: channelId %04X as private for %08X", m_mcs_sender_id, m_dwUserId));
  398. GCCError gccError = m_gcc_pIAppSap->RegisterChannel(
  399. m_gcc_conference_id, &m_registry_key_Private, m_mcs_sender_id);
  400. // This generates an async GCC_REGISTER_CHANNEL_CONFIRM
  401. TRACE_OUT(("GCCRegisterChannelRequest err=%s", GetGccErrorString(gccError)));
  402. return (DWORD) gccError;
  403. }
  404. // deal with a GCC_RETRIEVE_ENTRY_CONFIRM notification
  405. VOID CNmChannelData::ProcessEntryConfirm(GCCAppSapMsg * pMsg)
  406. {
  407. if (pMsg->RegistryConfirm.pRegKey->resource_id.length >=
  408. m_gcc_registry_key.resource_id.length
  409. &&
  410. 0 != memcmp(m_gcc_registry_key.resource_id.value,
  411. pMsg->RegistryConfirm.pRegKey->resource_id.value,
  412. m_gcc_registry_key.resource_id.length))
  413. {
  414. OnEntryConfirmRemote(pMsg);
  415. }
  416. else
  417. {
  418. OnEntryConfirmLocal(pMsg);
  419. }
  420. }
  421. // deal with a GCC_REGISTRY_HANDLE_CONFIRM notification
  422. VOID CNmChannelData::ProcessHandleConfirm(GCCAppSapMsg * pMsg)
  423. {
  424. ASSERT(NULL != pMsg);
  425. NotifySink(&pMsg->RegAllocHandleConfirm, OnAllocateHandleConfirm);
  426. }
  427. VOID CNmChannelData::OnEntryConfirmRemote(GCCAppSapMsg * pMsg)
  428. {
  429. DWORD dwUserId;
  430. ASSERT(cbKeyApp ==
  431. pMsg->RegistryConfirm.pRegKey->resource_id.length);
  432. CopyMemory(&dwUserId,
  433. pMsg->RegistryConfirm.pRegKey->resource_id.value +
  434. cbKeyApp - sizeof(DWORD), sizeof(DWORD));
  435. TRACE_OUT(("GCC_RETRIEVE_ENTRY_CONFIRM: user private channelId = %04X for userId=%04X result=%s",
  436. pMsg->RegistryConfirm.pRegItem->channel_id, dwUserId,
  437. GetGccResultString(pMsg->RegistryConfirm.nResult)));
  438. if (GCC_RESULT_SUCCESSFUL == pMsg->RegistryConfirm.nResult)
  439. {
  440. UpdateMemberChannelId(dwUserId,
  441. pMsg->RegistryConfirm.pRegItem->channel_id);
  442. }
  443. else
  444. {
  445. CNmMemberId * pMemberId = GetMemberId(dwUserId);
  446. if (NULL != pMemberId)
  447. {
  448. UINT cCount = pMemberId->GetCheckIdCount();
  449. if (0 == cCount)
  450. {
  451. TRACE_OUT(("CT120Channel: No more ChannelId requests %08X", dwUserId));
  452. }
  453. else
  454. {
  455. cCount--;
  456. TRACE_OUT(("CT120Channel: Request Count for %08X = %0d", dwUserId, cCount));
  457. pMemberId->SetCheckIdCount(cCount);
  458. // BUGBUG: T.120 should notify us when this information is available
  459. RequestChannelId(dwUserId);
  460. }
  461. }
  462. }
  463. }
  464. VOID CNmChannelData::OnEntryConfirmLocal(GCCAppSapMsg * pMsg)
  465. {
  466. TRACE_OUT(("GCC_RETRIEVE_ENTRY_CONFIRM: public channelId = %04X result=%s",
  467. pMsg->RegistryConfirm.pRegItem->channel_id,
  468. GetGccResultString(pMsg->RegistryConfirm.nResult)));
  469. // Processing initial request for guid channel information
  470. ASSERT(sizeof(m_gcc_registry_item) == sizeof(*(pMsg->RegistryConfirm.pRegItem)));
  471. CopyMemory(&m_gcc_registry_item, pMsg->RegistryConfirm.pRegItem,
  472. sizeof(m_gcc_registry_item));
  473. if (GCC_RESULT_SUCCESSFUL == pMsg->RegistryConfirm.nResult)
  474. {
  475. m_mcs_channel_id = m_gcc_registry_item.channel_id;
  476. ASSERT(SCS_REGRETRIEVE == m_scs);
  477. m_scs = SCS_REGRETRIEVE_EXISTS;
  478. UpdateScState(SCS_REGRETRIEVE_EXISTS, 0);
  479. }
  480. else if (GCC_RESULT_ENTRY_DOES_NOT_EXIST == pMsg->RegistryConfirm.nResult)
  481. {
  482. TRACE_OUT((" channel does not exist - proceeding to new state"));
  483. ASSERT(0 == m_mcs_channel_id);
  484. ASSERT(SCS_REGRETRIEVE == m_scs);
  485. m_scs = SCS_REGRETRIEVE_NEW;
  486. UpdateScState(SCS_REGRETRIEVE_NEW, 0);
  487. }
  488. }
  489. // deal with a GCC_APP_ROSTER_REPORT_INDICATION
  490. BOOL CNmChannelData::UpdateRoster(GCCAppSapMsg * pMsg)
  491. {
  492. UINT iRoster;
  493. GCCApplicationRoster * lpAppRoster;
  494. int iRecord;
  495. GCCApplicationRecord * lpAppRecord;
  496. DWORD dwUserId;
  497. UCID rgPeerTemp[MAX_NM_PEER];
  498. int cPeer;
  499. int i;
  500. BOOL fAdd = FALSE;
  501. BOOL fRemove = FALSE;
  502. BOOL fLocal = FALSE;
  503. TRACE_OUT(("CT120Channel::UpdateRoster: conf=%d, roster count=%d",
  504. pMsg->AppRosterReportInd.nConfID,
  505. pMsg->AppRosterReportInd.cRosters));
  506. ZeroMemory(rgPeerTemp, sizeof(rgPeerTemp));
  507. /* Create rgPeerTemp[], cPeer */
  508. cPeer = 0;
  509. for (iRoster = 0;
  510. iRoster < pMsg->AppRosterReportInd.cRosters;
  511. iRoster++)
  512. {
  513. lpAppRoster = pMsg->AppRosterReportInd.apAppRosters[iRoster];
  514. if (lpAppRoster->session_key.session_id != m_gcc_session_key.session_id)
  515. continue;
  516. // Must pay attention to these flags to avoid GCC weirdness
  517. if (lpAppRoster->nodes_were_added)
  518. fAdd = TRUE;
  519. if (lpAppRoster->nodes_were_removed)
  520. fRemove = TRUE;
  521. for (iRecord = 0;
  522. iRecord < lpAppRoster->number_of_records;
  523. iRecord++)
  524. {
  525. lpAppRecord = lpAppRoster->application_record_list[iRecord];
  526. TRACE_OUT(("Node=%X, Entity=%X, AppId=%X", lpAppRecord->node_id,
  527. lpAppRecord->entity_id, lpAppRecord->application_user_id));
  528. // Search for the node in the list
  529. dwUserId = lpAppRecord->node_id;
  530. //
  531. // Check for local node
  532. //
  533. fLocal |= (dwUserId == m_dwUserIdLocal);
  534. for (i = 0; i < cPeer; i++)
  535. {
  536. if (dwUserId == rgPeerTemp[i].dwUserId)
  537. break;
  538. }
  539. if (i >= cPeer)
  540. {
  541. if (cPeer >= MAX_NM_PEER)
  542. continue; // over our limit!
  543. // Add the node to our new list
  544. rgPeerTemp[cPeer++].dwUserId = dwUserId;
  545. }
  546. // Make sure we know the sender_id's
  547. if (MCS_DYNAMIC_PRIVATE_CHANNEL == lpAppRecord->startup_channel_type)
  548. {
  549. rgPeerTemp[i].sender_id_private = lpAppRecord->application_user_id;
  550. }
  551. else
  552. {
  553. rgPeerTemp[i].sender_id_public = lpAppRecord->application_user_id;
  554. }
  555. }
  556. break; // out of for (iRoster) loop
  557. }
  558. UpdateRoster(rgPeerTemp, cPeer, fAdd, fRemove);
  559. return (fAdd && fLocal);
  560. }
  561. /* H R S E N D D A T A */
  562. /*----------------------------------------------------------------------------
  563. %%Function: HrSendData
  564. Send data on a specific channel
  565. ----------------------------------------------------------------------------*/
  566. HRESULT CNmChannelData::HrSendData(ChannelID channel_id, DWORD dwUserId,
  567. LPVOID lpv, DWORD cb, ULONG dwFlags)
  568. {
  569. TRACE_OUT(("CT120Channel::HrSendData: %d bytes", cb));
  570. PDUPriority priority;
  571. SendDataFlags allocation = APP_ALLOCATION;
  572. DataRequestType requestType;
  573. if(dwFlags & DATA_TOP_PRIORITY)
  574. {
  575. priority = TOP_PRIORITY;
  576. }
  577. else if (dwFlags & DATA_HIGH_PRIORITY)
  578. {
  579. priority = HIGH_PRIORITY;
  580. }
  581. else if (dwFlags & DATA_MEDIUM_PRIORITY)
  582. {
  583. priority = MEDIUM_PRIORITY;
  584. }
  585. else
  586. {
  587. priority = LOW_PRIORITY;
  588. }
  589. if (dwFlags & DATA_UNIFORM_SEND)
  590. {
  591. requestType = UNIFORM_SEND_DATA;
  592. }
  593. else
  594. {
  595. requestType = NORMAL_SEND_DATA;
  596. }
  597. if ((0 == m_mcs_channel_id) || (NULL == m_pmcs_sap) || (0 == channel_id))
  598. {
  599. WARNING_OUT(("*** Attempted to send data on invalid channel"));
  600. return E_INVALIDARG;
  601. }
  602. MCSError mcsError = m_pmcs_sap->SendData(requestType, channel_id, priority,
  603. (unsigned char *)lpv, cb, allocation);
  604. if (0 != mcsError)
  605. {
  606. TRACE_OUT(("SendData err=%s", GetMcsErrorString(mcsError)));
  607. // Usually MCS_TRANSMIT_BUFFER_FULL
  608. return E_OUTOFMEMORY;
  609. }
  610. { // Inform the app the data has been sent
  611. NMN_DATA_XFER nmnData;
  612. nmnData.pMember = NULL;
  613. nmnData.pb = (LPBYTE) lpv;
  614. nmnData.cb = cb;
  615. nmnData.dwFlags = 0;
  616. if (0 == dwUserId)
  617. {
  618. // send out notification with NULL member (BROADCAST)
  619. NotifySink(&nmnData, OnNmDataSent);
  620. }
  621. else
  622. {
  623. nmnData.pMember = (INmMember *) PMemberFromDwUserId(dwUserId, GetMemberList());
  624. if (nmnData.pMember)
  625. {
  626. NotifySink(&nmnData, OnNmDataSent);
  627. nmnData.pMember->Release();
  628. }
  629. }
  630. }
  631. TRACE_OUT(("SendData completed successfully"));
  632. return S_OK;
  633. }
  634. // Ask GCC for the private channel id.
  635. VOID CNmChannelData::RequestChannelId(DWORD dwUserId)
  636. {
  637. BYTE keyChannel[cbKeyApp];
  638. GCCRegistryKey registry_key;
  639. TRACE_OUT(("Requesting channel id for %08X", dwUserId));
  640. CopyStruct(&registry_key.session_key, &m_gcc_session_key);
  641. CreateAppKey(keyChannel, m_pGuid, dwUserId);
  642. SetAppKey(&registry_key.resource_id, keyChannel);
  643. GCCError gccError = m_gcc_pIAppSap->RegistryRetrieveEntry(
  644. m_gcc_conference_id, &registry_key);
  645. // This generates an async GCC_RETRIEVE_ENTRY_CONFIRM
  646. if (0 != gccError)
  647. {
  648. WARNING_OUT(("RequestChannelId - problem with GCCRegistryRectreiveEntryRequest"));
  649. }
  650. }
  651. VOID CNmChannelData::NotifyChannelConnected(void)
  652. {
  653. DBGENTRY(CNmChannelData::NotifyChannelConnected);
  654. if (S_OK != IsActive())
  655. {
  656. CConfObject * pConference = PConference();
  657. if (NULL != pConference)
  658. {
  659. m_fActive = TRUE;
  660. TRACE_OUT(("The channel is now officially active"));
  661. }
  662. else
  663. {
  664. WARNING_OUT(("PConference is NULL!"));
  665. }
  666. }
  667. DBGEXIT(CNmChannelData::NotifyChannelConnected);
  668. }
  669. /* N M G C C M S G H A N D L E R */
  670. /*-------------------------------------------------------------------------
  671. %%Function: NmGccMsgHandler
  672. -------------------------------------------------------------------------*/
  673. void CALLBACK NmGccMsgHandler(GCCAppSapMsg * pMsg)
  674. {
  675. TRACE_OUT(("NmGccMsgHandler: [%d]", pMsg->eMsgType));
  676. CNmChannelData * psc = (CNmChannelData *) (pMsg->pAppData);
  677. ASSERT(NULL != psc);
  678. psc->AddRef();
  679. switch (pMsg->eMsgType)
  680. {
  681. case GCC_PERMIT_TO_ENROLL_INDICATION:
  682. TRACE_OUT((" m_conference_id = %X", pMsg->AppPermissionToEnrollInd.nConfID));
  683. TRACE_OUT((" permission = %X", pMsg->AppPermissionToEnrollInd.fPermissionGranted));
  684. if ((SCS_CONNECTED == psc->m_scs) &&
  685. (0 == pMsg->AppPermissionToEnrollInd.fPermissionGranted))
  686. {
  687. psc->CloseConnection();
  688. break;
  689. }
  690. if (SCS_CREATESAP != psc->m_scs)
  691. {
  692. TRACE_OUT((" ignoring Enroll Indication"));
  693. break;
  694. }
  695. psc->m_gcc_conference_id = pMsg->AppPermissionToEnrollInd.nConfID;
  696. psc->UpdateScState(SCS_CREATESAP, !pMsg->AppPermissionToEnrollInd.fPermissionGranted);
  697. break;
  698. case GCC_ENROLL_CONFIRM:
  699. TRACE_OUT((" result = %s", GetGccResultString(pMsg->AppEnrollConfirm.nResult)));
  700. if (GCC_RESULT_SUCCESSFUL == pMsg->AppEnrollConfirm.nResult)
  701. {
  702. TRACE_OUT((" m_conference_id = %X", pMsg->AppEnrollConfirm.nConfID));
  703. TRACE_OUT((" entity_id = %X", pMsg->AppEnrollConfirm.eidMyself));
  704. TRACE_OUT((" node_id = %X", pMsg->AppEnrollConfirm.nidMyself));
  705. psc->m_gcc_node_id = pMsg->AppEnrollConfirm.nidMyself;
  706. }
  707. break;
  708. case GCC_APP_ROSTER_REPORT_INDICATION:
  709. if(psc->UpdateRoster(pMsg) && psc->m_scs == SCS_ENROLL)
  710. {
  711. psc->UpdateScState(SCS_ENROLL, GCC_RESULT_SUCCESSFUL);
  712. }
  713. break;
  714. case GCC_REGISTER_CHANNEL_CONFIRM:
  715. TRACE_OUT(("GCC_REGISTER_CHANNEL_CONFIRM: channel id = %04X result = %s",
  716. pMsg->RegistryConfirm.pRegItem->channel_id,
  717. GetGccResultString(pMsg->RegistryConfirm.nResult)));
  718. if (GCC_RESULT_SUCCESSFUL == pMsg->RegistryConfirm.nResult)
  719. {
  720. if (psc->GetMcsChannelId() ==
  721. pMsg->RegistryConfirm.pRegItem->channel_id)
  722. {
  723. ASSERT((0 == psc->m_gcc_registry_item.item_type) ||
  724. (GCC_REGISTRY_NONE == psc->m_gcc_registry_item.item_type));
  725. ASSERT(sizeof(psc->m_gcc_registry_item) == sizeof(*(pMsg->RegistryConfirm.pRegItem)));
  726. CopyMemory(&psc->m_gcc_registry_item, pMsg->RegistryConfirm.pRegItem,
  727. sizeof(psc->m_gcc_registry_item));
  728. }
  729. else
  730. {
  731. ASSERT(psc->SenderChannelId() ==
  732. pMsg->RegistryConfirm.pRegItem->channel_id);
  733. ASSERT(0 == psc->m_registry_item_Private.item_type);
  734. ASSERT(sizeof(psc->m_registry_item_Private) == sizeof(*(pMsg->RegistryConfirm.pRegItem)));
  735. CopyMemory(&psc->m_registry_item_Private, pMsg->RegistryConfirm.pRegItem,
  736. sizeof(psc->m_registry_item_Private));
  737. }
  738. }
  739. ASSERT((SCS_REGCHANNEL == psc->m_scs) || (SCS_REGPRIVATE == psc->m_scs));
  740. psc->UpdateScState(psc->m_scs, pMsg->RegistryConfirm.nResult);
  741. break;
  742. case GCC_RETRIEVE_ENTRY_CONFIRM:
  743. psc->ProcessEntryConfirm(pMsg);
  744. break;
  745. case GCC_ALLOCATE_HANDLE_CONFIRM:
  746. psc->ProcessHandleConfirm(pMsg);
  747. break;
  748. default:
  749. break;
  750. }
  751. psc->Release();
  752. }
  753. /* N M M C S M S G H A N D L E R */
  754. /*-------------------------------------------------------------------------
  755. %%Function: NmMcsMsgHandler
  756. -------------------------------------------------------------------------*/
  757. void CALLBACK NmMcsMsgHandler(unsigned int uMsg, LPARAM lParam, PVOID pv)
  758. {
  759. CNmChannelData * psc = (CNmChannelData *) pv;
  760. ASSERT(NULL != psc);
  761. // TRACE_OUT(("[%s]", GetMcsMsgString(uMsg)));
  762. psc->AddRef();
  763. switch (uMsg)
  764. {
  765. case MCS_ATTACH_USER_CONFIRM:
  766. {
  767. TRACE_OUT(("MCS_ATTACH_USER_CONFIRM channelId=%04X result=%s",
  768. LOWORD(lParam), GetMcsResultString(HIWORD(lParam))));
  769. if (RESULT_SUCCESSFUL == HIWORD(lParam))
  770. {
  771. TRACE_OUT((" Local m_mcs_sender_id = %04X", LOWORD(lParam)));
  772. psc->m_mcs_sender_id = LOWORD(lParam);
  773. }
  774. psc->UpdateScState(SCS_ATTACH, (DWORD) HIWORD(lParam));
  775. break;
  776. }
  777. case MCS_CHANNEL_JOIN_CONFIRM:
  778. {
  779. TRACE_OUT(("MCS_CHANNEL_JOIN_CONFIRM channelId=%04X result=%s",
  780. LOWORD(lParam), GetMcsResultString(HIWORD(lParam))));
  781. if (RESULT_SUCCESSFUL == HIWORD(lParam))
  782. {
  783. if (psc->m_mcs_sender_id == LOWORD(lParam))
  784. {
  785. ASSERT(SCS_JOIN_PRIVATE == psc->m_scs);
  786. }
  787. else
  788. {
  789. ASSERT((0 == psc->m_mcs_channel_id) ||
  790. (psc->m_mcs_channel_id == LOWORD(lParam)));
  791. psc->m_mcs_channel_id = LOWORD(lParam);
  792. }
  793. }
  794. ASSERT((SCS_JOIN_NEW == psc->m_scs) ||
  795. (SCS_JOIN_OLD == psc->m_scs) ||
  796. (SCS_JOIN_PRIVATE == psc->m_scs) ||
  797. (SCS_CONNECTED == psc->m_scs)||
  798. (SCS_JOIN_STATIC_CHANNEL == psc->m_scs));
  799. psc->UpdateScState(psc->m_scs, (DWORD) HIWORD(lParam));
  800. break;
  801. }
  802. case MCS_UNIFORM_SEND_DATA_INDICATION:
  803. case MCS_SEND_DATA_INDICATION: // lParam == SendData *
  804. {
  805. SendData * pSendData = (SendData *) lParam;
  806. ASSERT(NULL != pSendData);
  807. CNmMember * pMember = psc->PMemberFromSenderId(pSendData->initiator);
  808. if (NULL != pMember)
  809. {
  810. if (uMsg == MCS_UNIFORM_SEND_DATA_INDICATION)
  811. {
  812. //
  813. // Skip UNIFORM notifications that came from us
  814. //
  815. ULONG memberID;
  816. pMember->GetID(&memberID);
  817. if (memberID == psc->m_gcc_node_id)
  818. {
  819. // We sent this, skip it.
  820. goto RelMember;
  821. }
  822. }
  823. ASSERT (pSendData->segmentation == (SEGMENTATION_BEGIN | SEGMENTATION_END));
  824. NMN_DATA_XFER nmnData;
  825. nmnData.pMember =(INmMember *) pMember;
  826. nmnData.pb = pSendData->user_data.value;
  827. nmnData.cb = pSendData->user_data.length;
  828. nmnData.dwFlags = (ULONG)
  829. (NM_DF_SEGMENT_BEGIN | NM_DF_SEGMENT_END) |
  830. ((psc->GetMcsChannelId() == pSendData->channel_id) ?
  831. NM_DF_BROADCAST : NM_DF_PRIVATE);
  832. psc->NotifySink((PVOID) &nmnData, OnNmDataReceived);
  833. RelMember:
  834. pMember->Release();
  835. }
  836. break;
  837. }
  838. default:
  839. break;
  840. }
  841. psc->Release();
  842. }
  843. //
  844. // CNmMemberId
  845. //
  846. CNmMemberId::CNmMemberId(CNmMember *pMember, UCID * pucid) :
  847. m_channelId(pucid->channelId),
  848. m_sender_id_public(pucid->sender_id_public),
  849. m_sender_id_private(pucid->sender_id_private),
  850. m_cCheckId(0),
  851. m_pMember(pMember)
  852. {
  853. }
  854. VOID CNmMemberId::UpdateRosterInfo(UCID * pucid)
  855. {
  856. if (0 == m_channelId)
  857. m_channelId = pucid->channelId;
  858. if (0 == m_sender_id_private)
  859. m_sender_id_private = pucid->sender_id_private;
  860. if (0 == m_sender_id_public)
  861. m_sender_id_public = pucid->sender_id_public;
  862. }
  863. //
  864. // CNmChannelData
  865. //
  866. CNmChannelData::CNmChannelData(CConfObject * pConference, REFGUID rguid) :
  867. CConnectionPointContainer(g_apiidCP, ARRAY_ELEMENTS(g_apiidCP)),
  868. m_pConference(pConference),
  869. m_fClosed(TRUE),
  870. m_fActive(FALSE),
  871. m_cMember(0),
  872. m_pListMemberId(NULL),
  873. m_pListMember(NULL),
  874. m_pGCCER(NULL)
  875. {
  876. m_guid = rguid;
  877. ASSERT(GUID_NULL != rguid);
  878. m_dwUserIdLocal = pConference->GetDwUserIdLocal();
  879. ASSERT(INVALID_GCCID != m_dwUserIdLocal);
  880. TRACE_OUT(("Obj: %08X created CNmChannelData", this));
  881. }
  882. CNmChannelData::~CNmChannelData(void)
  883. {
  884. DBGENTRY(CNmChannelData::~CNmChannelData);
  885. // This will keep us from being deleted again...
  886. ++m_ulcRef;
  887. CloseConnection();
  888. FreeMemberIdList(&m_pListMemberId);
  889. delete m_pListMember;
  890. TRACE_OUT(("Obj: %08X destroyed CNmChannelData", this));
  891. DBGEXIT(CNmChannelData::~CNmChannelData);
  892. }
  893. /* A D D M E M B E R */
  894. /*-------------------------------------------------------------------------
  895. %%Function: AddMember
  896. -------------------------------------------------------------------------*/
  897. VOID CNmChannelData::AddMember(CNmMember * pMember)
  898. {
  899. TRACE_OUT(("CNmChannelData::AddMember [%ls] id=%08X",
  900. pMember->GetName(), pMember->GetGCCID()));
  901. m_cMember++;
  902. pMember->AddRef();
  903. AddNode(pMember, &m_pListMember);
  904. }
  905. /* R E M O V E M E M B E R */
  906. /*-------------------------------------------------------------------------
  907. %%Function: RemoveMember
  908. -------------------------------------------------------------------------*/
  909. VOID CNmChannelData::RemoveMember(CNmMember * pMember)
  910. {
  911. TRACE_OUT(("CNmChannelData::RemoveMember [%ls] id=%08X",
  912. pMember->GetName(), pMember->GetGCCID()));
  913. m_cMember--;
  914. ASSERT(m_cMember >= 0);
  915. RemoveNode(pMember, m_pListMember);
  916. pMember->Release(); // Release AFTER notifying everyone
  917. }
  918. /* O P E N C O N N E C T I O N */
  919. /*-------------------------------------------------------------------------
  920. %%Function: OpenConnection
  921. Open a T.120 data connection (init both public and private channels)
  922. -------------------------------------------------------------------------*/
  923. HRESULT CNmChannelData::OpenConnection(void)
  924. {
  925. TRACE_OUT(("CNmChannelData::OpenConection()"));
  926. if (!m_fClosed)
  927. return E_FAIL; // already open
  928. m_fClosed = FALSE; // need to call CloseConnection after this
  929. InitCT120Channel(m_dwUserIdLocal);
  930. return S_OK;
  931. }
  932. /* C L O S E C O N N E C T I O N */
  933. /*-------------------------------------------------------------------------
  934. %%Function: CloseConnection
  935. Close the data channel - this matches what is done in OpenConnection
  936. -------------------------------------------------------------------------*/
  937. HRESULT CNmChannelData::CloseConnection(void)
  938. {
  939. DBGENTRY(CNmChannelData::CloseConnection);
  940. HRESULT hr = S_OK;
  941. if (!m_fClosed)
  942. {
  943. m_fClosed = TRUE;
  944. // Close any open T.120 channels
  945. CloseChannel();
  946. if (0 != m_cMember)
  947. {
  948. // force roster update with no peers
  949. TRACE_OUT(("CloseConnection: %d members left", m_cMember));
  950. UpdateRoster(NULL, 0, FALSE, TRUE /* fRemove */);
  951. ASSERT(IsEmpty());
  952. }
  953. CConfObject * pConference = PConference();
  954. if (NULL != pConference)
  955. {
  956. m_fActive = FALSE;
  957. }
  958. }
  959. DBGEXIT_HR(CNmChannelData::CloseConnection, hr);
  960. return hr;
  961. }
  962. /* U P D A T E P E E R */
  963. /*-------------------------------------------------------------------------
  964. %%Function: UpdatePeer
  965. -------------------------------------------------------------------------*/
  966. VOID CNmChannelData::UpdatePeer(CNmMember * pMember, UCID *pucid, BOOL fAdd)
  967. {
  968. #ifdef DEBUG
  969. TRACE_OUT(("UpdatePeer (%08X) fAdd=%d fLocal=%d", pMember, fAdd, pMember->FLocal()));
  970. if (NULL != pucid)
  971. {
  972. TRACE_OUT((" channelId=(%04X) dwUserId=%08X", pucid->channelId, pucid->dwUserId));
  973. }
  974. #endif /* DEBUG */
  975. if (fAdd)
  976. {
  977. CNmMemberId *pMemberId = new CNmMemberId(pMember, pucid);
  978. if (NULL != pMemberId)
  979. {
  980. AddNode(pMemberId, &m_pListMemberId);
  981. AddMember(pMember);
  982. }
  983. }
  984. else
  985. {
  986. CNmMemberId *pMemberId = GetMemberId(pMember);
  987. if (NULL != pMemberId)
  988. {
  989. RemoveNode(pMemberId, m_pListMemberId);
  990. delete pMemberId;
  991. RemoveMember(pMember);
  992. }
  993. }
  994. }
  995. /* U P D A T E R O S T E R */
  996. /*-------------------------------------------------------------------------
  997. %%Function: UpdateRoster
  998. Update the local peer list based on the new roster data
  999. -------------------------------------------------------------------------*/
  1000. VOID CNmChannelData::UpdateRoster(UCID * rgPeer, int cPeer, BOOL fAdd, BOOL fRemove)
  1001. {
  1002. int iPeer;
  1003. DWORD dwUserId;
  1004. CNmMember * pMember;
  1005. COBLIST * pList;
  1006. TRACE_OUT(("CNmChannelData::UpdateRoster: %d peers, fAdd=%d, fRemove=%d",
  1007. cPeer, fAdd, fRemove));
  1008. if (NULL != m_pListMemberId)
  1009. {
  1010. for (POSITION pos = m_pListMemberId->GetHeadPosition(); NULL != pos; )
  1011. {
  1012. BOOL fFound = FALSE;
  1013. CNmMemberId *pMemberId = (CNmMemberId *) m_pListMemberId->GetNext(pos);
  1014. ASSERT(NULL != pMemberId);
  1015. pMember = pMemberId->GetMember();
  1016. ASSERT(NULL != pMember);
  1017. dwUserId = pMember->GetGCCID();
  1018. if (0 != dwUserId)
  1019. {
  1020. for (iPeer = 0; iPeer < cPeer; iPeer++)
  1021. {
  1022. if (dwUserId == rgPeer[iPeer].dwUserId)
  1023. {
  1024. fFound = TRUE;
  1025. // remove from the new list
  1026. // so that the peer will not be added below
  1027. rgPeer[iPeer].dwUserId = 0;
  1028. // no change, but make sure we know sender_ids
  1029. pMemberId->UpdateRosterInfo(&rgPeer[iPeer]);
  1030. // try to find channel id, if necessary
  1031. if ((0 == pMemberId->GetChannelId()) &&
  1032. (0 == pMemberId->GetCheckIdCount())
  1033. && !pMember->FLocal())
  1034. {
  1035. pMemberId->SetCheckIdCount(MAX_CHECKID_COUNT);
  1036. RequestChannelId(dwUserId);
  1037. }
  1038. break;
  1039. }
  1040. }
  1041. }
  1042. if (!fFound && fRemove)
  1043. {
  1044. pMember->AddRef();
  1045. // Unable to find old peer in new list - delete it
  1046. UpdatePeer(pMember, NULL, FALSE /* fAdd */ );
  1047. pMember->Release();
  1048. }
  1049. }
  1050. }
  1051. if (!fAdd)
  1052. return;
  1053. // Use the conference list to find member data
  1054. pList = PConference()->GetMemberList();
  1055. /* Add new peers */
  1056. for (iPeer = 0; iPeer < cPeer; iPeer++)
  1057. {
  1058. dwUserId = rgPeer[iPeer].dwUserId;
  1059. if (0 == dwUserId)
  1060. continue;
  1061. // PMemberFromDwUserId returns AddRef'd member
  1062. pMember = PMemberFromDwUserId(dwUserId, pList);
  1063. if (NULL == pMember)
  1064. {
  1065. WARNING_OUT(("UpdateRoster: Member not found! dwUserId=%08X", dwUserId));
  1066. }
  1067. else
  1068. {
  1069. UpdatePeer(pMember, &rgPeer[iPeer], TRUE /* fAdd */);
  1070. pMember->Release();
  1071. }
  1072. }
  1073. }
  1074. /* U P D A T E M E M B E R C H A N N E L I D */
  1075. /*-------------------------------------------------------------------------
  1076. %%Function: UpdateMemberChannelId
  1077. -------------------------------------------------------------------------*/
  1078. VOID CNmChannelData::UpdateMemberChannelId(DWORD dwUserId, ChannelID channelId)
  1079. {
  1080. // PMemberFromDwUserId returns AddRef'd member
  1081. CNmMember * pMember = PMemberFromDwUserId(dwUserId, PConference()->GetMemberList());
  1082. TRACE_OUT(("Member (%08X) private channelId=(%04X)", pMember, channelId));
  1083. if (NULL != pMember)
  1084. {
  1085. UCID ucid;
  1086. ClearStruct(&ucid);
  1087. ucid.channelId = channelId;
  1088. UpdateRosterInfo(pMember, &ucid);
  1089. pMember->Release();
  1090. }
  1091. }
  1092. /* G E T M E M B E R I D */
  1093. /*-------------------------------------------------------------------------
  1094. %%Function: GetMemberId
  1095. -------------------------------------------------------------------------*/
  1096. CNmMemberId * CNmChannelData::GetMemberId(CNmMember *pMember)
  1097. {
  1098. if (NULL != m_pListMemberId)
  1099. {
  1100. POSITION pos = m_pListMemberId->GetHeadPosition();
  1101. while (NULL != pos)
  1102. {
  1103. CNmMemberId *pMemberId = (CNmMemberId *) m_pListMemberId->GetNext(pos);
  1104. ASSERT(NULL != pMemberId);
  1105. if (pMemberId->GetMember() == pMember)
  1106. {
  1107. return pMemberId;
  1108. }
  1109. }
  1110. }
  1111. return NULL;
  1112. }
  1113. /* G E T M E M B E R I D */
  1114. /*-------------------------------------------------------------------------
  1115. %%Function: GetMemberId
  1116. -------------------------------------------------------------------------*/
  1117. CNmMemberId * CNmChannelData::GetMemberId(DWORD dwUserId)
  1118. {
  1119. if (NULL != m_pListMemberId)
  1120. {
  1121. POSITION pos = m_pListMemberId->GetHeadPosition();
  1122. while (NULL != pos)
  1123. {
  1124. CNmMemberId *pMemberId = (CNmMemberId *) m_pListMemberId->GetNext(pos);
  1125. ASSERT(NULL != pMemberId);
  1126. CNmMember *pMember = pMemberId->GetMember();
  1127. ASSERT(NULL != pMember);
  1128. if (pMember->GetGCCID() == dwUserId)
  1129. {
  1130. return pMemberId;
  1131. }
  1132. }
  1133. }
  1134. return NULL;
  1135. }
  1136. /* U P D A T E R O S T E R I N F O */
  1137. /*-------------------------------------------------------------------------
  1138. %%Function: UpdateRosterInfo
  1139. -------------------------------------------------------------------------*/
  1140. VOID CNmChannelData::UpdateRosterInfo(CNmMember *pMember, UCID * pucid)
  1141. {
  1142. CNmMemberId *pMemberId = GetMemberId(pMember);
  1143. if (NULL != pMemberId)
  1144. {
  1145. pMemberId->UpdateRosterInfo(pucid);
  1146. }
  1147. }
  1148. /* G E T C H A N N E L I D */
  1149. /*-------------------------------------------------------------------------
  1150. %%Function: GetChannelId
  1151. -------------------------------------------------------------------------*/
  1152. ChannelID CNmChannelData::GetChannelId(CNmMember *pMember)
  1153. {
  1154. CNmMemberId *pMemberId = GetMemberId(pMember);
  1155. if (NULL != pMemberId)
  1156. {
  1157. return pMemberId->GetChannelId();
  1158. }
  1159. return 0;
  1160. }
  1161. /* P M E M B E R F R O M S E N D E R I D */
  1162. /*-------------------------------------------------------------------------
  1163. %%Function: PMemberFromSenderId
  1164. -------------------------------------------------------------------------*/
  1165. CNmMember * CNmChannelData::PMemberFromSenderId(UserID id)
  1166. {
  1167. if (NULL != m_pListMemberId)
  1168. {
  1169. POSITION pos = m_pListMemberId->GetHeadPosition();
  1170. while (NULL != pos)
  1171. {
  1172. CNmMemberId * pMemberId = (CNmMemberId *) m_pListMemberId->GetNext(pos);
  1173. ASSERT(NULL != pMemberId);
  1174. if (pMemberId->FSenderId(id))
  1175. {
  1176. CNmMember* pMember = pMemberId->GetMember();
  1177. ASSERT(NULL != pMember);
  1178. pMember->AddRef();
  1179. return pMember;
  1180. }
  1181. }
  1182. }
  1183. return NULL;
  1184. }
  1185. ///////////////////////////
  1186. // CNmChannelData:IUknown
  1187. ULONG STDMETHODCALLTYPE CNmChannelData::AddRef(void)
  1188. {
  1189. TRACE_OUT(("CNmChannelData::AddRef this = 0x%X", this));
  1190. return RefCount::AddRef();
  1191. }
  1192. ULONG STDMETHODCALLTYPE CNmChannelData::Release(void)
  1193. {
  1194. TRACE_OUT(("CNmChannelData::Release this = 0x%X", this));
  1195. return RefCount::Release();
  1196. }
  1197. HRESULT STDMETHODCALLTYPE CNmChannelData::QueryInterface(REFIID riid, PVOID *ppv)
  1198. {
  1199. HRESULT hr = S_OK;
  1200. if ((riid == IID_IUnknown) || (riid == IID_INmChannelData))
  1201. {
  1202. *ppv = (INmChannelData *)this;
  1203. TRACE_OUT(("CNmChannel::QueryInterface(): Returning INmChannelData."));
  1204. }
  1205. else if (riid == IID_IConnectionPointContainer)
  1206. {
  1207. *ppv = (IConnectionPointContainer *) this;
  1208. TRACE_OUT(("CNmChannel::QueryInterface(): Returning IConnectionPointContainer."));
  1209. }
  1210. else
  1211. {
  1212. hr = E_NOINTERFACE;
  1213. *ppv = NULL;
  1214. TRACE_OUT(("CNmChannel::QueryInterface(): Called on unknown interface."));
  1215. }
  1216. if (S_OK == hr)
  1217. {
  1218. AddRef();
  1219. }
  1220. return hr;
  1221. }
  1222. HRESULT STDMETHODCALLTYPE CNmChannelData::GetGuid(GUID *pGuid)
  1223. {
  1224. if (NULL == pGuid)
  1225. return E_POINTER;
  1226. *pGuid = m_guid;
  1227. return S_OK;
  1228. }
  1229. HRESULT STDMETHODCALLTYPE CNmChannelData::SendData(INmMember *pMember,
  1230. ULONG cb, LPBYTE pv, ULONG uOptions)
  1231. {
  1232. HRESULT hr;
  1233. if (!m_fActive)
  1234. {
  1235. // No active Channels, yet
  1236. return E_FAIL;
  1237. }
  1238. if ((NULL == pv) || (0 == cb))
  1239. {
  1240. return S_FALSE;
  1241. }
  1242. if (IsBadReadPtr(pv, cb))
  1243. {
  1244. return E_POINTER;
  1245. }
  1246. CNmMember * pDest = (CNmMember *) pMember;
  1247. COBLIST * pList = GetMemberList();
  1248. if (NULL == pMember)
  1249. {
  1250. hr = HrSendData(GetMcsChannelId(), 0, pv, cb, uOptions);
  1251. }
  1252. else if ((NULL == pList) || (NULL == pList->Lookup(pDest)) )
  1253. {
  1254. // Destination is not in list
  1255. hr = E_INVALIDARG;
  1256. }
  1257. else
  1258. {
  1259. ChannelID channel_id = GetChannelId(pDest);
  1260. if (0 == channel_id)
  1261. {
  1262. WARNING_OUT(("Unable to find user destination channel?"));
  1263. CNmMemberId *pMemberId = GetMemberId(pDest);
  1264. if (NULL == pMemberId)
  1265. {
  1266. hr = E_UNEXPECTED;
  1267. }
  1268. else
  1269. {
  1270. channel_id = pMemberId->SenderId();
  1271. hr = (0 == channel_id) ? E_FAIL : S_OK;
  1272. }
  1273. }
  1274. if (SUCCEEDED(hr))
  1275. {
  1276. hr = HrSendData(channel_id, pDest->GetGCCID(), pv, cb, uOptions);
  1277. }
  1278. }
  1279. return hr;
  1280. }
  1281. HRESULT STDMETHODCALLTYPE CNmChannelData::RegistryAllocateHandle(ULONG numberOfHandlesRequested)
  1282. {
  1283. if (!m_fActive)
  1284. {
  1285. // No active Channels, yet
  1286. return E_FAIL;
  1287. }
  1288. if(numberOfHandlesRequested == 0)
  1289. {
  1290. return E_INVALIDARG;
  1291. }
  1292. //
  1293. // Request handles from gcc
  1294. //
  1295. GCCError gccError = m_gcc_pIAppSap->RegistryAllocateHandle(m_gcc_conference_id, numberOfHandlesRequested);
  1296. if(gccError == GCC_NO_ERROR)
  1297. {
  1298. return S_OK;
  1299. }
  1300. else
  1301. {
  1302. return E_FAIL;
  1303. }
  1304. }
  1305. HRESULT STDMETHODCALLTYPE CNmChannelData::IsActive(void)
  1306. {
  1307. return m_fActive ? S_OK : S_FALSE;
  1308. }
  1309. HRESULT STDMETHODCALLTYPE CNmChannelData::SetActive(BOOL fActive)
  1310. {
  1311. TRACE_OUT(("CNmChannelData::SetActive(%d)", fActive));
  1312. NM_CONFERENCE_STATE state;
  1313. // Must be in a non-idle conference
  1314. CConfObject * pConference = PConference();
  1315. pConference->GetState(&state);
  1316. if ((NULL == pConference) || state == NM_CONFERENCE_IDLE)
  1317. return E_FAIL;
  1318. if (fActive)
  1319. {
  1320. if (S_OK == IsActive())
  1321. return S_OK;
  1322. return OpenConnection();
  1323. }
  1324. else
  1325. {
  1326. if (S_FALSE == IsActive())
  1327. return S_OK;
  1328. return CloseConnection();
  1329. }
  1330. }
  1331. HRESULT STDMETHODCALLTYPE CNmChannelData::GetConference(INmConference **ppConference)
  1332. {
  1333. return ::GetConference(ppConference);
  1334. }
  1335. HRESULT STDMETHODCALLTYPE CNmChannelData::EnumMember(IEnumNmMember **ppEnum)
  1336. {
  1337. HRESULT hr = E_POINTER;
  1338. if (NULL != ppEnum)
  1339. {
  1340. *ppEnum = new CEnumNmMember( GetMemberList(), m_cMember);
  1341. hr = (NULL != *ppEnum)? S_OK : E_OUTOFMEMORY;
  1342. }
  1343. return hr;
  1344. }
  1345. HRESULT STDMETHODCALLTYPE CNmChannelData::GetMemberCount(ULONG *puCount)
  1346. {
  1347. HRESULT hr = E_POINTER;
  1348. if (NULL != puCount)
  1349. {
  1350. *puCount = m_cMember;
  1351. hr = S_OK;
  1352. }
  1353. return hr;
  1354. }
  1355. ///////////////////////////////////////////////////////////////////////////
  1356. // Utility Functions
  1357. HRESULT OnNmDataSent(IUnknown *pChannelDataNotify, void *pv, REFIID riid)
  1358. {
  1359. NMN_DATA_XFER * pData = (NMN_DATA_XFER *) pv;
  1360. if (IID_INmChannelDataNotify.Data1 == riid.Data1)
  1361. {
  1362. ((INmChannelDataNotify*)pChannelDataNotify)->DataSent(
  1363. pData->pMember, pData->cb, pData->pb);
  1364. }
  1365. return S_OK;
  1366. }
  1367. HRESULT OnNmDataReceived(IUnknown *pChannelDataNotify, void *pv, REFIID riid)
  1368. {
  1369. NMN_DATA_XFER * pData = (NMN_DATA_XFER *) pv;
  1370. if (IID_INmChannelDataNotify.Data1 == riid.Data1)
  1371. {
  1372. ((INmChannelDataNotify*)pChannelDataNotify)->DataReceived(
  1373. pData->pMember, pData->cb, pData->pb, pData->dwFlags);
  1374. }
  1375. return S_OK;
  1376. }
  1377. HRESULT OnAllocateHandleConfirm(IUnknown *pChannelDataNotify, void *pv, REFIID riid)
  1378. {
  1379. if(IID_INmChannelDataNotify.Data1 == riid.Data1)
  1380. {
  1381. GCCRegAllocateHandleConfirm *pConfirm = (GCCRegAllocateHandleConfirm *)pv;
  1382. ((INmChannelDataNotify*)pChannelDataNotify)->AllocateHandleConfirm(pConfirm->nFirstHandle,
  1383. pConfirm->cHandles);
  1384. }
  1385. return S_OK;
  1386. }
  1387. ///////////////////////////////////////////////////////////////////////////
  1388. // Utility Functions
  1389. /* F R E E M E M B E R ID L I S T */
  1390. /*-------------------------------------------------------------------------
  1391. %%Function: FreeMemberIdList
  1392. -------------------------------------------------------------------------*/
  1393. VOID FreeMemberIdList(COBLIST ** ppList)
  1394. {
  1395. DBGENTRY(FreeMemberIdList);
  1396. ASSERT(NULL != ppList);
  1397. if (NULL != *ppList)
  1398. {
  1399. while (!(*ppList)->IsEmpty())
  1400. {
  1401. CNmMemberId * pMemberId = (CNmMemberId *) (*ppList)->RemoveHead();
  1402. delete pMemberId;
  1403. }
  1404. delete *ppList;
  1405. *ppList = NULL;
  1406. }
  1407. }
  1408. ///////////////////////////////////////////////////////////////////////////
  1409. //
  1410. // GCC / MCS Errors
  1411. #ifdef DEBUG
  1412. LPCTSTR _FormatSzErr(LPTSTR psz, UINT uErr)
  1413. {
  1414. static char szErr[MAX_PATH];
  1415. wsprintf(szErr, "%s 0x%08X (%d)", psz, uErr, uErr);
  1416. return szErr;
  1417. }
  1418. #define STRING_CASE(val) case val: pcsz = #val; break
  1419. LPCTSTR GetGccErrorString(GCCError uErr)
  1420. {
  1421. LPCTSTR pcsz;
  1422. switch (uErr)
  1423. {
  1424. STRING_CASE(GCC_NO_ERROR);
  1425. STRING_CASE(GCC_RESULT_ENTRY_DOES_NOT_EXIST);
  1426. STRING_CASE(GCC_NOT_INITIALIZED);
  1427. STRING_CASE(GCC_ALREADY_INITIALIZED);
  1428. STRING_CASE(GCC_ALLOCATION_FAILURE);
  1429. STRING_CASE(GCC_NO_SUCH_APPLICATION);
  1430. STRING_CASE(GCC_INVALID_CONFERENCE);
  1431. default:
  1432. pcsz = _FormatSzErr("GccError", uErr);
  1433. break;
  1434. }
  1435. return pcsz;
  1436. }
  1437. LPCTSTR GetMcsErrorString(MCSError uErr)
  1438. {
  1439. LPCTSTR pcsz;
  1440. switch (uErr)
  1441. {
  1442. STRING_CASE(MCS_NO_ERROR);
  1443. STRING_CASE(MCS_USER_NOT_ATTACHED);
  1444. STRING_CASE(MCS_NO_SUCH_USER);
  1445. STRING_CASE(MCS_TRANSMIT_BUFFER_FULL);
  1446. STRING_CASE(MCS_NO_SUCH_CONNECTION);
  1447. default:
  1448. pcsz = _FormatSzErr("McsError", uErr);
  1449. break;
  1450. }
  1451. return pcsz;
  1452. }
  1453. LPCTSTR GetGccResultString(UINT uErr)
  1454. {
  1455. LPCTSTR pcsz;
  1456. switch (uErr)
  1457. {
  1458. STRING_CASE(GCC_RESULT_ENTRY_DOES_NOT_EXIST);
  1459. default:
  1460. pcsz = _FormatSzErr("GccResult", uErr);
  1461. break;
  1462. }
  1463. return pcsz;
  1464. }
  1465. LPCTSTR GetMcsResultString(UINT uErr)
  1466. {
  1467. return _FormatSzErr("McsResult", uErr);
  1468. }
  1469. #endif /* DEBUG (T.120 Error routines) */